<commit_before>package main

import (
	"bytes"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/mamaar/risotto/generator"
	"github.com/mamaar/risotto/parser"
	"github.com/russross/blackfriday"
	"github.com/xyproto/amber"
	"github.com/yosssi/gcss"
	"github.com/yuin/gopher-lua"
	"html/template"
	"io"
	"net/http"
	"path"
	"strings"
)

// Default stylesheet filename (GCSS)
const defaultStyleFilename = "style.gcss"

// Expose functions that are related to rendering text, to the given Lua state
func exportRenderFunctions(w http.ResponseWriter, req *http.Request, L *lua.LState) {

	// Output Markdown as HTML
	L.SetGlobal("mprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Convert the buffer to markdown and return the translated string
		w.Write(blackfriday.MarkdownCommon([]byte(buf.String())))
		return 0 // number of results
	}))

	// TODO: Add two functions. One to compile amber templates and
	// store the result by filename and one to render data by using
	// compiled templates.

	// Output text as rendered amber.
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("aprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)

		// Use the buffer as a template.
		// Options are "Pretty printing, but without line numbers."
		tpl, err := amber.Compile(buf.String(), amber.Options{true, false})
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not compile Amber template:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not compile Amber template:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		// Using "MISSING" instead of nil for a slightly better error message
		// if the values in the template should not be found.
		tpl.Execute(w, "MISSING")
		return 0 // number of results
	}))

	// Output text as rendered GCSS
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("gprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Transform GCSS to CSS and output the result.
		// Ignoring the number of bytes written.
		// TODO: Can use &buf instead of using NewReader and .Bytes()?
		if _, err := gcss.Compile(w, bytes.NewReader(buf.Bytes())); err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not compile GCSS:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not compile GCSS:\n%s\n%s", err, buf.String())
			}
			//return 0 // number of results
		}
		return 0 // number of results
	}))

	// Output text as rendered JSX
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("jprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Transform JSX to JavaScript and output the result.
		prog, err := parser.ParseFile(nil, "<input>", &buf, parser.IgnoreRegExpErrors)
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not parse JSX:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not parse JSX:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		gen, err := generator.Generate(prog)
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not generate JavaScript:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not generate JavaScript:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		if gen != nil {
			io.Copy(w, gen)
		}
		return 0 // number of results
	}))

}

// Write the given source bytes as markdown wrapped in HTML to a writer, with a title
func markdownPage(w io.Writer, b []byte, filename string) {

	var title string

	// If the first line is "title: ...", use that as the title
	// and don't convert it to Markdown. This is a subset of MultiMarkdown.
	if bytes.HasPrefix(b, []byte("title:")) {
		fields := bytes.Split(b, []byte("\n"))
		if len(fields) > 1 {
			// Replace the title with the found title
			title = strings.TrimSpace(string(fields[0])[6:])
			// Remove the first line
			b = b[len(fields[0]):]
		}
	}

	// Convert from Markdown to HTML
	htmlbody := string(blackfriday.MarkdownCommon(b))

	// TODO: Check if handling "# title <tags" on the first line is valid
	// Markdown or not. Submit a patch to blackfriday if it is.

	h1title := ""
	if strings.HasPrefix(htmlbody, "
#") {
		fields := strings.Split(htmlbody, "<")
		if len(fields) > 2 {
			h1title = fields[1][2:]
			htmlbody = htmlbody[len("
"+h1title):]
			if strings.HasPrefix(h1title, "#") {
				h1title = h1title[1:]
			}
		}
	}

	// If there is no title, use the h1title
	if title == "" {
		if h1title != "" {
			title = h1title
		} else {
			// If no title has been provided, use the filename
			title = path.Base(filename)
		}
	}

	// If style.gcss is present, use that style in
	var markdownStyle string
	if exists(path.Join(path.Dir(filename), defaultStyleFilename)) {
		markdownStyle = `<link href="` + defaultStyleFilename + `" rel="stylesheet" type="text/css">`
	} else {
		// If not, use the default style in
		markdownStyle = ""
	}

	// Embed the style and rendered markdown into a simple HTML 5 page
	htmlbytes := []byte("<!doctype html><title>" + title + "</title>" + markdownStyle + "
" + h1title + "
" + htmlbody + "")

	// Write the rendered Markdown page to the http.ResponseWriter
	w.Write(htmlbytes)
}

// Write the given source bytes as Amber converted to HTML, to a writer.
// filename and luafilename are only used if there are errors.
func amberPage(w http.ResponseWriter, filename, luafilename string, amberdata []byte, funcs template.FuncMap) {

	var buf bytes.Buffer

	// If style.gcss is present, and a header is present, and it has not already been linked in, link it in
	if exists(path.Join(path.Dir(filename), defaultStyleFilename)) {
		linkToStyle(&amberdata, defaultStyleFilename)
	}

	// If the file starts with "html5\n", replace it with "doctype 5\nhtml\n"
	//amberdata = bytes.Replace(amberdata, []byte("html5\n"), []byte("doctype 5\nhtml\n"), 1)

	// Compile the given amber template
	tpl, err := amber.CompileData(amberdata, filename, amber.Options{true, false})
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, amberdata, err.Error(), "amber")
		} else {
			log.Errorf("Could not compile Amber template:\n%s\n%s", err, string(amberdata))
		}
		return
	}

	// Render the Amber template to the buffer
	if err := tpl.Execute(&buf, funcs); err != nil {

		// If it was one particular error, where the template can not find the
		// function or variable name that is used, give the user a friendlier
		// message.
		if strings.TrimSpace(err.Error()) == "reflect: call of reflect.Value.Type on zero Value" {
			errortext := "Could not execute Amber template!
One of the functions called by the template is not available."
			if DEBUG_MODE {
				prettyError(w, filename, amberdata, errortext, "amber")
			} else {
				errortext = strings.Replace(errortext, "
", "\n", 1)
				log.Errorf("Could not execute Amber template:\n%s", errortext)
			}
		} else {
			if DEBUG_MODE {
				prettyError(w, filename, amberdata, err.Error(), "amber")
			} else {
				log.Errorf("Could not execute Amber template:\n%s", err)
			}
		}
		return
	}
	// Write the rendered template to the http.ResponseWriter
	buf.WriteTo(w)
}

// Write the given source bytes as GCSS converted to CSS, to a writer.
// filename is only used if there are errors.
func gcssPage(w http.ResponseWriter, filename string, gcssdata []byte) {
	if _, err := gcss.Compile(w, bytes.NewReader(gcssdata)); err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, gcssdata, err.Error(), "gcss")
		} else {
			log.Errorf("Could not compile GCSS:\n%s\n%s", err, string(gcssdata))
		}
		return
	}
}

func jsxPage(w http.ResponseWriter, filename string, jsxdata []byte) {
	prog, err := parser.ParseFile(nil, filename, jsxdata, parser.IgnoreRegExpErrors)
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, jsxdata, err.Error(), "jsx")
		} else {
			log.Errorf("Could not compile JSX:\n%s\n%s", err, string(jsxdata))
		}
		return
	}
	gen, err := generator.Generate(prog)
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, jsxdata, err.Error(), "jsx")
		} else {
			log.Errorf("Could not generate javascript:\n%s\n%s", err, string(jsxdata))
		}
		return
	}
	if gen != nil {
		io.Copy(w, gen)
	}
}
<commit_msg>Switching back to the eknkc/amber package<commit_after>package main

import (
	"bytes"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/eknkc/amber"
	"github.com/mamaar/risotto/generator"
	"github.com/mamaar/risotto/parser"
	"github.com/russross/blackfriday"
	"github.com/yosssi/gcss"
	"github.com/yuin/gopher-lua"
	"html/template"
	"io"
	"net/http"
	"path"
	"strings"
)

// Default stylesheet filename (GCSS)
const defaultStyleFilename = "style.gcss"

// Expose functions that are related to rendering text, to the given Lua state
func exportRenderFunctions(w http.ResponseWriter, req *http.Request, L *lua.LState) {

	// Output Markdown as HTML
	L.SetGlobal("mprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Convert the buffer to markdown and return the translated string
		w.Write(blackfriday.MarkdownCommon([]byte(buf.String())))
		return 0 // number of results
	}))

	// TODO: Add two functions. One to compile amber templates and
	// store the result by filename and one to render data by using
	// compiled templates.

	// Output text as rendered amber.
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("aprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)

		// Use the buffer as a template.
		// Options are "Pretty printing, but without line numbers."
		tpl, err := amber.Compile(buf.String(), amber.Options{true, false})
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not compile Amber template:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not compile Amber template:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		// Using "MISSING" instead of nil for a slightly better error message
		// if the values in the template should not be found.
		tpl.Execute(w, "MISSING")
		return 0 // number of results
	}))

	// Output text as rendered GCSS
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("gprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Transform GCSS to CSS and output the result.
		// Ignoring the number of bytes written.
		// TODO: Can use &buf instead of using NewReader and .Bytes()?
		if _, err := gcss.Compile(w, bytes.NewReader(buf.Bytes())); err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not compile GCSS:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not compile GCSS:\n%s\n%s", err, buf.String())
			}
			//return 0 // number of results
		}
		return 0 // number of results
	}))

	// Output text as rendered JSX
	// TODO: Add caching, compilation and reuse
	L.SetGlobal("jprint", L.NewFunction(func(L *lua.LState) int {
		// Retrieve all the function arguments as a bytes.Buffer
		buf := arguments2buffer(L)
		// Transform JSX to JavaScript and output the result.
		prog, err := parser.ParseFile(nil, "<input>", &buf, parser.IgnoreRegExpErrors)
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not parse JSX:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not parse JSX:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		gen, err := generator.Generate(prog)
		if err != nil {
			if DEBUG_MODE {
				// TODO: Use a similar error page as for Lua
				fmt.Fprint(w, "Could not generate JavaScript:\n\t"+err.Error()+"\n\n"+buf.String())
			} else {
				log.Errorf("Could not generate JavaScript:\n%s\n%s", err, buf.String())
			}
			return 0 // number of results
		}
		if gen != nil {
			io.Copy(w, gen)
		}
		return 0 // number of results
	}))

}

// Write the given source bytes as markdown wrapped in HTML to a writer, with a title
func markdownPage(w io.Writer, b []byte, filename string) {

	var title string

	// If the first line is "title: ...", use that as the title
	// and don't convert it to Markdown. This is a subset of MultiMarkdown.
	if bytes.HasPrefix(b, []byte("title:")) {
		fields := bytes.Split(b, []byte("\n"))
		if len(fields) > 1 {
			// Replace the title with the found title
			title = strings.TrimSpace(string(fields[0])[6:])
			// Remove the first line
			b = b[len(fields[0]):]
		}
	}

	// Convert from Markdown to HTML
	htmlbody := string(blackfriday.MarkdownCommon(b))

	// TODO: Check if handling "# title <tags" on the first line is valid
	// Markdown or not. Submit a patch to blackfriday if it is.

	h1title := ""
	if strings.HasPrefix(htmlbody, "
#") {
		fields := strings.Split(htmlbody, "<")
		if len(fields) > 2 {
			h1title = fields[1][2:]
			htmlbody = htmlbody[len("
"+h1title):]
			if strings.HasPrefix(h1title, "#") {
				h1title = h1title[1:]
			}
		}
	}

	// If there is no title, use the h1title
	if title == "" {
		if h1title != "" {
			title = h1title
		} else {
			// If no title has been provided, use the filename
			title = path.Base(filename)
		}
	}

	// If style.gcss is present, use that style in
	var markdownStyle string
	if exists(path.Join(path.Dir(filename), defaultStyleFilename)) {
		markdownStyle = `<link href="` + defaultStyleFilename + `" rel="stylesheet" type="text/css">`
	} else {
		// If not, use the default style in
		markdownStyle = ""
	}

	// Embed the style and rendered markdown into a simple HTML 5 page
	htmlbytes := []byte("<!doctype html><title>" + title + "</title>" + markdownStyle + "
" + h1title + "
" + htmlbody + "")

	// Write the rendered Markdown page to the http.ResponseWriter
	w.Write(htmlbytes)
}

// Write the given source bytes as Amber converted to HTML, to a writer.
// filename and luafilename are only used if there are errors.
func amberPage(w http.ResponseWriter, filename, luafilename string, amberdata []byte, funcs template.FuncMap) {

	var buf bytes.Buffer

	// If style.gcss is present, and a header is present, and it has not already been linked in, link it in
	if exists(path.Join(path.Dir(filename), defaultStyleFilename)) {
		linkToStyle(&amberdata, defaultStyleFilename)
	}

	// If the file starts with "html5\n", replace it with "doctype 5\nhtml\n"
	//amberdata = bytes.Replace(amberdata, []byte("html5\n"), []byte("doctype 5\nhtml\n"), 1)

	// Compile the given amber template
	tpl, err := amber.CompileData(amberdata, filename, amber.Options{true, false})
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, amberdata, err.Error(), "amber")
		} else {
			log.Errorf("Could not compile Amber template:\n%s\n%s", err, string(amberdata))
		}
		return
	}

	// Render the Amber template to the buffer
	if err := tpl.Execute(&buf, funcs); err != nil {

		// If it was one particular error, where the template can not find the
		// function or variable name that is used, give the user a friendlier
		// message.
		if strings.TrimSpace(err.Error()) == "reflect: call of reflect.Value.Type on zero Value" {
			errortext := "Could not execute Amber template!
One of the functions called by the template is not available."
			if DEBUG_MODE {
				prettyError(w, filename, amberdata, errortext, "amber")
			} else {
				errortext = strings.Replace(errortext, "
", "\n", 1)
				log.Errorf("Could not execute Amber template:\n%s", errortext)
			}
		} else {
			if DEBUG_MODE {
				prettyError(w, filename, amberdata, err.Error(), "amber")
			} else {
				log.Errorf("Could not execute Amber template:\n%s", err)
			}
		}
		return
	}
	// Write the rendered template to the http.ResponseWriter
	buf.WriteTo(w)
}

// Write the given source bytes as GCSS converted to CSS, to a writer.
// filename is only used if there are errors.
func gcssPage(w http.ResponseWriter, filename string, gcssdata []byte) {
	if _, err := gcss.Compile(w, bytes.NewReader(gcssdata)); err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, gcssdata, err.Error(), "gcss")
		} else {
			log.Errorf("Could not compile GCSS:\n%s\n%s", err, string(gcssdata))
		}
		return
	}
}

