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

// Package server contains a web server that can serve an instance of
// the dataaccess.Repository interface via HTTP and HTTPs.
package server

import (
	"allmark.io/modules/common/config"
	"allmark.io/modules/common/logger"
	"allmark.io/modules/dataaccess"
	"allmark.io/modules/services/converter"
	"allmark.io/modules/services/parser"
	"allmark.io/modules/web/handlers"
	"allmark.io/modules/web/header"
	"allmark.io/modules/web/orchestrator"
	"allmark.io/modules/web/view/templates"
	"allmark.io/modules/web/webpaths"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/skratchdot/open-golang/open"
	"net/http"
)

// New creates a new Server instance for the given repository.
func New(logger logger.Logger, config config.Config, repository dataaccess.Repository, parser parser.Parser, converter converter.Converter) (*Server, error) {

	// create the request handlers
	patherFactory := webpaths.NewFactory(logger, repository)
	itemPathProvider := patherFactory.Absolute(handlers.BasePath)
	tagPathProvider := patherFactory.Absolute(handlers.TagPathPrefix)
	webPathProvider := webpaths.NewWebPathProvider(patherFactory, itemPathProvider, tagPathProvider)
	templateProvider := templates.NewProvider(config.TemplatesFolder())
	orchestratorFactory := orchestrator.NewFactory(logger, config, repository, parser, converter, webPathProvider)
	reindexInterval := config.Indexing.IntervalInSeconds
	headerWriterFactory := header.NewHeaderWriterFactory(reindexInterval)
	requestHandlers := handlers.GetBaseHandlers(logger, config, templateProvider, *orchestratorFactory, headerWriterFactory)

	return &Server{
		logger: logger,
		config: config,

		headerWriterFactory: headerWriterFactory,
		requestHandlers:     requestHandlers,
	}, nil

}

// Server represents a web server instance for a given repository.
type Server struct {
	logger logger.Logger
	config config.Config

	headerWriterFactory header.WriterFactory

	requestHandlers handlers.HandlerList
}

// Start starts the current web server.
func (server *Server) Start() chan error {

	result := make(chan error)

	standardRequestRouter := server.getStandardRequestRouter()

	// bindings
	httpEndpoint, httpEnabled := server.httpEndpoint()
	httpsEndpoint, httpsEnabled := server.httpsEndpoint()

	// abort if no tcp bindings are configured
	if len(httpEndpoint.Bindings()) == 0 && len(httpsEndpoint.Bindings()) == 0 {
		result <- fmt.Errorf("No TCP bindings configured")
		return result
	}

	uniqueURLs := make(map[string]string)

	// http
	if httpEnabled {

		for _, tcpBinding := range httpEndpoint.Bindings() {

			tcpBinding.AssignFreePort()

			tcpAddr := tcpBinding.GetTCPAddress()
			address := tcpAddr.String()

			// start listening
			go func() {
				server.logger.Info("HTTP Endpoint: %s", address)

				if httpEndpoint.ForceHTTPS() {

					// Redirect HTTP → HTTPS
					redirectTarget := httpsEndpoint.DefaultURL()
					httpsRedirectRouter := server.getRedirectRouter(redirectTarget)

					if err := http.ListenAndServe(address, httpsRedirectRouter); err != nil {
						result <- fmt.Errorf("Server failed with error: %v", err)
					} else {
						result <- nil
					}

				} else {

					// Standard HTTP Request Router
					if err := http.ListenAndServe(address, standardRequestRouter); err != nil {
						result <- fmt.Errorf("Server failed with error: %v", err)
					} else {
						result <- nil
					}

				}

			}()

			// store the URL for later opening
			if httpsEnabled == false {
				endpointURL := httpEndpoint.DefaultURL()
				uniqueURLs[endpointURL] = endpointURL
			}

		}
	}

	// https
	if httpsEnabled {

		for _, tcpBinding := range httpsEndpoint.Bindings() {

			tcpBinding.AssignFreePort()

			tcpAddr := tcpBinding.GetTCPAddress()
			address := tcpAddr.String()

			// start listening
			go func() {
				server.logger.Info("HTTPS Endpoint: %s", address)

				// Standard HTTPS Request Router
				if err := http.ListenAndServeTLS(address, httpsEndpoint.CertFilePath(), httpsEndpoint.KeyFilePath(), standardRequestRouter); err != nil {
					result <- fmt.Errorf("Server failed with error: %v", err)
				} else {
					result <- nil
				}

			}()

			// store the URL for later opening
			endpointURL := httpsEndpoint.DefaultURL()
			uniqueURLs[endpointURL] = endpointURL
		}

	}

	// open HTTP URL(s) in a browser
	for _, url := range uniqueURLs {
		server.logger.Info("Open URL: %s", url)
		go open.Run(url)
	}

	return result
}

// getRedirectRouter returns a router which redirects all requests to the url with the given base.
func (server *Server) getRedirectRouter(baseURITarget string) *mux.Router {
	redirectRouter := mux.NewRouter()

	for _, requestHandler := range handlers.GetRedirectHandlers(baseURITarget) {
		requestRoute := requestHandler.Route
		requestHandler := requestHandler.Handler

		redirectRouter.Handle(requestRoute, requestHandler)
	}

	return redirectRouter
}

// Get an instance of the standard request router for all repository related routes.
func (server *Server) getStandardRequestRouter() *mux.Router {

	// register requst routers
	requestRouter := mux.NewRouter()

	for _, requestHandler := range server.requestHandlers {
		requestRoute := requestHandler.Route
		requestHandler := requestHandler.Handler

		// add logging
		requestHandler = handlers.LogRequests(requestHandler)

		// add compression
		requestHandler = handlers.CompressResponses(requestHandler)

		// add authentication
		if _, httpsEnabled := server.httpsEndpoint(); httpsEnabled && server.config.AuthenticationIsEnabled() {
			secretProvider := server.config.GetAuthenticationUserStore()
			if secretProvider == nil {
				panic("Authentication is enabled but the supplied secret provider is nil.")
			}

			requestHandler = handlers.RequireDigestAuthentication(requestHandler, secretProvider)
		}

		requestRouter.Handle(requestRoute, requestHandler)
	}

	return requestRouter
}

// Get the http binding if it is enabled.
func (server *Server) httpEndpoint() (httpEndpoint HTTPEndpoint, enabled bool) {

	if !server.config.Server.HTTP.Enabled {
		return HTTPEndpoint{}, false
	}

	return HTTPEndpoint{
		isSecure:    false,
		forceHTTPS:  server.config.Server.HTTPS.HTTPSIsForced(),
		tcpBindings: server.config.Server.HTTP.Bindings,
	}, true

}

// Get the https binding if it is enabled.tcpBinding
func (server *Server) httpsEndpoint() (httpsEndpoint HTTPSEndpoint, enabled bool) {

	if !server.config.Server.HTTPS.Enabled {
		return HTTPSEndpoint{}, false
	}

	httpEndpoint := HTTPEndpoint{
		domain:      server.config.Server.DomainName,
		isSecure:    true,
		tcpBindings: server.config.Server.HTTPS.Bindings,
	}

	certFilePath, keyFilePath := server.config.CertificateFilePaths()

	httpsEndpoint = HTTPSEndpoint{
		HTTPEndpoint: httpEndpoint,
		certFilePath: certFilePath,
		keyFilePath:  keyFilePath,
	}

	return httpsEndpoint, true

}

// HTTPEndpoint contains HTTP server endpoint parameters such as a domain name and TCP bindings.
type HTTPEndpoint struct {
	domain      string
	isSecure    bool
	forceHTTPS  bool
	tcpBindings []*config.TCPBinding
}

// IsSecure returns a flag indicating whether the current HTTPEndpoint is secure (HTTPS) or not.
func (endpoint *HTTPEndpoint) IsSecure() bool {
	return endpoint.isSecure
}

// Protocol returns the protocol of the current HTTPEndpoint. "https" if this endpoint is secure; otherwise "http".
func (endpoint *HTTPEndpoint) Protocol() string {
	if endpoint.isSecure {
		return "https"
	}
	return "http"
}

// ForceHTTPS returns a flag indicating whether a secure connection shall be preferred over insecure connections.
func (endpoint *HTTPEndpoint) ForceHTTPS() bool {
	return endpoint.forceHTTPS
}

// Bindings returns all TCP bindings of the current HTTP endpoint.
func (endpoint *HTTPEndpoint) Bindings() []*config.TCPBinding {
	return endpoint.tcpBindings
}

// URL return the formatted URL (e.g. "https://127.0.0.1:8080") for the given TCP binding, using the IP address as the hostname.
func (endpoint *HTTPEndpoint) URL(tcpBinding config.TCPBinding) string {
	tcpAddress := tcpBinding.GetTCPAddress()
	return fmt.Sprintf("%s://%s", endpoint.Protocol(), tcpAddress.String())
}

// DefaultURL return the default url for the current HTTP endpoint. It will include the domain name if one is configured.
// If none is configured it will use the IP address as the host name.
func (endpoint *HTTPEndpoint) DefaultURL() string {

	// no point in returning a url if there are no tcp bindings
	if len(endpoint.tcpBindings) == 0 {
		return ""
	}

	// use the first tcp binding as the default
	defaultBinding := *endpoint.tcpBindings[0]

	// create an URL from the tcp binding if no domain is configured
	if endpoint.domain == "" {
		return endpoint.URL(defaultBinding)
	}

	// determine the port suffix (e.g. ":8080")
	portSuffix := ""
	portNumber := defaultBinding.Port
	isDefaultPort := portNumber == 80 || portNumber == 443
	if !isDefaultPort {
		portSuffix = fmt.Sprintf(":%v", portNumber)
	}

	return fmt.Sprintf("%s://%s%s", endpoint.Protocol(), endpoint.domain, portSuffix)
}

// HTTPSEndpoint contains a secure version of a HTTPEndpoint with parameters for secure TLS connections such as the certificate paths.
type HTTPSEndpoint struct {
	HTTPEndpoint

	certFilePath string
	keyFilePath  string
}

// CertFilePath returns the SSL certificate file (e.g. "cert.pem") name of this HTTPSEndpoint.
func (endpoint *HTTPSEndpoint) CertFilePath() string {
	return endpoint.certFilePath
}

// KeyFilePath returns the SSL certificate key file name (e.g. "cert.key") of this HTTPSEndpoint.
func (endpoint *HTTPSEndpoint) KeyFilePath() string {
	return endpoint.keyFilePath
}
<commit_msg>Don't use wildcard addresses for the server URL - use localhost instead.<commit_after>// Copyright 2015 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package server contains a web server that can serve an instance of
// the dataaccess.Repository interface via HTTP and HTTPs.
package server

import (
	"allmark.io/modules/common/config"
	"allmark.io/modules/common/logger"
	"allmark.io/modules/dataaccess"
	"allmark.io/modules/services/converter"
	"allmark.io/modules/services/parser"
	"allmark.io/modules/web/handlers"
	"allmark.io/modules/web/header"
	"allmark.io/modules/web/orchestrator"
	"allmark.io/modules/web/view/templates"
	"allmark.io/modules/web/webpaths"
	"fmt"
	"github.com/gorilla/mux"
	"github.com/skratchdot/open-golang/open"
	"net/http"
	"strings"
)

// New creates a new Server instance for the given repository.
func New(logger logger.Logger, config config.Config, repository dataaccess.Repository, parser parser.Parser, converter converter.Converter) (*Server, error) {

	// create the request handlers
	patherFactory := webpaths.NewFactory(logger, repository)
	itemPathProvider := patherFactory.Absolute(handlers.BasePath)
	tagPathProvider := patherFactory.Absolute(handlers.TagPathPrefix)
	webPathProvider := webpaths.NewWebPathProvider(patherFactory, itemPathProvider, tagPathProvider)
	templateProvider := templates.NewProvider(config.TemplatesFolder())
	orchestratorFactory := orchestrator.NewFactory(logger, config, repository, parser, converter, webPathProvider)
	reindexInterval := config.Indexing.IntervalInSeconds
	headerWriterFactory := header.NewHeaderWriterFactory(reindexInterval)
	requestHandlers := handlers.GetBaseHandlers(logger, config, templateProvider, *orchestratorFactory, headerWriterFactory)

	return &Server{
		logger: logger,
		config: config,

		headerWriterFactory: headerWriterFactory,
		requestHandlers:     requestHandlers,
	}, nil

}

