<commit_before>package iglo

import (
	"bitbucket.org/pkg/inflect"
	"bytes"
	bf "github.com/russross/blackfriday"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func markdownize(str string) template.HTML {
	b := bf.MarkdownCommon([]byte(str))
	return template.HTML(string(b))
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize":   inflect.Dasherize,
		"trim":        strings.Trim,
		"labelize":    labelize,
		"markdownize": markdownize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

func MarkdownToHTML(w io.Writer, r io.Reader) error {
	data, err := ParseMarkdown(r)
	if err != nil {
		return err
	}

	err = JSONToHTML(w, bytes.NewBuffer(data))
	if err != nil {
		return err
	}

	return nil
}

func JSONToHTML(w io.Writer, r io.Reader) error {
	api, err := ParseJSON(r)
	if err != nil {
		return err
	}

	err = HTML(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Headers"}}

	{{range $index, $element := .}}

{{$index}}

{{.Value}}

	{{end}}

{{end}}

{{define "Responses"}}
	{{range .}}

			Response {{.Name}}
			{{if .Body}}

					SHOW

			{{end}}

			{{if .Headers}}
				{{template "Headers" .Headers}}

			{{end}}
			{{if .Body}}

{{.Body}}

			{{end}}

	{{end}}
{{end}}

{{define "Requests"}}
	{{range .}}

			Requests

				SHOW

			{{if .Headers}}
				{{range $index, $element := .Headers}}> {{$index}}: {{.Value}}
{{end}}
			{{end}}
			{{if .Body}}

{{.Body}}

			{{end}}

	{{end}}
{{end}}

{{define "Examples"}}
	{{range .}}
		{{template "Requests" .Requests}}
		{{template "Responses" .Responses}}
	{{end}}
{{end}}

{{define "Parameters"}}

	{{range $index, $element := .}}

{{$index}}

		{{if .Required}}
		{{else}}
			(required)
		{{end}}
		{{.Type}} {{.Description}}

	{{end}}

{{end}}

{{define "Resources"}}
{{range .}}
	{{$UriTemplate := .UriTemplate}}
	{{$Parameters := .Parameters}}

	{{range .Actions}}

			{{.Method}}
			{{$UriTemplate}}

			{{.Description | markdownize}}

			{{if $Parameters}}

Parameters

{{template "Parameters" $Parameters}}

			{{end}}
			{{if .Examples}}{{template "Examples" .Examples}}{{end}}

	{{end}}
{{end}}
{{end}}

{{define "ResourceGroups"}}
{{range .}}

{{.Name}}

{{.Description}}

				{{template "Resources" .Resources}}

{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}

{{.Name}}

	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
		<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>

{{.Name}}

{{.Description | markdownize}}

					{{template "NavResourceGroups" .ResourceGroups}}

						{{template "ResourceGroups" .ResourceGroups}}

`
<commit_msg>simplify header<commit_after>package iglo

import (
	"bitbucket.org/pkg/inflect"
	"bytes"
	bf "github.com/russross/blackfriday"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func markdownize(str string) template.HTML {
	b := bf.MarkdownCommon([]byte(str))
	return template.HTML(string(b))
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize":   inflect.Dasherize,
		"trim":        strings.Trim,
		"labelize":    labelize,
		"markdownize": markdownize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

func MarkdownToHTML(w io.Writer, r io.Reader) error {
	data, err := ParseMarkdown(r)
	if err != nil {
		return err
	}

	err = JSONToHTML(w, bytes.NewBuffer(data))
	if err != nil {
		return err
	}

	return nil
}

func JSONToHTML(w io.Writer, r io.Reader) error {
	api, err := ParseJSON(r)
	if err != nil {
		return err
	}

	err = HTML(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Responses"}}
	{{range .}}

			Response {{.Name}}
			{{if .Body}}

					SHOW

			{{end}}

			{{if .Headers}}
				{{range $index, $element := .Headers}}< {{$index}}: {{.Value}}
{{end}}
			{{end}}
			{{if .Body}}

{{.Body}}

			{{end}}

	{{end}}
{{end}}

{{define "Requests"}}
	{{range .}}

			Requests

				SHOW

			{{if .Headers}}
				{{range $index, $element := .Headers}}> {{$index}}: {{.Value}}
{{end}}
			{{end}}
			{{if .Body}}

{{.Body}}

			{{end}}

	{{end}}
{{end}}

{{define "Examples"}}
	{{range .}}
		{{template "Requests" .Requests}}
		{{template "Responses" .Responses}}
	{{end}}
{{end}}

{{define "Parameters"}}

	{{range $index, $element := .}}

{{$index}}

		{{if .Required}}
		{{else}}
			(required)
		{{end}}
		{{.Type}} {{.Description}}

	{{end}}

{{end}}

{{define "Resources"}}
{{range .}}
	{{$UriTemplate := .UriTemplate}}
	{{$Parameters := .Parameters}}

	{{range .Actions}}

			{{.Method}}
			{{$UriTemplate}}

			{{.Description | markdownize}}

			{{if $Parameters}}

Parameters

{{template "Parameters" $Parameters}}

			{{end}}
			{{if .Examples}}{{template "Examples" .Examples}}{{end}}

	{{end}}
{{end}}
{{end}}

{{define "ResourceGroups"}}
{{range .}}

{{.Name}}

{{.Description}}

				{{template "Resources" .Resources}}

{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}

{{.Name}}

	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
		<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>

{{.Name}}

{{.Description | markdownize}}

					{{template "NavResourceGroups" .ResourceGroups}}

						{{template "ResourceGroups" .ResourceGroups}}

`
<|endoftext|>


<commit_before>package protocol

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

// JSONIn is what's sent into the function
// All HTTP request headers should be set in env
type JSONIO struct {
	Headers    http.Header `json:"headers,omitempty"`
	Body       string      `json:"body"`
	StatusCode int         `json:"status_code,omitempty"`
}

// JSONProtocol converts stdin/stdout streams from HTTP into JSON format.
type JSONProtocol struct {
	in  io.Writer
	out io.Reader
}

func (p *JSONProtocol) IsStreamable() bool {
	return true
}

func (h *JSONProtocol) Dispatch(w io.Writer, req *http.Request) error {
	var body bytes.Buffer
	if req.Body != nil {
		var dest io.Writer = &body

		// TODO copy w/ ctx
		_, err := io.Copy(dest, req.Body)
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("error reader JSON object from request body: %s", err.Error()))
		}
		defer req.Body.Close()
	}

	// convert to JSON func format
	jin := &JSONIO{
		Headers: req.Header,
		Body:    body.String(),
	}
	b, err := json.Marshal(jin)
	if err != nil {
		// this shouldn't happen
		return respondWithError(
			w, fmt.Errorf("error marshalling JSONInput: %s", err.Error()))
	}
	// TODO: write in chunks, how big should chunk be?
	_, err = h.in.Write(b)
	if err != nil {
		return respondWithError(
			w, fmt.Errorf("error writing JSON object to function's STDIN: %s", err.Error()))
	}

	if rw, ok := w.(http.ResponseWriter); ok {
		// this has to be done for pulling out:
		// - status code
		// - body
		jout := new(JSONIO)
		dec := json.NewDecoder(h.out)
		if err := dec.Decode(jout); err != nil {
			return respondWithError(
				w, fmt.Errorf("unable to decode JSON response object: %s", err.Error()))
		}
		rw.WriteHeader(jout.StatusCode)
		_, err = rw.Write([]byte(jout.Body)) // TODO timeout
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("unable to write JSON response object: %s", err.Error()))
		}
	} else {
		// logs can just copy the full thing in there, headers and all.
		_, err = io.Copy(w, bufio.NewReader(h.out))
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("error reading function response: %s", err.Error()))
		}
	}
	return nil
}

func respondWithError(w io.Writer, err error) error {
	writeResponse(w, []byte(err.Error()), http.StatusInternalServerError)
	return err
}

func writeResponse(w io.Writer, b []byte, statusCode int) {
	if rw, ok := w.(http.ResponseWriter); ok {
		rw.WriteHeader(statusCode)
		_, err := rw.Write(b) // TODO timeout
		if err != nil {
			err = fmt.Errorf("unable to write JSON response object: %s", err.Error())
			respondWithError(w, err)
		}
	} else {
		// logs can just copy the full thing in there, headers and all.
		w.Write(b) // TODO timeout
	}
}
<commit_msg>Dismiss redundant function<commit_after>package protocol

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

// JSONIn is what's sent into the function
// All HTTP request headers should be set in env
type JSONIO struct {
	Headers    http.Header `json:"headers,omitempty"`
	Body       string      `json:"body"`
	StatusCode int         `json:"status_code,omitempty"`
}

// JSONProtocol converts stdin/stdout streams from HTTP into JSON format.
type JSONProtocol struct {
	in  io.Writer
	out io.Reader
}

func (p *JSONProtocol) IsStreamable() bool {
	return true
}

func (h *JSONProtocol) Dispatch(w io.Writer, req *http.Request) error {
	var body bytes.Buffer
	if req.Body != nil {
		var dest io.Writer = &body

		// TODO copy w/ ctx
		_, err := io.Copy(dest, req.Body)
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("error reader JSON object from request body: %s", err.Error()))
		}
		defer req.Body.Close()
	}

	// convert to JSON func format
	jin := &JSONIO{
		Headers: req.Header,
		Body:    body.String(),
	}
	b, err := json.Marshal(jin)
	if err != nil {
		// this shouldn't happen
		return respondWithError(
			w, fmt.Errorf("error marshalling JSONInput: %s", err.Error()))
	}
	// TODO: write in chunks, how big should chunk be?
	_, err = h.in.Write(b)
	if err != nil {
		return respondWithError(
			w, fmt.Errorf("error writing JSON object to function's STDIN: %s", err.Error()))
	}

	if rw, ok := w.(http.ResponseWriter); ok {
		// this has to be done for pulling out:
		// - status code
		// - body
		jout := new(JSONIO)
		dec := json.NewDecoder(h.out)
		if err := dec.Decode(jout); err != nil {
			return respondWithError(
				w, fmt.Errorf("unable to decode JSON response object: %s", err.Error()))
		}
		rw.WriteHeader(jout.StatusCode)
		_, err = rw.Write([]byte(jout.Body)) // TODO timeout
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("unable to write JSON response object: %s", err.Error()))
		}
	} else {
		// logs can just copy the full thing in there, headers and all.
		_, err = io.Copy(w, bufio.NewReader(h.out))
		if err != nil {
			return respondWithError(
				w, fmt.Errorf("error reading function response: %s", err.Error()))
		}
	}
	return nil
}

func respondWithError(w io.Writer, err error) error {
	errMsg := []byte(err.Error())
	statusCode := http.StatusInternalServerError
	if rw, ok := w.(http.ResponseWriter); ok {
		rw.WriteHeader(statusCode)
		rw.Write(errMsg)
	} else {
		// logs can just copy the full thing in there, headers and all.
		w.Write(errMsg)
	}

	return err
}
<|endoftext|>


<commit_before><commit_msg>detach v2.0.1<commit_after><|endoftext|>