func jsxPage(w http.ResponseWriter, filename string, jsxdata []byte) {
	prog, err := parser.ParseFile(nil, filename, jsxdata, parser.IgnoreRegExpErrors)
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, jsxdata, err.Error(), "jsx")
		} else {
			log.Errorf("Could not compile JSX:\n%s\n%s", err, string(jsxdata))
		}
		return
	}
	gen, err := generator.Generate(prog)
	if err != nil {
		if DEBUG_MODE {
			prettyError(w, filename, jsxdata, err.Error(), "jsx")
		} else {
			log.Errorf("Could not generate javascript:\n%s\n%s", err, string(jsxdata))
		}
		return
	}
	if gen != nil {
		io.Copy(w, gen)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Peter Waller <p@pwaller.net>. 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 (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// Test program which references a non-existent package. This forces goimports
// to do the maximal amount of work to determine it doesn't exist.
const fakePkg = "package main\nvar _ = thisPackageDoesNotExist328955Z828592.X()"

type ø struct{} // Alt-Gr + O

func main() {
	var (
		maxDepth    = flag.Int("max-depth", 3, "maximum depth of ignore rules to produce")
		measureOnly = flag.Bool("measure-only", false, "do not generate ignore rules, only measure goimports")
	)

	flag.Parse()

	if *maxDepth < 1 {
		log.Fatal("invalid maxDepth, must be >= 1")
	}

	goPath := filepath.Join(os.Getenv("GOPATH"), "src")

	if *measureOnly {
		showStats(readIgnored(goPath))
		return
	}

	hasGo, err := getGoDirectories(goPath, *maxDepth)
	if err != nil {
		log.Fatal(err)
	}

	nIgnored, err := writeGoImportsIgnore(goPath, *maxDepth, hasGo)
	if err != nil {
		log.Fatal(err)
	}

	showStats(nIgnored)
}

func readIgnored(path string) int {
	var ignored int
	slurp, err := ioutil.ReadFile(filepath.Join(path, ".goimportsignore"))
	if err != nil {
		return 0
	}
	bs := bufio.NewScanner(bytes.NewReader(slurp))
	for bs.Scan() {
		line := strings.TrimSpace(bs.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		if _, err := os.Stat(filepath.Join(path, line)); err == nil {
			ignored++
		}
	}
	return ignored
}

func showStats(nIgnored int) {
	nScanned, wallTime, uTime, err := countGoImportsScanned()
	if err != nil {
		log.Printf("countGoImportsScanned warning: %v", err)
	}

	log.Printf("Ignored %d directories. goimports considers %d directories in %.0fms (cpu=%0.fms).",
		nIgnored, nScanned, wallTime.Seconds()*1000, uTime.Seconds()*1000)
}

// countGoImportsScanned runs goimports and looks out the verbose log output to
// determine the number of directories scanned. A separate non-verbose run is
// done to measure the run time.
func countGoImportsScanned() (int, time.Duration, time.Duration, error) {
	cmd := exec.Command("goimports", "-v")
	cmd.Stdin = strings.NewReader(fakePkg)

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return 0, 0, 0, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, 0, 0, err
	}

	nScans, err := countScans(stderr)
	if err != nil {
		return 0, 0, 0, err
	}

	err = cmd.Wait()
	if err != nil {
		return 0, 0, 0, err
	}

	// Separate timing run without verbose output which slows things down.
	start := time.Now()
	cmd = exec.Command("goimports")
	cmd.Stdin = strings.NewReader(fakePkg)
	err = cmd.Run()

	return nScans, time.Since(start), cmd.ProcessState.UserTime(), err
}

func countScans(r io.Reader) (int, error) {
	var n int
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		if !bytes.Contains(scanner.Bytes(), []byte("scanning dir")) {
			continue
		}
		n++
	}
	return n, scanner.Err()
}

func getGoDirectories(goPath string, maxDepth int) (func(string) bool, error) {

	// goDirectories will contain all directories at `depth` or less
	// which have .go files.
	goDirectories := map[string]ø{}
	hasGo := func(p string) bool {
		_, ok := goDirectories[p]
		return ok
	}

	err := filepath.Walk(goPath, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		path, err = filepath.Rel(goPath, path)
		if err != nil {
			return err
		}
		if !strings.HasSuffix(path, ".go") {
			return err
		}

		path = filepath.ToSlash(path)
		parts := strings.Split(path, "/")
		for i := 0; i < maxDepth && i+1 < len(parts); i++ {
			goDirectories[filepath.Join(parts[:i+1]...)] = ø{}
		}
		return err
	})

	return hasGo, err
}

func writeGoImportsIgnore(
	goPath string, maxDepth int, hasGo func(string) bool,
) (int, error) {
	fd, err := os.Create(filepath.Join(goPath, ".goimportsignore"))
	if err != nil {
		return 0, err
	}
	defer fd.Close()

	_, _ = fmt.Fprintf(fd, "# Generated by goimports-update-ignore %v\n", time.Now().UTC())

	var ignored int

	err = filepath.Walk(goPath, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		path, err = filepath.Rel(goPath, path)
		if err != nil {
			return err
		}
		if path == "." {
			// Ignore goPath itself.
			return nil
		}

		path = filepath.ToSlash(path)
		curDepth := strings.Count(path, "/") + 1

		switch {
		case !fi.IsDir():
			// Only directories are ignored, not files.
			return nil
		case strings.HasPrefix(filepath.Base(path), "."):
			// .git, etc. Ignored by goimports anyway.
			return filepath.SkipDir
		case !hasGo(path):
			// These are paths which should be ignored
			fmt.Fprintln(fd, path)
			ignored++
			// It's ignored so we don't need t olook inside.
			return filepath.SkipDir
		case curDepth >= maxDepth:
			// These are too deep to explicitly ignore.
			return filepath.SkipDir
		}
		return nil
	})

	return ignored, err
}
<commit_msg>Do not crash when directory cannot be read<commit_after>// Copyright 2016 Peter Waller <p@pwaller.net>. 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 (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

// Test program which references a non-existent package. This forces goimports
// to do the maximal amount of work to determine it doesn't exist.
const fakePkg = "package main\nvar _ = thisPackageDoesNotExist328955Z828592.X()"

type ø struct{} // Alt-Gr + O

func main() {
	var (
		maxDepth    = flag.Int("max-depth", 3, "maximum depth of ignore rules to produce")
		measureOnly = flag.Bool("measure-only", false, "do not generate ignore rules, only measure goimports")
	)

	flag.Parse()

	if *maxDepth < 1 {
		log.Fatal("invalid maxDepth, must be >= 1")
	}

	goPath := filepath.Join(os.Getenv("GOPATH"), "src")

	if *measureOnly {
		showStats(readIgnored(goPath))
		return
	}

	hasGo, err := getGoDirectories(goPath, *maxDepth)
	if err != nil {
		log.Fatal(err)
	}

	nIgnored, err := writeGoImportsIgnore(goPath, *maxDepth, hasGo)
	if err != nil {
		log.Fatal(err)
	}

	showStats(nIgnored)
}

func readIgnored(path string) int {
	var ignored int
	slurp, err := ioutil.ReadFile(filepath.Join(path, ".goimportsignore"))
	if err != nil {
		return 0
	}
	bs := bufio.NewScanner(bytes.NewReader(slurp))
	for bs.Scan() {
		line := strings.TrimSpace(bs.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		if _, err := os.Stat(filepath.Join(path, line)); err == nil {
			ignored++
		}
	}
	return ignored
}

func showStats(nIgnored int) {
	nScanned, wallTime, uTime, err := countGoImportsScanned()
	if err != nil {
		log.Printf("countGoImportsScanned warning: %v", err)
	}

	log.Printf("Ignored %d directories. goimports considers %d directories in %.0fms (cpu=%0.fms).",
		nIgnored, nScanned, wallTime.Seconds()*1000, uTime.Seconds()*1000)
}

// countGoImportsScanned runs goimports and looks out the verbose log output to
// determine the number of directories scanned. A separate non-verbose run is
// done to measure the run time.
func countGoImportsScanned() (int, time.Duration, time.Duration, error) {
	cmd := exec.Command("goimports", "-v")
	cmd.Stdin = strings.NewReader(fakePkg)

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return 0, 0, 0, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, 0, 0, err
	}

	nScans, err := countScans(stderr)
	if err != nil {
		return 0, 0, 0, err
	}

	err = cmd.Wait()
	if err != nil {
		return 0, 0, 0, err
	}

	// Separate timing run without verbose output which slows things down.
	start := time.Now()
	cmd = exec.Command("goimports")
	cmd.Stdin = strings.NewReader(fakePkg)
	err = cmd.Run()

	return nScans, time.Since(start), cmd.ProcessState.UserTime(), err
}

func countScans(r io.Reader) (int, error) {
	var n int
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		if !bytes.Contains(scanner.Bytes(), []byte("scanning dir")) {
			continue
		}
		n++
	}
	return n, scanner.Err()
}

func getGoDirectories(goPath string, maxDepth int) (func(string) bool, error) {

	// goDirectories will contain all directories at `depth` or less
	// which have .go files.
	goDirectories := map[string]ø{}
	hasGo := func(p string) bool {
		_, ok := goDirectories[p]
		return ok
	}

	err := filepath.Walk(goPath, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			if os.IsPermission(err) {
				log.Printf("permission denied: %s", path)
				return nil
			}
			return err
		}
		path, err = filepath.Rel(goPath, path)
		if err != nil {
			return err
		}
		if !strings.HasSuffix(path, ".go") {
			return err
		}

		path = filepath.ToSlash(path)
		parts := strings.Split(path, "/")
		for i := 0; i < maxDepth && i+1 < len(parts); i++ {
			goDirectories[filepath.Join(parts[:i+1]...)] = ø{}
		}
		return err
	})

	return hasGo, err
}

func writeGoImportsIgnore(
	goPath string, maxDepth int, hasGo func(string) bool,
) (int, error) {
	fd, err := os.Create(filepath.Join(goPath, ".goimportsignore"))
	if err != nil {
		return 0, err
	}
	defer fd.Close()

	_, _ = fmt.Fprintf(fd, "# Generated by goimports-update-ignore %v\n", time.Now().UTC())

	var ignored int

	err = filepath.Walk(goPath, func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		path, err = filepath.Rel(goPath, path)
		if err != nil {
			return err
		}
		if path == "." {
			// Ignore goPath itself.
			return nil
		}

		path = filepath.ToSlash(path)
		curDepth := strings.Count(path, "/") + 1

		switch {
		case !fi.IsDir():
			// Only directories are ignored, not files.
			return nil
		case strings.HasPrefix(filepath.Base(path), "."):
			// .git, etc. Ignored by goimports anyway.
			return filepath.SkipDir
		case !hasGo(path):
			// These are paths which should be ignored
			fmt.Fprintln(fd, path)
			ignored++
			// It's ignored so we don't need t olook inside.
			return filepath.SkipDir
		case curDepth >= maxDepth:
			// These are too deep to explicitly ignore.
			return filepath.SkipDir
		}
		return nil
	})

	return ignored, err
}
<|endoftext|>