// Server represents a web server instance for a given repository.
type Server struct {
	logger logger.Logger
	config config.Config

	headerWriterFactory header.WriterFactory

	requestHandlers handlers.HandlerList
}

// Start starts the current web server.
func (server *Server) Start() chan error {

	result := make(chan error)

	standardRequestRouter := server.getStandardRequestRouter()

	// bindings
	httpEndpoint, httpEnabled := server.httpEndpoint()
	httpsEndpoint, httpsEnabled := server.httpsEndpoint()

	// abort if no tcp bindings are configured
	if len(httpEndpoint.Bindings()) == 0 && len(httpsEndpoint.Bindings()) == 0 {
		result <- fmt.Errorf("No TCP bindings configured")
		return result
	}

	uniqueURLs := make(map[string]string)

	// http
	if httpEnabled {

		for _, tcpBinding := range httpEndpoint.Bindings() {

			tcpBinding.AssignFreePort()

			tcpAddr := tcpBinding.GetTCPAddress()
			address := tcpAddr.String()

			// start listening
			go func() {
				server.logger.Info("HTTP Endpoint: %s", address)

				if httpEndpoint.ForceHTTPS() {

					// Redirect HTTP → HTTPS
					redirectTarget := httpsEndpoint.DefaultURL()
					httpsRedirectRouter := server.getRedirectRouter(redirectTarget)

					if err := http.ListenAndServe(address, httpsRedirectRouter); err != nil {
						result <- fmt.Errorf("Server failed with error: %v", err)
					} else {
						result <- nil
					}

				} else {

					// Standard HTTP Request Router
					if err := http.ListenAndServe(address, standardRequestRouter); err != nil {
						result <- fmt.Errorf("Server failed with error: %v", err)
					} else {
						result <- nil
					}

				}

			}()

			// store the URL for later opening
			if httpsEnabled == false {
				endpointURL := httpEndpoint.DefaultURL()
				uniqueURLs[endpointURL] = endpointURL
			}

		}
	}

	// https
	if httpsEnabled {

		for _, tcpBinding := range httpsEndpoint.Bindings() {

			tcpBinding.AssignFreePort()

			tcpAddr := tcpBinding.GetTCPAddress()
			address := tcpAddr.String()

			// start listening
			go func() {
				server.logger.Info("HTTPS Endpoint: %s", address)

				// Standard HTTPS Request Router
				if err := http.ListenAndServeTLS(address, httpsEndpoint.CertFilePath(), httpsEndpoint.KeyFilePath(), standardRequestRouter); err != nil {
					result <- fmt.Errorf("Server failed with error: %v", err)
				} else {
					result <- nil
				}

			}()

			// store the URL for later opening
			endpointURL := httpsEndpoint.DefaultURL()
			uniqueURLs[endpointURL] = endpointURL
		}

	}

	// open HTTP URL(s) in a browser
	for _, url := range uniqueURLs {
		server.logger.Info("Open URL: %s", url)
		go open.Run(url)
	}

	return result
}

// getRedirectRouter returns a router which redirects all requests to the url with the given base.
func (server *Server) getRedirectRouter(baseURITarget string) *mux.Router {
	redirectRouter := mux.NewRouter()

	for _, requestHandler := range handlers.GetRedirectHandlers(baseURITarget) {
		requestRoute := requestHandler.Route
		requestHandler := requestHandler.Handler

		redirectRouter.Handle(requestRoute, requestHandler)
	}

	return redirectRouter
}

// Get an instance of the standard request router for all repository related routes.
func (server *Server) getStandardRequestRouter() *mux.Router {

	// register requst routers
	requestRouter := mux.NewRouter()

	for _, requestHandler := range server.requestHandlers {
		requestRoute := requestHandler.Route
		requestHandler := requestHandler.Handler

		// add logging
		requestHandler = handlers.LogRequests(requestHandler)

		// add compression
		requestHandler = handlers.CompressResponses(requestHandler)

		// add authentication
		if _, httpsEnabled := server.httpsEndpoint(); httpsEnabled && server.config.AuthenticationIsEnabled() {
			secretProvider := server.config.GetAuthenticationUserStore()
			if secretProvider == nil {
				panic("Authentication is enabled but the supplied secret provider is nil.")
			}

			requestHandler = handlers.RequireDigestAuthentication(requestHandler, secretProvider)
		}

		requestRouter.Handle(requestRoute, requestHandler)
	}

	return requestRouter
}

// Get the http binding if it is enabled.
func (server *Server) httpEndpoint() (httpEndpoint HTTPEndpoint, enabled bool) {

	if !server.config.Server.HTTP.Enabled {
		return HTTPEndpoint{}, false
	}

	return HTTPEndpoint{
		isSecure:    false,
		forceHTTPS:  server.config.Server.HTTPS.HTTPSIsForced(),
		tcpBindings: server.config.Server.HTTP.Bindings,
	}, true

}

// Get the https binding if it is enabled.tcpBinding
func (server *Server) httpsEndpoint() (httpsEndpoint HTTPSEndpoint, enabled bool) {

	if !server.config.Server.HTTPS.Enabled {
		return HTTPSEndpoint{}, false
	}

	httpEndpoint := HTTPEndpoint{
		domain:      server.config.Server.DomainName,
		isSecure:    true,
		tcpBindings: server.config.Server.HTTPS.Bindings,
	}

	certFilePath, keyFilePath := server.config.CertificateFilePaths()

	httpsEndpoint = HTTPSEndpoint{
		HTTPEndpoint: httpEndpoint,
		certFilePath: certFilePath,
		keyFilePath:  keyFilePath,
	}

	return httpsEndpoint, true

}

// HTTPEndpoint contains HTTP server endpoint parameters such as a domain name and TCP bindings.
type HTTPEndpoint struct {
	domain      string
	isSecure    bool
	forceHTTPS  bool
	tcpBindings []*config.TCPBinding
}

// IsSecure returns a flag indicating whether the current HTTPEndpoint is secure (HTTPS) or not.
func (endpoint *HTTPEndpoint) IsSecure() bool {
	return endpoint.isSecure
}

// Protocol returns the protocol of the current HTTPEndpoint. "https" if this endpoint is secure; otherwise "http".
func (endpoint *HTTPEndpoint) Protocol() string {
	if endpoint.isSecure {
		return "https"
	}
	return "http"
}

// ForceHTTPS returns a flag indicating whether a secure connection shall be preferred over insecure connections.
func (endpoint *HTTPEndpoint) ForceHTTPS() bool {
	return endpoint.forceHTTPS
}

// Bindings returns all TCP bindings of the current HTTP endpoint.
func (endpoint *HTTPEndpoint) Bindings() []*config.TCPBinding {
	return endpoint.tcpBindings
}

// URL return the formatted URL (e.g. "https://127.0.0.1:8080") for the given TCP binding, using the IP address as the hostname.
func (endpoint *HTTPEndpoint) URL(tcpBinding config.TCPBinding) string {
	tcpAddress := tcpBinding.GetTCPAddress()
	hostname := tcpAddress.String()

	// don't use default tcp addresses for the URL
	hostname = strings.Replace(hostname, "0.0.0.0", "localhost", 1)
	hostname = strings.Replace(hostname, "::", "localhost", 1)

	return fmt.Sprintf("%s://%s", endpoint.Protocol(), hostname)
}

// DefaultURL return the default url for the current HTTP endpoint. It will include the domain name if one is configured.
// If none is configured it will use the IP address as the host name.
func (endpoint *HTTPEndpoint) DefaultURL() string {

	// no point in returning a url if there are no tcp bindings
	if len(endpoint.tcpBindings) == 0 {
		return ""
	}

	// use the first tcp binding as the default
	defaultBinding := *endpoint.tcpBindings[0]

	// create an URL from the tcp binding if no domain is configured
	if endpoint.domain == "" {
		return endpoint.URL(defaultBinding)
	}

	// determine the port suffix (e.g. ":8080")
	portSuffix := ""
	portNumber := defaultBinding.Port
	isDefaultPort := portNumber == 80 || portNumber == 443
	if !isDefaultPort {
		portSuffix = fmt.Sprintf(":%v", portNumber)
	}

	return fmt.Sprintf("%s://%s%s", endpoint.Protocol(), endpoint.domain, portSuffix)
}

// HTTPSEndpoint contains a secure version of a HTTPEndpoint with parameters for secure TLS connections such as the certificate paths.
type HTTPSEndpoint struct {
	HTTPEndpoint

	certFilePath string
	keyFilePath  string
}

// CertFilePath returns the SSL certificate file (e.g. "cert.pem") name of this HTTPSEndpoint.
func (endpoint *HTTPSEndpoint) CertFilePath() string {
	return endpoint.certFilePath
}

// KeyFilePath returns the SSL certificate key file name (e.g. "cert.key") of this HTTPSEndpoint.
func (endpoint *HTTPSEndpoint) KeyFilePath() string {
	return endpoint.keyFilePath
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"github.com/zephyyrr/goda"
)

var dba *goda.DatabaseAdministrator
var storer goda.Storer

var debugging = true

func init() {
        if debugging {
                log.Println("Connecting to Database...")
        }
        //Setup Database Connection
        //log.Println(goda.LoadPGEnv())
        var err error
        dba, err = goda.NewDatabaseAdministrator(goda.LoadPGEnv())
        if err != nil {
                log.Fatalln("Cleaner: Database Connection Error: ", err)
        }

        //storer, err = dba.Storer("measurements", Measurements{})
        if err != nil {
                panic(err)
        }

        if debugging {
                log.Println("Initialize Finished!")
        }
}
<commit_msg>Added storerMap and simple main funcion<commit_after>package main

import (
	"log"
	"github.com/zephyyrr/goda"
	tdb "github.com/SudoQ/tenordb"
)

var dba *goda.DatabaseAdministrator
var storerMap map[string] goda.Storer

var debugging = true

func init() {
        if debugging {
                log.Println("Connecting to Database...")
        }
        //Setup Database Connection
        //log.Println(goda.LoadPGEnv())
        var err error
        dba, err = goda.NewDatabaseAdministrator(goda.LoadPGEnv())
        if err != nil {
                log.Fatalln("Cleaner: Database Connection Error: ", err)
        }
		storerMap = make(map[string] goda.Storer)
		storerMap["AbsNote"],_ = dba.Storer("AbsNote", tdb.AbsNote{})
		storerMap["RelNote"],_ = dba.Storer("RelNote", tdb.RelNote{})
		storerMap["Chord"],_ = dba.Storer("Chord", tdb.Chord{})
		storerMap["Scale"],_ = dba.Storer("Scale", tdb.Scale{})
		storerMap["ChordPattern"],_ = dba.Storer("ChordPattern", tdb.ChordPattern{})
		storerMap["ScalePattern"],_ = dba.Storer("ScalePattern", tdb.ScalePattern{})
		storerMap["ChordNote"],_ = dba.Storer("ChordNote", tdb.ChordNote{})
		storerMap["ScaleNote"],_ = dba.Storer("ScaleNote", tdb.ScaleNote{})
		storerMap["ChordPatternNote"],_ = dba.Storer("ChordPatternNote", tdb.ChordPatternNote{})
		storerMap["ScalePatternNote"],_ = dba.Storer("ScalePatternNote", tdb.ScalePatternNote{})
        //storer, err = dba.Storer("measurements", Measurements{})
        if err != nil {
                panic(err)
        }

        if debugging {
                log.Println("Initialize Finished!")
        }
}

func main() {
	// Gen AbsNotes
	err := storerMap["AbsNote"].Store(tdb.AbsNote{Id: 0, Name: "C"})
	if err != nil {
		log.Println(err)
	}
}
<|endoftext|>


<commit_before>package revelmgo

import (
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
)

var (
	Session *mgo.Session
	Url     string
)

func Init() {
	var found bool
	if Url, found = revel.Config.String("mgo.url"); !found {
		revel.ERROR.Fatal("No mgo.url found")
	}

	var err error
	if Session, err = mgo.Dial(Url); err != nil {
		revel.ERROR.Panic(err)
	}
}

type MgoController struct {
	*revel.Controller
	MgoSession *mgo.Session
}