<commit_before>// A command line tool for fragmenta which can be used to build and run websites
// this tool calls subcommands for most of the work, usually one command per file in this pkg
// See docs at http://godoc.org/github.com/fragmenta/fragmenta

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

const (
	// The version of this tool
	fragmentaVersion = "1.5.4"

	// Used for outputting console messages
	fragmentaDivider = "\n------\n"
)

// Modes used for setting the config used
const (
	ModeProduction  = "production"
	ModeDevelopment = "development"
	ModeTest        = "test"
)

var (
	// ConfigDevelopment holds the development config from fragmenta.json
	ConfigDevelopment map[string]string

	// ConfigProduction holds development config from fragmenta.json
	ConfigProduction map[string]string

	// ConfigTest holds the app test config from fragmenta.json
	ConfigTest map[string]string
)

// main - Parse the command line arguments and respond
func main() {

	log.SetFlags(log.Ltime)

	args := os.Args
	command := ""

	if len(args) > 1 {
		command = args[1]
	}

	// We should intelligently read project path depending on the command?
	// Or just assume we act on the current directory?
	// NB projectPath might be different from the path in config, which MUST be within a GOPATH
	// this is the local project path
	projectPath, err := filepath.Abs(".")
	if err != nil {
		log.Printf("Error getting path %s", err)
		return
	}

	// If this is a valid fragmenta project, try reading the config
	// NB we still run even if config fails,
	// as we want to at least try a build/run cycle to enable bootstrap
	if isValidProject(projectPath) {
		readConfig(projectPath)
	}

	switch command {

	case "new", "n":
		RunNew(args)

	case "version", "v":
		ShowVersion()

	case "help", "h", "wat", "?":
		ShowHelp(args)

	case "server", "s":
		if requireValidProject(projectPath) {
			RunServer(projectPath)
		}

	case "test", "t":
		if requireValidProject(projectPath) {
			// Remove fragmenta test from args list
			args = args[2:]
			RunTests(args)
		}

	case "build", "B":
		if requireValidProject(projectPath) {
			RunBuild(args)
		}

	case "generate", "g":
		if requireValidProject(projectPath) {
			RunGenerate(args)
		}

	case "migrate", "m":
		if requireValidProject(projectPath) {
			RunMigrate(args)
		}

	case "backup", "b":
		if requireValidProject(projectPath) {
			RunBackup(args)
		}

	case "restore", "r":
		if requireValidProject(projectPath) {
			RunRestore(args)
		}

	case "deploy", "d":
		if requireValidProject(projectPath) {
			RunDeploy(args)
		}

	default:
		if requireValidProject(projectPath) {
			RunServer(projectPath)
		} else {
			ShowHelp(args)
		}
	}

}

// ShowVersion shows the version of this tool
func ShowVersion() {
	helpString := fragmentaDivider
	helpString += fmt.Sprintf("Fragmenta version: %s", fragmentaVersion)
	helpString += fragmentaDivider
	log.Print(helpString)
}

// ShowHelp shows the help for this tool
func ShowHelp(args []string) {
	helpString := fragmentaDivider
	helpString += fmt.Sprintf("Fragmenta version: %s", fragmentaVersion)
	helpString += "\n  fragmenta version -> display version"
	helpString += "\n  fragmenta help -> display help"
	helpString += "\n  fragmenta new [app|cms|blog|URL] path/to/app -> creates a new app from the repository at URL at the path supplied"
	helpString += "\n  fragmenta -> builds and runs a fragmenta app"
	helpString += "\n  fragmenta server -> builds and runs a fragmenta app"
	helpString += "\n  fragmenta test  -> run tests"
	helpString += "\n  fragmenta migrate -> runs new sql migrations in db/migrate"
	helpString += "\n  fragmenta backup [development|production|test] -> backup the database to db/backup"
	helpString += "\n  fragmenta restore [development|production|test] -> backup the database from latest file in db/backup"
	helpString += "\n  fragmenta deploy [development|production|test] -> build and deploy using bin/deploy"
	helpString += "\n  fragmenta generate resource [name] [fieldname]:[fieldtype]* -> creates resource CRUD actions and views"
	helpString += "\n  fragmenta generate migration [name] -> creates a new named sql migration in db/migrate"

	helpString += fragmentaDivider
	log.Print(helpString)
}

// FIXME - move all instances of hardcoded paths out into optional app config variables
// Ideally we don't care about project structure apart from the load the fragmenta.json file

// serverName returns the name of our server file - TODO:read from config
func serverName() string {
	return "fragmenta-server" // for now, should use configs
}

func localServerPath(projectPath string) string {
	return fmt.Sprintf("%s/bin/%s-local", projectPath, serverName())
}

func serverPath(projectPath string) string {
	return fmt.Sprintf("%s/bin/%s", projectPath, serverName())
}

func serverCompilePath(projectPath string) string {
	return filepath.Join(projectPath, "server.go")
}

// Return the src to scan assets for compilation
// Can this be set within the project setup instead to avoid hardcoding here?
func srcPath(projectPath string) string {
	return projectPath + "src"
}

func publicPath(projectPath string) string {
	return projectPath + "public"
}

func configPath(projectPath string) string {
	return projectPath + "/secrets/fragmenta.json"
}

func secretsPath(projectPath string) string {
	return projectPath + "/secrets"
}

func templatesPath() string {
	return os.ExpandEnv("$GOPATH/src/github.com/fragmenta/fragmenta/templates")
}

// RunServer runs the server
func RunServer(projectPath string) {
	ShowVersion()

	killServer()

	log.Println("Building server...")
	err := buildServer(localServerPath(projectPath), nil)

	if err != nil {
		log.Printf("Error building server: %s", err)
		return
	}

	log.Println("Launching server...")
	cmd := exec.Command(localServerPath(projectPath))
	stdout, _ := cmd.StdoutPipe()
	stderr, _ := cmd.StderrPipe()
	err = cmd.Start()
	if err != nil {
		log.Println(err)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()

}

// killServer kills the server with a unix command - FIXME:Windows
func killServer() {
	runCommand("killall", "-9", serverName())
}

// runCommand runs a command with exec.Command
func runCommand(command string, args ...string) ([]byte, error) {

	cmd := exec.Command(command, args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return output, err
	}

	return output, nil
}

// requireValidProject returns true if we have a valid project at projectPath
func requireValidProject(projectPath string) bool {
	if isValidProject(projectPath) {
		return true
	}

	log.Printf("\nNo fragmenta project found at this path\n")
	return false

}

// isValidProject returns true if this is a valid fragmenta project (checks for server.go file and config file)
func isValidProject(projectPath string) bool {

	// Make sure we have server.go at root of this dir
	_, err := os.Stat(serverCompilePath(projectPath))
	if err != nil {
		return false
	}

	return true
}

// fileExists returns true if this file exists
func fileExists(p string) bool {
	_, err := os.Stat(p)
	if err != nil && os.IsNotExist(err) {
		return false
	}

	return true
}

// FIXME - use new config pkg to load this instead

// readConfig reads our config file and set up the server accordingly
func readConfig(projectPath string) error {
	configPath := configPath(projectPath)

	// Read the config json file
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		log.Printf("Error opening config at %s\n%s", configPath, err)
		return err
	}

	var data map[string]map[string]string
	err = json.Unmarshal(file, &data)
	if err != nil {
		log.Printf("Error parsing config %s %v", configPath, err)
		return err
	}

	ConfigDevelopment = data["development"]
	ConfigProduction = data["production"]
	ConfigTest = data["test"]

	return nil
}
<commit_msg>Bump version to 1.5.6<commit_after>// A command line tool for fragmenta which can be used to build and run websites
// this tool calls subcommands for most of the work, usually one command per file in this pkg
// See docs at http://godoc.org/github.com/fragmenta/fragmenta

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

const (
	// The version of this tool
	fragmentaVersion = "1.5.6"

	// Used for outputting console messages
	fragmentaDivider = "\n------\n"
)

// Modes used for setting the config used
const (
	ModeProduction  = "production"
	ModeDevelopment = "development"
	ModeTest        = "test"
)

var (
	// ConfigDevelopment holds the development config from fragmenta.json
	ConfigDevelopment map[string]string

	// ConfigProduction holds development config from fragmenta.json
	ConfigProduction map[string]string

	// ConfigTest holds the app test config from fragmenta.json
	ConfigTest map[string]string
)

// main - Parse the command line arguments and respond
func main() {

	log.SetFlags(log.Ltime)

	args := os.Args
	command := ""

	if len(args) > 1 {
		command = args[1]
	}

	// We should intelligently read project path depending on the command?
	// Or just assume we act on the current directory?
	// NB projectPath might be different from the path in config, which MUST be within a GOPATH
	// this is the local project path
	projectPath, err := filepath.Abs(".")
	if err != nil {
		log.Printf("Error getting path %s", err)
		return
	}

	// If this is a valid fragmenta project, try reading the config
	// NB we still run even if config fails,
	// as we want to at least try a build/run cycle to enable bootstrap
	if isValidProject(projectPath) {
		readConfig(projectPath)
	}

	switch command {

	case "new", "n":
		RunNew(args)

	case "version", "v":
		ShowVersion()

	case "help", "h", "wat", "?":
		ShowHelp(args)

	case "server", "s":
		if requireValidProject(projectPath) {
			RunServer(projectPath)
		}

	case "test", "t":
		if requireValidProject(projectPath) {
			// Remove fragmenta test from args list
			args = args[2:]
			RunTests(args)
		}

	case "build", "B":
		if requireValidProject(projectPath) {
			RunBuild(args)
		}

	case "generate", "g":
		if requireValidProject(projectPath) {
			RunGenerate(args)
		}

	case "migrate", "m":
		if requireValidProject(projectPath) {
			RunMigrate(args)
		}

	case "backup", "b":
		if requireValidProject(projectPath) {
			RunBackup(args)
		}

	case "restore", "r":
		if requireValidProject(projectPath) {
			RunRestore(args)
		}

	case "deploy", "d":
		if requireValidProject(projectPath) {
			RunDeploy(args)
		}

	default:
		if requireValidProject(projectPath) {
			RunServer(projectPath)
		} else {
			ShowHelp(args)
		}
	}

}

// ShowVersion shows the version of this tool
func ShowVersion() {
	helpString := fragmentaDivider
	helpString += fmt.Sprintf("Fragmenta version: %s", fragmentaVersion)
	helpString += fragmentaDivider
	log.Print(helpString)
}

// ShowHelp shows the help for this tool
func ShowHelp(args []string) {
	helpString := fragmentaDivider
	helpString += fmt.Sprintf("Fragmenta version: %s", fragmentaVersion)
	helpString += "\n  fragmenta version -> display version"
	helpString += "\n  fragmenta help -> display help"
	helpString += "\n  fragmenta new [app|cms|blog|URL] path/to/app -> creates a new app from the repository at URL at the path supplied"
	helpString += "\n  fragmenta -> builds and runs a fragmenta app"
	helpString += "\n  fragmenta server -> builds and runs a fragmenta app"
	helpString += "\n  fragmenta test  -> run tests"
	helpString += "\n  fragmenta migrate -> runs new sql migrations in db/migrate"
	helpString += "\n  fragmenta backup [development|production|test] -> backup the database to db/backup"
	helpString += "\n  fragmenta restore [development|production|test] -> backup the database from latest file in db/backup"
	helpString += "\n  fragmenta deploy [development|production|test] -> build and deploy using bin/deploy"
	helpString += "\n  fragmenta generate resource [name] [fieldname]:[fieldtype]* -> creates resource CRUD actions and views"
	helpString += "\n  fragmenta generate migration [name] -> creates a new named sql migration in db/migrate"

	helpString += fragmentaDivider
	log.Print(helpString)
}