<commit_before>package disasm

import "fmt"

type bin []byte

func (b bin) String() string {
	s := ""
	for _, byt := range []byte(b) {
		s += fmt.Sprintf("%02X", byt)
	}
	return s
}

// Cmd represents an assemply command.
type Cmd struct {
	pos  int
	bin  bin
	opc  string
	w    bool
	opr1 string
	opr2 string
}

func (a *Cmd) String() string {
	// byte or word instruction
	size := "byte "
	if a.w {
		size = "word "
	}

	return fmt.Sprintf("%08X  %X %s %s %s%s,%s", a.pos, a.bin, a.opc, size, a.opr1, a.opr2)
}

func NewCmd(pos int, b bin, opc string, w bool, opr1, opr2 string) *Cmd {
	return &Cmd{
		pos:  pos,
		bin:  b,
		opc:  opc,
		w:    w,
		opr1: opr1,
		opr2: opr2,
	}
}
<commit_msg>disasm: fix the field name of Cmd<commit_after>package disasm

import "fmt"

type bin []byte

func (b bin) String() string {
	s := ""
	for _, byt := range []byte(b) {
		s += fmt.Sprintf("%X", byt)
	}
	return s
}

// Cmd represents an assemply command.
type Cmd struct {
	pos  int
	bin  bin
	opc  Opcode
	w    bool
	opr1 string
	opr2 string
}

func (a *Cmd) String() string {
	// byte or word instruction
	size := "byte "
	if a.w {
		size = "word "
	}

	return fmt.Sprintf("%08X  %X %s %s %s%s,%s", a.pos, a.bin, a.opc.String(), size, a.opr1, a.opr2)
}

func NewCmd(pos int, b bin, opc Opcode, w bool, opr1, opr2 string) *Cmd {
	return &Cmd{
		pos:  pos,
		bin:  b,
		opc:  opc,
		w:    w,
		opr1: opr1,
		opr2: opr2,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"path/filepath"
)

func main() {
	router := mux.NewRouter()

	s := router.Path("/{user}/{repo}/objects/{oid}").Subrouter()

	s.Methods("GET").Headers("Accept", "application/vnd.git-media").HandlerFunc(GetHandler)
	s.Methods("GET").Headers("Accept", "application/vnd.git-media+json").HandlerFunc(GetUploadHandler)

	log.Fatal(http.ListenAndServe(":8083", router))
}

func GetHandler(w http.ResponseWriter, r *http.Request) {

}

func GetUploadHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	oid := vars["oid"]
	path := oidPath(oid)
	token := S3NewToken("PUT", path, oid)

	m := make(map[string]map[string]string)
	header := make(map[string]string)
	header["Date"] = token.Time.Format(http.TimeFormat)
	header["Authorization"] = token.Token
	header["x-amz-content-sha256"] = oid
	m["header"] = header

	links := make(map[string]string)
	links["upload"] = token.Location
	links["callback"] = "http://somecallback.com"
	m["_links"] = links

	enc := json.NewEncoder(w)
	enc.Encode(m)
}

func oidPath(oid string) string {
	dir := filepath.Join(oid[0:2], oid[2:4])

	return filepath.Join("/", dir, oid)
}
<commit_msg>get content as redirect<commit_after>package main

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"path/filepath"
)

const (
	contentMediaType = "application/vnd.git-media"
	metaMediaType    = contentMediaType + ".json"
)

func main() {
	router := mux.NewRouter()

	s := router.Path("/{user}/{repo}/objects/{oid}").Subrouter()

	s.Methods("GET", "HEAD").Headers("Accept", contentMediaType).HandlerFunc(GetContentHandler)
	s.Methods("GET", "HEAD").Headers("Accept", metaMediaType).HandlerFunc(GetMetaHandler)

	log.Fatal(http.ListenAndServe(":8083", router))
}

func GetContentHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	oid := vars["oid"]
	path := oidPath(oid)
	token := S3NewToken("GET", path, oid)

	header := w.Header()
	header.Set("Git-Media-Set-Date", token.Time.Format(http.TimeFormat))
	header.Set("Git-Media-Set-Authorization", token.Token)
	header.Set("Git-Media-Set-x-amz-content-sha256", oid)
	header.Set("Location", token.Location)
	w.WriteHeader(302)
}

// Get the rest of the metadata
func GetMetaHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	oid := vars["oid"]
	path := oidPath(oid)
	token := S3NewToken("PUT", path, oid)

	m := make(map[string]map[string]string)
	header := make(map[string]string)
	header["Date"] = token.Time.Format(http.TimeFormat)
	header["Authorization"] = token.Token
	header["x-amz-content-sha256"] = oid
	m["header"] = header

	links := make(map[string]string)
	links["upload"] = token.Location
	links["callback"] = "http://somecallback.com"
	m["_links"] = links

	w.Header().Set("Content-Type", metaMediaType)
	enc := json.NewEncoder(w)
	enc.Encode(m)
}

func oidPath(oid string) string {
	dir := filepath.Join(oid[0:2], oid[2:4])

	return filepath.Join("/", dir, oid)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"

	"github.com/boltdb/bolt"
)

const DEBUG bool = true

var DB *bolt.DB

func main() {
	fmt.Println("Setting up DB...")
	db, err := SetupDB("gerph.db")
	DB = db
	if err != nil {
		log.Fatal(err)
	}
	defer CloseDB()

	fmt.Println("Now listening...")
	Listen("3000")
}
<commit_msg>CLI flags and signal handling<commit_after>package main

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

	"github.com/boltdb/bolt"
)

const DEBUG bool = true

var (
	DB *bolt.DB
	portPtr *string
	dbPathPtr *string
)

func catchSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func(){
		<- c
		fmt.Println("\n* Interrupt received, stopping...")
		fmt.Print("[..] Closing DB\r")
		CloseDB()
		fmt.Println("[OK] Closing DB")

		fmt.Println()
		os.Exit(0)
	}()
}

func main() {
	portPtr = flag.String("port", "3000", "The port to listen on.")
	dbPathPtr = flag.String("dbpath", "./gerph.db", "The path to the file to save the keystore in.")
	flag.Parse()

	fmt.Print("[..] Setting up DB in \"" + *dbPathPtr + "\"\r")
	db, err := SetupDB(*dbPathPtr)
	DB = db
	if err != nil {
		log.Fatal(err)
	}
	defer CloseDB()
	fmt.Println("[OK] Setting up DB in \"" + *dbPathPtr + "\"")

	catchSignals()

	fmt.Print("[..] Listening on port " + *portPtr + "\r")
	go func() {
		Listen(*portPtr)
	}()
	fmt.Println("[OK] Listening on port " + *portPtr)
	fmt.Println("\n* Ready!")
	select{}
}
<|endoftext|>


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

package main

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

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

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

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

package main

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

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

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

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


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/robvanmieghem/go-opencl/cl"
	"github.com/robvanmieghem/gominer/clients"
)

//Version is the released version string of gominer
var Version = "0.5"

var intensity = 28
var devicesTypesForMining = cl.DeviceTypeGPU

const maxUint32 = int64(^uint32(0))

func createWork(siaclient clients.SiaClient, miningWorkChannel chan *MiningWork, nrOfMiningDevices int, globalItemSize int) {
	//Register a function to clear the generated work if a job gets deprecated
	// It does not matter if we clear too many, is worse to work on a stale job
	siaclient.SetDeprecatedJobCall(func() {
		numberOfWorkItemsToRemove := len(miningWorkChannel)
		for i := 0; i < numberOfWorkItemsToRemove; i++ {
			<-miningWorkChannel
		}
	})

	siaclient.Start()

	for {
		target, header, deprecationChannel, job, err := siaclient.GetHeaderForWork()

		if err != nil {
			log.Println("ERROR fetching work -", err)
			time.Sleep(1000 * time.Millisecond)
			continue
		}

		//copy target to header
		for i := 0; i < 8; i++ {
			header[i+32] = target[7-i]
		}
		//Fill the workchannel with work
		// Only generate nonces for a 32 bit space (since gpu's are mostly 32 bit)
	nonce32loop:
		for i := int64(0); i*int64(globalItemSize) < (maxUint32 - int64(globalItemSize)); i++ {
			//Do not continue mining the 32 bit nonce space if the current job is deprecated
			select {
			case <-deprecationChannel:
				break nonce32loop
			default:
			}

			miningWorkChannel <- &MiningWork{header, int(i) * globalItemSize, job}
		}
	}
}

func main() {
	printVersion := flag.Bool("v", false, "Show version and exit")
	useCPU := flag.Bool("cpu", false, "If set, also use the CPU for mining, only GPU's are used by default")
	flag.IntVar(&intensity, "I", intensity, "Intensity")
	siadHost := flag.String("url", "localhost:9980", "siad host and port, for stratum servers, use `stratum+tcp://<host>:<port>`")
	pooluser := flag.String("user", "payoutaddress.rigname", "username, most stratum servers take this in the form [payoutaddress].[rigname]")
	excludedGPUs := flag.String("E", "", "Exclude GPU's: comma separated list of devicenumbers")
	flag.Parse()

	if *printVersion {
		fmt.Println("gominer version", Version)
		os.Exit(0)
	}

	siaclient := clients.NewSiaClient(*siadHost, *pooluser)

	if *useCPU {
		devicesTypesForMining = cl.DeviceTypeAll
	}
	globalItemSize := int(math.Exp2(float64(intensity)))

	platforms, err := cl.GetPlatforms()
	if err != nil {
		log.Panic(err)
	}

	clDevices := make([]*cl.Device, 0, 4)
	for _, platform := range platforms {
		log.Println("Platform", platform.Name())
		platormDevices, err := cl.GetDevices(platform, devicesTypesForMining)
		if err != nil {
			log.Println(err)
		}
		log.Println(len(platormDevices), "device(s) found:")
		for i, device := range platormDevices {
			log.Println(i, "-", device.Type(), "-", device.Name())
			clDevices = append(clDevices, device)
		}
	}

	nrOfMiningDevices := len(clDevices)

	if nrOfMiningDevices == 0 {
		log.Println("No suitable opencl devices found")
		os.Exit(1)
	}

	//Start fetching work
	workChannel := make(chan *MiningWork, nrOfMiningDevices)
	go createWork(siaclient, workChannel, nrOfMiningDevices, globalItemSize)

	//Start mining routines
	var hashRateReportsChannel = make(chan *HashRateReport, nrOfMiningDevices*10)
	for i, device := range clDevices {
		if deviceExcludedForMining(i, *excludedGPUs) {
			continue
		}
		miner := &Miner{
			clDevice:          device,
			minerID:           i,
			hashRateReports:   hashRateReportsChannel,
			miningWorkChannel: workChannel,
			GlobalItemSize:    globalItemSize,
			siad:              siaclient,
		}
		go miner.mine()
	}

	//Start printing out the hashrates of the different gpu's
	hashRateReports := make([]float64, nrOfMiningDevices)
	for {
		//No need to print at every hashreport, we have time
		for i := 0; i < nrOfMiningDevices; i++ {
			report := <-hashRateReportsChannel
			hashRateReports[report.MinerID] = report.HashRate
		}
		fmt.Print("\r")
		var totalHashRate float64
		for minerID, hashrate := range hashRateReports {
			fmt.Printf("%d-%.1f ", minerID, hashrate)
			totalHashRate += hashrate
		}
		fmt.Printf("Total: %.1f MH/s  ", totalHashRate)

	}
}

//deviceExcludedForMining checks if the device is in the exclusion list
func deviceExcludedForMining(deviceID int, excludedGPUs string) bool {
	excludedGPUList := strings.Split(excludedGPUs, ",")
	for _, excludedGPU := range excludedGPUList {
		if strconv.Itoa(deviceID) == excludedGPU {
			return true
		}
	}
	return false
}
<commit_msg>Clear one more more workitem<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/robvanmieghem/go-opencl/cl"
	"github.com/robvanmieghem/gominer/clients"
)