func New() {
	revel.InterceptMethod((*MgoController).new, revel.BEFORE)
}

func Copy() {
	revel.InterceptMethod((*MgoController).copy, revel.BEFORE)
}

func Clone() {
	revel.InterceptMethod((*MgoController).clone, revel.BEFORE)
}

func (c *MgoController) new() revel.Result {
	c.MgoSession = Session.New()
	return nil
}

func (c *MgoController) copy() revel.Result {
	c.MgoSession = Session.Copy()
	return nil
}

func (c *MgoController) clone() revel.Result {
	c.MgoSession = Session.Clone()
	return nil
}

func (c *MgoController) close() revel.Result {
	c.MgoSession.Close()
	return nil
}

func init() {
	revel.InterceptMethod((*MgoController).close, revel.FINALLY)
}
<commit_msg>add some logging<commit_after>package revelmgo

import (
	"fmt"
	"github.com/robfig/revel"
	"labix.org/v2/mgo"
)

var (
	Session *mgo.Session
	Url     string
)

func Init() {
	var found bool
	if Url, found = revel.Config.String("mgo.url"); !found {
		revel.ERROR.Panic("No mgo.url found")
	}

	revel.INFO.Println(fmt.Sprintf("Dialing url: %s", Url))

	var err error
	if Session, err = mgo.Dial(Url); err != nil {
		revel.ERROR.Panic(err)
	}
}

type MgoController struct {
	*revel.Controller
	MgoSession *mgo.Session
}

func New() {
	revel.InterceptMethod((*MgoController).new, revel.BEFORE)
}

func Copy() {
	revel.InterceptMethod((*MgoController).copy, revel.BEFORE)
}

func Clone() {
	revel.InterceptMethod((*MgoController).clone, revel.BEFORE)
}

func (c *MgoController) new() revel.Result {
	c.MgoSession = Session.New()
	return nil
}

func (c *MgoController) copy() revel.Result {
	c.MgoSession = Session.Copy()
	return nil
}

func (c *MgoController) clone() revel.Result {
	c.MgoSession = Session.Clone()
	return nil
}

func (c *MgoController) close() revel.Result {
	c.MgoSession.Close()
	return nil
}

func init() {
	revel.InterceptMethod((*MgoController).close, revel.FINALLY)
}
<|endoftext|>


<commit_before>package kodingcontext

import (
	"fmt"
	"io"
	"path"

	"github.com/mitchellh/cli"
)

type ArgsFunc func(paths *paths, destroy bool) []string

func (c *KodingContext) run(cmd cli.Command, content io.Reader, destroy bool, argsFunc ArgsFunc) (*paths, error) {
	// copy all contents from remote to local for operating
	if err := c.RemoteStorage.Clone(c.ContentID, c.LocalStorage); err != nil {
		return nil, err
	}

	// populate paths
	paths, err := c.paths()
	if err != nil {
		return nil, err
	}

	if !destroy && content != nil {
		// override the current main file
		if err := c.LocalStorage.Write(paths.mainRelativePath, content); err != nil {
			return nil, err
		}
	}

	args := argsFunc(paths, destroy)
	exitCode := cmd.Run(args)
	if exitCode != 0 {
		return nil, fmt.Errorf(
			"apply failed with code: %d, output: %s",
			exitCode,
			c.Buffer.String(),
		)
	}

	if !destroy {
		// copy all contents from local to remote for later operating
		if err := c.LocalStorage.Clone(c.ContentID, c.RemoteStorage); err != nil {
			return nil, err
		}
	}

	return paths, nil
}

type paths struct {
	contentPath      string
	statePath        string
	planPath         string
	mainRelativePath string
}

func (c *KodingContext) paths() (*paths, error) {
	basePath, err := c.LocalStorage.BasePath()
	if err != nil {
		return nil, err
	}

	contentPath := path.Join(basePath, c.ContentID)
	mainFileRelativePath := path.Join(c.ContentID, mainFileName+terraformFileExt)
	stateFilePath := path.Join(contentPath, stateFileName+terraformStateFileExt)
	planFilePath := path.Join(contentPath, planFileName+terraformPlanFileExt)

	return &paths{
		contentPath:      contentPath,
		statePath:        stateFilePath,
		mainRelativePath: mainFileRelativePath,
		planPath:         planFilePath,
	}, nil
}
<commit_msg>provider/aws: update state.tf after destroy<commit_after>package kodingcontext

import (
	"fmt"
	"io"
	"path"

	"github.com/mitchellh/cli"
)

type ArgsFunc func(paths *paths, destroy bool) []string

func (c *KodingContext) run(cmd cli.Command, content io.Reader, destroy bool, argsFunc ArgsFunc) (*paths, error) {
	// copy all contents from remote to local for operating
	if err := c.RemoteStorage.Clone(c.ContentID, c.LocalStorage); err != nil {
		return nil, err
	}

	// populate paths
	paths, err := c.paths()
	if err != nil {
		return nil, err
	}

	if !destroy && content != nil {
		// override the current main file
		if err := c.LocalStorage.Write(paths.mainRelativePath, content); err != nil {
			return nil, err
		}
	}

	args := argsFunc(paths, destroy)
	exitCode := cmd.Run(args)
	if exitCode != 0 {
		return nil, fmt.Errorf(
			"apply failed with code: %d, output: %s",
			exitCode,
			c.Buffer.String(),
		)
	}

	// copy all contents from local to remote for later operating
	if err := c.LocalStorage.Clone(c.ContentID, c.RemoteStorage); err != nil {
		return nil, err
	}

	return paths, nil
}

type paths struct {
	contentPath      string
	statePath        string
	planPath         string
	mainRelativePath string
}

func (c *KodingContext) paths() (*paths, error) {
	basePath, err := c.LocalStorage.BasePath()
	if err != nil {
		return nil, err
	}

	contentPath := path.Join(basePath, c.ContentID)
	mainFileRelativePath := path.Join(c.ContentID, mainFileName+terraformFileExt)
	stateFilePath := path.Join(contentPath, stateFileName+terraformStateFileExt)
	planFilePath := path.Join(contentPath, planFileName+terraformPlanFileExt)

	return &paths{
		contentPath:      contentPath,
		statePath:        stateFilePath,
		mainRelativePath: mainFileRelativePath,
		planPath:         planFilePath,
	}, nil
}
<|endoftext|>


<commit_before>package sync_test

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"koding/klient/machine/client"
	"koding/klient/machine/client/clienttest"
	"koding/klient/machine/mount"
	"koding/klient/machine/mount/mounttest"
	"koding/klient/machine/mount/notify/silent"
	msync "koding/klient/machine/mount/sync"
	"koding/klient/machine/mount/sync/discard"
)

func TestSyncNew(t *testing.T) {
	wd, m, clean, err := mounttest.MountDirs()
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer clean()

	// Create new Sync.
	mountID := mount.MakeID()
	sA, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer sA.Close()

	// Check file structure.
	if _, err := os.Stat(filepath.Join(wd, "data")); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}
	if _, err := os.Stat(filepath.Join(wd, msync.LocalIndexName)); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}
	if _, err := os.Stat(filepath.Join(wd, msync.RemoteIndexName)); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}

	// Check indexes.
	info := sA.Info()
	if info == nil {
		t.Fatalf("want info != nil; got nil")
	}
	if info.AllDiskSize == 0 {
		t.Error("want all disk size > 0")
	}

	expected := &msync.Info{
		ID:           mountID,
		Mount:        m,
		SyncCount:    0,
		AllCount:     1,
		SyncDiskSize: 0,
		AllDiskSize:  info.AllDiskSize,
		Queued:       0,
		Syncing:      0,
	}

	if !reflect.DeepEqual(info, expected) {
		t.Errorf("want info = %#v; got %#v", expected, info)
	}

	// Add files to remote and cache paths.
	if _, err := mounttest.TempFile(m.RemotePath); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if _, err := mounttest.TempFile(filepath.Join(wd, "data")); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// New add of existing mount.
	sB, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer sB.Close()

	if info = sB.Info(); info == nil {
		t.Fatalf("want info != nil; got nil")
	}

	// TODO: All count should be two, since synced file is not the one from
	// remote directory. This is temporary state since sync will balance
	// indexes, but should be handled anyway.
	expected.SyncCount = 1
	expected.SyncDiskSize = info.SyncDiskSize

	if !reflect.DeepEqual(info, expected) {
		t.Errorf("want info = %#v; got %#v", expected, info)
	}
}

func TestSyncDrop(t *testing.T) {
	wd, m, clean, err := mounttest.MountDirs()
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer clean()

	// Create new Sync.
	mountID := mount.MakeID()
	s, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer s.Close()

	if err := s.Drop(); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// Working directory should not exist.
	if _, err := os.Stat(wd); !os.IsNotExist(err) {
		t.Errorf("want err = os.ErrNotExist; got %v", err)
	}
}

func defaultSyncOpts(wd string) msync.SyncOpts {
	return msync.SyncOpts{
		ClientFunc: func() (client.Client, error) {
			return clienttest.NewClient(), nil
		},
		NotifyBuilder: silent.SilentBuilder{},
		SyncBuilder:   discard.DiscardBuilder{},
		WorkDir:       wd,
	}
}
<commit_msg>machine/sync: change root dir size to 10<commit_after>package sync_test

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"koding/klient/machine/client"
	"koding/klient/machine/client/clienttest"
	"koding/klient/machine/mount"
	"koding/klient/machine/mount/mounttest"
	"koding/klient/machine/mount/notify/silent"
	msync "koding/klient/machine/mount/sync"
	"koding/klient/machine/mount/sync/discard"
)

func TestSyncNew(t *testing.T) {
	wd, m, clean, err := mounttest.MountDirs()
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer clean()

	// Create new Sync.
	mountID := mount.MakeID()
	sA, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer sA.Close()

	// Check file structure.
	if _, err := os.Stat(filepath.Join(wd, "data")); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}
	if _, err := os.Stat(filepath.Join(wd, msync.LocalIndexName)); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}
	if _, err := os.Stat(filepath.Join(wd, msync.RemoteIndexName)); err != nil {
		t.Errorf("want err = nil; got %v", err)
	}

	// Check indexes.
	info := sA.Info()
	if info == nil {
		t.Fatalf("want info != nil; got nil")
	}
	if info.AllDiskSize == 0 {
		t.Error("want all disk size > 0")
	}

	expected := &msync.Info{
		ID:           mountID,
		Mount:        m,
		SyncCount:    0,
		AllCount:     1,
		SyncDiskSize: 10,
		AllDiskSize:  info.AllDiskSize,
		Queued:       0,
		Syncing:      0,
	}

	if !reflect.DeepEqual(info, expected) {
		t.Errorf("want info = %#v; got %#v", expected, info)
	}

	// Add files to remote and cache paths.
	if _, err := mounttest.TempFile(m.RemotePath); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if _, err := mounttest.TempFile(filepath.Join(wd, "data")); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// New add of existing mount.
	sB, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer sB.Close()

	if info = sB.Info(); info == nil {
		t.Fatalf("want info != nil; got nil")
	}

	// TODO: All count should be two, since synced file is not the one from
	// remote directory. This is temporary state since sync will balance
	// indexes, but should be handled anyway.
	expected.SyncCount = 1
	expected.SyncDiskSize = info.SyncDiskSize

	if !reflect.DeepEqual(info, expected) {
		t.Errorf("want info = %#v; got %#v", expected, info)
	}
}

func TestSyncDrop(t *testing.T) {
	wd, m, clean, err := mounttest.MountDirs()
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer clean()

	// Create new Sync.
	mountID := mount.MakeID()
	s, err := msync.NewSync(mountID, m, defaultSyncOpts(wd))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer s.Close()

	if err := s.Drop(); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// Working directory should not exist.
	if _, err := os.Stat(wd); !os.IsNotExist(err) {
		t.Errorf("want err = os.ErrNotExist; got %v", err)
	}
}

func defaultSyncOpts(wd string) msync.SyncOpts {
	return msync.SyncOpts{
		ClientFunc: func() (client.Client, error) {
			return clienttest.NewClient(), nil
		},
		NotifyBuilder: silent.SilentBuilder{},
		SyncBuilder:   discard.DiscardBuilder{},
		WorkDir:       wd,
	}
}
<|endoftext|>


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