// FIXME - move all instances of hardcoded paths out into optional app config variables
// Ideally we don't care about project structure apart from the load the fragmenta.json file

// serverName returns the name of our server file - TODO:read from config
func serverName() string {
	return "fragmenta-server" // for now, should use configs
}

func localServerPath(projectPath string) string {
	return fmt.Sprintf("%s/bin/%s-local", projectPath, serverName())
}

func serverPath(projectPath string) string {
	return fmt.Sprintf("%s/bin/%s", projectPath, serverName())
}

func serverCompilePath(projectPath string) string {
	return filepath.Join(projectPath, "server.go")
}

// Return the src to scan assets for compilation
// Can this be set within the project setup instead to avoid hardcoding here?
func srcPath(projectPath string) string {
	return projectPath + "src"
}

func publicPath(projectPath string) string {
	return projectPath + "public"
}

func configPath(projectPath string) string {
	return projectPath + "/secrets/fragmenta.json"
}

func secretsPath(projectPath string) string {
	return projectPath + "/secrets"
}

func templatesPath() string {
	return os.ExpandEnv("$GOPATH/src/github.com/fragmenta/fragmenta/templates")
}

// RunServer runs the server
func RunServer(projectPath string) {
	ShowVersion()

	killServer()

	log.Println("Building server...")
	err := buildServer(localServerPath(projectPath), nil)

	if err != nil {
		log.Printf("Error building server: %s", err)
		return
	}

	log.Println("Launching server...")
	cmd := exec.Command(localServerPath(projectPath))
	stdout, _ := cmd.StdoutPipe()
	stderr, _ := cmd.StderrPipe()
	err = cmd.Start()
	if err != nil {
		log.Println(err)
	}
	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stderr, stderr)
	cmd.Wait()

}

// killServer kills the server with a unix command - FIXME:Windows
func killServer() {
	runCommand("killall", "-9", serverName())
}

// runCommand runs a command with exec.Command
func runCommand(command string, args ...string) ([]byte, error) {

	cmd := exec.Command(command, args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return output, err
	}

	return output, nil
}

// requireValidProject returns true if we have a valid project at projectPath
func requireValidProject(projectPath string) bool {
	if isValidProject(projectPath) {
		return true
	}

	log.Printf("\nNo fragmenta project found at this path\n")
	return false

}

// isValidProject returns true if this is a valid fragmenta project (checks for server.go file and config file)
func isValidProject(projectPath string) bool {

	// Make sure we have server.go at root of this dir
	_, err := os.Stat(serverCompilePath(projectPath))
	if err != nil {
		return false
	}

	return true
}

// fileExists returns true if this file exists
func fileExists(p string) bool {
	_, err := os.Stat(p)
	if err != nil && os.IsNotExist(err) {
		return false
	}

	return true
}

// FIXME - use new config pkg to load this instead

// readConfig reads our config file and set up the server accordingly
func readConfig(projectPath string) error {
	configPath := configPath(projectPath)

	// Read the config json file
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		log.Printf("Error opening config at %s\n%s", configPath, err)
		return err
	}

	var data map[string]map[string]string
	err = json.Unmarshal(file, &data)
	if err != nil {
		log.Printf("Error parsing config %s %v", configPath, err)
		return err
	}

	ConfigDevelopment = data["development"]
	ConfigProduction = data["production"]
	ConfigTest = data["test"]

	return nil
}
<|endoftext|>


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

package main

import (
	"bytes"
	"database/sql"
	"encoding/binary"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/fiorix/go-redis/redis"
	"github.com/fiorix/go-web/httpxtra"
	_ "github.com/mattn/go-sqlite3"
)

const (
	// API limits
	maxrequests = 10000
	expire      = 3600

	// Server settings
	debug      = true
	addr       = ":8080"            // ip:port or /path/to/unix.sock
	redisaddr  = "127.0.0.1:6379"   // redis server
	staticpath = "./static"         // public website
	ipdb       = "./db/ipdb.sqlite" // geoip database
)

func main() {
	http.Handle("/", http.FileServer(http.Dir(staticpath)))
	h := GeoipHandler()
	http.HandleFunc("/csv/", h)
	http.HandleFunc("/xml/", h)
	http.HandleFunc("/json/", h)
	server := http.Server{
		Addr:         addr,
		Handler:      httpxtra.Handler{Logger: logger},
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
	}
	log.Println("FreeGeoIP server starting")
	if e := httpxtra.ListenAndServe(server); e != nil {
		log.Println(e.Error())
	}
}

func logger(r *http.Request, created time.Time, status, bytes int) {
	//fmt.Println(httpxtra.ApacheCommonLog(r, created, status, bytes))
	log.Printf("HTTP %d %s %s (%s) :: %s",
		status,
		r.Method,
		r.URL.Path,
		r.RemoteAddr,
		time.Since(created))
}

// GeoipHandler handles GET on /csv, /xml and /json.
func GeoipHandler() http.HandlerFunc {
	db, err := sql.Open("sqlite3", ipdb)
	if err != nil {
		panic(err)
	}
	rc := redis.New(redisaddr)
	return func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			w.Header().Set("Access-Control-Allow-Origin", "*")
		case "OPTIONS":
			w.Header().Set("Access-Control-Allow-Origin", "*")
			w.Header().Set("Content-Type", "text/plain")
			w.Header().Set("Access-Control-Allow-Methods", "GET")
			w.Header().Set("Access-Control-Allow-Headers",
				"X-Requested-With")
			return
		default:
			w.Header().Set("Allow", "GET, OPTIONS")
			http.Error(w, http.StatusText(405), 405)
			return
		}
		// GET
		// Check quota
		var ipkey string
		if ip, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
			ipkey = r.RemoteAddr // support for XHeaders
		} else {
			ipkey = ip
		}
		if qcs, err := rc.Get(ipkey); err != nil {
			http.Error(w, http.StatusText(503), 503) // redis down
			return
		} else if qcs == "" {
			if err := rc.Set(r.RemoteAddr, "1"); err == nil {
				rc.Expire(r.RemoteAddr, expire)
			}
		} else if qc, _ := strconv.Atoi(qcs); qc < maxrequests {
			rc.Incr(r.RemoteAddr)
		} else {
			// Out of quota, soz :(
			http.Error(w, http.StatusText(403), 403)
			return
		}
		// Parse URL and build the query.
		var ip string
		a := strings.SplitN(r.URL.Path, "/", 3)
		if len(a) == 3 && a[2] != "" {
			// e.g. /csv/google.com
			addrs, err := net.LookupHost(a[2])
			if err != nil {
				http.Error(w, http.StatusText(404), 404)
				return
			}
			ip = addrs[0]
		} else {
			ip = ipkey
		}
		geoip, err := GeoipLookup(db, ip)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		switch a[1] {
		case "csv":
			w.Header().Set("Content-Type", "application/csv")
			fmt.Fprintf(w, `"%s","%s","%s","%s","%s","%s",`+
				`"%s","%0.4f","%0.4f","%s","%s"`+"\r\n",
				geoip.Ip,
				geoip.CountryCode, geoip.CountryName,
				geoip.RegionCode, geoip.RegionName,
				geoip.CityName, geoip.ZipCode,
				geoip.Latitude, geoip.Longitude,
				geoip.MetroCode, geoip.AreaCode)
		case "json":
			resp, err := json.Marshal(geoip)
			if err != nil {
				if debug {
					log.Println("JSON error:", err.Error())
				}
				http.NotFound(w, r)
				return
			}
			callback := r.FormValue("callback")
			if callback != "" {
				w.Header().Set("Content-Type", "text/javascript")
				fmt.Fprintf(w, "%s(%s);\n", callback, resp)
			} else {
				w.Header().Set("Content-Type", "application/json")
				fmt.Fprintf(w, "%s", resp)
			}
		case "xml":
			w.Header().Set("Content-Type", "application/xml")
			resp, err := xml.MarshalIndent(geoip, "", " ")
			if err != nil {
				if debug {
					log.Println("XML error:", err.Error())
				}
				http.Error(w, http.StatusText(500), 500)
				return
			}
			fmt.Fprintf(w, xml.Header+"%s\n", resp)
		}
	}
}

func GeoipLookup(db *sql.DB, ip string) (*GeoIP, error) {
	IP := net.ParseIP(ip)
	reserved := false
	for _, net := range reservedIPs {
		if net.Contains(IP) {
			reserved = true
			break
		}
	}
	geoip := GeoIP{Ip: ip}
	if reserved {
		geoip.CountryCode = "RD"
		geoip.CountryName = "Reserved"
	} else {
		q := `SELECT
		  city_location.country_code, country_blocks.country_name,
		  city_location.region_code, region_names.region_name,
		  city_location.city_name, city_location.postal_code,
		  city_location.latitude, city_location.longitude,
		  city_location.metro_code, city_location.area_code
		FROM city_blocks
		  NATURAL JOIN city_location
		  INNER JOIN country_blocks ON
		    city_location.country_code = country_blocks.country_code
		  LEFT OUTER JOIN region_names ON
		    city_location.country_code = region_names.country_code
		    AND
		    city_location.region_code = region_names.region_code
		WHERE city_blocks.ip_start <= ?
		ORDER BY city_blocks.ip_start DESC LIMIT 1`
		stmt, err := db.Prepare(q)
		if err != nil {
			if debug {
				log.Println("[debug] SQLite", err.Error())
			}
			return nil, err
		}
		defer stmt.Close()
		var uintIP uint32
		b := bytes.NewBuffer(IP.To4())
		binary.Read(b, binary.BigEndian, &uintIP)
		err = stmt.QueryRow(uintIP).Scan(
			&geoip.CountryCode,
			&geoip.CountryName,
			&geoip.RegionCode,
			&geoip.RegionName,
			&geoip.CityName,
			&geoip.ZipCode,
			&geoip.Latitude,
			&geoip.Longitude,
			&geoip.MetroCode,
			&geoip.AreaCode)
		if err != nil {
			return nil, err
		}
	}
	return &geoip, nil
}

type GeoIP struct {
	XMLName     xml.Name `json:"-" xml:"Response"`
	Ip          string   `json:"ip"`
	CountryCode string   `json:"country_code"`
	CountryName string   `json:"country_name"`
	RegionCode  string   `json:"region_code"`
	RegionName  string   `json:"region_name"`
	CityName    string   `json:"city" xml:"City"`
	ZipCode     string   `json:"zipcode"`
	Latitude    float32  `json:"latitude"`
	Longitude   float32  `json:"longitude"`
	MetroCode   string   `json:"metro_code"`
	AreaCode    string   `json:"areacode"`
}