//Version is the released version string of gominer
var Version = "0.5"

var intensity = 28
var devicesTypesForMining = cl.DeviceTypeGPU

const maxUint32 = int64(^uint32(0))

func createWork(siaclient clients.SiaClient, miningWorkChannel chan *MiningWork, nrOfMiningDevices int, globalItemSize int) {
	//Register a function to clear the generated work if a job gets deprecated.
	// It does not matter if we clear too many, it is worse to work on a stale job.
	siaclient.SetDeprecatedJobCall(func() {
		numberOfWorkItemsToRemove := len(miningWorkChannel)
		for i := 0; i <= numberOfWorkItemsToRemove; i++ {
			<-miningWorkChannel
		}
	})

	siaclient.Start()

	for {
		target, header, deprecationChannel, job, err := siaclient.GetHeaderForWork()

		if err != nil {
			log.Println("ERROR fetching work -", err)
			time.Sleep(1000 * time.Millisecond)
			continue
		}

		//copy target to header
		for i := 0; i < 8; i++ {
			header[i+32] = target[7-i]
		}
		//Fill the workchannel with work
		// Only generate nonces for a 32 bit space (since gpu's are mostly 32 bit)
	nonce32loop:
		for i := int64(0); i*int64(globalItemSize) < (maxUint32 - int64(globalItemSize)); i++ {
			//Do not continue mining the 32 bit nonce space if the current job is deprecated
			select {
			case <-deprecationChannel:
				break nonce32loop
			default:
			}

			miningWorkChannel <- &MiningWork{header, int(i) * globalItemSize, job}
		}
	}
}

func main() {
	printVersion := flag.Bool("v", false, "Show version and exit")
	useCPU := flag.Bool("cpu", false, "If set, also use the CPU for mining, only GPU's are used by default")
	flag.IntVar(&intensity, "I", intensity, "Intensity")
	siadHost := flag.String("url", "localhost:9980", "siad host and port, for stratum servers, use `stratum+tcp://<host>:<port>`")
	pooluser := flag.String("user", "payoutaddress.rigname", "username, most stratum servers take this in the form [payoutaddress].[rigname]")
	excludedGPUs := flag.String("E", "", "Exclude GPU's: comma separated list of devicenumbers")
	flag.Parse()

	if *printVersion {
		fmt.Println("gominer version", Version)
		os.Exit(0)
	}

	siaclient := clients.NewSiaClient(*siadHost, *pooluser)

	if *useCPU {
		devicesTypesForMining = cl.DeviceTypeAll
	}
	globalItemSize := int(math.Exp2(float64(intensity)))

	platforms, err := cl.GetPlatforms()
	if err != nil {
		log.Panic(err)
	}

	clDevices := make([]*cl.Device, 0, 4)
	for _, platform := range platforms {
		log.Println("Platform", platform.Name())
		platormDevices, err := cl.GetDevices(platform, devicesTypesForMining)
		if err != nil {
			log.Println(err)
		}
		log.Println(len(platormDevices), "device(s) found:")
		for i, device := range platormDevices {
			log.Println(i, "-", device.Type(), "-", device.Name())
			clDevices = append(clDevices, device)
		}
	}

	nrOfMiningDevices := len(clDevices)

	if nrOfMiningDevices == 0 {
		log.Println("No suitable opencl devices found")
		os.Exit(1)
	}

	//Start fetching work
	workChannel := make(chan *MiningWork, nrOfMiningDevices)
	go createWork(siaclient, workChannel, nrOfMiningDevices, globalItemSize)

	//Start mining routines
	var hashRateReportsChannel = make(chan *HashRateReport, nrOfMiningDevices*10)
	for i, device := range clDevices {
		if deviceExcludedForMining(i, *excludedGPUs) {
			continue
		}
		miner := &Miner{
			clDevice:          device,
			minerID:           i,
			hashRateReports:   hashRateReportsChannel,
			miningWorkChannel: workChannel,
			GlobalItemSize:    globalItemSize,
			siad:              siaclient,
		}
		go miner.mine()
	}

	//Start printing out the hashrates of the different gpu's
	hashRateReports := make([]float64, nrOfMiningDevices)
	for {
		//No need to print at every hashreport, we have time
		for i := 0; i < nrOfMiningDevices; i++ {
			report := <-hashRateReportsChannel
			hashRateReports[report.MinerID] = report.HashRate
		}
		fmt.Print("\r")
		var totalHashRate float64
		for minerID, hashrate := range hashRateReports {
			fmt.Printf("%d-%.1f ", minerID, hashrate)
			totalHashRate += hashrate
		}
		fmt.Printf("Total: %.1f MH/s  ", totalHashRate)

	}
}

//deviceExcludedForMining checks if the device is in the exclusion list
func deviceExcludedForMining(deviceID int, excludedGPUs string) bool {
	excludedGPUList := strings.Split(excludedGPUs, ",")
	for _, excludedGPU := range excludedGPUList {
		if strconv.Itoa(deviceID) == excludedGPU {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"unicode/utf16"
)

type File struct {
	stringPool  *ResStringPool
	resourceMap []uint32
	Namespace   *ResXMLTreeNamespaceExt
	XMLBuffer   bytes.Buffer
}

const (
	RES_NULL_TYPE        = 0x0000
	RES_STRING_POOL_TYPE = 0x0001
	RES_TABLE_TYPE       = 0x0002
	RES_XML_TYPE         = 0x0003

	// Chunk types in RES_XML_TYPE
	RES_XML_FIRST_CHUNK_TYPE     = 0x0100
	RES_XML_START_NAMESPACE_TYPE = 0x0100
	RES_XML_END_NAMESPACE_TYPE   = 0x0101
	RES_XML_START_ELEMENT_TYPE   = 0x0102
	RES_XML_END_ELEMENT_TYPE     = 0x0103
	RES_XML_CDATA_TYPE           = 0x0104
	RES_XML_LAST_CHUNK_TYPE      = 0x017f

	// This contains a uint32_t array mapping strings in the string
	// pool back to resource identifiers.  It is optional.
	RES_XML_RESOURCE_MAP_TYPE = 0x0180

	// Chunk types in RES_TABLE_TYPE
	RES_TABLE_PACKAGE_TYPE   = 0x0200
	RES_TABLE_TYPE_TYPE      = 0x0201
	RES_TABLE_TYPE_SPEC_TYPE = 0x0202
)

type ResChunkHeader struct {
	Type       uint16
	HeaderSize uint16
	Size       uint32
}

const SORTED_FLAG = 1 << 0
const UTF8_FLAG = 1 << 8

type ResStringPoolRef uint32

const NilResStringPoolRef = ResStringPoolRef(0xFFFFFFFF)

type ResStringPoolHeader struct {
	Header      ResChunkHeader
	StringCount uint32
	StyleCount  uint32
	Flags       uint32
	StringStart uint32
	StylesStart uint32
}

type ResStringPool struct {
	Header  ResStringPoolHeader
	Strings []string
	Styles  []string
}

type ResXMLTreeNode struct {
	Header     ResChunkHeader
	LineNumber uint32
	Comment    ResStringPoolRef
}

type ResXMLTreeNamespaceExt struct {
	Prefix ResStringPoolRef
	Uri    ResStringPoolRef
}

type ResXMLTreeAttrExt struct {
	NS             ResStringPoolRef
	Name           ResStringPoolRef
	AttributeStart uint16
	AttributeSize  uint16
	AttributeCount uint16
	IdIndex        uint16
	ClassIndex     uint16
	StyleIndex     uint16
}

type ResXMLTreeAttribute struct {
	NS         ResStringPoolRef
	Name       ResStringPoolRef
	RawValue   ResStringPoolRef
	TypedValue ResValue
}

const (
	TYPE_NULL            = 0x00
	TYPE_REFERENCE       = 0x01
	TYPE_ATTRIBUTE       = 0x02
	TYPE_STRING          = 0x03
	TYPE_FLOAT           = 0x04
	TYPE_DIMENSION       = 0x05
	TYPE_FRACTION        = 0x06
	TYPE_FIRST_INT       = 0x10
	TYPE_INT_DEC         = 0x10
	TYPE_INT_HEX         = 0x11
	TYPE_INT_BOOLEAN     = 0x12
	TYPE_FIRST_COLOR_INT = 0x1c
	TYPE_INT_COLOR_ARGB8 = 0x1c
	TYPE_INT_COLOR_RGB8  = 0x1d
	TYPE_INT_COLOR_ARGB4 = 0x1e
	TYPE_INT_COLOR_RGB4  = 0x1f
	TYPE_LAST_COLOR_INT  = 0x1f
	TYPE_LAST_INT        = 0x1f
)

type ResValue struct {
	Size     uint16
	Res0     uint8
	DataType uint8
	Data     uint32
}

type ResXMLTreeEndElementExt struct {
	NS   ResStringPoolRef
	Name ResStringPoolRef
}

func NewFile(r io.ReaderAt) (*File, error) {
	f := new(File)
	sr := io.NewSectionReader(r, 0, 1<<63-1)

	header := new(ResChunkHeader)
	binary.Read(sr, binary.LittleEndian, header)
	offset := uint32(header.HeaderSize)

	for offset < header.Size {
		sr.Seek(int64(offset), os.SEEK_SET)
		chunkHeader := &ResChunkHeader{}
		binary.Read(sr, binary.LittleEndian, chunkHeader)

		var err error
		chunkReader := io.NewSectionReader(r, int64(offset), int64(chunkHeader.Size))
		switch chunkHeader.Type {
		case RES_STRING_POOL_TYPE:
			f.stringPool, err = ReadStringPool(chunkReader)
		case RES_XML_RESOURCE_MAP_TYPE:
			f.resourceMap, err = ReadResourceMap(chunkReader)
		case RES_XML_START_NAMESPACE_TYPE:
			err = f.ReadStartNamespace(chunkReader)
		case RES_XML_START_ELEMENT_TYPE:
			err = f.ReadStartElement(chunkReader)
		case RES_XML_END_ELEMENT_TYPE:
			err = f.ReadEndElement(chunkReader)
		}
		if err != nil {
			return nil, err
		}

		offset += chunkHeader.Size
	}
	return f, nil
}

func (f *File) GetString(ref ResStringPoolRef) string {
	if ref == NilResStringPoolRef {
		return ""
	}
	return f.stringPool.Strings[int(ref)]
}

func ReadStringPool(sr *io.SectionReader) (*ResStringPool, error) {
	sp := new(ResStringPool)
	binary.Read(sr, binary.LittleEndian, &sp.Header)

	stringStarts := make([]uint32, sp.Header.StringCount)
	binary.Read(sr, binary.LittleEndian, stringStarts)
	styleStarts := make([]uint32, sp.Header.StyleCount)
	binary.Read(sr, binary.LittleEndian, styleStarts)

	sp.Strings = make([]string, sp.Header.StringCount)
	for i, start := range stringStarts {
		var str string
		var err error
		if (sp.Header.Flags & UTF8_FLAG) == 0 {
			str, err = ReadUTF16(sr, int64(sp.Header.StringStart+start))
		} else {
			str, err = ReadUTF8(sr, int64(sp.Header.StringStart+start))
		}
		if err != nil {
			return nil, err
		}
		sp.Strings[i] = str
	}

	sp.Styles = make([]string, sp.Header.StyleCount)
	for i, start := range styleStarts {
		var str string
		var err error
		if (sp.Header.Flags & UTF8_FLAG) == 0 {
			str, err = ReadUTF16(sr, int64(sp.Header.StylesStart+start))
		} else {
			str, err = ReadUTF8(sr, int64(sp.Header.StylesStart+start))
		}
		if err != nil {
			return nil, err
		}
		sp.Styles[i] = str
	}

	return sp, nil
}

func ReadUTF16(sr *io.SectionReader, offset int64) (string, error) {
	var size uint16
	sr.Seek(offset, os.SEEK_SET)
	if err := binary.Read(sr, binary.LittleEndian, &size); err != nil {
		return "", err
	}
	buf := make([]uint16, size)
	if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
		return "", err
	}
	return string(utf16.Decode(buf)), nil
}

func ReadUTF8(sr *io.SectionReader, offset int64) (string, error) {
	var size uint16
	sr.Seek(offset, os.SEEK_SET)
	if err := binary.Read(sr, binary.LittleEndian, &size); err != nil {
		return "", err
	}
	buf := make([]uint8, size)
	if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
		return "", err
	}
	return string(buf), nil
}