package main

import (
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
)

var cmdTool = &Command{
	Run:       runTool,
	UsageLine: "tool [-n] command [args...]",
	Short:     "run specified go tool",
	Long: `
Tool runs the go tool command identified by the arguments.
With no arguments it prints the list of known tools.

The -n flag causes tool to print the command that would be
executed but not execute it.

For more about each tool command, see 'go tool command -h'.
`,
}

var (
	toolGOOS      = runtime.GOOS
	toolGOARCH    = runtime.GOARCH
	toolIsWindows = toolGOOS == "windows"
	toolDir       = build.ToolDir

	toolN bool
)

func init() {
	cmdTool.Flag.BoolVar(&toolN, "n", false, "")
}

const toolWindowsExtension = ".exe"

func tool(toolName string) string {
	toolPath := filepath.Join(toolDir, toolName)
	if toolIsWindows && toolName != "pprof" {
		toolPath += toolWindowsExtension
	}
	// Give a nice message if there is no tool with that name.
	if _, err := os.Stat(toolPath); err != nil {
		if isInGoToolsRepo(toolName) {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
		} else {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
		}
		setExitStatus(3)
		exit()
	}
	return toolPath
}

func isInGoToolsRepo(toolName string) bool {
	switch toolName {
	case "cover", "vet":
		return true
	}
	return false
}

func runTool(cmd *Command, args []string) {
	if len(args) == 0 {
		listTools()
		return
	}
	toolName := args[0]
	// The tool name must be lower-case letters, numbers or underscores.
	for _, c := range toolName {
		switch {
		case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
		default:
			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
			setExitStatus(2)
			return
		}
	}
	toolPath := tool(toolName)
	if toolPath == "" {
		return
	}
	if toolIsWindows && toolName == "pprof" {
		args = append([]string{"perl", toolPath}, args[1:]...)
		var err error
		toolPath, err = exec.LookPath("perl")
		if err != nil {
			fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
			setExitStatus(3)
			return
		}
	}
	if toolN {
		fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
		return
	}
	toolCmd := &exec.Cmd{
		Path:   toolPath,
		Args:   args,
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	err := toolCmd.Run()
	if err != nil {
		// Only print about the exit status if the command
		// didn't even run (not an ExitError) or it didn't exit cleanly
		// or we're printing command lines too (-x mode).
		// Assume if command exited cleanly (even with non-zero status)
		// it printed any messages it wanted to print.
		if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
			fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
		}
		setExitStatus(1)
		return
	}
}

// listTools prints a list of the available tools in the tools directory.
func listTools() {
	f, err := os.Open(toolDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
		setExitStatus(2)
		return
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
		setExitStatus(2)
		return
	}

	sort.Strings(names)
	for _, name := range names {
		// Unify presentation by going to lower case.
		name = strings.ToLower(name)
		// If it's windows, don't show the .exe suffix.
		if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
			name = name[:len(name)-len(toolWindowsExtension)]
		}
		fmt.Println(name)
	}
}
<commit_msg>cmd/go: fix running pprof on windows.<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
)

var cmdTool = &Command{
	Run:       runTool,
	UsageLine: "tool [-n] command [args...]",
	Short:     "run specified go tool",
	Long: `
Tool runs the go tool command identified by the arguments.
With no arguments it prints the list of known tools.

The -n flag causes tool to print the command that would be
executed but not execute it.

For more about each tool command, see 'go tool command -h'.
`,
}

var (
	toolGOOS      = runtime.GOOS
	toolGOARCH    = runtime.GOARCH
	toolIsWindows = toolGOOS == "windows"
	toolDir       = build.ToolDir

	toolN bool
)

func init() {
	cmdTool.Flag.BoolVar(&toolN, "n", false, "")
}

const toolWindowsExtension = ".exe"

func tool(toolName string) string {
	toolPath := filepath.Join(toolDir, toolName)
	if toolIsWindows {
		toolPath += toolWindowsExtension
	}
	// Give a nice message if there is no tool with that name.
	if _, err := os.Stat(toolPath); err != nil {
		if isInGoToolsRepo(toolName) {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
		} else {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
		}
		setExitStatus(3)
		exit()
	}
	return toolPath
}

func isInGoToolsRepo(toolName string) bool {
	switch toolName {
	case "cover", "vet":
		return true
	}
	return false
}

func runTool(cmd *Command, args []string) {
	if len(args) == 0 {
		listTools()
		return
	}
	toolName := args[0]
	// The tool name must be lower-case letters, numbers or underscores.
	for _, c := range toolName {
		switch {
		case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
		default:
			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
			setExitStatus(2)
			return
		}
	}
	toolPath := tool(toolName)
	if toolPath == "" {
		return
	}
	if toolN {
		fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
		return
	}
	toolCmd := &exec.Cmd{
		Path:   toolPath,
		Args:   args,
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	err := toolCmd.Run()
	if err != nil {
		// Only print about the exit status if the command
		// didn't even run (not an ExitError) or it didn't exit cleanly
		// or we're printing command lines too (-x mode).
		// Assume if command exited cleanly (even with non-zero status)
		// it printed any messages it wanted to print.
		if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
			fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
		}
		setExitStatus(1)
		return
	}
}

// listTools prints a list of the available tools in the tools directory.
func listTools() {
	f, err := os.Open(toolDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
		setExitStatus(2)
		return
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
		setExitStatus(2)
		return
	}

	sort.Strings(names)
	for _, name := range names {
		// Unify presentation by going to lower case.
		name = strings.ToLower(name)
		// If it's windows, don't show the .exe suffix.
		if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
			name = name[:len(name)-len(toolWindowsExtension)]
		}
		fmt.Println(name)
	}
}
<|endoftext|>


<commit_before>package pkglib

// Thin wrappers around git CLI invocations

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"

	log "github.com/sirupsen/logrus"
)

// 040000 tree 7804129bd06218b72c298139a25698a748d253c6\tpkg/init
var treeHashRe *regexp.Regexp

func init() {
	treeHashRe = regexp.MustCompile("^[0-7]{6} [^ ]+ ([0-9a-f]{40})\t.+\n$")
}

type git struct {
	dir string
}

// Returns git==nil and no error if the path is not within a git repository
func newGit(dir string) (*git, error) {
	g := &git{dir}

	// Check if dir really is within a git directory
	ok, err := g.isWorkTree(dir)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, nil
	}
	return g, nil
}

func (g git) mkCmd(args ...string) *exec.Cmd {
	return exec.Command("git", append([]string{"-C", g.dir}, args...)...)
}

func (g git) commandStdout(stderr io.Writer, args ...string) (string, error) {
	cmd := g.mkCmd(args...)
	cmd.Stderr = stderr
	log.Debugf("Executing: %v", cmd.Args)

	out, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(out), nil
}