// http://en.wikipedia.org/wiki/Reserved_IP_addresses
var reservedIPs = []net.IPNet{
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 192, 0, 0)},
	{net.IPv4(127, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(169, 254, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)},
	{net.IPv4(192, 0, 0, 0), net.IPv4Mask(255, 255, 255, 248)},
	{net.IPv4(192, 0, 2, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 88, 99, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(198, 18, 0, 0), net.IPv4Mask(255, 254, 0, 0)},
	{net.IPv4(198, 51, 100, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(203, 0, 113, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(224, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(240, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(255, 255, 255, 255), net.IPv4Mask(255, 255, 255, 255)},
}
<commit_msg>bugfix in quota<commit_after>// Copyright 2013 Alexandre Fiori
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"bytes"
	"database/sql"
	"encoding/binary"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/fiorix/go-redis/redis"
	"github.com/fiorix/go-web/httpxtra"
	_ "github.com/mattn/go-sqlite3"
)

const (
	// API limits
	maxrequests = 10000
	expire      = 3600

	// Server settings
	debug      = true
	addr       = ":8080"            // ip:port or /path/to/unix.sock
	redisaddr  = "127.0.0.1:6379"   // redis server
	staticpath = "./static"         // public website
	ipdb       = "./db/ipdb.sqlite" // geoip database
)

func main() {
	http.Handle("/", http.FileServer(http.Dir(staticpath)))
	h := GeoipHandler()
	http.HandleFunc("/csv/", h)
	http.HandleFunc("/xml/", h)
	http.HandleFunc("/json/", h)
	server := http.Server{
		Addr:         addr,
		Handler:      httpxtra.Handler{Logger: logger},
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
	}
	log.Println("FreeGeoIP server starting")
	if e := httpxtra.ListenAndServe(server); e != nil {
		log.Println(e.Error())
	}
}

func logger(r *http.Request, created time.Time, status, bytes int) {
	//fmt.Println(httpxtra.ApacheCommonLog(r, created, status, bytes))
	log.Printf("HTTP %d %s %s (%s) :: %s",
		status,
		r.Method,
		r.URL.Path,
		r.RemoteAddr,
		time.Since(created))
}

// GeoipHandler handles GET on /csv, /xml and /json.
func GeoipHandler() http.HandlerFunc {
	db, err := sql.Open("sqlite3", ipdb)
	if err != nil {
		panic(err)
	}
	rc := redis.New(redisaddr)
	return func(w http.ResponseWriter, r *http.Request) {
		switch r.Method {
		case "GET":
			w.Header().Set("Access-Control-Allow-Origin", "*")
		case "OPTIONS":
			w.Header().Set("Access-Control-Allow-Origin", "*")
			w.Header().Set("Content-Type", "text/plain")
			w.Header().Set("Access-Control-Allow-Methods", "GET")
			w.Header().Set("Access-Control-Allow-Headers",
				"X-Requested-With")
			return
		default:
			w.Header().Set("Allow", "GET, OPTIONS")
			http.Error(w, http.StatusText(405), 405)
			return
		}
		// GET
		// Check quota
		var ipkey string
		if ip, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
			ipkey = r.RemoteAddr // support for XHeaders
		} else {
			ipkey = ip
		}
		if qcs, err := rc.Get(ipkey); err != nil {
			http.Error(w, http.StatusText(503), 503) // redis down
			return
		} else if qcs == "" {
			if err := rc.Set(ipkey, "1"); err == nil {
				rc.Expire(ipkey, expire)
			}
		} else if qc, _ := strconv.Atoi(qcs); qc < maxrequests {
			rc.Incr(ipkey)
		} else {
			// Out of quota, soz :(
			http.Error(w, http.StatusText(403), 403)
			return
		}
		// Parse URL and build the query.
		var ip string
		a := strings.SplitN(r.URL.Path, "/", 3)
		if len(a) == 3 && a[2] != "" {
			// e.g. /csv/google.com
			addrs, err := net.LookupHost(a[2])
			if err != nil {
				http.Error(w, http.StatusText(404), 404)
				return
			}
			ip = addrs[0]
		} else {
			ip = ipkey
		}
		geoip, err := GeoipLookup(db, ip)
		if err != nil {
			http.NotFound(w, r)
			return
		}
		switch a[1] {
		case "csv":
			w.Header().Set("Content-Type", "application/csv")
			fmt.Fprintf(w, `"%s","%s","%s","%s","%s","%s",`+
				`"%s","%0.4f","%0.4f","%s","%s"`+"\r\n",
				geoip.Ip,
				geoip.CountryCode, geoip.CountryName,
				geoip.RegionCode, geoip.RegionName,
				geoip.CityName, geoip.ZipCode,
				geoip.Latitude, geoip.Longitude,
				geoip.MetroCode, geoip.AreaCode)
		case "json":
			resp, err := json.Marshal(geoip)
			if err != nil {
				if debug {
					log.Println("JSON error:", err.Error())
				}
				http.NotFound(w, r)
				return
			}
			callback := r.FormValue("callback")
			if callback != "" {
				w.Header().Set("Content-Type", "text/javascript")
				fmt.Fprintf(w, "%s(%s);\n", callback, resp)
			} else {
				w.Header().Set("Content-Type", "application/json")
				fmt.Fprintf(w, "%s", resp)
			}
		case "xml":
			w.Header().Set("Content-Type", "application/xml")
			resp, err := xml.MarshalIndent(geoip, "", " ")
			if err != nil {
				if debug {
					log.Println("XML error:", err.Error())
				}
				http.Error(w, http.StatusText(500), 500)
				return
			}
			fmt.Fprintf(w, xml.Header+"%s\n", resp)
		}
	}
}

func GeoipLookup(db *sql.DB, ip string) (*GeoIP, error) {
	IP := net.ParseIP(ip)
	reserved := false
	for _, net := range reservedIPs {
		if net.Contains(IP) {
			reserved = true
			break
		}
	}
	geoip := GeoIP{Ip: ip}
	if reserved {
		geoip.CountryCode = "RD"
		geoip.CountryName = "Reserved"
	} else {
		q := `SELECT
		  city_location.country_code, country_blocks.country_name,
		  city_location.region_code, region_names.region_name,
		  city_location.city_name, city_location.postal_code,
		  city_location.latitude, city_location.longitude,
		  city_location.metro_code, city_location.area_code
		FROM city_blocks
		  NATURAL JOIN city_location
		  INNER JOIN country_blocks ON
		    city_location.country_code = country_blocks.country_code
		  LEFT OUTER JOIN region_names ON
		    city_location.country_code = region_names.country_code
		    AND
		    city_location.region_code = region_names.region_code
		WHERE city_blocks.ip_start <= ?
		ORDER BY city_blocks.ip_start DESC LIMIT 1`
		stmt, err := db.Prepare(q)
		if err != nil {
			if debug {
				log.Println("[debug] SQLite", err.Error())
			}
			return nil, err
		}
		defer stmt.Close()
		var uintIP uint32
		b := bytes.NewBuffer(IP.To4())
		binary.Read(b, binary.BigEndian, &uintIP)
		err = stmt.QueryRow(uintIP).Scan(
			&geoip.CountryCode,
			&geoip.CountryName,
			&geoip.RegionCode,
			&geoip.RegionName,
			&geoip.CityName,
			&geoip.ZipCode,
			&geoip.Latitude,
			&geoip.Longitude,
			&geoip.MetroCode,
			&geoip.AreaCode)
		if err != nil {
			return nil, err
		}
	}
	return &geoip, nil
}

type GeoIP struct {
	XMLName     xml.Name `json:"-" xml:"Response"`
	Ip          string   `json:"ip"`
	CountryCode string   `json:"country_code"`
	CountryName string   `json:"country_name"`
	RegionCode  string   `json:"region_code"`
	RegionName  string   `json:"region_name"`
	CityName    string   `json:"city" xml:"City"`
	ZipCode     string   `json:"zipcode"`
	Latitude    float32  `json:"latitude"`
	Longitude   float32  `json:"longitude"`
	MetroCode   string   `json:"metro_code"`
	AreaCode    string   `json:"areacode"`
}

// http://en.wikipedia.org/wiki/Reserved_IP_addresses
var reservedIPs = []net.IPNet{
	{net.IPv4(0, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(10, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(100, 64, 0, 0), net.IPv4Mask(255, 192, 0, 0)},
	{net.IPv4(127, 0, 0, 0), net.IPv4Mask(255, 0, 0, 0)},
	{net.IPv4(169, 254, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(172, 16, 0, 0), net.IPv4Mask(255, 240, 0, 0)},
	{net.IPv4(192, 0, 0, 0), net.IPv4Mask(255, 255, 255, 248)},
	{net.IPv4(192, 0, 2, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 88, 99, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(192, 168, 0, 0), net.IPv4Mask(255, 255, 0, 0)},
	{net.IPv4(198, 18, 0, 0), net.IPv4Mask(255, 254, 0, 0)},
	{net.IPv4(198, 51, 100, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(203, 0, 113, 0), net.IPv4Mask(255, 255, 255, 0)},
	{net.IPv4(224, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(240, 0, 0, 0), net.IPv4Mask(240, 0, 0, 0)},
	{net.IPv4(255, 255, 255, 255), net.IPv4Mask(255, 255, 255, 255)},
}
<|endoftext|>


<commit_before>package inventory

import (
	"sync"

	"chunkymonkey/proto"
	"chunkymonkey/slot"
	. "chunkymonkey/types"
)

type IInventorySubscriber interface {
	SlotUpdate(slot *slot.Slot, slotId SlotId)
}

type Inventory struct {
	lock        sync.Mutex
	slots       []slot.Slot
	subscribers map[IInventorySubscriber]bool
}

func (inv *Inventory) Init(size int) {
	inv.slots = make([]slot.Slot, size)
	for i := range inv.slots {
		inv.slots[i].Init()
	}
	inv.subscribers = make(map[IInventorySubscriber]bool)
}

func (inv *Inventory) AddSubscriber(subscriber IInventorySubscriber) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	inv.subscribers[subscriber] = true
}

func (inv *Inventory) RemoveSubscriber(subscriber IInventorySubscriber) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	inv.subscribers[subscriber] = false, false
}

// StandardClick takes the default actions upon a click event from a player.
func (inv *Inventory) StandardClick(slotId SlotId, cursor *slot.Slot, rightClick bool, shiftClick bool) (accepted bool) {
	inv.lock.Lock()
	defer inv.lock.Unlock()

	if slotId < 0 || int(slotId) > len(inv.slots) {
		return false
	}

	clickedSlot := &inv.slots[slotId]

	// Apply the change.
	if cursor.Count == 0 {
		if rightClick {
			accepted = clickedSlot.Split(cursor)
		} else {
			accepted = clickedSlot.Swap(cursor)
		}
	} else {
		if rightClick {
			accepted = clickedSlot.AddOne(cursor)
		} else {
			accepted = clickedSlot.Add(cursor)
		}

		if !accepted {
			accepted = clickedSlot.Swap(cursor)
		}
	}

	// We send slot updates in case we have custom max counts that differ
	// from the client's idea.
	inv.slotUpdate(clickedSlot, slotId)

	return
}

// PutItem attempts to put the given item into the inventory.
func (inv *Inventory) PutItem(item *slot.Slot) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	// TODO optimize this algorithm, maybe by maintaining a map of non-full
	// slots containing an item of various item type IDs. Additionally, it
	// should prefer to put stackable items into stacks of the same type,
	// rather than in empty slots.
	for slotIndex := range inv.slots {
		if item.Count <= 0 {
			break
		}
		slot := &inv.slots[slotIndex]
		if slot.ItemType == nil || slot.ItemType == item.ItemType {
			if slot.Add(item) {
				inv.slotUpdate(slot, SlotId(slotIndex))
			}
		}
	}
	return
}

// WriteProtoSlots stores into the slots parameter the proto version of the
// item data in the inventory.
// Precondition: len(slots) == len(inv.slots)
func (inv *Inventory) writeProtoSlots(slots []proto.WindowSlot) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	for i := range inv.slots {
		src := &inv.slots[i]
		itemTypeId := ItemTypeIdNull
		if src.ItemType != nil {
			itemTypeId = src.ItemType.Id
		}
		slots[i] = proto.WindowSlot {
			ItemTypeId: itemTypeId,
			Count: src.Count,
			Data: src.Data,
		}
	}
}

// Send message about the slot change to the relevant places.
func (inv *Inventory) slotUpdate(slot *slot.Slot, slotId SlotId) {
	for subscriber := range inv.subscribers {
		subscriber.SlotUpdate(slot, slotId)
	}
}
<commit_msg>Minor Gofmt run.<commit_after>package inventory

import (
	"sync"

	"chunkymonkey/proto"
	"chunkymonkey/slot"
	. "chunkymonkey/types"
)

type IInventorySubscriber interface {
	SlotUpdate(slot *slot.Slot, slotId SlotId)
}

type Inventory struct {
	lock        sync.Mutex
	slots       []slot.Slot
	subscribers map[IInventorySubscriber]bool
}

func (inv *Inventory) Init(size int) {
	inv.slots = make([]slot.Slot, size)
	for i := range inv.slots {
		inv.slots[i].Init()
	}
	inv.subscribers = make(map[IInventorySubscriber]bool)
}

func (inv *Inventory) AddSubscriber(subscriber IInventorySubscriber) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	inv.subscribers[subscriber] = true
}

func (inv *Inventory) RemoveSubscriber(subscriber IInventorySubscriber) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	inv.subscribers[subscriber] = false, false
}

// StandardClick takes the default actions upon a click event from a player.
func (inv *Inventory) StandardClick(slotId SlotId, cursor *slot.Slot, rightClick bool, shiftClick bool) (accepted bool) {
	inv.lock.Lock()
	defer inv.lock.Unlock()

	if slotId < 0 || int(slotId) > len(inv.slots) {
		return false
	}

	clickedSlot := &inv.slots[slotId]

	// Apply the change.
	if cursor.Count == 0 {
		if rightClick {
			accepted = clickedSlot.Split(cursor)
		} else {
			accepted = clickedSlot.Swap(cursor)
		}
	} else {
		if rightClick {
			accepted = clickedSlot.AddOne(cursor)
		} else {
			accepted = clickedSlot.Add(cursor)
		}

		if !accepted {
			accepted = clickedSlot.Swap(cursor)
		}
	}

	// We send slot updates in case we have custom max counts that differ
	// from the client's idea.
	inv.slotUpdate(clickedSlot, slotId)

	return
}

// PutItem attempts to put the given item into the inventory.
func (inv *Inventory) PutItem(item *slot.Slot) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	// TODO optimize this algorithm, maybe by maintaining a map of non-full
	// slots containing an item of various item type IDs. Additionally, it
	// should prefer to put stackable items into stacks of the same type,
	// rather than in empty slots.
	for slotIndex := range inv.slots {
		if item.Count <= 0 {
			break
		}
		slot := &inv.slots[slotIndex]
		if slot.ItemType == nil || slot.ItemType == item.ItemType {
			if slot.Add(item) {
				inv.slotUpdate(slot, SlotId(slotIndex))
			}
		}
	}
	return
}

// WriteProtoSlots stores into the slots parameter the proto version of the
// item data in the inventory.
// Precondition: len(slots) == len(inv.slots)
func (inv *Inventory) writeProtoSlots(slots []proto.WindowSlot) {
	inv.lock.Lock()
	defer inv.lock.Unlock()
	for i := range inv.slots {
		src := &inv.slots[i]
		itemTypeId := ItemTypeIdNull
		if src.ItemType != nil {
			itemTypeId = src.ItemType.Id
		}
		slots[i] = proto.WindowSlot{
			ItemTypeId: itemTypeId,
			Count:      src.Count,
			Data:       src.Data,
		}
	}
}

// Send message about the slot change to the relevant places.
func (inv *Inventory) slotUpdate(slot *slot.Slot, slotId SlotId) {
	for subscriber := range inv.subscribers {
		subscriber.SlotUpdate(slot, slotId)
	}
}
<|endoftext|>


<commit_before>package handlers

import (
	"net/http"

	"github.com/danielkrainas/gobag/context"
	"github.com/gorilla/mux"

	"github.com/danielkrainas/shex/api/v1"
	"github.com/danielkrainas/shex/registry/actions"
)

const ServerVersionHeader = "Shex-Registry-Version"
const ApiVersionHeader = "Shex-Api-Version"
const ApiVersion = "1"

type Api struct {
	router *mux.Router
}

func NewApi(actionPack actions.Pack) (*Api, error) {
	api := &Api{
		router: v1.RouterWithPrefix(""),
	}

	api.register(v1.RouteNameBase, Base)

	return api, nil
}

func (api *Api) register(routeName string, dispatch http.HandlerFunc) {
	api.router.GetRoute(routeName).Handler(api.dispatcher(dispatch))
}

func (api *Api) dispatcher(dispatch http.HandlerFunc) http.Handler {
	return http.Handler(dispatch)
}

func (api *Api) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	w.Header().Add(ServerVersionHeader, acontext.GetVersion(r.Context()))
	w.Header().Add(ApiVersionHeader, ApiVersion)
	api.router.ServeHTTP(w, r)
}

/* API endpoint
app.post('/profiles/:user/:profileId', function (req, res) {
	console.log('profile posted:');
	console.log(JSON.stringify(req.body, null, 4));
	res.send('1');// return current version number of profile
});

app.head('/profiles/:user/:profileId', function (req, res) {
	//If-Modified-Since: version
});

app.get('/profiles/:user/:profileId', function (req, res) {
	var name = req.params.user + '/' + req.params.profileId;
	console.log('profile request:', name);
	res.json({
		rev: 1,
		name: name,
		mods: {},
	});
});

app.get('/mods/:user/:mod/v', function (req, res) {
	res.json(['0.1.8', '1.0.0']);
});

app.get('/mods/:user/:mod/v/:version/meta', function (req, res) {
	if (req.params.version === 'latest') {
		req.params.version = '1.0.0';
	}

	console.info('params ', req.params);
	var result = {
		name: req.params.user + '/' + req.params.mod,
		version: req.params.version
	};

	console.info('meta ', result);
	res.json(result);
});

app.get('/mods/:user/v/:mod/:version', function (req, res) {
	if (req.params.version === 'latest') {
		req.params.version = '1.0.0';
	}

	console.info('params ', req.params);

	res.sendFile(path.join(__dirname, '/candyland2.smod'), function (err) {
		if (err) {
			console.error(err);
			return;
		}
	});
});*/
<commit_msg>wire in mods route<commit_after>package handlers

import (
	"net/http"

	"github.com/danielkrainas/gobag/context"
	"github.com/gorilla/mux"

	"github.com/danielkrainas/shex/api/v1"
	"github.com/danielkrainas/shex/registry/actions"
)

const ServerVersionHeader = "Shex-Registry-Version"
const ApiVersionHeader = "Shex-Api-Version"
const ApiVersion = "1"

type Api struct {
	router *mux.Router
}

func NewApi(actionPack actions.Pack) (*Api, error) {
	api := &Api{
		router: v1.RouterWithPrefix(""),
	}

	api.register(v1.RouteNameBase, Base)
	api.register(v1.RouteNameMods, Mods(actionPack))

	return api, nil
}

func (api *Api) register(routeName string, dispatch http.HandlerFunc) {
	api.router.GetRoute(routeName).Handler(api.dispatcher(dispatch))
}

func (api *Api) dispatcher(dispatch http.HandlerFunc) http.Handler {
	return http.Handler(dispatch)
}

func (api *Api) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()

	w.Header().Add(ServerVersionHeader, acontext.GetVersion(r.Context()))
	w.Header().Add(ApiVersionHeader, ApiVersion)
	api.router.ServeHTTP(w, r)
}