func ReadResourceMap(sr *io.SectionReader) ([]uint32, error) {
	header := new(ResChunkHeader)
	binary.Read(sr, binary.LittleEndian, header)
	count := (header.Size - uint32(header.HeaderSize)) / 4
	resourceMap := make([]uint32, count)
	if err := binary.Read(sr, binary.LittleEndian, resourceMap); err != nil {
		return nil, err
	}
	return resourceMap, nil
}

func (f *File) ReadStartNamespace(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	binary.Read(sr, binary.LittleEndian, header)
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	namespace := new(ResXMLTreeNamespaceExt)
	binary.Read(sr, binary.LittleEndian, namespace)
	f.Namespace = namespace
	return nil
}

func (f *File) ReadStartElement(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	binary.Read(sr, binary.LittleEndian, header)
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	ext := new(ResXMLTreeAttrExt)
	binary.Read(sr, binary.LittleEndian, ext)

	fmt.Fprintf(&f.XMLBuffer, "<%s", f.AddNamespace(ext.NS, ext.Name))

	offset := int64(ext.AttributeStart + header.Header.HeaderSize)
	for i := 0; i < int(ext.AttributeCount); i++ {
		sr.Seek(offset, os.SEEK_SET)
		attr := new(ResXMLTreeAttribute)
		binary.Read(sr, binary.LittleEndian, attr)

		var value string
		if attr.RawValue != NilResStringPoolRef {
			value = f.GetString(attr.RawValue)
		} else {
			data := attr.TypedValue.Data
			switch attr.TypedValue.DataType {
			case TYPE_NULL:
				value = ""
			case TYPE_REFERENCE:
				value = fmt.Sprintf("@0x%08X", data)
			case TYPE_INT_DEC:
				value = fmt.Sprintf("%d", data)
			case TYPE_INT_HEX:
				value = fmt.Sprintf("0x%08X", data)
			case TYPE_INT_BOOLEAN:
				if data != 0 {
					value = "true"
				} else {
					value = "false"
				}
			default:
				value = fmt.Sprintf("@0x%08X", data)
			}
		}

		fmt.Fprintf(&f.XMLBuffer, " %s=\"%s\"", f.AddNamespace(attr.NS, attr.Name), value)
		offset += int64(ext.AttributeSize)
	}
	fmt.Fprint(&f.XMLBuffer, ">")
	return nil
}

func (f *File) ReadEndElement(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	if err := binary.Read(sr, binary.LittleEndian, header); err != nil {
		return err
	}
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	ext := new(ResXMLTreeEndElementExt)
	if err := binary.Read(sr, binary.LittleEndian, ext); err != nil {
		return err
	}
	fmt.Fprintf(&f.XMLBuffer, "</%s>", f.AddNamespace(ext.NS, ext.Name))
	return nil
}

func (f *File) AddNamespace(ns, name ResStringPoolRef) string {
	if ns != NilResStringPoolRef {
		return fmt.Sprintf("%s:%s", f.GetString(f.Namespace.Prefix), f.GetString(name))
	} else {
		return f.GetString(name)
	}
}

func main() {
	f, _ := os.Open("AndroidManifest.xml")
	xml, _ := NewFile(f)
	fmt.Println(xml.XMLBuffer.String())
}
<commit_msg>属性値をエスケープ<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"unicode/utf16"
)

type File struct {
	stringPool  *ResStringPool
	resourceMap []uint32
	Namespace   *ResXMLTreeNamespaceExt
	XMLBuffer   bytes.Buffer
}

const (
	RES_NULL_TYPE        = 0x0000
	RES_STRING_POOL_TYPE = 0x0001
	RES_TABLE_TYPE       = 0x0002
	RES_XML_TYPE         = 0x0003

	// Chunk types in RES_XML_TYPE
	RES_XML_FIRST_CHUNK_TYPE     = 0x0100
	RES_XML_START_NAMESPACE_TYPE = 0x0100
	RES_XML_END_NAMESPACE_TYPE   = 0x0101
	RES_XML_START_ELEMENT_TYPE   = 0x0102
	RES_XML_END_ELEMENT_TYPE     = 0x0103
	RES_XML_CDATA_TYPE           = 0x0104
	RES_XML_LAST_CHUNK_TYPE      = 0x017f

	// This contains a uint32_t array mapping strings in the string
	// pool back to resource identifiers.  It is optional.
	RES_XML_RESOURCE_MAP_TYPE = 0x0180

	// Chunk types in RES_TABLE_TYPE
	RES_TABLE_PACKAGE_TYPE   = 0x0200
	RES_TABLE_TYPE_TYPE      = 0x0201
	RES_TABLE_TYPE_SPEC_TYPE = 0x0202
)

type ResChunkHeader struct {
	Type       uint16
	HeaderSize uint16
	Size       uint32
}

const SORTED_FLAG = 1 << 0
const UTF8_FLAG = 1 << 8

type ResStringPoolRef uint32

const NilResStringPoolRef = ResStringPoolRef(0xFFFFFFFF)

type ResStringPoolHeader struct {
	Header      ResChunkHeader
	StringCount uint32
	StyleCount  uint32
	Flags       uint32
	StringStart uint32
	StylesStart uint32
}

type ResStringPool struct {
	Header  ResStringPoolHeader
	Strings []string
	Styles  []string
}

type ResXMLTreeNode struct {
	Header     ResChunkHeader
	LineNumber uint32
	Comment    ResStringPoolRef
}

type ResXMLTreeNamespaceExt struct {
	Prefix ResStringPoolRef
	Uri    ResStringPoolRef
}

type ResXMLTreeAttrExt struct {
	NS             ResStringPoolRef
	Name           ResStringPoolRef
	AttributeStart uint16
	AttributeSize  uint16
	AttributeCount uint16
	IdIndex        uint16
	ClassIndex     uint16
	StyleIndex     uint16
}

type ResXMLTreeAttribute struct {
	NS         ResStringPoolRef
	Name       ResStringPoolRef
	RawValue   ResStringPoolRef
	TypedValue ResValue
}

const (
	TYPE_NULL            = 0x00
	TYPE_REFERENCE       = 0x01
	TYPE_ATTRIBUTE       = 0x02
	TYPE_STRING          = 0x03
	TYPE_FLOAT           = 0x04
	TYPE_DIMENSION       = 0x05
	TYPE_FRACTION        = 0x06
	TYPE_FIRST_INT       = 0x10
	TYPE_INT_DEC         = 0x10
	TYPE_INT_HEX         = 0x11
	TYPE_INT_BOOLEAN     = 0x12
	TYPE_FIRST_COLOR_INT = 0x1c
	TYPE_INT_COLOR_ARGB8 = 0x1c
	TYPE_INT_COLOR_RGB8  = 0x1d
	TYPE_INT_COLOR_ARGB4 = 0x1e
	TYPE_INT_COLOR_RGB4  = 0x1f
	TYPE_LAST_COLOR_INT  = 0x1f
	TYPE_LAST_INT        = 0x1f
)

type ResValue struct {
	Size     uint16
	Res0     uint8
	DataType uint8
	Data     uint32
}

type ResXMLTreeEndElementExt struct {
	NS   ResStringPoolRef
	Name ResStringPoolRef
}

func NewFile(r io.ReaderAt) (*File, error) {
	f := new(File)
	sr := io.NewSectionReader(r, 0, 1<<63-1)

	header := new(ResChunkHeader)
	binary.Read(sr, binary.LittleEndian, header)
	offset := uint32(header.HeaderSize)

	for offset < header.Size {
		sr.Seek(int64(offset), os.SEEK_SET)
		chunkHeader := &ResChunkHeader{}
		binary.Read(sr, binary.LittleEndian, chunkHeader)

		var err error
		chunkReader := io.NewSectionReader(r, int64(offset), int64(chunkHeader.Size))
		switch chunkHeader.Type {
		case RES_STRING_POOL_TYPE:
			f.stringPool, err = ReadStringPool(chunkReader)
		case RES_XML_RESOURCE_MAP_TYPE:
			f.resourceMap, err = ReadResourceMap(chunkReader)
		case RES_XML_START_NAMESPACE_TYPE:
			err = f.ReadStartNamespace(chunkReader)
		case RES_XML_START_ELEMENT_TYPE:
			err = f.ReadStartElement(chunkReader)
		case RES_XML_END_ELEMENT_TYPE:
			err = f.ReadEndElement(chunkReader)
		}
		if err != nil {
			return nil, err
		}

		offset += chunkHeader.Size
	}
	return f, nil
}

func (f *File) GetString(ref ResStringPoolRef) string {
	if ref == NilResStringPoolRef {
		return ""
	}
	return f.stringPool.Strings[int(ref)]
}

func ReadStringPool(sr *io.SectionReader) (*ResStringPool, error) {
	sp := new(ResStringPool)
	binary.Read(sr, binary.LittleEndian, &sp.Header)

	stringStarts := make([]uint32, sp.Header.StringCount)
	binary.Read(sr, binary.LittleEndian, stringStarts)
	styleStarts := make([]uint32, sp.Header.StyleCount)
	binary.Read(sr, binary.LittleEndian, styleStarts)

	sp.Strings = make([]string, sp.Header.StringCount)
	for i, start := range stringStarts {
		var str string
		var err error
		if (sp.Header.Flags & UTF8_FLAG) == 0 {
			str, err = ReadUTF16(sr, int64(sp.Header.StringStart+start))
		} else {
			str, err = ReadUTF8(sr, int64(sp.Header.StringStart+start))
		}
		if err != nil {
			return nil, err
		}
		sp.Strings[i] = str
	}

	sp.Styles = make([]string, sp.Header.StyleCount)
	for i, start := range styleStarts {
		var str string
		var err error
		if (sp.Header.Flags & UTF8_FLAG) == 0 {
			str, err = ReadUTF16(sr, int64(sp.Header.StylesStart+start))
		} else {
			str, err = ReadUTF8(sr, int64(sp.Header.StylesStart+start))
		}
		if err != nil {
			return nil, err
		}
		sp.Styles[i] = str
	}

	return sp, nil
}

func ReadUTF16(sr *io.SectionReader, offset int64) (string, error) {
	var size uint16
	sr.Seek(offset, os.SEEK_SET)
	if err := binary.Read(sr, binary.LittleEndian, &size); err != nil {
		return "", err
	}
	buf := make([]uint16, size)
	if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
		return "", err
	}
	return string(utf16.Decode(buf)), nil
}

func ReadUTF8(sr *io.SectionReader, offset int64) (string, error) {
	var size uint16
	sr.Seek(offset, os.SEEK_SET)
	if err := binary.Read(sr, binary.LittleEndian, &size); err != nil {
		return "", err
	}
	buf := make([]uint8, size)
	if err := binary.Read(sr, binary.LittleEndian, buf); err != nil {
		return "", err
	}
	return string(buf), nil
}

func ReadResourceMap(sr *io.SectionReader) ([]uint32, error) {
	header := new(ResChunkHeader)
	binary.Read(sr, binary.LittleEndian, header)
	count := (header.Size - uint32(header.HeaderSize)) / 4
	resourceMap := make([]uint32, count)
	if err := binary.Read(sr, binary.LittleEndian, resourceMap); err != nil {
		return nil, err
	}
	return resourceMap, nil
}

func (f *File) ReadStartNamespace(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	binary.Read(sr, binary.LittleEndian, header)
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	namespace := new(ResXMLTreeNamespaceExt)
	binary.Read(sr, binary.LittleEndian, namespace)
	f.Namespace = namespace
	return nil
}

func (f *File) ReadStartElement(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	binary.Read(sr, binary.LittleEndian, header)
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	ext := new(ResXMLTreeAttrExt)
	binary.Read(sr, binary.LittleEndian, ext)

	fmt.Fprintf(&f.XMLBuffer, "<%s", f.AddNamespace(ext.NS, ext.Name))

	offset := int64(ext.AttributeStart + header.Header.HeaderSize)
	for i := 0; i < int(ext.AttributeCount); i++ {
		sr.Seek(offset, os.SEEK_SET)
		attr := new(ResXMLTreeAttribute)
		binary.Read(sr, binary.LittleEndian, attr)

		var value string
		if attr.RawValue != NilResStringPoolRef {
			value = f.GetString(attr.RawValue)
		} else {
			data := attr.TypedValue.Data
			switch attr.TypedValue.DataType {
			case TYPE_NULL:
				value = ""
			case TYPE_REFERENCE:
				value = fmt.Sprintf("@0x%08X", data)
			case TYPE_INT_DEC:
				value = fmt.Sprintf("%d", data)
			case TYPE_INT_HEX:
				value = fmt.Sprintf("0x%08X", data)
			case TYPE_INT_BOOLEAN:
				if data != 0 {
					value = "true"
				} else {
					value = "false"
				}
			default:
				value = fmt.Sprintf("@0x%08X", data)
			}
		}

		fmt.Fprintf(&f.XMLBuffer, " %s=\"", f.AddNamespace(attr.NS, attr.Name))
		xml.Escape(&f.XMLBuffer, []byte(value))
		fmt.Fprint(&f.XMLBuffer, "\"")
		offset += int64(ext.AttributeSize)
	}
	fmt.Fprint(&f.XMLBuffer, ">")
	return nil
}