func (g git) command(args ...string) error {
	cmd := g.mkCmd(args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	log.Debugf("Executing: %v", cmd.Args)

	return cmd.Run()
}

func (g git) isWorkTree(pkg string) (bool, error) {
	tf, err := g.commandStdout(nil, "rev-parse", "--is-inside-work-tree")
	if err != nil {
		// If we executed git ok but it errored then that's because this isn't a git repo
		if _, ok := err.(*exec.ExitError); ok {
			return false, nil
		}
		return false, err
	}

	tf = strings.TrimSpace(tf)

	if tf == "true" {
		return true, nil
	}

	return false, fmt.Errorf("unexpected output from git rev-parse --is-inside-work-tree: %s", tf)
}

func (g git) treeHash(pkg, commit string) (string, error) {
	out, err := g.commandStdout(os.Stderr, "ls-tree", "--full-tree", commit, "--", pkg)
	if err != nil {
		return "", err
	}

	if out == "" {
		return "", fmt.Errorf("Package %s is not in git", pkg)
	}

	matches := treeHashRe.FindStringSubmatch(out)
	if len(matches) != 2 {
		return "", fmt.Errorf("Unable to parse ls-tree output: %q", out)
	}

	return matches[1], nil
}

func (g git) commitHash(commit string) (string, error) {
	out, err := g.commandStdout(os.Stderr, "rev-parse", commit)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(out), nil
}

func (g git) commitTag(commit string) (string, error) {
	out, err := g.commandStdout(os.Stderr, "tag", "-l", "--points-at", commit)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(out), nil
}

func (g git) isDirty(pkg, commit string) (bool, error) {
	// If it isn't HEAD it can't be dirty
	if commit != "HEAD" {
		return false, nil
	}

	// Update cache, otherwise files which have an updated
	// timestamp but no actual changes are marked as changes
	// because `git diff-index` only uses the `lstat` result and
	// not the actual file contents. Running `git update-index
	// --refresh` updates the cache.
	if err := g.command("update-index", "-q", "--refresh"); err != nil {
		return false, err
	}

	err := g.command("diff-index", "--quiet", commit, "--", pkg)
	if err == nil {
		return false, nil
	}
	switch err.(type) {
	case *exec.ExitError:
		// diff-index exits with an error if there are differences
		return true, nil
	default:
		return false, err
	}
}
<commit_msg>Make it possible to key the package tags off of top level tree hash<commit_after>package pkglib

// Thin wrappers around git CLI invocations

import (
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"

	log "github.com/sirupsen/logrus"
)

// 040000 tree 7804129bd06218b72c298139a25698a748d253c6\tpkg/init
var treeHashRe *regexp.Regexp

func init() {
	treeHashRe = regexp.MustCompile("^[0-7]{6} [^ ]+ ([0-9a-f]{40})\t.+\n$")
}

type git struct {
	dir string
}

// Returns git==nil and no error if the path is not within a git repository
func newGit(dir string) (*git, error) {
	g := &git{dir}

	// Check if dir really is within a git directory
	ok, err := g.isWorkTree(dir)
	if err != nil {
		return nil, err
	}
	if !ok {
		return nil, nil
	}
	return g, nil
}

func (g git) mkCmd(args ...string) *exec.Cmd {
	return exec.Command("git", append([]string{"-C", g.dir}, args...)...)
}

func (g git) commandStdout(stderr io.Writer, args ...string) (string, error) {
	cmd := g.mkCmd(args...)
	cmd.Stderr = stderr
	log.Debugf("Executing: %v", cmd.Args)

	out, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(out), nil
}

func (g git) command(args ...string) error {
	cmd := g.mkCmd(args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	log.Debugf("Executing: %v", cmd.Args)

	return cmd.Run()
}

func (g git) isWorkTree(pkg string) (bool, error) {
	tf, err := g.commandStdout(nil, "rev-parse", "--is-inside-work-tree")
	if err != nil {
		// If we executed git ok but it errored then that's because this isn't a git repo
		if _, ok := err.(*exec.ExitError); ok {
			return false, nil
		}
		return false, err
	}

	tf = strings.TrimSpace(tf)

	if tf == "true" {
		return true, nil
	}

	return false, fmt.Errorf("unexpected output from git rev-parse --is-inside-work-tree: %s", tf)
}

func (g git) treeHash(pkg, commit string) (string, error) {
	// we have to check if pkg is at the top level of the git tree,
	// if that's the case we need to use tree hash from the commit itself
	out, err := g.commandStdout(nil, "rev-parse", "--prefix", pkg, "--show-toplevel")
	if err != nil {
		return "", err
	}
	if strings.TrimSpace(out) == pkg {
		out, err = g.commandStdout(nil, "show", "--format=%T", "-s", commit)
		if err != nil {
			return "", err
		}
		return strings.TrimSpace(out), nil
	}

	out, err = g.commandStdout(os.Stderr, "ls-tree", "--full-tree", commit, "--", pkg)
	if err != nil {
		return "", err
	}

	if out == "" {
		return "", fmt.Errorf("Package %s is not in git", pkg)
	}

	matches := treeHashRe.FindStringSubmatch(out)
	if len(matches) != 2 {
		return "", fmt.Errorf("Unable to parse ls-tree output: %q", out)
	}

	return matches[1], nil
}

func (g git) commitHash(commit string) (string, error) {
	out, err := g.commandStdout(os.Stderr, "rev-parse", commit)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(out), nil
}

func (g git) commitTag(commit string) (string, error) {
	out, err := g.commandStdout(os.Stderr, "tag", "-l", "--points-at", commit)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(out), nil
}

func (g git) isDirty(pkg, commit string) (bool, error) {
	// If it isn't HEAD it can't be dirty
	if commit != "HEAD" {
		return false, nil
	}

	// Update cache, otherwise files which have an updated
	// timestamp but no actual changes are marked as changes
	// because `git diff-index` only uses the `lstat` result and
	// not the actual file contents. Running `git update-index
	// --refresh` updates the cache.
	if err := g.command("update-index", "-q", "--refresh"); err != nil {
		return false, err
	}

	err := g.command("diff-index", "--quiet", commit, "--", pkg)
	if err == nil {
		return false, nil
	}
	switch err.(type) {
	case *exec.ExitError:
		// diff-index exits with an error if there are differences
		return true, nil
	default:
		return false, err
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"plugin"
	"rais/src/iiif"
	"reflect"
	"sort"
	"strings"

	"github.com/uoregon-libraries/gopkg/logger"
)

var idToPathPlugins []func(iiif.ID) (string, error)
var wrapHandlerPlugins []func(string, http.Handler) (http.Handler, error)
var teardownPlugins []func()

// pluginsFor returns a list of all plugin files which matched the given
// pattern.  Files are sorted by name.
func pluginsFor(pattern string) ([]string, error) {
	if !filepath.IsAbs(pattern) {
		var dir = filepath.Join(filepath.Dir(os.Args[0]), "plugins")
		pattern = filepath.Join(dir, pattern)
	}

	var files, err = filepath.Glob(pattern)
	if err != nil {
		return nil, fmt.Errorf("invalid plugin file pattern %q", pattern)
	}
	if len(files) == 0 {
		return nil, fmt.Errorf("plugin pattern %q doesn't match any files", pattern)
	}

	sort.Strings(files)
	return files, nil
}

// LoadPlugins searches for any plugins matching the pattern given.  If the
// pattern is not an absolute URL, it is treated as a pattern under the
// binary's dir/plugins.
func LoadPlugins(l *logger.Logger, patterns []string) {
	var plugFiles []string
	var seen = make(map[string]bool)
	for _, pattern := range patterns {
		var matches, err = pluginsFor(pattern)
		if err != nil {
			l.Fatalf("Cannot process pattern %q: %s", pattern, err)
		}

		// We do a sanity check before actually processing any plugins
		for _, file := range matches {
			if filepath.Ext(file) != ".so" {
				l.Fatalf("Cannot load unknown file %q (plugins must be compiled .so files)", file)
			}
			if seen[file] {
				l.Fatalf("Cannot load the same plugin twice (%q)", file)
			}
			seen[file] = true
		}

		plugFiles = append(plugFiles, matches...)
	}

	for _, file := range plugFiles {
		l.Infof("Loading plugin %q", file)
		var err = loadPlugin(file, l)
		if err != nil {
			l.Errorf("Unable to load %q: %s", file, err)
		}
	}
}

type pluginWrapper struct {
	*plugin.Plugin
	path      string
	functions []string
	errors    []string
}

func newPluginWrapper(path string) (*pluginWrapper, error) {
	var p, err = plugin.Open(path)
	if err != nil {
		return nil, fmt.Errorf("cannot load plugin %q: %s", path, err)
	}
	return &pluginWrapper{Plugin: p, path: path}, nil
}

// loadPluginFn loads the symbol by the given name and attempts to set it to
// the given object via reflection.  If the two aren't the same type, an error
// is added to the pluginWrapper's error list.
func (pw *pluginWrapper) loadPluginFn(name string, obj interface{}) {
	var sym, err = pw.Lookup(name)
	if err != nil {
		return
	}

	var objElem = reflect.ValueOf(obj).Elem()
	var objType = objElem.Type()
	var symV = reflect.ValueOf(sym)

	if !symV.Type().AssignableTo(objType) {
		pw.errors = append(pw.errors, fmt.Sprintf("invalid signature for %s (expecting %s)", name, objType))
		return
	}

	objElem.Set(symV)
	pw.functions = append(pw.functions, name)
}

// loadPlugin attempts to read the given plugin file and extract known symbols.
// If a plugin exposes Initialize or SetLogger, they're called here once we're
// sure the plugin is valid.  IDToPath functions are indexed globally for use
// in the RAIS image serving handler.
func loadPlugin(fullpath string, l *logger.Logger) error {
	var pw, err = newPluginWrapper(fullpath)
	if err != nil {
		return err
	}

	// Set up dummy / no-op functions so we can call these without risk
	var log = func(*logger.Logger) {}
	var initialize = func() {}

	// Simply initialize those functions we only want indexed if they exist
	var idToPath func(iiif.ID) (string, error)
	var teardown func()
	var wrapHandler func(string, http.Handler) (http.Handler, error)

	pw.loadPluginFn("SetLogger", &log)
	pw.loadPluginFn("IDToPath", &idToPath)
	pw.loadPluginFn("Initialize", &initialize)
	pw.loadPluginFn("Teardown", &teardown)
	pw.loadPluginFn("WrapHandler", &wrapHandler)

	if len(pw.errors) != 0 {
		return errors.New(strings.Join(pw.errors, ", "))
	}
	if len(pw.functions) == 0 {
		return fmt.Errorf("no known functions exposed")
	}

	// We need to call SetLogger and Initialize immediately, as they're never
	// called a second time and they tell us if the plugin is going to be used
	log(l)
	initialize()

	// After initialization, we check if the plugin explicitly set itself to Disabled
	var sym plugin.Symbol
	sym, err = pw.Lookup("Disabled")
	if err == nil {
		var disabled, ok = sym.(*bool)
		if !ok {
			return fmt.Errorf("non-boolean Disabled value exposed")
		}
		if *disabled {
			l.Infof("%q is disabled", fullpath)
			return nil
		}
		l.Debugf("%q is explicitly enabled", fullpath)
	}

	// Index remaining functions
	if idToPath != nil {
		idToPathPlugins = append(idToPathPlugins, idToPath)
	}
	if teardown != nil {
		teardownPlugins = append(teardownPlugins, teardown)
	}
	if wrapHandler != nil {
		wrapHandlerPlugins = append(wrapHandlerPlugins, wrapHandler)
	}

	return nil
}
<commit_msg>plugins: add plugin data to stats structure<commit_after>package main

import (
	"errors"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"plugin"
	"rais/src/iiif"
	"reflect"
	"sort"
	"strings"

	"github.com/uoregon-libraries/gopkg/logger"
)

var idToPathPlugins []func(iiif.ID) (string, error)
var wrapHandlerPlugins []func(string, http.Handler) (http.Handler, error)
var teardownPlugins []func()

// pluginsFor returns a list of all plugin files which matched the given
// pattern.  Files are sorted by name.
func pluginsFor(pattern string) ([]string, error) {
	if !filepath.IsAbs(pattern) {
		var dir = filepath.Join(filepath.Dir(os.Args[0]), "plugins")
		pattern = filepath.Join(dir, pattern)
	}

	var files, err = filepath.Glob(pattern)
	if err != nil {
		return nil, fmt.Errorf("invalid plugin file pattern %q", pattern)
	}
	if len(files) == 0 {
		return nil, fmt.Errorf("plugin pattern %q doesn't match any files", pattern)
	}

	sort.Strings(files)
	return files, nil
}

// LoadPlugins searches for any plugins matching the pattern given.  If the
// pattern is not an absolute URL, it is treated as a pattern under the
// binary's dir/plugins.
func LoadPlugins(l *logger.Logger, patterns []string) {
	var plugFiles []string
	var seen = make(map[string]bool)
	for _, pattern := range patterns {
		var matches, err = pluginsFor(pattern)
		if err != nil {
			l.Fatalf("Cannot process pattern %q: %s", pattern, err)
		}

		// We do a sanity check before actually processing any plugins
		for _, file := range matches {
			if filepath.Ext(file) != ".so" {
				l.Fatalf("Cannot load unknown file %q (plugins must be compiled .so files)", file)
			}
			if seen[file] {
				l.Fatalf("Cannot load the same plugin twice (%q)", file)
			}
			seen[file] = true
		}

		plugFiles = append(plugFiles, matches...)
	}

	for _, file := range plugFiles {
		l.Infof("Loading plugin %q", file)
		var err = loadPlugin(file, l)
		if err != nil {
			l.Errorf("Unable to load %q: %s", file, err)
		}
	}
}

type pluginWrapper struct {
	*plugin.Plugin
	path      string
	functions []string
	errors    []string
}

func newPluginWrapper(path string) (*pluginWrapper, error) {
	var p, err = plugin.Open(path)
	if err != nil {
		return nil, fmt.Errorf("cannot load plugin %q: %s", path, err)
	}
	return &pluginWrapper{Plugin: p, path: path}, nil
}

// loadPluginFn loads the symbol by the given name and attempts to set it to
// the given object via reflection.  If the two aren't the same type, an error
// is added to the pluginWrapper's error list.
func (pw *pluginWrapper) loadPluginFn(name string, obj interface{}) {
	var sym, err = pw.Lookup(name)
	if err != nil {
		return
	}

	var objElem = reflect.ValueOf(obj).Elem()
	var objType = objElem.Type()
	var symV = reflect.ValueOf(sym)

	if !symV.Type().AssignableTo(objType) {
		pw.errors = append(pw.errors, fmt.Sprintf("invalid signature for %s (expecting %s)", name, objType))
		return
	}

	objElem.Set(symV)
	pw.functions = append(pw.functions, name)
}

// loadPlugin attempts to read the given plugin file and extract known symbols.
// If a plugin exposes Initialize or SetLogger, they're called here once we're
// sure the plugin is valid.  IDToPath functions are indexed globally for use
// in the RAIS image serving handler.
func loadPlugin(fullpath string, l *logger.Logger) error {
	var pw, err = newPluginWrapper(fullpath)
	if err != nil {
		return err
	}

	// Set up dummy / no-op functions so we can call these without risk
	var log = func(*logger.Logger) {}
	var initialize = func() {}

	// Simply initialize those functions we only want indexed if they exist
	var idToPath func(iiif.ID) (string, error)
	var teardown func()
	var wrapHandler func(string, http.Handler) (http.Handler, error)

	pw.loadPluginFn("SetLogger", &log)
	pw.loadPluginFn("IDToPath", &idToPath)
	pw.loadPluginFn("Initialize", &initialize)
	pw.loadPluginFn("Teardown", &teardown)
	pw.loadPluginFn("WrapHandler", &wrapHandler)

	if len(pw.errors) != 0 {
		return errors.New(strings.Join(pw.errors, ", "))
	}
	if len(pw.functions) == 0 {
		return fmt.Errorf("no known functions exposed")
	}

	// We need to call SetLogger and Initialize immediately, as they're never
	// called a second time and they tell us if the plugin is going to be used
	log(l)
	initialize()

	// After initialization, we check if the plugin explicitly set itself to Disabled
	var sym plugin.Symbol
	sym, err = pw.Lookup("Disabled")
	if err == nil {
		var disabled, ok = sym.(*bool)
		if !ok {
			return fmt.Errorf("non-boolean Disabled value exposed")
		}
		if *disabled {
			l.Infof("%q is disabled", fullpath)
			return nil
		}
		l.Debugf("%q is explicitly enabled", fullpath)
	}

	// Index remaining functions
	if idToPath != nil {
		idToPathPlugins = append(idToPathPlugins, idToPath)
	}
	if teardown != nil {
		teardownPlugins = append(teardownPlugins, teardown)
	}
	if wrapHandler != nil {
		wrapHandlerPlugins = append(wrapHandlerPlugins, wrapHandler)
	}

	// Add info to stats
	stats.Plugins = append(stats.Plugins, plugStats{
		Path:      fullpath,
		Functions: pw.functions,
	})

	return nil
}
<|endoftext|>


<commit_before>package kindergarten

import (
	"fmt"
	"strings"
)

// Define the Garden type here.
type Garden struct {
	diagram  []string
	children []string
}

var symbolToPlant = map[string]string{
	"R": "radishes",
	"C": "clover",
	"G": "grass",
	"V": "violets",
}

// The diagram argument starts each row with a '\n'.  This allows Go's
// raw string literals to present diagrams in source code nicely as two
// rows flush left, for example,
//
//     diagram := `
//     VVCCGG
//     VVCCGG`

func NewGarden(diagram string, children []string) (*Garden, error) {
	trimmed := strings.Trim(diagram, "\n")
	rows := strings.Split(trimmed, "\n")
	return &Garden{diagram: rows, children: children}, nil
}

func (g *Garden) Plants(child string) (plants []string, ok bool) {
	fmt.Printf("diagrams %v\n", g.diagram)
	index := indexOf(g.children, child)
	column := index * 2
	cups := []string{
		string(g.diagram[0][column]),
		string(g.diagram[0][column+1]),
		string(g.diagram[1][column]),
		string(g.diagram[1][column+1]),
	}
	for _, cup := range cups {
		plants = append(plants, symbolToPlant[cup])
	}
	return plants, true
}

func indexOf(slice []string, element string) int {
	for i, v := range slice {
		if v == element {
			return i
		}
	}
	return -1
}
<commit_msg>Pass test 6 by sorting children<commit_after>package kindergarten

import (
	"fmt"
	"sort"
	"strings"
)

// Define the Garden type here.
type Garden struct {
	diagram  []string
	children []string
}

var symbolToPlant = map[string]string{
	"R": "radishes",
	"C": "clover",
	"G": "grass",
	"V": "violets",
}

// The diagram argument starts each row with a '\n'.  This allows Go's
// raw string literals to present diagrams in source code nicely as two
// rows flush left, for example,
//
//     diagram := `
//     VVCCGG
//     VVCCGG`

func NewGarden(diagram string, children []string) (*Garden, error) {
	trimmed := strings.Trim(diagram, "\n")
	rows := strings.Split(trimmed, "\n")
	sort.Strings(children)
	return &Garden{diagram: rows, children: children}, nil
}

func (g *Garden) Plants(child string) (plants []string, ok bool) {
	fmt.Printf("diagrams %v\n", g.diagram)
	index := indexOf(g.children, child)
	column := index * 2
	cups := []string{
		string(g.diagram[0][column]),
		string(g.diagram[0][column+1]),
		string(g.diagram[1][column]),
		string(g.diagram[1][column+1]),
	}
	for _, cup := range cups {
		plants = append(plants, symbolToPlant[cup])
	}
	return plants, true
}

func indexOf(slice []string, element string) int {
	for i, v := range slice {
		if v == element {
			return i
		}
	}
	return -1
}
<|endoftext|>


<commit_before>package protein

import "errors"

// ErrStop represents a STOP codon
var ErrStop error = errors.New("stop codon")

// ErrInvalidBase represents an invalid base that cannot me mapped to an amino acid.
var ErrInvalidBase error = errors.New("invalid base")

// Codon                 | Protein
// :---                  | :---
// AUG                   | Methionine
// UUU, UUC              | Phenylalanine
// UUA, UUG              | Leucine
// UCU, UCC, UCA, UCG    | Serine
// UAU, UAC              | Tyrosine
// UGU, UGC              | Cysteine
// UGG                   | Tryptophan
// UAA, UAG, UGA         | STOP

var stopCodons = map[string]bool{
	"UAA": true,
	"UAG": true,
	"UGA": true,
}

var codonToProtein = map[string]string{
	"AUG": "Methionine",
	"UUU": "Phenylalanine",
	"UUC": "Phenylalanine",
	"UUA": "Leucine",
	"UUG": "Leucine",
	"UCU": "Serine",
	"UCC": "Serine",
	"UCA": "Serine",
	"UCG": "Serine",
	"UAU": "Tyrosine",
	"UAC": "Tyrosine",
	"UGU": "Cysteine",
	"UGC": "Cysteine",
	"UGG": "Tryptophan",
}

func FromCodon(codon string) (protein string, e error) {
	if _, ok := stopCodons[codon]; ok {
		return "", ErrStop
	}
	if _, ok := codonToProtein[codon]; !ok {
		return "", ErrInvalidBase
	}
	return codonToProtein[codon], nil
}

func FromRNA(codons string) (proteins string, e error) {
	return "bar", nil
}
<commit_msg>Solve protein translation<commit_after>package protein

import (
	"errors"
)

// ErrStop represents a STOP codon
var ErrStop error = errors.New("stop codon")

// ErrInvalidBase represents an invalid base that cannot me mapped to an amino acid.
var ErrInvalidBase error = errors.New("invalid base")

// Codon                 | Protein
// :---                  | :---
// AUG                   | Methionine
// UUU, UUC              | Phenylalanine
// UUA, UUG              | Leucine
// UCU, UCC, UCA, UCG    | Serine
// UAU, UAC              | Tyrosine
// UGU, UGC              | Cysteine
// UGG                   | Tryptophan
// UAA, UAG, UGA         | STOP

var stopCodons = map[string]bool{
	"UAA": true,
	"UAG": true,
	"UGA": true,
}

var codonToProtein = map[string]string{
	"AUG": "Methionine",
	"UUU": "Phenylalanine",
	"UUC": "Phenylalanine",
	"UUA": "Leucine",
	"UUG": "Leucine",
	"UCU": "Serine",
	"UCC": "Serine",
	"UCA": "Serine",
	"UCG": "Serine",
	"UAU": "Tyrosine",
	"UAC": "Tyrosine",
	"UGU": "Cysteine",
	"UGC": "Cysteine",
	"UGG": "Tryptophan",
}

func FromCodon(codon string) (protein string, e error) {
	if _, ok := stopCodons[codon]; ok {
		return "", ErrStop
	}
	if _, ok := codonToProtein[codon]; !ok {
		return "", ErrInvalidBase
	}
	return codonToProtein[codon], nil
}

const CODON_LENGTH = 3

func FromRNA(codons string) (proteins []string, e error) {
	for i := 0; i <= len(codons)-CODON_LENGTH; i += CODON_LENGTH {
		codon := codons[i : i+CODON_LENGTH]
		codon, err := FromCodon(codon)
		if errors.Is(err, ErrStop) {
			return proteins, nil
		}
		if errors.Is(err, ErrInvalidBase) {
			return proteins, ErrInvalidBase
		}
		proteins = append(proteins, codon)
	}
	return proteins, nil
}
<|endoftext|>


<commit_before>package kontrol

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"
	"github.com/hashicorp/go-version"
	"github.com/koding/kite"
	kontrolprotocol "github.com/koding/kite/kontrol/protocol"
	"github.com/koding/kite/protocol"
)

// keyOrder defines the order of the query paramaters.
var keyOrder = []string{
	"username",
	"environment",
	"name",
	"version",
	"region",
	"hostname",
	"id",
}

// Etcd implements the Storage interface
type Etcd struct {
	client *etcd.Client
	log    kite.Logger
}

func NewEtcd(machines []string, log kite.Logger) *Etcd {
	if machines == nil || len(machines) == 0 {
		machines = []string{"127.0.0.1:4001"}
	}

	client := etcd.NewClient(machines)
	ok := client.SetCluster(machines)
	if !ok {
		panic("cannot connect to etcd cluster: " + strings.Join(machines, ","))
	}

	return &Etcd{
		client: client,
		log:    log,
	}
}

func (e *Etcd) Delete(k *protocol.Kite) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	_, err := e.client.Delete(etcdKey, true)
	_, err = e.client.Delete(etcdIDKey, true)
	return err
}

func (e *Etcd) Clear() error {
	_, err := e.client.Delete(KitesPrefix, true)
	return err
}

func (e *Etcd) Upsert(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	return e.Add(k, value)
}

func (e *Etcd) Add(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	valueBytes, err := json.Marshal(value)
	if err != nil {
		return err
	}

	valueString := string(valueBytes)

	// Set the kite key.
	// Example "/koding/production/os/0.0.1/sj/kontainer1.sj.koding.com/1234asdf..."
	_, err = e.client.Set(etcdKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	// Also store the the kite.Key Id for easy lookup
	_, err = e.client.Set(etcdIDKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	return nil
}

func (e *Etcd) Update(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	valueBytes, err := json.Marshal(value)
	if err != nil {
		return err
	}

	valueString := string(valueBytes)

	// update the kite key.
	// Example "/koding/production/os/0.0.1/sj/kontainer1.sj.koding.com/1234asdf..."
	_, err = e.client.Update(etcdKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	// Also update the the kite.Key Id for easy lookup
	_, err = e.client.Update(etcdIDKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	// Set the TTL for the username. Otherwise, empty dirs remain in etcd.
	_, err = e.client.Update(KitesPrefix+"/"+k.Username,
		"", uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	return nil
}

func (e *Etcd) Get(query *protocol.KontrolQuery) (Kites, error) {
	// We will make a get request to etcd store with this key. So get a "etcd"
	// key from the given query so that we can use it to query from Etcd.
	etcdKey, err := e.etcdKey(query)
	if err != nil {
		return nil, err
	}

	// If version field contains a constraint we need no make a new query up to
	// "name" field and filter the results after getting all versions.
	// NewVersion returns an error if it's a constraint, like: ">= 1.0, < 1.4"
	// Because NewConstraint doesn't return an error for version's like "0.0.1"
	// we check it with the NewVersion function.
	var hasVersionConstraint bool // does query contains a constraint on version?
	var keyRest string            // query key after the version field
	var versionConstraint version.Constraints
	_, err = version.NewVersion(query.Version)
	if err != nil && query.Version != "" {
		// now parse our constraint
		versionConstraint, err = version.NewConstraint(query.Version)
		if err != nil {
			// version is a malformed, just return the error
			return nil, err
		}

		hasVersionConstraint = true
		nameQuery := &protocol.KontrolQuery{
			Username:    query.Username,
			Environment: query.Environment,
			Name:        query.Name,
		}
		// We will make a get request to all nodes under this name
		// and filter the result later.
		etcdKey, _ = GetQueryKey(nameQuery)

		// Rest of the key after version field
		keyRest = "/" + strings.TrimRight(
			query.Region+"/"+query.Hostname+"/"+query.ID, "/")
	}

	resp, err := e.client.Get(KitesPrefix+etcdKey, false, true)
	if err != nil {
		// if it's something else just return
		return nil, err
	}

	kites := make(Kites, 0)

	node := NewNode(resp.Node)

	// means a query with all fields were made or a query with an ID was made,
	// in which case also returns a full path. This path has a value that
	// contains the final kite URL. Therefore this is a single kite result,
	// create it and pass it back.
	if node.HasValue() {
		oneKite, err := node.Kite()
		if err != nil {
			return nil, err
		}

		kites = append(kites, oneKite)
	} else {
		kites, err = node.Kites()
		if err != nil {
			return nil, err
		}

		// Filter kites by version constraint
		if hasVersionConstraint {
			kites.Filter(versionConstraint, keyRest)
		}
	}

	// Shuffle the list
	kites.Shuffle()

	return kites, nil
}

func (e *Etcd) etcdKey(query *protocol.KontrolQuery) (string, error) {
	if onlyIDQuery(query) {
		resp, err := e.client.Get(KitesPrefix+"/"+query.ID, false, true)
		if err != nil {
			return "", err
		}

		return resp.Node.Value, nil
	}

	return GetQueryKey(query)
}

// RegisterValue is the type of the value that is saved to etcd.
type RegisterValue struct {
	URL string `json:"url"`
}

// validateKiteKey returns a string representing the kite uniquely
// that is suitable to use as a key for etcd.
func validateKiteKey(k *protocol.Kite) error {
	fields := k.Query().Fields()

	// Validate fields.
	for k, v := range fields {
		if v == "" {
			return fmt.Errorf("Empty Kite field: %s", k)
		}
		if strings.ContainsRune(v, '/') {
			return fmt.Errorf("Field \"%s\" must not contain '/'", k)
		}
	}

	return nil
}

// onlyIDQuery returns true if the query contains only a non-empty ID and all
// others keys are empty
func onlyIDQuery(q *protocol.KontrolQuery) bool {
	fields := q.Fields()

	// check if any other key exist, if yes return a false
	for _, k := range keyOrder {
		v := fields[k]
		if k != "id" && v != "" {
			return false
		}
	}

	// now all other keys are empty, check finally for our ID
	if fields["id"] != "" {
		return true
	}

	// ID is empty too!
	return false
}

// getQueryKey returns the etcd key for the query.
func GetQueryKey(q *protocol.KontrolQuery) (string, error) {
	fields := q.Fields()

	if q.Username == "" {
		return "", errors.New("Empty username field")
	}

	// Validate query and build key.
	path := "/"

	empty := false   // encountered with empty field?
	empytField := "" // for error log

	// http://golang.org/doc/go1.3#map, order is important and we can't rely on
	// maps because the keys are not ordered :)
	for _, key := range keyOrder {
		v := fields[key]
		if v == "" {
			empty = true
			empytField = key
			continue
		}

		if empty && v != "" {
			return "", fmt.Errorf("Invalid query. Query option is not set: %s", empytField)
		}

		path = path + v + "/"
	}

	path = strings.TrimSuffix(path, "/")

	return path, nil
}

func getAudience(q *protocol.KontrolQuery) string {
	if q.Name != "" {
		return "/" + q.Username + "/" + q.Environment + "/" + q.Name
	} else if q.Environment != "" {
		return "/" + q.Username + "/" + q.Environment
	} else {
		return "/" + q.Username
	}
}
<commit_msg>Fix from https://github.com/koding/kite/pull/139<commit_after>package kontrol

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/coreos/go-etcd/etcd"
	"github.com/hashicorp/go-version"
	"github.com/koding/kite"
	kontrolprotocol "github.com/koding/kite/kontrol/protocol"
	"github.com/koding/kite/protocol"
)

// keyOrder defines the order of the query paramaters.
var keyOrder = []string{
	"username",
	"environment",
	"name",
	"version",
	"region",
	"hostname",
	"id",
}

// Etcd implements the Storage interface
type Etcd struct {
	client *etcd.Client
	log    kite.Logger
}

func NewEtcd(machines []string, log kite.Logger) *Etcd {
	if machines == nil || len(machines) == 0 {
		machines = []string{"127.0.0.1:4001"}
	}

	client := etcd.NewClient(machines)
	ok := client.SetCluster(machines)
	if !ok {
		panic("cannot connect to etcd cluster: " + strings.Join(machines, ","))
	}

	return &Etcd{
		client: client,
		log:    log,
	}
}

func (e *Etcd) Delete(k *protocol.Kite) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	_, err := e.client.Delete(etcdKey, true)
	_, err = e.client.Delete(etcdIDKey, true)
	return err
}

func (e *Etcd) Clear() error {
	_, err := e.client.Delete(KitesPrefix, true)
	return err
}

func (e *Etcd) Upsert(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	return e.Add(k, value)
}

func (e *Etcd) Add(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	valueBytes, err := json.Marshal(value)
	if err != nil {
		return err
	}

	valueString := string(valueBytes)

	// Set the kite key.
	// Example "/koding/production/os/0.0.1/sj/kontainer1.sj.koding.com/1234asdf..."
	_, err = e.client.Set(etcdKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	// Also store the the kite.Key Id for easy lookup
	_, err = e.client.Set(etcdIDKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	return nil
}

func (e *Etcd) Update(k *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	etcdKey := KitesPrefix + k.String()
	etcdIDKey := KitesPrefix + "/" + k.ID

	valueBytes, err := json.Marshal(value)
	if err != nil {
		return err
	}

	valueString := string(valueBytes)

	// update the kite key.
	// Example "/koding/production/os/0.0.1/sj/kontainer1.sj.koding.com/1234asdf..."
	_, err = e.client.Update(etcdKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		err = e.Add(k, value)
		if err != nil {
			return err
		}
		return nil
	}

	// Also update the the kite.Key Id for easy lookup
	_, err = e.client.Update(etcdIDKey, valueString, uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	// Set the TTL for the username. Otherwise, empty dirs remain in etcd.
	_, err = e.client.Update(KitesPrefix+"/"+k.Username,
		"", uint64(KeyTTL/time.Second))
	if err != nil {
		return err
	}

	return nil
}

func (e *Etcd) Get(query *protocol.KontrolQuery) (Kites, error) {
	// We will make a get request to etcd store with this key. So get a "etcd"
	// key from the given query so that we can use it to query from Etcd.
	etcdKey, err := e.etcdKey(query)
	if err != nil {
		return nil, err
	}

	// If version field contains a constraint we need no make a new query up to
	// "name" field and filter the results after getting all versions.
	// NewVersion returns an error if it's a constraint, like: ">= 1.0, < 1.4"
	// Because NewConstraint doesn't return an error for version's like "0.0.1"
	// we check it with the NewVersion function.
	var hasVersionConstraint bool // does query contains a constraint on version?
	var keyRest string            // query key after the version field
	var versionConstraint version.Constraints
	_, err = version.NewVersion(query.Version)
	if err != nil && query.Version != "" {
		// now parse our constraint
		versionConstraint, err = version.NewConstraint(query.Version)
		if err != nil {
			// version is a malformed, just return the error
			return nil, err
		}

		hasVersionConstraint = true
		nameQuery := &protocol.KontrolQuery{
			Username:    query.Username,
			Environment: query.Environment,
			Name:        query.Name,
		}
		// We will make a get request to all nodes under this name
		// and filter the result later.
		etcdKey, _ = GetQueryKey(nameQuery)

		// Rest of the key after version field
		keyRest = "/" + strings.TrimRight(
			query.Region+"/"+query.Hostname+"/"+query.ID, "/")
	}

	resp, err := e.client.Get(KitesPrefix+etcdKey, false, true)
	if err != nil {
		// if it's something else just return
		return nil, err
	}

	kites := make(Kites, 0)

	node := NewNode(resp.Node)

	// means a query with all fields were made or a query with an ID was made,
	// in which case also returns a full path. This path has a value that
	// contains the final kite URL. Therefore this is a single kite result,
	// create it and pass it back.
	if node.HasValue() {
		oneKite, err := node.Kite()
		if err != nil {
			return nil, err
		}

		kites = append(kites, oneKite)
	} else {
		kites, err = node.Kites()
		if err != nil {
			return nil, err
		}

		// Filter kites by version constraint
		if hasVersionConstraint {
			kites.Filter(versionConstraint, keyRest)
		}
	}

	// Shuffle the list
	kites.Shuffle()

	return kites, nil
}

func (e *Etcd) etcdKey(query *protocol.KontrolQuery) (string, error) {
	if onlyIDQuery(query) {
		resp, err := e.client.Get(KitesPrefix+"/"+query.ID, false, true)
		if err != nil {
			return "", err
		}

		return resp.Node.Value, nil
	}

	return GetQueryKey(query)
}

// RegisterValue is the type of the value that is saved to etcd.
type RegisterValue struct {
	URL string `json:"url"`
}

// validateKiteKey returns a string representing the kite uniquely
// that is suitable to use as a key for etcd.
func validateKiteKey(k *protocol.Kite) error {
	fields := k.Query().Fields()

	// Validate fields.
	for k, v := range fields {
		if v == "" {
			return fmt.Errorf("Empty Kite field: %s", k)
		}
		if strings.ContainsRune(v, '/') {
			return fmt.Errorf("Field \"%s\" must not contain '/'", k)
		}
	}

	return nil
}

// onlyIDQuery returns true if the query contains only a non-empty ID and all
// others keys are empty
func onlyIDQuery(q *protocol.KontrolQuery) bool {
	fields := q.Fields()

	// check if any other key exist, if yes return a false
	for _, k := range keyOrder {
		v := fields[k]
		if k != "id" && v != "" {
			return false
		}
	}

	// now all other keys are empty, check finally for our ID
	if fields["id"] != "" {
		return true
	}

	// ID is empty too!
	return false
}

// getQueryKey returns the etcd key for the query.
func GetQueryKey(q *protocol.KontrolQuery) (string, error) {
	fields := q.Fields()

	if q.Username == "" {
		return "", errors.New("Empty username field")
	}

	// Validate query and build key.
	path := "/"

	empty := false   // encountered with empty field?
	empytField := "" // for error log

	// http://golang.org/doc/go1.3#map, order is important and we can't rely on
	// maps because the keys are not ordered :)
	for _, key := range keyOrder {
		v := fields[key]
		if v == "" {
			empty = true
			empytField = key
			continue
		}

		if empty && v != "" {
			return "", fmt.Errorf("Invalid query. Query option is not set: %s", empytField)
		}

		path = path + v + "/"
	}

	path = strings.TrimSuffix(path, "/")

	return path, nil
}

func getAudience(q *protocol.KontrolQuery) string {
	if q.Name != "" {
		return "/" + q.Username + "/" + q.Environment + "/" + q.Name
	} else if q.Environment != "" {
		return "/" + q.Username + "/" + q.Environment
	} else {
		return "/" + q.Username
	}
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

func GetGroup(groupname string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"title": groupname}).One(&group)
	}

	err := mongodb.Run("jGroups", query)
	if err != nil {
		return nil, err
	}

	return group, nil
}
<commit_msg>Migration: CheckGroupExistence function is added<commit_after>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
)

func GetGroup(groupname string) (*models.Group, error) {
	group := new(models.Group)

	query := func(c *mgo.Collection) error {
		return c.Find(Selector{"title": groupname}).One(&group)
	}

	return group, mongodb.Run("jGroups", query)
}

func CheckGroupExistence(groupname string) (bool, error) {
	var count int
	query := func(c *mgo.Collection) error {
		var err error
		count, err = c.Find(Selector{"slug": groupname}).Count()
		if err != nil {
			return err
		}
		return nil
	}

	return count > 0, mongodb.Run("jGroups", query)
}
<|endoftext|>


<commit_before>package github_squares

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/ami-GS/soac"
	"strconv"
	"strings"
)

var colorMap map[string]byte = map[string]byte{
	"#d6e685": 156,
	"#8cc665": 112,
	"#44a340": 34,
	"#1e6823": 22,
	"#eeeeee": 237,
}

var Changer *soac.Changer

func init() {
	Changer = soac.NewChanger()
}

type Rect struct {
	color string
	count byte
	date  string
}

func GetData(reqUrl string) (results [7][54]Rect, month [12]string) {
	doc, _ := goquery.NewDocument(reqUrl)
	column := 0

	doc.Find("rect").Each(func(_ int, s *goquery.Selection) {
		yTmp, _ := s.Attr("y")
		y, _ := strconv.Atoi(yTmp)
		color, _ := s.Attr("fill")
		countTmp, _ := s.Attr("data-count")
		count, _ := strconv.Atoi(countTmp)
		date, _ := s.Attr("data-date")
		results[y/13][column] = Rect{color, byte(count), date}
		if y == 78 {
			column++
		}
	})

	m := 0
	doc.Find("text").Each(func(_ int, s *goquery.Selection) {
		attr, exists := s.Attr("class")
		if exists && attr == "month" {
			month[m] = s.Text()
			m++
		}
	})
	return
}

func GetString(rects [7][54]Rect, month [12]string) (ans string) {
	ans = "  "
	prev := "00"
	m := 0
	for col := 0; col < 54; col++ {
		mStr := strings.Split(rects[0][col].date, "-")
		if len(mStr) >= 2 && mStr[1] != prev {
			ans += string(month[m][0])
			prev = mStr[1]
			m++
			if m == 12 {
				break
			}
		} else {
			ans += " "
		}
	}
	ans += "\n"

	for row := 0; row < 7; row++ {
		switch {
		case row == 1:
			ans += "M "
		case row == 3:
			ans += "W "
		case row == 5:
			ans += "F "
		default:
			ans += "  "
		}

		for col := 0; col < 54; col++ {
			if rects[row][col].date != "" {
				Changer.Set256(colorMap[rects[row][col].color])
				ans += Changer.Apply("■")
			} else {
				ans += " "
			}
		}
		ans += "\n"
	}
	return
}

func ShowSquare(userName string) {
	reqUrl := fmt.Sprintf("http://github.com/%s/", userName)
	rects, month := GetData(reqUrl)
	str := GetString(rects, month)
	fmt.Println(str)
}
<commit_msg>implement Contributions type to use number infomation<commit_after>package github_squares

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/ami-GS/soac"
	"strconv"
	"strings"
)

var colorMap map[string]byte = map[string]byte{
	"#d6e685": 156,
	"#8cc665": 112,
	"#44a340": 34,
	"#1e6823": 22,
	"#eeeeee": 237,
}

var Changer *soac.Changer

func init() {
	Changer = soac.NewChanger()
}

type Contributions struct {
	rects         [7][54]Rect
	yearNum       uint16
	longestStreak uint16
	currentStreak uint16
	month         [12]string
}

func (self Contributions) Get(row, column int) Rect {
	return self.rects[row][column]
}

type Rect struct {
	color string
	count byte
	date  string
}

func GetData(reqUrl string) (contrib Contributions) {
	doc, _ := goquery.NewDocument(reqUrl)
	column := 0
	rects := [7][54]Rect{}
	doc.Find("rect").Each(func(_ int, s *goquery.Selection) {
		yTmp, _ := s.Attr("y")
		y, _ := strconv.Atoi(yTmp)
		color, _ := s.Attr("fill")
		countTmp, _ := s.Attr("data-count")
		count, _ := strconv.Atoi(countTmp)
		date, _ := s.Attr("data-date")
		rects[y/13][column] = Rect{color, byte(count), date}
		if y == 78 {
			column++
		}
	})

	m := 0
	var month [12]string
	doc.Find("text").Each(func(_ int, s *goquery.Selection) {
		attr, exists := s.Attr("class")
		if exists && attr == "month" {
			month[m] = s.Text()
			m++
		}
	})

	var yearNum uint16
	var streaks [2]uint16
	doc.Find("div[class='contrib-column contrib-column-first table-column']").Each(func(_ int, s *goquery.Selection) {
		text := s.Find("span[class='contrib-number']").Text()
		result := strings.Split(text, " ")
		num, _ := strconv.Atoi(result[0])
		yearNum = uint16(num)
	})

	streakIdx := 0
	doc.Find("div[class='contrib-column table-column']").Each(func(_ int, s *goquery.Selection) {
		text := s.Find("span[class='contrib-number']").Text()
		result := strings.Split(text, " ")
		num, _ := strconv.Atoi(result[0])
		streaks[streakIdx] = uint16(num)
		streakIdx++
	})

	contrib = Contributions{rects, yearNum, streaks[0], streaks[1], month}
	return
}

func GetString(contrib Contributions) (ans string) {
	ans = "  "
	prev := "00"
	m := 0
	for col := 0; col < 54; col++ {
		rect := contrib.Get(0, col)
		mStr := strings.Split(rect.date, "-")
		if len(mStr) >= 2 && mStr[1] != prev {
			ans += string(contrib.month[m][0])
			prev = mStr[1]
			m++
			if m == 12 {
				break
			}
		} else {
			ans += " "
		}
	}
	ans += "\n"

	for row := 0; row < 7; row++ {
		switch {
		case row == 1:
			ans += "M "
		case row == 3:
			ans += "W "
		case row == 5:
			ans += "F "
		default:
			ans += "  "
		}

		for col := 0; col < 54; col++ {
			rect := contrib.Get(row, col)
			if rect.date != "" {
				Changer.Set256(colorMap[rect.color])
				ans += Changer.Apply("■")
			} else {
				ans += " "
			}
		}
		ans += "\n"
	}
	return
}

func ShowSquare(userName string) {
	reqUrl := fmt.Sprintf("http://github.com/%s/", userName)
	contrib := GetData(reqUrl)
	str := GetString(contrib)
	fmt.Println(str)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/ofesseler/gluster_exporter/structs"
	"github.com/prometheus/common/log"
)

func execGlusterCommand(arg ...string) (*bytes.Buffer, error) {
	stdoutBuffer := &bytes.Buffer{}
	argXML := append(arg, "--xml")
	glusterExec := exec.Command(GlusterCmd, argXML...)
	glusterExec.Stdout = stdoutBuffer
	err := glusterExec.Run()

	if err != nil {
		log.Errorf("tried to execute %v and got error: %v", arg, err)
		return stdoutBuffer, err
	}
	return stdoutBuffer, nil
}

func execMountCheck() (*bytes.Buffer, error) {
	stdoutBuffer := &bytes.Buffer{}
	mountCmd := exec.Command("mount", "-t", "fuse.glusterfs")

	mountCmd.Stdout = stdoutBuffer

	return stdoutBuffer, mountCmd.Run()
}

func execTouchOnVolumes(mountpoint string) (bool, error) {
	testFileName := fmt.Sprintf("%v/%v_%v", mountpoint, "gluster_mount.test", time.Now())
	_, createErr := os.Create(testFileName)
	if createErr != nil {
		return false, createErr
	}
	removeErr := os.Remove(testFileName)
	if removeErr != nil {
		return false, removeErr
	}
	return true, nil
}

// ExecVolumeInfo executes "gluster volume info" at the local machine and
// returns VolumeInfoXML struct and error
func ExecVolumeInfo() (structs.VolumeInfoXML, error) {
	args := []string{"volume", "info"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeInfoXML{}, cmdErr
	}
	volumeInfo, err := structs.VolumeInfoXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeInfo, err
	}

	return volumeInfo, nil
}

// ExecVolumeList executes "gluster volume info" at the local machine and
// returns VolumeList struct and error
func ExecVolumeList() (structs.VolList, error) {
	args := []string{"volume", "list"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolList{}, cmdErr
	}
	volumeList, err := structs.VolumeListXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeList.VolList, err
	}

	return volumeList.VolList, nil
}