/* API endpoint
app.post('/profiles/:user/:profileId', function (req, res) {
	console.log('profile posted:');
	console.log(JSON.stringify(req.body, null, 4));
	res.send('1');// return current version number of profile
});

app.head('/profiles/:user/:profileId', function (req, res) {
	//If-Modified-Since: version
});

app.get('/profiles/:user/:profileId', function (req, res) {
	var name = req.params.user + '/' + req.params.profileId;
	console.log('profile request:', name);
	res.json({
		rev: 1,
		name: name,
		mods: {},
	});
});

app.get('/mods/:user/:mod/v', function (req, res) {
	res.json(['0.1.8', '1.0.0']);
});

app.get('/mods/:user/:mod/v/:version/meta', function (req, res) {
	if (req.params.version === 'latest') {
		req.params.version = '1.0.0';
	}

	console.info('params ', req.params);
	var result = {
		name: req.params.user + '/' + req.params.mod,
		version: req.params.version
	};

	console.info('meta ', result);
	res.json(result);
});

app.get('/mods/:user/v/:mod/:version', function (req, res) {
	if (req.params.version === 'latest') {
		req.params.version = '1.0.0';
	}

	console.info('params ', req.params);

	res.sendFile(path.join(__dirname, '/candyland2.smod'), function (err) {
		if (err) {
			console.error(err);
			return;
		}
	});
});*/
<|endoftext|>


<commit_before>package main

import (
	"os"
	"testing"
)

func cleanSmtpVars() {
	for _, env := range []string{"SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_HOST", "SMTP_FROM_ADDRESS"} {
		os.Setenv(env, "")
	}
}

func TestSmtpConfigureBasics(t *testing.T) {
	failTestOnError(t, setupTestEnv())

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_HOST", "smtp.commento.io")
	os.Setenv("SMTP_FROM_ADDRESS", "no-reply@commento.io")

	if err := smtpConfigure(); err != nil {
		t.Errorf("unexpected error when configuring SMTP: %v", err)
		return
	}

	cleanSmtpVars()
}

func TestSmtpConfigureEmptyHost(t *testing.T) {
	failTestOnError(t, setupTestEnv())

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_FROM_ADDRESS", "no-reply@commento.io")

	if err := smtpConfigure(); err != nil {
		t.Errorf("unexpected error when configuring SMTP: %v", err)
		return
	}

	if smtpConfigured {
		t.Errorf("SMTP configured when it should not be due to empty COMMENTO_SMTP_HOST")
		return
	}

	cleanSmtpVars()
}