func (f *File) ReadEndElement(sr *io.SectionReader) error {
	header := new(ResXMLTreeNode)
	if err := binary.Read(sr, binary.LittleEndian, header); err != nil {
		return err
	}
	sr.Seek(int64(header.Header.HeaderSize), os.SEEK_SET)
	ext := new(ResXMLTreeEndElementExt)
	if err := binary.Read(sr, binary.LittleEndian, ext); err != nil {
		return err
	}
	fmt.Fprintf(&f.XMLBuffer, "</%s>", f.AddNamespace(ext.NS, ext.Name))
	return nil
}

func (f *File) AddNamespace(ns, name ResStringPoolRef) string {
	if ns != NilResStringPoolRef {
		return fmt.Sprintf("%s:%s", f.GetString(f.Namespace.Prefix), f.GetString(name))
	} else {
		return f.GetString(name)
	}
}

func main() {
	f, _ := os.Open("AndroidManifest.xml")
	xml, _ := NewFile(f)
	fmt.Println(xml.XMLBuffer.String())
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/pkg/profile"
	"github.com/verath/archipelago/lib"
	"net/http"
	"os"
	"os/signal"
	"path"
	"time"
)

const (
	httpReadTimeout  = 10 * time.Second
	httpWriteTimeout = 10 * time.Second
)

func main() {
	var (
		debug       bool
		serveStatic bool
		serverAddr  string
		profileMode string
	)
	flag.BoolVar(&debug, "debug", false, "Set to true to log debug messages.")
	flag.BoolVar(&serveStatic, "servestatic", false, "Enable serving of static assets.")
	flag.StringVar(&serverAddr, "addr", ":8080", "TCP address for the http server to listen on.")
	flag.StringVar(&profileMode, "profile", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
	flag.Parse()

	logger := logrus.New()
	logger.Formatter = &logrus.TextFormatter{}
	if debug {
		logger.Level = logrus.DebugLevel
	}
	// Setup profiling, if profile flag was set
	switch profileMode {
	case "cpu":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.BlockProfile).Stop()
	default:
	}

	archipelagoServer, err := archipelago.New(logger)
	if err != nil {
		logger.Fatalf("Error creating game: %+v", err)
	}

	http.Handle("/ws", archipelagoServer.WebsocketHandler())
	if serveStatic {
		staticPath := "./web/dist"
		// Explicitly set a max-age of 0 for service worker script.
		http.HandleFunc("/sw.js", func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Cache-Control", "max-age=0")
			http.ServeFile(w, r, path.Join(staticPath, "sw.js"))
		})
		http.Handle("/", http.FileServer(http.Dir(staticPath)))
	}
	http.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})
	httpServer := &http.Server{
		Addr:         serverAddr,
		ReadTimeout:  httpReadTimeout,
		WriteTimeout: httpWriteTimeout,
	}

	ctx, cancel := context.WithCancel(lifetimeContext(logger))
	errCh := make(chan error)
	go func() { errCh <- archipelagoServer.Run(ctx) }()
	go func() { errCh <- runHTTPServer(ctx, httpServer) }()
	err = <-errCh
	cancel()
	<-errCh
	if errors.Cause(err) == context.Canceled {
		logger.Debugf("Error caught in main: %+v", err)
	} else {
		logger.Fatalf("Error caught in main: %+v", err)
	}
}

// lifetimeContext returns a context that is cancelled on the first SIGINT or
// SIGKILL signal received. The application is force closed if more than
// one signal is received.
func lifetimeContext(logger *logrus.Logger) context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	stopSigs := make(chan os.Signal, 2)
	signal.Notify(stopSigs, os.Interrupt, os.Kill)
	go func() {
		<-stopSigs
		logger.Info("Caught interrupt, shutting down")
		cancel()
		<-stopSigs
		logger.Fatal("Caught second interrupt, force closing")
	}()
	return ctx
}

// runHTTPServer starts and runs the given HTTP server until either an error
// occurs or the context is cancelled.
func runHTTPServer(ctx context.Context, server *http.Server) error {
	errCh := make(chan error)
	go func() { errCh <- server.ListenAndServe() }()
	select {
	case err := <-errCh:
		return err
	case <-ctx.Done():
		server.Close()
		return ctx.Err()
	}
}
<commit_msg>Moves registering status handler above static serving<commit_after>package main

import (
	"context"
	"flag"
	"github.com/Sirupsen/logrus"
	"github.com/pkg/errors"
	"github.com/pkg/profile"
	"github.com/verath/archipelago/lib"
	"net/http"
	"os"
	"os/signal"
	"path"
	"time"
)

const (
	httpReadTimeout  = 10 * time.Second
	httpWriteTimeout = 10 * time.Second
)

func main() {
	var (
		debug       bool
		serveStatic bool
		serverAddr  string
		profileMode string
	)
	flag.BoolVar(&debug, "debug", false, "Set to true to log debug messages.")
	flag.BoolVar(&serveStatic, "servestatic", false, "Enable serving of static assets.")
	flag.StringVar(&serverAddr, "addr", ":8080", "TCP address for the http server to listen on.")
	flag.StringVar(&profileMode, "profile", "", "Enable profiling mode, one of [cpu, mem, mutex, block]")
	flag.Parse()

	logger := logrus.New()
	logger.Formatter = &logrus.TextFormatter{}
	if debug {
		logger.Level = logrus.DebugLevel
	}
	// Setup profiling, if profile flag was set
	switch profileMode {
	case "cpu":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop()
	case "mem":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MemProfile).Stop()
	case "mutex":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.MutexProfile).Stop()
	case "block":
		defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.BlockProfile).Stop()
	default:
	}

	archipelagoServer, err := archipelago.New(logger)
	if err != nil {
		logger.Fatalf("Error creating game: %+v", err)
	}

	http.Handle("/ws", archipelagoServer.WebsocketHandler())
	http.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("OK"))
	})
	if serveStatic {
		staticPath := "./web/dist"
		// Explicitly set a max-age of 0 for service worker script.
		http.HandleFunc("/sw.js", func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Cache-Control", "max-age=0")
			http.ServeFile(w, r, path.Join(staticPath, "sw.js"))
		})
		http.Handle("/", http.FileServer(http.Dir(staticPath)))
	}
	httpServer := &http.Server{
		Addr:         serverAddr,
		ReadTimeout:  httpReadTimeout,
		WriteTimeout: httpWriteTimeout,
	}

	ctx, cancel := context.WithCancel(lifetimeContext(logger))
	errCh := make(chan error)
	go func() { errCh <- archipelagoServer.Run(ctx) }()
	go func() { errCh <- runHTTPServer(ctx, httpServer) }()
	err = <-errCh
	cancel()
	<-errCh
	if errors.Cause(err) == context.Canceled {
		logger.Debugf("Error caught in main: %+v", err)
	} else {
		logger.Fatalf("Error caught in main: %+v", err)
	}
}

// lifetimeContext returns a context that is cancelled on the first SIGINT or
// SIGKILL signal received. The application is force closed if more than
// one signal is received.
func lifetimeContext(logger *logrus.Logger) context.Context {
	ctx, cancel := context.WithCancel(context.Background())
	stopSigs := make(chan os.Signal, 2)
	signal.Notify(stopSigs, os.Interrupt, os.Kill)
	go func() {
		<-stopSigs
		logger.Info("Caught interrupt, shutting down")
		cancel()
		<-stopSigs
		logger.Fatal("Caught second interrupt, force closing")
	}()
	return ctx
}

// runHTTPServer starts and runs the given HTTP server until either an error
// occurs or the context is cancelled.
func runHTTPServer(ctx context.Context, server *http.Server) error {
	errCh := make(chan error)
	go func() { errCh <- server.ListenAndServe() }()
	select {
	case err := <-errCh:
		return err
	case <-ctx.Done():
		server.Close()
		return ctx.Err()
	}
}
<|endoftext|>