// ExecPeerStatus executes "gluster peer status" at the local machine and
// returns PeerStatus struct and error
func ExecPeerStatus() (structs.PeerStatus, error) {
	args := []string{"peer", "status"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.PeerStatus{}, cmdErr
	}
	peerStatus, err := structs.PeerStatusXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return peerStatus.PeerStatus, err
	}

	return peerStatus.PeerStatus, nil
}

// ExecVolumeProfileGvInfoCumulative executes "gluster volume {volume] profile info cumulative" at the local machine and
// returns VolumeInfoXML struct and error
func ExecVolumeProfileGvInfoCumulative(volumeName string) (structs.VolProfile, error) {
	args := []string{"volume", "profile"}
	args = append(args, volumeName)
	args = append(args, "info", "cumulative")
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolProfile{}, cmdErr
	}
	volumeProfile, err := structs.VolumeProfileGvInfoCumulativeXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeProfile.VolProfile, err
	}
	return volumeProfile.VolProfile, nil
}

// ExecVolumeStatusAllDetail executes "gluster volume status all detail" at the local machine
// returns VolumeStatusXML struct and error
func ExecVolumeStatusAllDetail() (structs.VolumeStatusXML, error) {
	args := []string{"volume", "status", "all", "detail"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeStatusXML{}, cmdErr
	}
	volumeStatus, err := structs.VolumeStatusAllDetailXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeStatus, err
	}
	return volumeStatus, nil
}