func TestSmtpConfigureEmptyAddress(t *testing.T) {
	failTestOnError(t, setupTestEnv())

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_HOST", "smtp.commento.io")
	os.Setenv("SMTP_PORT", "25")

	if err := smtpConfigure(); err == nil {
		t.Errorf("expected error not found; SMTP should not be configured when COMMENTO_SMTP_FROM_ADDRESS is empty")
		return
	}

	cleanSmtpVars()
}
<commit_msg>smtp_configure_test.go: clean env before test<commit_after>package main

import (
	"os"
	"testing"
)

func cleanSmtpVars() {
	for _, env := range []string{"SMTP_USERNAME", "SMTP_PASSWORD", "SMTP_HOST", "SMTP_FROM_ADDRESS"} {
		os.Setenv(env, "")
	}
}

func TestSmtpConfigureBasics(t *testing.T) {
	failTestOnError(t, setupTestEnv())
	cleanSmtpVars()

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_HOST", "smtp.commento.io")
	os.Setenv("SMTP_FROM_ADDRESS", "no-reply@commento.io")

	if err := smtpConfigure(); err != nil {
		t.Errorf("unexpected error when configuring SMTP: %v", err)
		return
	}
}

func TestSmtpConfigureEmptyHost(t *testing.T) {
	failTestOnError(t, setupTestEnv())
	cleanSmtpVars()

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_FROM_ADDRESS", "no-reply@commento.io")

	if err := smtpConfigure(); err != nil {
		t.Errorf("unexpected error when configuring SMTP: %v", err)
		return
	}

	if smtpConfigured {
		t.Errorf("SMTP configured when it should not be due to empty COMMENTO_SMTP_HOST")
		return
	}
}

func TestSmtpConfigureEmptyAddress(t *testing.T) {
	failTestOnError(t, setupTestEnv())
	cleanSmtpVars()

	os.Setenv("SMTP_USERNAME", "test@example.com")
	os.Setenv("SMTP_PASSWORD", "hunter2")
	os.Setenv("SMTP_HOST", "smtp.commento.io")
	os.Setenv("SMTP_PORT", "25")

	if err := smtpConfigure(); err == nil {
		t.Errorf("expected error not found; SMTP should not be configured when COMMENTO_SMTP_FROM_ADDRESS is empty")
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"code.google.com/p/go.exp/fsnotify"
)

func StartWatch(path string, recursive bool) (*fsnotify.Watcher, int, error) {
	// TODO: Check and handle a non-recursive watch request
	// TODO: Handle directory excludes on startup
	watched := 0
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		fmt.Println("Error with establishing watcher, fsmonitor.go line 17:", err)
	}

	err = filepath.Walk(path, func (path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			go func (path string) (err error) {
				err = watcher.Watch(path)
				if err != nil {
					fmt.Printf("fsmonitor.go line 25\terror: %v: %v\n", err, path)
					return err
				}
				watched++
				return nil
				// increment how many dirs are watched
				// TODO: try to find out why the number of directories
				//       watched seems to be different between executions
			}(path)
		}
		return err
	})
	if err != nil {
		fmt.Println("Error with walking filepath, fsmonitor.go line 36:", err)
	}

	return watcher, watched, err
}

//Perhaps this later changes to logEvent or something
func handleEvent(name string, eventType string) {
	// after deletion (and potentially rename) we cannot ascertain
	// if the thing renamed or deleted was a file or directory. This
	// more or may not be a problem.
	info, err := os.Lstat(name)
	if err != nil {
		fmt.Println(err)
		return
	}
	if info.IsDir() {
		fmt.Printf("Directory %s: %v\n", eventType, name)
	} else if !(info.IsDir()) {
		fmt.Printf("File %s: %v\n", eventType, name)
	}
	return
}

func EventHandler(watcher *fsnotify.Watcher, manager chan *Command) {
	for {
		select {
		case ev := <-watcher.Event:
			//encrypt() upload()
			switch {
			case ev.IsCreate():
				handleEvent(ev.Name, "create")
				watcher.Watch(ev.Name)

			case ev.IsDelete():
				handleEvent(ev.Name, "delete")
				// something like this could be done for rename
				watcher.RemoveWatch(ev.Name)

			case ev.IsModify():
				handleEvent(ev.Name, "modify")

			case ev.IsAttrib():
				handleEvent(ev.Name, "modify attrib")

			case ev.IsRename():
				watcher.RemoveWatch(ev.Name)
				handleEvent(ev.Name, "rename")

			default:
				fmt.Println("Something is weird. Event but not type?")
			}
		case err := <- watcher.Error:
			// TODO: handle errors and see why reading from this can cause a block.
			fmt.Println(err)
		case com := <-manager:
			// TODO: Add in ability to add/remove watches from a recieved command
			if com.exitP {
				err := watcher.Close()
				fmt.Println("Returning EventHandler")
				if err != nil {
					fmt.Println("Error on close of watch: ", err)
				}
				return
			}
		}
	}
}
<commit_msg>Added handleEvent() call on rename that will print something other than the os.Lstat error.<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"code.google.com/p/go.exp/fsnotify"
)

func StartWatch(path string, recursive bool) (*fsnotify.Watcher, int, error) {
	// TODO: Check and handle a non-recursive watch request
	// TODO: Handle directory excludes on startup
	watched := 0
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		fmt.Println("Error with establishing watcher, fsmonitor.go line 17:", err)
	}

	err = filepath.Walk(path, func (path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			go func (path string) (err error) {
				err = watcher.Watch(path)
				if err != nil {
					fmt.Printf("fsmonitor.go line 25\terror: %v: %v\n", err, path)
					return err
				}
				watched++
				return nil
				// increment how many dirs are watched
				// TODO: try to find out why the number of directories
				//       watched seems to be different between executions
			}(path)
		}
		return err
	})
	if err != nil {
		fmt.Println("Error with walking filepath, fsmonitor.go line 36:", err)
	}

	return watcher, watched, err
}

//Perhaps this later changes to logEvent or something
func handleEvent(name string, eventType string) {
	// after deletion (and potentially rename) we cannot ascertain
	// if the thing renamed or deleted was a file or directory. This
	// more or may not be a problem.
	info, err := os.Lstat(name)
	if err != nil {
		fmt.Printf("File or directory %s: %v\n", eventType, name)
		return
	}
	if info.IsDir() {
		fmt.Printf("Directory %s: %v\n", eventType, name)
	} else if !(info.IsDir()) {
		fmt.Printf("File %s: %v\n", eventType, name)
	}
	return
}

func EventHandler(watcher *fsnotify.Watcher, manager chan *Command) {
	for {
		select {
		case ev := <-watcher.Event:
			//encrypt() upload()
			switch {
			case ev.IsCreate():
				handleEvent(ev.Name, "create")
				watcher.Watch(ev.Name)

			case ev.IsDelete():
				handleEvent(ev.Name, "delete")
				// something like this could be done for rename
				watcher.RemoveWatch(ev.Name)

			case ev.IsModify():
				handleEvent(ev.Name, "modify")

			case ev.IsAttrib():
				handleEvent(ev.Name, "modify attrib")

			case ev.IsRename():
				watcher.RemoveWatch(ev.Name)
				handleEvent(ev.Name, "rename")

			default:
				fmt.Println("Something is weird. Event but not type?")
			}
		case err := <- watcher.Error:
			// TODO: handle errors and see why reading from this can cause a block.
			fmt.Println(err)
		case com := <-manager:
			// TODO: Add in ability to add/remove watches from a recieved command
			if com.exitP {
				err := watcher.Close()
				fmt.Println("Returning EventHandler")
				if err != nil {
					fmt.Println("Error on close of watch: ", err)
				}
				return
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net"
	"sync"

	"github.com/calmh/syncthing/discover"
)

type Node struct {
	IP   []byte
	Port uint16
}

var (
	nodes = make(map[string]Node)
	lock  sync.Mutex
)

func main() {
	addr, _ := net.ResolveUDPAddr("udp", ":22025")
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		panic(err)
	}

	var buf = make([]byte, 1024)
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			panic(err)
		}
		pkt, err := discover.DecodePacket(buf[:n])
		if err != nil {
			log.Println("Warning:", err)
			continue
		}

		switch pkt.Magic {
		case 0x20121025:
			// Announcement
			//lock.Lock()
			ip := addr.IP.To4()
			if ip == nil {
				ip = addr.IP.To16()
			}
			node := Node{ip, uint16(pkt.Port)}
			log.Println("<-", pkt.ID, node)
			nodes[pkt.ID] = node
			//lock.Unlock()
		case 0x19760309:
			// Query
			//lock.Lock()
			node, ok := nodes[pkt.ID]
			//lock.Unlock()
			if ok {
				pkt := discover.Packet{
					Magic: 0x20121025,
					ID:    pkt.ID,
					Port:  node.Port,
					IP:    node.IP,
				}
				_, _, err = conn.WriteMsgUDP(discover.EncodePacket(pkt), nil, addr)
				if err != nil {
					log.Println("Warning:", err)
				} else {
					log.Println("->", pkt.ID, node)
				}
			}
		}

	}
}
<commit_msg>discosrv: Expire nodes, reduce debug logging<commit_after>package main

import (
	"log"
	"net"
	"sync"
	"time"

	"github.com/calmh/syncthing/discover"
)

type Node struct {
	IP      []byte
	Port    uint16
	Updated time.Time
}

var (
	nodes   = make(map[string]Node)
	lock    sync.Mutex
	queries = 0
)