<commit_before>/*

Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

package main

import (
	"flag"

	"github.com/golang/glog"
	"github.com/google/go-microservice-helpers/server"
	"github.com/google/go-microservice-helpers/tracing"
	"github.com/grpc-ecosystem/go-grpc-prometheus"
	"google.golang.org/grpc/reflection"

	pb "github.com/google/lvmd/proto"
	"github.com/google/lvmd/server"
)

func main() {
	flag.Parse()
	defer glog.Flush()

	err := tracing.InitTracer(*serverhelpers.ListenAddress, "lvmd")
	if err != nil {
		glog.Fatalf("failed to init tracing interface: %v", err)
	}

	svr := server.NewServer()

	grpcServer, _, err := serverhelpers.NewServer()
	if err != nil {
		glog.Fatalf("failed to init GRPC server: %v", err)
	}

	pb.RegisterLVMServer(grpcServer, &svr)
	reflection.Register(grpcServer)
	grpc_prometheus.Register(grpcServer)

	err = serverhelpers.ListenAndServe(grpcServer, nil)
	if err != nil {
		glog.Fatalf("failed to serve: %v", err)
	}
}
<commit_msg>Fixed duplicate services being registered<commit_after>/*

Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

package main

import (
	"flag"

	"github.com/golang/glog"
	"github.com/google/go-microservice-helpers/server"
	"github.com/google/go-microservice-helpers/tracing"

	pb "github.com/google/lvmd/proto"
	"github.com/google/lvmd/server"
)

func main() {
	flag.Parse()
	defer glog.Flush()

	err := tracing.InitTracer(*serverhelpers.ListenAddress, "lvmd")
	if err != nil {
		glog.Fatalf("failed to init tracing interface: %v", err)
	}

	svr := server.NewServer()

	grpcServer, _, err := serverhelpers.NewServer()
	if err != nil {
		glog.Fatalf("failed to init GRPC server: %v", err)
	}

	pb.RegisterLVMServer(grpcServer, &svr)

	err = serverhelpers.ListenAndServe(grpcServer, nil)
	if err != nil {
		glog.Fatalf("failed to serve: %v", err)
	}
}
<|endoftext|>


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

// Glusterfs exorter currently scaping volume info
package main

import (
	"flag"
	"net/http"
	"os/exec"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"bytes"
	"encoding/xml"
	"io/ioutil"
	"github.com/prometheus/common/log"
	"strconv"
	"fmt"
	"github.com/prometheus/common/version"
	"os"
)

const (
	VERSION string = "0.1.0"
)

type CliOutput struct {
	XMLName  xml.Name  `xml:"cliOutput"`
	OpRet    int         `xml:"opRet"`
	OpErrno  int       `xml:"opErrno"`
	OpErrstr string   `xml:"opErrstr"`
	VolInfo  VolInfo   `xml:"volInfo"`
}

type VolInfo struct {
	XMLName xml.Name  `xml:"volInfo"`
	Volumes Volumes   `xml:"volumes"`
}

type Volumes struct {
	XMLName xml.Name  `xml:"volumes"`
	Volume  []Volume   `xml:"volume"`
	Count   int         `xml:"count"`
}

type Volume struct {
	XMLName    xml.Name  `xml:"volume"`
	Name       string       `xml:"name"`
	Id         string         `xml:"id"`
	Status     int        `xml:"status"`
	StatusStr  string  `xml:"statusStr"`
	BrickCount int    `xml:"brickCount"`
	Bricks     []Brick    `xml:"bricks"`
	DistCount  int     `xml:"distCount"`
}

type Brick struct {
	Uuid      string       `xml:"brick>uuid"`
	Name      string       `xml:"brick>name"`
	HostUuid  string   `xml:"brick>hostUuid"`
	IsArbiter int     `xml:"brick>isArbiter"`
}

var (
	// Error number from GlusterFS
	errno = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_errno",
			Help:"Error Number Glusterfs",
		},
		[]string{},
	)

	// creates a gauge of active nodes in glusterfs
	volume_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_volume_count",
			Help:"Number of active glusterfs nodes",
		},
		[]string{},
	)

	// Count of bricks for gluster volume
	brick_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_brick_count",
			Help:"Count of bricks for gluster volume",
		},
		[]string{"volume"},
	)

	// distribution count of bricks
	distribution_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_nodes_active",
			Help:"distribution count of bricks",
		},
		[]string{"volume"},
	)
)

func init() {
	// register metric to prometheus's default registry
	prometheus.MustRegister(errno)
	prometheus.MustRegister(volume_count)
	prometheus.MustRegister(brick_count)
	prometheus.MustRegister(distribution_count)
}

func versionInfo() {
	fmt.Println("Gluster Exporter Version: ", VERSION)
	fmt.Println("Tested Gluster Version:   ", "3.8.5")
	fmt.Println("Go Version:               ", version.GoVersion)

	os.Exit(0)
}

func GlusterVolumeInfo(sec_int int) {
	// Gluster Info
	cmd_profile := exec.Command("/usr/sbin/gluster", "volume", "info", "--xml")
	//cmd_profile := exec.Command("/home/oli/dev/glusterfs_exporter_go/gluster_info")

	stdOutbuff := &bytes.Buffer{}

	cmd_profile.Stdout = stdOutbuff

	err := cmd_profile.Run()

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

	var vol CliOutput
	b, err := ioutil.ReadAll(stdOutbuff)
	if err != nil {
		log.Fatal(err)
	}
	xml.Unmarshal(b, &vol)

	// set opErrno
	errno.WithLabelValues().Set(float64(vol.OpErrno))
	log.Debug("opErrno: %v", vol.OpErrno)

	// set volume count
	volume_count.WithLabelValues().Set(float64(vol.VolInfo.Volumes.Count))
	log.Debug("volume_count: %v", vol.VolInfo.Volumes.Count)

	// Volume based values
	for _, v := range vol.VolInfo.Volumes.Volume {
		// brick count with volume label
		brick_count.WithLabelValues(v.Name).Set(float64(v.BrickCount))
		log.Debug("opErrno: %v", vol.OpErrno)

		// distribution count with volume label
		distribution_count.WithLabelValues(v.Name).Set(float64(v.DistCount))
		log.Debug("opErrno: %v", vol.OpErrno)

	}
}

func glusterProfile(sec_int int) {
	// Gluster Profile

	// Get gluster volumes, then call gluster profile on every volume

	//  gluster volume profile gv_leoticket info cumulative --xml
	//cmd_profile := exec.Command("/usr/sbin/gluster", "volume", "profile", "gv_leoticket", "info", "cumulative", "--xml")
}

func main() {

	// commandline arguments
	var (
		metricPath = flag.String("metrics-path", "/metrics", "URL Endpoint for metrics")
		addr = flag.String("listen-address", ":9189", "The address to listen on for HTTP requests.")
		sec = flag.String("scrape-seconds", "2", "Frequency of scraping glusterfs in seconds")
		version_tag = flag.Bool("version", false, "Prints version information")
	)

	flag.Parse()

	if *version_tag {
		versionInfo()
	}

	log.Info("GlusterFS Metrics Exporter v", VERSION)

	// ensure that sec is int
	sec_int, err := strconv.Atoi(*sec)
	if err != nil {
		log.Fatal("Parameter -scrape-seconds is not an int value")
	}

	// gluster volume info
	go GlusterVolumeInfo(sec_int)

	http.Handle("/metrics", promhttp.Handler())
	log.Fatal(http.ListenAndServe(*addr, nil))
}
<commit_msg>adds welcome page<commit_after>// Copyright 2015 Oliver Fesseler
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Glusterfs exorter currently scaping volume info
package main

import (
	"flag"
	"net/http"
	"os/exec"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"bytes"
	"encoding/xml"
	"io/ioutil"
	"github.com/prometheus/common/log"
	"strconv"
	"fmt"
	"github.com/prometheus/common/version"
	"os"
)

const (
	VERSION string = "0.1.0"
)

type CliOutput struct {
	XMLName  xml.Name  `xml:"cliOutput"`
	OpRet    int         `xml:"opRet"`
	OpErrno  int       `xml:"opErrno"`
	OpErrstr string   `xml:"opErrstr"`
	VolInfo  VolInfo   `xml:"volInfo"`
}

type VolInfo struct {
	XMLName xml.Name  `xml:"volInfo"`
	Volumes Volumes   `xml:"volumes"`
}

type Volumes struct {
	XMLName xml.Name  `xml:"volumes"`
	Volume  []Volume   `xml:"volume"`
	Count   int         `xml:"count"`
}

type Volume struct {
	XMLName    xml.Name  `xml:"volume"`
	Name       string       `xml:"name"`
	Id         string         `xml:"id"`
	Status     int        `xml:"status"`
	StatusStr  string  `xml:"statusStr"`
	BrickCount int    `xml:"brickCount"`
	Bricks     []Brick    `xml:"bricks"`
	DistCount  int     `xml:"distCount"`
}

type Brick struct {
	Uuid      string       `xml:"brick>uuid"`
	Name      string       `xml:"brick>name"`
	HostUuid  string   `xml:"brick>hostUuid"`
	IsArbiter int     `xml:"brick>isArbiter"`
}

var (
	// Error number from GlusterFS
	errno = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_errno",
			Help:"Error Number Glusterfs",
		},
		[]string{},
	)

	// creates a gauge of active nodes in glusterfs
	volume_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_volume_count",
			Help:"Number of active glusterfs nodes",
		},
		[]string{},
	)

	// Count of bricks for gluster volume
	brick_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_brick_count",
			Help:"Count of bricks for gluster volume",
		},
		[]string{"volume"},
	)

	// distribution count of bricks
	distribution_count = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name:"glusterfs_nodes_active",
			Help:"distribution count of bricks",
		},
		[]string{"volume"},
	)
)

func init() {
	// register metric to prometheus's default registry
	prometheus.MustRegister(errno)
	prometheus.MustRegister(volume_count)
	prometheus.MustRegister(brick_count)
	prometheus.MustRegister(distribution_count)
}

func versionInfo() {
	fmt.Println("Gluster Exporter Version: ", VERSION)
	fmt.Println("Tested Gluster Version:   ", "3.8.5")
	fmt.Println("Go Version:               ", version.GoVersion)

	os.Exit(0)
}

func GlusterVolumeInfo(sec_int int) {
	// Gluster Info
	cmd_profile := exec.Command("/usr/sbin/gluster", "volume", "info", "--xml")
	//cmd_profile := exec.Command("/home/oli/dev/glusterfs_exporter_go/gluster_info")

	stdOutbuff := &bytes.Buffer{}

	cmd_profile.Stdout = stdOutbuff

	err := cmd_profile.Run()

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

	var vol CliOutput
	b, err := ioutil.ReadAll(stdOutbuff)
	if err != nil {
		log.Fatal(err)
	}
	xml.Unmarshal(b, &vol)

	// set opErrno
	errno.WithLabelValues().Set(float64(vol.OpErrno))
	log.Debug("opErrno: %v", vol.OpErrno)

	// set volume count
	volume_count.WithLabelValues().Set(float64(vol.VolInfo.Volumes.Count))
	log.Debug("volume_count: %v", vol.VolInfo.Volumes.Count)

	// Volume based values
	for _, v := range vol.VolInfo.Volumes.Volume {
		// brick count with volume label
		brick_count.WithLabelValues(v.Name).Set(float64(v.BrickCount))
		log.Debug("opErrno: %v", vol.OpErrno)

		// distribution count with volume label
		distribution_count.WithLabelValues(v.Name).Set(float64(v.DistCount))
		log.Debug("opErrno: %v", vol.OpErrno)

	}
}

func glusterProfile(sec_int int) {
	// Gluster Profile

	// Get gluster volumes, then call gluster profile on every volume

	//  gluster volume profile gv_leoticket info cumulative --xml
	//cmd_profile := exec.Command("/usr/sbin/gluster", "volume", "profile", "gv_leoticket", "info", "cumulative", "--xml")
}

func main() {

	// commandline arguments
	var (
		metricPath = flag.String("metrics-path", "/metrics", "URL Endpoint for metrics")
		addr = flag.String("listen-address", ":9189", "The address to listen on for HTTP requests.")
		sec = flag.String("scrape-seconds", "2", "Frequency of scraping glusterfs in seconds")
		version_tag = flag.Bool("version", false, "Prints version information")
	)

	flag.Parse()

	if *version_tag {
		versionInfo()
	}

	log.Info("GlusterFS Metrics Exporter v", VERSION)

	// ensure that sec is int
	sec_int, err := strconv.Atoi(*sec)
	if err != nil {
		log.Fatal("Parameter -scrape-seconds is not an int value")
	}

	// gluster volume info
	go GlusterVolumeInfo(sec_int)

	http.Handle("/metrics", promhttp.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
<title>GlusterFS Exporter v` + VERSION + `</title>

GlusterFS Exporter v` + VERSION + `

<a href='` + *metricPath + `'>Metrics

						`))
	})
	log.Fatal(http.ListenAndServe(*addr, nil))
}
<|endoftext|>


<commit_before>// Copyright 2017 Mathew Robinson <mrobinson@praelatus.io>. All rights reserved.
// Use of this source code is governed by the AGPLv3 license that can be found in
// the LICENSE file.

// +build !release

package repo

import (
	"math/rand"
	"strconv"

	"github.com/praelatus/praelatus/models"
	"gopkg.in/mgo.v2/bson"
)

var tickets []models.Ticket

func init() {
	for i := 0; i < 100; i++ {
		t := models.Ticket{
			Key:     "TEST-" + strconv.Itoa(i+1),
			Summary: "This is test ticket #" + strconv.Itoa(i),
			Description: `# Refugam in se fuit quae

## Pariter vel sine frustra

Lorem markdownum Diomede quid, ab oracula diligit; aut qui nam. Dum postquam tu
fecit *numerare dederat es* animae dederat, quem soror. Venae potentem minacia
summa precantem statque procubuisse et sui et deus sceleri?

1. Irascitur inter de cunctae arva tenet pectore
2. Tabo messibus
3. Duobus undae

## Truncis sulcat Stymphalide

Sollertius nomina plectrumque nec nec animos, Rhadamanthon figitur vulgata
hominum ad. Vulnere pendentemque soror incubuit lenta vertunt. Deae cepit
quotiensque toto Aenea curvamine cum non sua divus audet patriae si et fit
vineta. Aquas nimium: postquam hominum promissa!

    if (isdn >= personal_executable(cJquery)) {
        redundancy_firmware_guid = infringement;
        keystroke += pum_document(page_wins, icq_nanometer_malware +
                barInternal);
        mcaQueryMarketing(portLeak, guiPhreaking, thunderbolt(4, twainAtaLink));
    }
    addressTorrent = boot_character_website(linkedinVaporware, plugRightBoot);
    var megabit_standalone_of = nocSo + program_mouse + 26;

## Nostra est perdix annos et quas

Vellentem quaerit est umeros celsior navis intrat
[saepe](http://minosiuvenis.net/numen.html). Saxo vocet turris Athamanta
membris, semesaque: nate leto summos instabiles primosque avertite nostras tu
quies in [avidisque](http://www.templaaequora.net/). Summa se expulit perfide
mirum, suo brevi absentem umerus vultumque cognata. Nempe ipsi quod procul
verba, frusta, sed gemitu non huius odit; non aprica pedumque Hectoris, taxo.
Mentis vivit tori erubuit, qui flebile natura Echo percussis pallet?

- Ministros tumebat famuli
- Aristas per blandis
- Corpora qua Medea acu potentia inrita

Non Cipe reges, laetitiam filius sceleratum naidas, fortunaque occidit. Laeva et
ipsa divite, est ille ver verba vicisse, exsiliantque aprica illius, rapta?`,
			Reporter: users[rand.Intn(2)].Username,
			Assignee: users[rand.Intn(2)].Username,
			Type:     p.TicketTypes[rand.Intn(3)],
			Project:  p.Key,
		}

		for i := 0; i < rand.Intn(50); i++ {
			c := models.Comment{
				Author: users[rand.Intn(2)].Username,
				Body: `# Yo Dawg

I heard you like **markdown**.

So I put markdown in your comment.`,
			}

			t.Comments = append(t.Comments, c)
		}

		tickets = append(tickets, t)
	}

}

type mockRepo struct{}

func NewMockRepo() Repo {
	return mockRepo{}
}

type mockProjectRepo struct{}

func (pr mockProjectRepo) Get(u *models.User, uid string) (models.Project, error) {
	return p1, nil
}

func (pr mockProjectRepo) Search(u *models.User, query string) ([]models.Project, error) {
	return []models.Project{p, p1}, nil
}

func (pr mockProjectRepo) Update(u *models.User, uid string, updated models.Project) error {
	return nil
}

func (pr mockProjectRepo) Create(u *models.User, project models.Project) (models.Project, error) {
	return project, nil
}

func (pr mockProjectRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockTicketRepo struct{}

func (t mockTicketRepo) Get(u *models.User, uid string) (models.Ticket, error) {
	return tickets[0], nil
}

func (t mockTicketRepo) Search(u *models.User, query string) ([]models.Ticket, error) {
	return tickets, nil
}

func (t mockTicketRepo) Update(u *models.User, uid string, updated models.Ticket) error {
	return nil
}

func (t mockTicketRepo) Create(u *models.User, ticket models.Ticket) (models.Ticket, error) {
	return ticket, nil
}

func (t mockTicketRepo) Delete(u *models.User, uid string) error {
	return nil
}

func (t mockTicketRepo) LabelSearch(u *models.User, query string) ([]string, error) {
	return []string{"label1", "label2"}, nil
}

func (t mockTicketRepo) AddComment(u *models.User, uid string, comment models.Comment) (models.Ticket, error) {
	tickets[0].Comments = append(tickets[0].Comments, comment)
	return tickets[0], nil
}

func (t mockTicketRepo) NextTicketKey(u *models.User, projectKey string) (string, error) {
	return projectKey + string(len(tickets)+1), nil
}

type mockUserRepo struct{}

func (ur mockUserRepo) Get(u *models.User, uid string) (models.User, error) {
	return *u1, nil
}

func (ur mockUserRepo) Search(u *models.User, query string) ([]models.User, error) {
	return users, nil
}

func (ur mockUserRepo) Update(u *models.User, uid string, updated models.User) error {
	return nil
}

func (ur mockUserRepo) Create(u *models.User, user models.User) (models.User, error) {
	return user, nil
}

func (ur mockUserRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockFieldRepo struct{}

func (fsr mockFieldRepo) Get(u *models.User, uid string) (models.FieldScheme, error) {
	// Hardcode to the ID expected in tests.
	fs.ID = "59e3f2026791c08e74da1bb2"
	return fs, nil
}

func (fsr mockFieldRepo) Search(u *models.User, query string) ([]models.FieldScheme, error) {
	return []models.FieldScheme{fs}, nil
}

func (fsr mockFieldRepo) Update(u *models.User, uid string, updated models.FieldScheme) error {
	return nil
}

func (fsr mockFieldRepo) Create(u *models.User, fieldScheme models.FieldScheme) (models.FieldScheme, error) {
	fieldScheme.ID = bson.NewObjectId()
	return fieldScheme, nil
}

func (fsr mockFieldRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockWorkflowRepo struct{}

func (wr mockWorkflowRepo) Get(u *models.User, uid string) (models.Workflow, error) {
	wrk := workflows[0]
	// Hardcode to the ID expected in tests.
	wrk.ID = "59e3f2026791c08e74da1bb2"
	return wrk, nil
}

func (wr mockWorkflowRepo) Search(u *models.User, query string) ([]models.Workflow, error) {
	return workflows, nil
}

func (wr mockWorkflowRepo) Update(u *models.User, uid string, updated models.Workflow) error {
	return nil
}

func (wr mockWorkflowRepo) Create(u *models.User, workflow models.Workflow) (models.Workflow, error) {
	workflow.ID = bson.NewObjectId()
	return workflow, nil
}

func (wr mockWorkflowRepo) Delete(u *models.User, uid string) error {
	return nil
}

func (m mockRepo) Projects() ProjectRepo {
	return mockProjectRepo{}
}

func (m mockRepo) Tickets() TicketRepo {
	return mockTicketRepo{}
}

func (m mockRepo) Users() UserRepo {
	return mockUserRepo{}
}

func (m mockRepo) Fields() FieldSchemeRepo {
	return mockFieldRepo{}
}

func (m mockRepo) Workflows() WorkflowRepo {
	return mockWorkflowRepo{}
}

func (m mockRepo) Clean() error { return nil }
func (m mockRepo) Test() error  { return nil }
func (m mockRepo) Init() error  { return nil }
<commit_msg>add haslead to mock repo<commit_after>// Copyright 2017 Mathew Robinson <mrobinson@praelatus.io>. All rights reserved.
// Use of this source code is governed by the AGPLv3 license that can be found in
// the LICENSE file.

// +build !release

package repo

import (
	"math/rand"
	"strconv"

	"github.com/praelatus/praelatus/models"
	"gopkg.in/mgo.v2/bson"
)

var tickets []models.Ticket

func init() {
	for i := 0; i < 100; i++ {
		t := models.Ticket{
			Key:     "TEST-" + strconv.Itoa(i+1),
			Summary: "This is test ticket #" + strconv.Itoa(i),
			Description: `# Refugam in se fuit quae

## Pariter vel sine frustra

Lorem markdownum Diomede quid, ab oracula diligit; aut qui nam. Dum postquam tu
fecit *numerare dederat es* animae dederat, quem soror. Venae potentem minacia
summa precantem statque procubuisse et sui et deus sceleri?

1. Irascitur inter de cunctae arva tenet pectore
2. Tabo messibus
3. Duobus undae

## Truncis sulcat Stymphalide

Sollertius nomina plectrumque nec nec animos, Rhadamanthon figitur vulgata
hominum ad. Vulnere pendentemque soror incubuit lenta vertunt. Deae cepit
quotiensque toto Aenea curvamine cum non sua divus audet patriae si et fit
vineta. Aquas nimium: postquam hominum promissa!

    if (isdn >= personal_executable(cJquery)) {
        redundancy_firmware_guid = infringement;
        keystroke += pum_document(page_wins, icq_nanometer_malware +
                barInternal);
        mcaQueryMarketing(portLeak, guiPhreaking, thunderbolt(4, twainAtaLink));
    }
    addressTorrent = boot_character_website(linkedinVaporware, plugRightBoot);
    var megabit_standalone_of = nocSo + program_mouse + 26;

## Nostra est perdix annos et quas

Vellentem quaerit est umeros celsior navis intrat
[saepe](http://minosiuvenis.net/numen.html). Saxo vocet turris Athamanta
membris, semesaque: nate leto summos instabiles primosque avertite nostras tu
quies in [avidisque](http://www.templaaequora.net/). Summa se expulit perfide
mirum, suo brevi absentem umerus vultumque cognata. Nempe ipsi quod procul
verba, frusta, sed gemitu non huius odit; non aprica pedumque Hectoris, taxo.
Mentis vivit tori erubuit, qui flebile natura Echo percussis pallet?

- Ministros tumebat famuli
- Aristas per blandis
- Corpora qua Medea acu potentia inrita

Non Cipe reges, laetitiam filius sceleratum naidas, fortunaque occidit. Laeva et
ipsa divite, est ille ver verba vicisse, exsiliantque aprica illius, rapta?`,
			Reporter: users[rand.Intn(2)].Username,
			Assignee: users[rand.Intn(2)].Username,
			Type:     p.TicketTypes[rand.Intn(3)],
			Project:  p.Key,
		}

		for i := 0; i < rand.Intn(50); i++ {
			c := models.Comment{
				Author: users[rand.Intn(2)].Username,
				Body: `# Yo Dawg

I heard you like **markdown**.

So I put markdown in your comment.`,
			}

			t.Comments = append(t.Comments, c)
		}

		tickets = append(tickets, t)
	}

}

type mockRepo struct{}

func NewMockRepo() Repo {
	return mockRepo{}
}

type mockProjectRepo struct{}

func (pr mockProjectRepo) Get(u *models.User, uid string) (models.Project, error) {
	return p1, nil
}

func (pr mockProjectRepo) Search(u *models.User, query string) ([]models.Project, error) {
	return []models.Project{p, p1}, nil
}

func (pr mockProjectRepo) HasLead(u *models.User, lead models.User) ([]models.Project, error) {
	return []models.Project{p, p1}, nil
}

func (pr mockProjectRepo) Update(u *models.User, uid string, updated models.Project) error {
	return nil
}

func (pr mockProjectRepo) Create(u *models.User, project models.Project) (models.Project, error) {
	return project, nil
}

func (pr mockProjectRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockTicketRepo struct{}

func (t mockTicketRepo) Get(u *models.User, uid string) (models.Ticket, error) {
	return tickets[0], nil
}

func (t mockTicketRepo) Search(u *models.User, query string) ([]models.Ticket, error) {
	return tickets, nil
}

func (t mockTicketRepo) Update(u *models.User, uid string, updated models.Ticket) error {
	return nil
}

func (t mockTicketRepo) Create(u *models.User, ticket models.Ticket) (models.Ticket, error) {
	return ticket, nil
}

func (t mockTicketRepo) Delete(u *models.User, uid string) error {
	return nil
}

func (t mockTicketRepo) LabelSearch(u *models.User, query string) ([]string, error) {
	return []string{"label1", "label2"}, nil
}

func (t mockTicketRepo) AddComment(u *models.User, uid string, comment models.Comment) (models.Ticket, error) {
	tickets[0].Comments = append(tickets[0].Comments, comment)
	return tickets[0], nil
}

func (t mockTicketRepo) NextTicketKey(u *models.User, projectKey string) (string, error) {
	return projectKey + string(len(tickets)+1), nil
}

type mockUserRepo struct{}

func (ur mockUserRepo) Get(u *models.User, uid string) (models.User, error) {
	return *u1, nil
}

func (ur mockUserRepo) Search(u *models.User, query string) ([]models.User, error) {
	return users, nil
}

func (ur mockUserRepo) Update(u *models.User, uid string, updated models.User) error {
	return nil
}

func (ur mockUserRepo) Create(u *models.User, user models.User) (models.User, error) {
	return user, nil
}

func (ur mockUserRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockFieldRepo struct{}

func (fsr mockFieldRepo) Get(u *models.User, uid string) (models.FieldScheme, error) {
	// Hardcode to the ID expected in tests.
	fs.ID = "59e3f2026791c08e74da1bb2"
	return fs, nil
}

func (fsr mockFieldRepo) Search(u *models.User, query string) ([]models.FieldScheme, error) {
	return []models.FieldScheme{fs}, nil
}

func (fsr mockFieldRepo) Update(u *models.User, uid string, updated models.FieldScheme) error {
	return nil
}

func (fsr mockFieldRepo) Create(u *models.User, fieldScheme models.FieldScheme) (models.FieldScheme, error) {
	fieldScheme.ID = bson.NewObjectId()
	return fieldScheme, nil
}

func (fsr mockFieldRepo) Delete(u *models.User, uid string) error {
	return nil
}

type mockWorkflowRepo struct{}

func (wr mockWorkflowRepo) Get(u *models.User, uid string) (models.Workflow, error) {
	wrk := workflows[0]
	// Hardcode to the ID expected in tests.
	wrk.ID = "59e3f2026791c08e74da1bb2"
	return wrk, nil
}

func (wr mockWorkflowRepo) Search(u *models.User, query string) ([]models.Workflow, error) {
	return workflows, nil
}

func (wr mockWorkflowRepo) Update(u *models.User, uid string, updated models.Workflow) error {
	return nil
}

func (wr mockWorkflowRepo) Create(u *models.User, workflow models.Workflow) (models.Workflow, error) {
	workflow.ID = bson.NewObjectId()
	return workflow, nil
}

func (wr mockWorkflowRepo) Delete(u *models.User, uid string) error {
	return nil
}

func (m mockRepo) Projects() ProjectRepo {
	return mockProjectRepo{}
}

func (m mockRepo) Tickets() TicketRepo {
	return mockTicketRepo{}
}

func (m mockRepo) Users() UserRepo {
	return mockUserRepo{}
}

func (m mockRepo) Fields() FieldSchemeRepo {
	return mockFieldRepo{}
}

func (m mockRepo) Workflows() WorkflowRepo {
	return mockWorkflowRepo{}
}

func (m mockRepo) Clean() error { return nil }
func (m mockRepo) Test() error  { return nil }
func (m mockRepo) Init() error  { return nil }
<|endoftext|>