// ExecVolumeHealInfo executes volume heal info on host system and processes input
// returns (int) number of unsynced files
func ExecVolumeHealInfo(volumeName string) (int, error) {
	args := []string{"volume", "heal", volumeName, "info"}
	entriesOutOfSync := 0
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return -1, cmdErr
	}
	healInfo, err := structs.VolumeHealInfoXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Error(err)
		return -1, err
	}

	for _, brick := range healInfo.HealInfo.Bricks.Brick {
		var count int
		count, _ = strconv.Atoi(brick.NumberOfEntries)
		entriesOutOfSync += count
	}
	return entriesOutOfSync, nil
}

// ExecVolumeQuotaList executes volume quota list on host system and processess input
// returns QuotaList structs and errors
func ExecVolumeQuotaList(volumeName string) (structs.VolumeQuotaXML, error) {
	args := []string{"volume", "quota", volumeName, "list"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeQuotaXML{}, cmdErr
	}
	volumeQuota, err := structs.VolumeQuotaListXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeQuota, err
	}
	return volumeQuota, nil
}
<commit_msg>gluster_client.go: remove unnecessary append<commit_after>package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/ofesseler/gluster_exporter/structs"
	"github.com/prometheus/common/log"
)

func execGlusterCommand(arg ...string) (*bytes.Buffer, error) {
	stdoutBuffer := &bytes.Buffer{}
	argXML := append(arg, "--xml")
	glusterExec := exec.Command(GlusterCmd, argXML...)
	glusterExec.Stdout = stdoutBuffer
	err := glusterExec.Run()

	if err != nil {
		log.Errorf("tried to execute %v and got error: %v", arg, err)
		return stdoutBuffer, err
	}
	return stdoutBuffer, nil
}