func main() {
	addr, _ := net.ResolveUDPAddr("udp", ":22025")
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		panic(err)
	}

	go func() {
		for {
			time.Sleep(600 * time.Second)

			lock.Lock()

			var deleted = 0
			for id, node := range nodes {
				if time.Since(node.Updated) > 60*time.Minute {
					delete(nodes, id)
					deleted++
				}
			}
			log.Printf("Expired %d nodes; %d nodes in registry; %d queries", deleted, len(nodes), queries)
			queries = 0

			lock.Unlock()
		}
	}()

	var buf = make([]byte, 1024)
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		if err != nil {
			panic(err)
		}
		pkt, err := discover.DecodePacket(buf[:n])
		if err != nil {
			log.Println("Warning:", err)
			continue
		}

		switch pkt.Magic {
		case 0x20121025:
			// Announcement
			lock.Lock()
			ip := addr.IP.To4()
			if ip == nil {
				ip = addr.IP.To16()
			}
			node := Node{
				IP:      ip,
				Port:    uint16(pkt.Port),
				Updated: time.Now(),
			}
			//log.Println("<-", pkt.ID, node)
			nodes[pkt.ID] = node
			lock.Unlock()
		case 0x19760309:
			// Query
			lock.Lock()
			node, ok := nodes[pkt.ID]
			queries++
			lock.Unlock()
			if ok {
				pkt := discover.Packet{
					Magic: 0x20121025,
					ID:    pkt.ID,
					Port:  node.Port,
					IP:    node.IP,
				}
				_, _, err = conn.WriteMsgUDP(discover.EncodePacket(pkt), nil, addr)
				if err != nil {
					log.Println("Warning:", err)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package gemini

import (
	"fmt"
	"reflect"
)

func (g *Gemini) Get(i interface{}, key interface{}) error {
	// TODO(ttacon): really the key param should be variadic (for composite primary keys)
	val := reflect.ValueOf(i)
	if !val.IsValid() {
		return fmt.Errorf("invalid struct value")
	}

	keyVal := reflect.ValueOf(i)
	if !keyVal.IsValid() {
		return fmt.Errorf("invalid key value")
	}

	table := g.tableFor(i)

	// NOTE(ttacon): for now we won't support composite primary keys
	// if we have no primary key at this point, let's
	// let them know that Get() was a silly idea
	if !table.HasPrimaryKey() {
		return NoPrimaryKey
	}

	return g.getItFrom(i, key, table)
}

func (g *Gemini) getItFrom(i interface{}, key interface{}, table *TableMap) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Insert(i interface{}) error {
	// TODO(ttacon)
	tableName := tableNameForStruct(reflect.TypeOf(i))

	// TODO(ttacon): perhaps we should be smart and try to just insert if there is only one db
	// even if we don't have a mapping from table to db
	db, ok := g.TablesToDb[tableName]
	if !ok {
		return fmt.Errorf("table %s is not specified to interact with any db", tableName)
	}

	tMap, ok := g.StructsMap[tableName]
	if !ok {
		return fmt.Errorf("table %s does not have a table map", tableName)
	}

	// TODO(ttacon): make smart mapping of table name to db driver and dialect
	query, args := insertQueryAndArgs(i, tMap, g.DbToDriver[db])
	result, err := db.Exec(query, args...)
	if err != nil {
		return err
	}

	fmt.Printf("%#v\n", result)

	return nil
}

func (g *Gemini) Delete(i interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Update(i interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Select(i interface{}, query string, args ...interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Exec(i interface{}, query string, args ...interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) tableFor(i interface{}) *TableMap {
	var (
		tableName string
		val       = reflect.ValueOf(i)
	)

	if v, ok := val.Type().FieldByName("TableInfo"); ok && v.Tag.Get("name") != "" {
		tableName = v.Tag.Get("name")
	} else {
		tableName = val.Type().Name()
	}

	// see if struct exists in table map
	if tMap, ok := g.StructsMap[tableName]; ok {
		return tMap
	}

	return TableMapFromStruct(i, tableName)
}
<commit_msg>Remove println<commit_after>package gemini

import (
	"fmt"
	"reflect"
)

func (g *Gemini) Get(i interface{}, key interface{}) error {
	// TODO(ttacon): really the key param should be variadic (for composite primary keys)
	val := reflect.ValueOf(i)
	if !val.IsValid() {
		return fmt.Errorf("invalid struct value")
	}

	keyVal := reflect.ValueOf(i)
	if !keyVal.IsValid() {
		return fmt.Errorf("invalid key value")
	}

	table := g.tableFor(i)

	// NOTE(ttacon): for now we won't support composite primary keys
	// if we have no primary key at this point, let's
	// let them know that Get() was a silly idea
	if !table.HasPrimaryKey() {
		return NoPrimaryKey
	}

	return g.getItFrom(i, key, table)
}

func (g *Gemini) getItFrom(i interface{}, key interface{}, table *TableMap) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Insert(i interface{}) error {
	// TODO(ttacon)
	tableName := tableNameForStruct(reflect.TypeOf(i))

	// TODO(ttacon): perhaps we should be smart and try to just insert if there is only one db
	// even if we don't have a mapping from table to db
	db, ok := g.TablesToDb[tableName]
	if !ok {
		return fmt.Errorf("table %s is not specified to interact with any db", tableName)
	}

	tMap, ok := g.StructsMap[tableName]
	if !ok {
		return fmt.Errorf("table %s does not have a table map", tableName)
	}

	// TODO(ttacon): make smart mapping of table name to db driver and dialect
	query, args := insertQueryAndArgs(i, tMap, g.DbToDriver[db])
	result, err := db.Exec(query, args...)
	if err != nil {
		return err
	}

	return nil
}

func (g *Gemini) Delete(i interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Update(i interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Select(i interface{}, query string, args ...interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) Exec(i interface{}, query string, args ...interface{}) error {
	// TODO(ttacon)
	return nil
}

func (g *Gemini) tableFor(i interface{}) *TableMap {
	var (
		tableName string
		val       = reflect.ValueOf(i)
	)

	if v, ok := val.Type().FieldByName("TableInfo"); ok && v.Tag.Get("name") != "" {
		tableName = v.Tag.Get("name")
	} else {
		tableName = val.Type().Name()
	}

	// see if struct exists in table map
	if tMap, ok := g.StructsMap[tableName]; ok {
		return tMap
	}

	return TableMapFromStruct(i, tableName)
}
<|endoftext|>


<commit_before>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"os"
	"path"
	"syscall"
	"unsafe"
)

const (
	bufSize = 65536 + 100 // See the link above for the details
)

type FileSystem interface{}

type MountPoint struct {
	mountPoint string
	f          *os.File
}

// Mount create a fuse fs on the specified mount point.
func Mount(mountPoint string, fs FileSystem) (m *MountPoint, err os.Error) {
	local, remote, err := net.Socketpair("unixgram")
	if err != nil {
		return
	}

	defer local.Close()
	defer remote.Close()

	mountPoint = path.Clean(mountPoint)
	if !path.Rooted(mountPoint) {
		cwd, err := os.Getwd()
		if err != nil {
			return
		}
		mountPoint = path.Clean(path.Join(cwd, mountPoint))
	}
	pid, err := os.ForkExec("/bin/fusermount",
		[]string{"/bin/fusermount", mountPoint},
		[]string{"_FUSE_COMMFD=3"},
		"",
		[]*os.File{nil, nil, nil, remote.File()})
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return nil, os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}

	f, err := getFuseConn(local)
	if err != nil {
		return
	}
	m = &MountPoint{mountPoint, f}
	go m.loop()
	return
}

func (m *MountPoint) loop() {
	buf := make([]byte, bufSize)
	f := m.f
	for {
		n, err := f.Read(buf)
		r := bytes.NewBuffer(buf[0:n])
		if err != nil {
			fmt.Printf("MountPoint.loop: Read failed, err: %v\n", err)
			os.Exit(1)
		}
		var h InHeader
		err = binary.Read(r, binary.LittleEndian, &h)
		if err != nil {
			fmt.Printf("MountPoint.loop: binary.Read of fuse_in_header failed with err: %v\n", err)
			os.Exit(1)
		}
		fmt.Printf("Here! n = %d, buf = %v, h = %v\n", n, buf[0:n], h)
		os.Exit(0)
	}
}

func (m *MountPoint) Unmount() (err os.Error) {
	if m == nil {
		return nil
	}
	pid, err := os.ForkExec("/bin/fusermount",
		[]string{"/bin/fusermount", "-u", m.mountPoint},
		nil,
		"",
		[]*os.File{nil, nil, os.Stderr})
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	m.f.Close()
	return
}

func recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(syscall.SYS_RECVMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags))
	n = int(n1)
	errno = int(e1)
	return
}

func Recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, err os.Error) {
	n, errno := recvmsg(fd, msg, flags)
	if errno != 0 {
		err = os.NewSyscallError("recvmsg", errno)
	}
	return
}

func getFuseConn(local net.Conn) (f *os.File, err os.Error) {
	var msg syscall.Msghdr
	var iov syscall.Iovec
	base := make([]int32, 256)
	control := make([]int32, 256)

	iov.Base = (*byte)(unsafe.Pointer(&base[0]))
	iov.Len = uint64(len(base) * 4)
	msg.Iov = (*syscall.Iovec)(unsafe.Pointer(&iov))
	msg.Iovlen = 1
	msg.Control = (*byte)(unsafe.Pointer(&control[0]))
	msg.Controllen = uint64(len(control) * 4)

	_, err = Recvmsg(local.File().Fd(), &msg, 0)
	if err != nil {
		return
	}

	length := control[0]
	typ := control[2] // syscall.Cmsghdr.Type
	fd := control[4]
	if typ != 1 {
		err = os.NewError(fmt.Sprintf("getFuseConn: recvmsg returned wrong control type: %d", typ))
		return
	}
	if length < 20 {
		err = os.NewError(fmt.Sprintf("getFuseConn: too short control message. Length: %d", length))
		return
	}

	if fd < 0 {
		err = os.NewError(fmt.Sprintf("getFuseConn: fd < 0: %d", fd))
		return
	}
	f = os.NewFile(int(fd), "fuse-conn")
	return
}
<commit_msg>Loop is now just listening, there's writer, errorHandler goroutines and a handler goroutine per request<commit_after>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
	"net"
	"os"
	"path"
	"syscall"
	"unsafe"
)

const (
	bufSize = 65536 + 100 // See the link above for the details
)

type FileSystem interface{}

type MountPoint struct {
	mountPoint string
	f          *os.File
}

// Mount create a fuse fs on the specified mount point.
func Mount(mountPoint string, fs FileSystem) (m *MountPoint, err os.Error) {
	local, remote, err := net.Socketpair("unixgram")
	if err != nil {
		return
	}

	defer local.Close()
	defer remote.Close()

	mountPoint = path.Clean(mountPoint)
	if !path.Rooted(mountPoint) {
		cwd, err := os.Getwd()
		if err != nil {
			return
		}
		mountPoint = path.Clean(path.Join(cwd, mountPoint))
	}
	pid, err := os.ForkExec("/bin/fusermount",
		[]string{"/bin/fusermount", mountPoint},
		[]string{"_FUSE_COMMFD=3"},
		"",
		[]*os.File{nil, nil, nil, remote.File()})
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return nil, os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}

	f, err := getFuseConn(local)
	if err != nil {
		return
	}
	m = &MountPoint{mountPoint, f}
	go m.loop()
	return
}

func (m *MountPoint) loop() {
	buf := make([]byte, bufSize)
	f := m.f
	errors := make(chan os.Error, 100)
	toW := make(chan [][]byte, 100)
	go m.errorHandler(errors)
	go m.writer(f, toW, errors)
	for {
		n, err := f.Read(buf)
		if err != nil {
			errors <- err
		}
		go m.handle(buf[0:n], toW, errors)
	}
}

func (m *MountPoint) handle(in []byte, toW chan [][]byte, errors chan os.Error) {
	r := bytes.NewBuffer(in)
	var h InHeader
	err := binary.Read(r, binary.LittleEndian, &h)
	if err != nil {
		errors <- err
		return
	}
	fmt.Printf("Here! in = %v, h = %v\n", in, h)
	os.Exit(0)

}

func (m *MountPoint) writer(f *os.File, in chan [][]byte, errors chan os.Error) {
	fd := f.Fd()
	for packet := range in {
		_, err := Writev(fd, packet)
		if err != nil {
			errors <- err
			continue
		}
	}
}

func (m *MountPoint) errorHandler(errors chan os.Error) {
	for err := range errors {
		log.Stderr("MountPoint.errorHandler: ", err)
	}
}

func (m *MountPoint) Unmount() (err os.Error) {
	if m == nil {
		return nil
	}
	pid, err := os.ForkExec("/bin/fusermount",
		[]string{"/bin/fusermount", "-u", m.mountPoint},
		nil,
		"",
		[]*os.File{nil, nil, os.Stderr})
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	m.f.Close()
	return
}

func recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(syscall.SYS_RECVMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags))
	n = int(n1)
	errno = int(e1)
	return
}

func Recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, err os.Error) {
	n, errno := recvmsg(fd, msg, flags)
	if errno != 0 {
		err = os.NewSyscallError("recvmsg", errno)
	}
	return
}

func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(syscall.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
	n = int(n1)
	errno = int(e1)
	return
}

func Writev(fd int, packet [][]byte) (n int, err os.Error) {
	if len(packet) == 0 {
		return
	}
	iovecs := make([]syscall.Iovec, len(packet))
	for i, v := range packet {
		if v == nil {
			continue
		}
		iovecs[i].Base = (*byte)(unsafe.Pointer(&packet[i][0]))
		iovecs[i].Len = uint64(len(packet[i]))
	}
	n, errno := writev(fd, (*syscall.Iovec)(unsafe.Pointer(&iovecs[0])), len(iovecs))
	if errno != 0 {
		err = os.NewSyscallError("writev", errno)
		return
	}
	return
}

func getFuseConn(local net.Conn) (f *os.File, err os.Error) {
	var msg syscall.Msghdr
	var iov syscall.Iovec
	base := make([]int32, 256)
	control := make([]int32, 256)

	iov.Base = (*byte)(unsafe.Pointer(&base[0]))
	iov.Len = uint64(len(base) * 4)
	msg.Iov = (*syscall.Iovec)(unsafe.Pointer(&iov))
	msg.Iovlen = 1
	msg.Control = (*byte)(unsafe.Pointer(&control[0]))
	msg.Controllen = uint64(len(control) * 4)

	_, err = Recvmsg(local.File().Fd(), &msg, 0)
	if err != nil {
		return
	}

	length := control[0]
	typ := control[2] // syscall.Cmsghdr.Type
	fd := control[4]
	if typ != 1 {
		err = os.NewError(fmt.Sprintf("getFuseConn: recvmsg returned wrong control type: %d", typ))
		return
	}
	if length < 20 {
		err = os.NewError(fmt.Sprintf("getFuseConn: too short control message. Length: %d", length))
		return
	}

	if fd < 0 {
		err = os.NewError(fmt.Sprintf("getFuseConn: fd < 0: %d", fd))
		return
	}
	f = os.NewFile(int(fd), "fuse-conn")
	return
}
<|endoftext|>


<commit_before>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html

import (
	"fmt"
	"net"
	"os"
	"path"
)

type FileSystem interface {
}

type MountPoint struct {
	mountPoint string
	f *os.File
}

// Mount create a fuse fs on the specified mount point.
func Mount(mountPoint string, fs FileSystem) (m *MountPoint, err os.Error) {
	local, remote, err := net.Socketpair("unixgram")
	if err != nil {
		return
	}
	defer local.Close()
	defer remote.Close()

	mountPoint = path.Clean(mountPoint)
	if !path.Rooted(mountPoint) {
		cwd, err := os.Getwd()
		if err != nil {
			return
		}
		mountPoint = path.Clean(path.Join(cwd, mountPoint))
	}
	pid, err := os.ForkExec("/bin/fusermount",
			[]string { "/bin/fusermount", mountPoint },
			[]string { "_FUSE_COMMFD=3" },
			"",
			[]*os.File { nil, nil, os.Stderr, remote.File() })
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return nil, os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	f, err := getFuseConn(local)
	if err != nil {
		return
	}
	m = &MountPoint { mountPoint, f }
	return
}

func (m *MountPoint) Unmount() (err os.Error) {
	pid, err := os.ForkExec("/bin/fusermount",
			[]string { "/bin/fusermount", "-u", "m", m.mountPoint },
			nil,
			"",
			[]*os.File { nil, nil, os.Stderr })
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	m.f.Close()
	return
}

func getFuseConn(local net.Conn) (f * os.File, err os.Error) {
	var fd int
	return nil, os.NewError(fmt.Sprintf("receive_fuse_conn failed with errno: %d", errno))
//	f = os.NewFile(fd, "fuse-conn")
//	return
}

<commit_msg>Implemented getFuseConn (compiles but never was run)<commit_after>package fuse

// Written with a look to http://ptspts.blogspot.com/2009/11/fuse-protocol-tutorial-for-linux-26.html

import (
	"fmt"
	"net"
	"os"
	"path"
	"syscall"
	"unsafe"
)

type FileSystem interface {
}

type MountPoint struct {
	mountPoint string
	f *os.File
}

// Mount create a fuse fs on the specified mount point.
func Mount(mountPoint string, fs FileSystem) (m *MountPoint, err os.Error) {
	local, remote, err := net.Socketpair("unixgram")
	if err != nil {
		return
	}
	defer local.Close()
	defer remote.Close()

	mountPoint = path.Clean(mountPoint)
	if !path.Rooted(mountPoint) {
		cwd, err := os.Getwd()
		if err != nil {
			return
		}
		mountPoint = path.Clean(path.Join(cwd, mountPoint))
	}
	pid, err := os.ForkExec("/bin/fusermount",
			[]string { "/bin/fusermount", mountPoint },
			[]string { "_FUSE_COMMFD=3" },
			"",
			[]*os.File { nil, nil, os.Stderr, remote.File() })
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return nil, os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	f, err := getFuseConn(local)
	if err != nil {
		return
	}
	m = &MountPoint { mountPoint, f }
	return
}

func (m *MountPoint) Unmount() (err os.Error) {
	pid, err := os.ForkExec("/bin/fusermount",
			[]string { "/bin/fusermount", "-u", "m", m.mountPoint },
			nil,
			"",
			[]*os.File { nil, nil, os.Stderr })
	if err != nil {
		return
	}
	w, err := os.Wait(pid, 0)
	if err != nil {
		return
	}
	if w.ExitStatus() != 0 {
		return os.NewError(fmt.Sprintf("fusermount exited with code %d\n", w.ExitStatus()))
	}
	m.f.Close()
	return
}

func recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, errno int) {
	n1, _, e1 := syscall.Syscall(syscall.SYS_RECVMSG, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags))
	n = int(n1)
	errno = int(e1)
	return
}

func Recvmsg(fd int, msg *syscall.Msghdr, flags int) (n int, err os.Error) {
	n, errno := recvmsg(fd, msg, flags)
	if errno != 0 {
		err = os.NewSyscallError("recvmsg", errno)
	}
	return
}

func getFuseConn(local net.Conn) (f * os.File, err os.Error) {
	var msg syscall.Msghdr
	var iov syscall.Iovec
	base := make([]int32, 256)
	control := make([]int32, 256)

	iov.Base = (*byte)(unsafe.Pointer(&base))
	iov.Len = uint64(len(base) * 4)
	msg.Iov = &iov
	msg.Iovlen = 1
	msg.Control = (*byte)(unsafe.Pointer(&control))
	msg.Controllen = uint64(len(control) * 4)

	_, err = Recvmsg(local.File().Fd(), &msg, 0)
	if err != nil {
		return
	}

	length := control[0]
	typ := control[2] // syscall.Cmsghdr.Type
	fd := control[4]
	if typ != 1 {
		err = os.NewError(fmt.Sprintf("getFuseConn: recvmsg returned wrong control type: %d", typ))
		return
	}
	if length < 20 {
		err = os.NewError(fmt.Sprintf("getFuseConn: too short control message. Length: %d", length))
		return
	}

	if (fd < 0) {
		err = os.NewError(fmt.Sprintf("getFuseConn: fd < 0: %d", fd))
		return
	}

	f = os.NewFile(int(fd), "fuse-conn")
	return
}

<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"path"
	"runtime"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/gce"
	"go.skia.org/infra/go/gce/server"
	logging "google.golang.org/api/logging/v2"
)

func FuzzerBase(name string) *gce.Instance {
	vm := server.Server20170928(name)
	vm.BootDisk.Type = gce.DISK_TYPE_PERSISTENT_SSD
	vm.DataDisks[0].SizeGb = 375
	vm.DataDisks[0].Type = gce.DISK_TYPE_LOCAL_SSD
	vm.Metadata["owner_primary"] = "kjlubick"
	vm.Metadata["owner_secondary"] = "jcgregorio"
	vm.Scopes = append(vm.Scopes, auth.SCOPE_READ_WRITE, logging.LoggingWriteScope)

	_, filename, _, _ := runtime.Caller(0)
	dir := path.Dir(filename)
	vm.SetupScript = path.Join(dir, "setup-script.sh")
	vm.StartupScript = path.Join(dir, "startup-script.sh")
	return vm
}

func FrontEnd() *gce.Instance {
	vm := FuzzerBase("skia-fuzzer-fe")
	vm.MachineType = gce.MACHINE_TYPE_STANDARD_8
	return vm
}

func BackEnd(num int) *gce.Instance {
	vm := FuzzerBase(fmt.Sprintf("skia-fuzzer-be-%d", num))
	vm.MachineType = gce.MACHINE_TYPE_HIGHCPU_64
	return vm
}

func main() {
	common.Init()
	server.Main(gce.ZONE_DEFAULT, map[string]*gce.Instance{
		"fe":   FrontEnd(),
		"be-1": BackEnd(1),
		"be-2": BackEnd(2),
		"be-3": BackEnd(3),
	})
}
<commit_msg>Add service account code (to deprecated vm.go for fuzzer-fe)<commit_after>package main

import (
	"path"
	"runtime"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/common"
	"go.skia.org/infra/go/gce"
	"go.skia.org/infra/go/gce/server"
	logging "google.golang.org/api/logging/v2"
)

func FuzzerBase(name string) *gce.Instance {
	vm := server.Server20170928(name)
	vm.BootDisk.Type = gce.DISK_TYPE_PERSISTENT_SSD
	vm.DataDisks[0].SizeGb = 375
	vm.DataDisks[0].Type = gce.DISK_TYPE_LOCAL_SSD
	vm.Metadata["owner_primary"] = "kjlubick"
	vm.Metadata["owner_secondary"] = "jcgregorio"
	vm.Scopes = append(vm.Scopes, auth.SCOPE_READ_WRITE, logging.LoggingWriteScope)
	vm.ServiceAccount = "fuzzer@skia-buildbots.google.com.iam.gserviceaccount.com"

	_, filename, _, _ := runtime.Caller(0)
	dir := path.Dir(filename)
	vm.SetupScript = path.Join(dir, "setup-script.sh")
	vm.StartupScript = path.Join(dir, "startup-script.sh")
	return vm
}

func FrontEnd() *gce.Instance {
	vm := FuzzerBase("skia-fuzzer-fe")
	vm.MachineType = gce.MACHINE_TYPE_STANDARD_8
	return vm
}

func main() {
	common.Init()
	server.Main(gce.ZONE_DEFAULT, map[string]*gce.Instance{
		"fe": FrontEnd(),
	})
}
<|endoftext|>