func execMountCheck() (*bytes.Buffer, error) {
	stdoutBuffer := &bytes.Buffer{}
	mountCmd := exec.Command("mount", "-t", "fuse.glusterfs")

	mountCmd.Stdout = stdoutBuffer

	return stdoutBuffer, mountCmd.Run()
}

func execTouchOnVolumes(mountpoint string) (bool, error) {
	testFileName := fmt.Sprintf("%v/%v_%v", mountpoint, "gluster_mount.test", time.Now())
	_, createErr := os.Create(testFileName)
	if createErr != nil {
		return false, createErr
	}
	removeErr := os.Remove(testFileName)
	if removeErr != nil {
		return false, removeErr
	}
	return true, nil
}

// ExecVolumeInfo executes "gluster volume info" at the local machine and
// returns VolumeInfoXML struct and error
func ExecVolumeInfo() (structs.VolumeInfoXML, error) {
	args := []string{"volume", "info"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeInfoXML{}, cmdErr
	}
	volumeInfo, err := structs.VolumeInfoXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeInfo, err
	}

	return volumeInfo, nil
}

// ExecVolumeList executes "gluster volume info" at the local machine and
// returns VolumeList struct and error
func ExecVolumeList() (structs.VolList, error) {
	args := []string{"volume", "list"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolList{}, cmdErr
	}
	volumeList, err := structs.VolumeListXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeList.VolList, err
	}

	return volumeList.VolList, nil
}

// ExecPeerStatus executes "gluster peer status" at the local machine and
// returns PeerStatus struct and error
func ExecPeerStatus() (structs.PeerStatus, error) {
	args := []string{"peer", "status"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.PeerStatus{}, cmdErr
	}
	peerStatus, err := structs.PeerStatusXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return peerStatus.PeerStatus, err
	}

	return peerStatus.PeerStatus, nil
}

// ExecVolumeProfileGvInfoCumulative executes "gluster volume {volume] profile info cumulative" at the local machine and
// returns VolumeInfoXML struct and error
func ExecVolumeProfileGvInfoCumulative(volumeName string) (structs.VolProfile, error) {
	args := []string{"volume", "profile", volumeName, "info", "cumulative"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolProfile{}, cmdErr
	}
	volumeProfile, err := structs.VolumeProfileGvInfoCumulativeXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeProfile.VolProfile, err
	}
	return volumeProfile.VolProfile, nil
}

// ExecVolumeStatusAllDetail executes "gluster volume status all detail" at the local machine
// returns VolumeStatusXML struct and error
func ExecVolumeStatusAllDetail() (structs.VolumeStatusXML, error) {
	args := []string{"volume", "status", "all", "detail"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeStatusXML{}, cmdErr
	}
	volumeStatus, err := structs.VolumeStatusAllDetailXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeStatus, err
	}
	return volumeStatus, nil
}

// ExecVolumeHealInfo executes volume heal info on host system and processes input
// returns (int) number of unsynced files
func ExecVolumeHealInfo(volumeName string) (int, error) {
	args := []string{"volume", "heal", volumeName, "info"}
	entriesOutOfSync := 0
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return -1, cmdErr
	}
	healInfo, err := structs.VolumeHealInfoXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Error(err)
		return -1, err
	}

	for _, brick := range healInfo.HealInfo.Bricks.Brick {
		var count int
		count, _ = strconv.Atoi(brick.NumberOfEntries)
		entriesOutOfSync += count
	}
	return entriesOutOfSync, nil
}

// ExecVolumeQuotaList executes volume quota list on host system and processess input
// returns QuotaList structs and errors
func ExecVolumeQuotaList(volumeName string) (structs.VolumeQuotaXML, error) {
	args := []string{"volume", "quota", volumeName, "list"}
	bytesBuffer, cmdErr := execGlusterCommand(args...)
	if cmdErr != nil {
		return structs.VolumeQuotaXML{}, cmdErr
	}
	volumeQuota, err := structs.VolumeQuotaListXMLUnmarshall(bytesBuffer)
	if err != nil {
		log.Errorf("Something went wrong while unmarshalling xml: %v", err)
		return volumeQuota, err
	}
	return volumeQuota, nil
}
<|endoftext|>