<commit_before>package neo

import (
	"container/list"
	"errors"
)

///////////////////////////////////////////////////////////////////
// Route
///////////////////////////////////////////////////////////////////

type handler func(*Ctx)

// composing route with middlewares. Will be called from ``compose`` fn.
func (h handler) apply(ctx *Ctx, fns []appliable) {
	h(ctx)

	if len(fns) > 0 {
		fns[0].apply(ctx, fns[1:])
	}
}

type Route struct {
	*interceptor
	fn      handler
	fnChain func(*Ctx)
}

///////////////////////////////////////////////////////////////////
// Router
///////////////////////////////////////////////////////////////////

type router struct {
	*interceptor
	*methods
	regions *list.List
}

type Region struct {
	*interceptor
	*methods
}

func (r *router) initRouter() {
	m := &methods{}
	i := &interceptor{[]appliable{}}

	r.methods = m.init()
	r.interceptor = i
	r.regions = list.New()
}

// making new region instance
func (r *router) makeRegion() *Region {
	m := &methods{}
	i := &interceptor{[]appliable{}}

	region := &Region{i, m.init()}
	r.regions.PushBack(region)

	return region
}

// forcing all middlewares to copy to appropriate routes
// also cleans up intrnal structures
func (router *router) flush() {
	// first copy all middlewares to top-level routes
	for method, routesmap := range router.routes {
		for path, route := range routesmap {

			route.fnChain = compose(merge(
				router.middlewares,
				route.middlewares,
				[]appliable{route.fn},
			))

			router.routes[method][path] = route
		}
	}

	// then copy all middlewares for region level routes
	// this will copy all b/a from router and region
	// so at the end all b/a for route will be placed directly in route
	//
	// mr = maybeRegion
	for mr := router.regions.Front(); mr != nil; mr = mr.Next() {
		region, ok := mr.Value.(*Region)
		if !ok {
			log.Error("cannot convert element to region")
			continue
		}

		for method, routesmap := range region.routes {
			for path, route := range routesmap {

				route.fnChain = compose(merge(
					router.middlewares,
					region.middlewares,
					route.middlewares,
					[]appliable{route.fn},
				))

				router.routes[method][path] = route

				// remove route from region
				// we are doing this because route reference is now in top level
				delete(region.routes[method], path)
			}

			// remove method key from region (GET, POST,...)
			delete(region.routes, method)
		}

		// remove region from router region list
		// in case of failed cast to region, this won't be invoked
		router.regions.Remove(mr)
	}
}

// main API function of router
// if will try to invoke fns which are realted to route (if any)
func (router *router) match(req *Request) (*Route, error) {
	// todo: consider using goroutines for searching for route

	method := req.Method
	path := req.URL.Path

	for k, _ := range router.routes[method] {
		params, err := k.Match(path)

		if err == nil {
			route := router.routes[method][k]
			req.Params = params
			return &route, nil
		}
	}

	return nil, errors.New("[" + req.Method + "] handler for route " + path + " not found")
}
<commit_msg>code cleanup<commit_after>package neo

import (
	"container/list"
	"errors"
)

///////////////////////////////////////////////////////////////////
// Route
///////////////////////////////////////////////////////////////////

type handler func(*Ctx)

// composing route with middlewares. Will be called from ``compose`` fn.
func (h handler) apply(ctx *Ctx, fns []appliable) {
	h(ctx)

	if len(fns) > 0 {
		fns[0].apply(ctx, fns[1:])
	}
}

type Route struct {
	*interceptor
	fn      handler
	fnChain func(*Ctx)
}

///////////////////////////////////////////////////////////////////
// Router
///////////////////////////////////////////////////////////////////

type router struct {
	*interceptor
	*methods
	regions *list.List
}

type Region struct {
	*interceptor
	*methods
}

func (r *router) initRouter() {
	m := &methods{}
	i := &interceptor{[]appliable{}}

	r.methods = m.init()
	r.interceptor = i
	r.regions = list.New()
}

// making new region instance
func (r *router) makeRegion() *Region {
	m := &methods{}
	i := &interceptor{[]appliable{}}

	region := &Region{i, m.init()}
	r.regions.PushBack(region)

	return region
}

// forcing all middlewares to copy to appropriate routes
// also cleans up intrnal structures
func (router *router) flush() {
	// first copy all middlewares to top-level routes
	for method, routesmap := range router.routes {
		for path, route := range routesmap {

			route.fnChain = compose(merge(
				router.middlewares,
				route.middlewares,
				[]appliable{route.fn},
			))

			router.routes[method][path] = route
		}
	}

	// then copy all middlewares for region level routes
	// this will copy all b/a from router and region
	// so at the end all b/a for route will be placed directly in route
	//
	// mr = maybeRegion
	for mr := router.regions.Front(); mr != nil; mr = mr.Next() {
		region, ok := mr.Value.(*Region)
		if !ok {
			log.Error("cannot convert element to region")
			continue
		}

		for method, routesmap := range region.routes {
			for path, route := range routesmap {

				route.fnChain = compose(merge(
					router.middlewares,
					region.middlewares,
					route.middlewares,
					[]appliable{route.fn},
				))

				router.routes[method][path] = route

				// remove route from region
				// we are doing this because route reference is now in top level
				delete(region.routes[method], path)
			}

			// remove method key from region (GET, POST,...)
			delete(region.routes, method)
		}

		// remove region from router region list
		// in case of failed cast to region, this won't be invoked
		router.regions.Remove(mr)
	}
}

// main API function of router
// if will try to invoke fns which are realted to route (if any)
func (router *router) match(req *Request) (*Route, error) {
	// todo: consider using goroutines for searching for route

	method := req.Method
	path := req.URL.Path

	for k, v := range router.routes[method] {
		params, err := k.Match(path)

		if err == nil {
			req.Params = params
			return &v, nil
		}
	}

	return nil, errors.New("[" + req.Method + "] handler for route " + path + " not found")
}
<|endoftext|>


<commit_before>// Copyright 2015 Arne Roomann-Kurrik
//
// 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 core

import (
	"fmt"
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
	"strings"
	"unsafe"
)

type Uniform struct {
	location int32
}

func (u *Uniform) Mat4(m mgl32.Mat4) {
	gl.UniformMatrix4fv(u.location, 1, false, &m[0])
}

type Program struct {
	vao     uint32
	program uint32
}

func NewProgram() *Program {
	return &Program{}
}

func (p *Program) Delete() {
	gl.DeleteVertexArrays(1, &p.vao)
	p.vao = 0
	gl.DeleteProgram(p.program)
	p.program = 0
}

func (p *Program) Bind() {
	gl.BindVertexArray(p.vao)
	gl.UseProgram(p.program)
}

func (p *Program) Unbind() {
	gl.BindVertexArray(0)
}

func (p *Program) ID() uint32 {
	return p.program
}

func (p *Program) Load(vertex, fragment string) (err error) {
	if err = p.createVAO(); err != nil {
		return
	}
	if err = p.buildProgram(vertex, fragment); err != nil {
		return
	}
	return
}

func (p *Program) Uniform(name string) *Uniform {
	var nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
	return &Uniform{
		location: gl.GetUniformLocation(p.ID(), nameStr),
	}
}

func (p *Program) UniformBlock(name string, binding uint32) *UniformBlock {
	var (
		nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
		index   = uint32(gl.GetUniformBlockIndex(p.program, nameStr))
	)
	gl.UniformBlockBinding(p.program, index, binding)
	return &UniformBlock{
		binding: binding,
	}
}

func (p *Program) Attrib(name string, stride uintptr) *VertexAttribute {
	var nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
	return &VertexAttribute{
		location: uint32(gl.GetAttribLocation(p.program, nameStr)),
		stride:   stride,
	}
}

func (p *Program) createVAO() error {
	gl.GenVertexArrays(1, &p.vao)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR gl.GenVertexArray %X", e)
	}
	gl.BindVertexArray(p.vao)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR array.Bind %X", e)
	}
	return nil
}

func (p *Program) compileShader(stype uint32, source string) (shader uint32, err error) {
	csource := gl.Str(source)
	shader = gl.CreateShader(stype)
	gl.ShaderSource(shader, 1, &csource, nil)
	gl.CompileShader(shader)
	var status int32
	if gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status); status == gl.FALSE {
		var length int32
		gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &length)
		log := strings.Repeat("\x00", int(length+1))
		gl.GetShaderInfoLog(shader, length, nil, gl.Str(log))
		err = fmt.Errorf("ERROR shader compile:\n%s", log)
	}
	return
}

func (p *Program) linkProgram(vertex uint32, fragment uint32) (program uint32, err error) {
	program = gl.CreateProgram()
	gl.AttachShader(program, vertex)
	gl.AttachShader(program, fragment)
	gl.BindFragDataLocation(program, 0, gl.Str("v_FragData\x00"))
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR program.BindFragDataLocation %X", e)
		return
	}
	gl.LinkProgram(program)
	var status int32
	if gl.GetProgramiv(program, gl.LINK_STATUS, &status); status == gl.FALSE {
		var length int32
		gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &length)
		log := strings.Repeat("\x00", int(length+1))
		gl.GetProgramInfoLog(program, length, nil, gl.Str(log))
		err = fmt.Errorf("ERROR program link:\n%s", log)
	}
	gl.DeleteShader(vertex)
	gl.DeleteShader(fragment)
	return
}

func (p *Program) buildProgram(vsrc string, fsrc string) (err error) {
	var (
		vertex   uint32
		fragment uint32
		glsrc    string
	)
	glsrc = fmt.Sprintf("%v\x00", vsrc)
	if vertex, err = p.compileShader(gl.VERTEX_SHADER, glsrc); err != nil {
		return
	}
	glsrc = fmt.Sprintf("%v\x00", fsrc)
	if fragment, err = p.compileShader(gl.FRAGMENT_SHADER, glsrc); err != nil {
		return
	}
	p.program, err = p.linkProgram(vertex, fragment)
	return
}

type UniformBlock struct {
	binding uint32
}

func (b *UniformBlock) Bind(bufferID uint32, size int) {
	gl.BindBufferRange(gl.UNIFORM_BUFFER, b.binding, bufferID, 0, size)
}

type VertexAttribute struct {
	location uint32
	stride   uintptr
}

func (a *VertexAttribute) vertexAttrib(l uint32, size int32, xtype uint32, offset uintptr, divisor uint32) {
	var offsetPtr = gl.PtrOffset(int(offset))
	gl.EnableVertexAttribArray(a.location + l)
	gl.VertexAttribPointer(a.location+l, size, xtype, false, int32(a.stride), offsetPtr)
	gl.VertexAttribDivisor(a.location+l, divisor)
}

func (a *VertexAttribute) Float(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 1, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec2(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 2, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec3(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 3, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec4(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 4, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Mat4(offset uintptr, divisor uint32) {
	var (
		float    float32
		sizeVec4 = unsafe.Sizeof(float) * 4
	)
	a.vertexAttrib(0, 4, gl.FLOAT, offset, divisor)
	a.vertexAttrib(1, 4, gl.FLOAT, offset+sizeVec4, divisor)
	a.vertexAttrib(2, 4, gl.FLOAT, offset+2*sizeVec4, divisor)
	a.vertexAttrib(3, 4, gl.FLOAT, offset+3*sizeVec4, divisor)
}
<commit_msg>Fix for go 1.6<commit_after>// Copyright 2015 Arne Roomann-Kurrik
//
// 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 core

import (
	"fmt"
	"github.com/go-gl/gl/v3.3-core/gl"
	"github.com/go-gl/mathgl/mgl32"
	"strings"
	"unsafe"
)

type Uniform struct {
	location int32
}

func (u *Uniform) Mat4(m mgl32.Mat4) {
	gl.UniformMatrix4fv(u.location, 1, false, &m[0])
}

type Program struct {
	vao     uint32
	program uint32
}

func NewProgram() *Program {
	return &Program{}
}

func (p *Program) Delete() {
	gl.DeleteVertexArrays(1, &p.vao)
	p.vao = 0
	gl.DeleteProgram(p.program)
	p.program = 0
}

func (p *Program) Bind() {
	gl.BindVertexArray(p.vao)
	gl.UseProgram(p.program)
}

func (p *Program) Unbind() {
	gl.BindVertexArray(0)
}

func (p *Program) ID() uint32 {
	return p.program
}

func (p *Program) Load(vertex, fragment string) (err error) {
	if err = p.createVAO(); err != nil {
		return
	}
	if err = p.buildProgram(vertex, fragment); err != nil {
		return
	}
	return
}

func (p *Program) Uniform(name string) *Uniform {
	var nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
	return &Uniform{
		location: gl.GetUniformLocation(p.ID(), nameStr),
	}
}

func (p *Program) UniformBlock(name string, binding uint32) *UniformBlock {
	var (
		nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
		index   = uint32(gl.GetUniformBlockIndex(p.program, nameStr))
	)
	gl.UniformBlockBinding(p.program, index, binding)
	return &UniformBlock{
		binding: binding,
	}
}

func (p *Program) Attrib(name string, stride uintptr) *VertexAttribute {
	var nameStr = gl.Str(fmt.Sprintf("%v\x00", name))
	return &VertexAttribute{
		location: uint32(gl.GetAttribLocation(p.program, nameStr)),
		stride:   stride,
	}
}

func (p *Program) createVAO() error {
	gl.GenVertexArrays(1, &p.vao)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR gl.GenVertexArray %X", e)
	}
	gl.BindVertexArray(p.vao)
	if e := gl.GetError(); e != 0 {
		return fmt.Errorf("ERROR array.Bind %X", e)
	}
	return nil
}

func (p *Program) compileShader(stype uint32, source string) (shader uint32, err error) {
	csources, free := gl.Strs(source)
	shader = gl.CreateShader(stype)
	gl.ShaderSource(shader, 1, csources, nil)
	free()
	gl.CompileShader(shader)
	var status int32
	if gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status); status == gl.FALSE {
		var length int32
		gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &length)
		log := strings.Repeat("\x00", int(length+1))
		gl.GetShaderInfoLog(shader, length, nil, gl.Str(log))
		err = fmt.Errorf("ERROR shader compile:\n%s", log)
	}
	return
}

func (p *Program) linkProgram(vertex uint32, fragment uint32) (program uint32, err error) {
	program = gl.CreateProgram()
	gl.AttachShader(program, vertex)
	gl.AttachShader(program, fragment)
	gl.BindFragDataLocation(program, 0, gl.Str("v_FragData\x00"))
	if e := gl.GetError(); e != 0 {
		err = fmt.Errorf("ERROR program.BindFragDataLocation %X", e)
		return
	}
	gl.LinkProgram(program)
	var status int32
	if gl.GetProgramiv(program, gl.LINK_STATUS, &status); status == gl.FALSE {
		var length int32
		gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &length)
		log := strings.Repeat("\x00", int(length+1))
		gl.GetProgramInfoLog(program, length, nil, gl.Str(log))
		err = fmt.Errorf("ERROR program link:\n%s", log)
	}
	gl.DeleteShader(vertex)
	gl.DeleteShader(fragment)
	return
}

func (p *Program) buildProgram(vsrc string, fsrc string) (err error) {
	var (
		vertex   uint32
		fragment uint32
		glsrc    string
	)
	glsrc = fmt.Sprintf("%v\x00", vsrc)
	if vertex, err = p.compileShader(gl.VERTEX_SHADER, glsrc); err != nil {
		return
	}
	glsrc = fmt.Sprintf("%v\x00", fsrc)
	if fragment, err = p.compileShader(gl.FRAGMENT_SHADER, glsrc); err != nil {
		return
	}
	p.program, err = p.linkProgram(vertex, fragment)
	return
}

type UniformBlock struct {
	binding uint32
}

func (b *UniformBlock) Bind(bufferID uint32, size int) {
	gl.BindBufferRange(gl.UNIFORM_BUFFER, b.binding, bufferID, 0, size)
}

type VertexAttribute struct {
	location uint32
	stride   uintptr
}

func (a *VertexAttribute) vertexAttrib(l uint32, size int32, xtype uint32, offset uintptr, divisor uint32) {
	var offsetPtr = gl.PtrOffset(int(offset))
	gl.EnableVertexAttribArray(a.location + l)
	gl.VertexAttribPointer(a.location+l, size, xtype, false, int32(a.stride), offsetPtr)
	gl.VertexAttribDivisor(a.location+l, divisor)
}

func (a *VertexAttribute) Float(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 1, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec2(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 2, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec3(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 3, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Vec4(offset uintptr, divisor uint32) {
	a.vertexAttrib(0, 4, gl.FLOAT, offset, divisor)
}

func (a *VertexAttribute) Mat4(offset uintptr, divisor uint32) {
	var (
		float    float32
		sizeVec4 = unsafe.Sizeof(float) * 4
	)
	a.vertexAttrib(0, 4, gl.FLOAT, offset, divisor)
	a.vertexAttrib(1, 4, gl.FLOAT, offset+sizeVec4, divisor)
	a.vertexAttrib(2, 4, gl.FLOAT, offset+2*sizeVec4, divisor)
	a.vertexAttrib(3, 4, gl.FLOAT, offset+3*sizeVec4, divisor)
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"io/ioutil"
	"os/exec"
	"strings"

	"github.com/buaazp/fasthttprouter"
	"github.com/shurcooL/github_flavored_markdown"
	"github.com/valyala/fasthttp"
)

const EmptyPageText = "Page does not exist. Click on the Go button above to create it."

type Page struct {
	Title  string
	Source string
	Body   template.HTML
}

type H map[string]interface{} // a standard hash map

func Router() *fasthttprouter.Router {
	router := fasthttprouter.New()
	router.ServeFiles("/assets/*filepath", "assets")

	// / root path
	router.GET("/", func(ctx *fasthttp.RequestCtx) {
		ctx.Redirect("/docs/Main_page", fasthttp.StatusMovedPermanently)
	})

	// /edit launch edit mode from top bar
	router.GET("/edit", func(ctx *fasthttp.RequestCtx) {
		term := string(ctx.FormValue("term"))
		redirection := "/docs/"+term+"/edit"
		if term == "" {
			redirection = "/docs"
		}
		ctx.Redirect(redirection, fasthttp.StatusMovedPermanently)
	})

	// /search find pages
	router.GET("/search", func(ctx *fasthttp.RequestCtx) {
		term := string(ctx.FormValue("term"))
		if term == "" {
			ctx.Redirect("/docs", fasthttp.StatusMovedPermanently)
			return
		}
		files, _ := ioutil.ReadDir("pages/")
		var pages []string
		for _, f := range files {
			title := f.Name()
			if strings.Contains(strings.ToLower(title), strings.ToLower(term)) {
				pages = append(pages, title)
			}
		}

		var content = map[string]string{}
		results, _ := exec.Command("bash", "-c", "cd pages; grep '"+term+"' *").Output() // TODO case insensitive search
		for _, result := range strings.Split(string(results), "\n") {
			matches := strings.Split(result, ":")
			page := matches[0]
			if page == "" {
				continue
			}
			line := strings.Join(matches[1:], "\n")
			content[page] += strings.TrimSpace(line) + "\n"
		}

		page := Page{"Main page", "", ""}
		t := template.Must(template.ParseFiles("views/layout.html", "views/search.html"))
		t.Execute(ctx, H{
			"page":    page,
			"pages":   pages,   // pages with search term in name
			"content": content, // pages with search term in content
			"term":    term,
			"title":   "Main page",
		})
		ctx.SetContentType("text/html")
	})

	// /docs display all pages
	router.GET("/docs", func(ctx *fasthttp.RequestCtx) {
		files, _ := ioutil.ReadDir("pages/")
		var pages []string
		for _, f := range files {
			title := f.Name()
			if title[0] != '.' && title != "Main_page" {
				pages = append(pages, title)
			}
		}

		page := Page{
			"All",
			"",
			"",
		}
		t := template.Must(template.ParseFiles("views/layout.html", "views/show_all.html"))
		t.Execute(ctx, H{
			"page":  page,
			"pages": pages,
			"title": "All",
		})
		ctx.SetContentType("text/html")
	})

	// /docs/:title display page
	router.GET("/docs/:title", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		if title == "All" {
			ctx.Redirect("/docs", fasthttp.StatusMovedPermanently)
			return
		}
		page := loadPage(title)
		term := ""
		if page.Source == EmptyPageText {
			term = title
		}
		t := template.Must(template.ParseFiles("views/layout.html", "views/show.html"))
		t.Execute(ctx, H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
			"term":  term,
		})
		ctx.SetContentType("text/html")
	})

	// /docs/:title/edit edit page
	router.GET("/docs/:title/edit", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		page := loadPage(title)
		t := template.Must(template.ParseFiles("views/layout.html", "views/edit.html"))
		t.Execute(ctx, H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
		})
		ctx.SetContentType("text/html")
	})

	// /docs/:title/edit edit page action
	router.POST("/docs/:title/edit", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		source := ctx.FormValue("source")
		ioutil.WriteFile("pages/"+title+".mw.html.md", []byte(source), 0644)

		ctx.Redirect("/docs/"+title, fasthttp.StatusMovedPermanently)
	})

	// /docs/:title/preview preview page action
	router.POST("/docs/:title/preview", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		source := ctx.FormValue("source")
		page := Page{
			title,
			string(source),
			template.HTML(github_flavored_markdown.Markdown(source)),
		}

		t := template.Must(template.ParseFiles("views/layout.html", "views/edit.html"))
		t.Execute(ctx, H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
		})
		ctx.SetContentType("text/html")
	})

	return router
}

func loadPage(title string) Page {
	source, err := ioutil.ReadFile("pages/" + title)
	if err != nil {
		source = []byte(EmptyPageText)
	}

	page := Page{
		title,
		string(source),
		template.HTML(github_flavored_markdown.Markdown(source)),
	}
	return page
}

func pageTitle(ctx *fasthttp.RequestCtx) string {
	title, _ := ctx.UserValue("title").(string)
	if title == "" {
		title = "Main_page"
	}
	return title
}
<commit_msg>Extract render function<commit_after>package main

import (
	"html/template"
	"io/ioutil"
	"os/exec"
	"strings"

	"github.com/buaazp/fasthttprouter"
	"github.com/shurcooL/github_flavored_markdown"
	"github.com/valyala/fasthttp"
)

const EmptyPageText = "Page does not exist. Click on the Go button above to create it."

type Page struct {
	Title  string
	Source string
	Body   template.HTML
}

type H map[string]interface{} // a standard hash map

func Router() *fasthttprouter.Router {
	router := fasthttprouter.New()
	router.ServeFiles("/assets/*filepath", "assets")

	// / root path
	router.GET("/", func(ctx *fasthttp.RequestCtx) {
		ctx.Redirect("/docs/Main_page", fasthttp.StatusMovedPermanently)
	})

	// /edit launch edit mode from top bar
	router.GET("/edit", func(ctx *fasthttp.RequestCtx) {
		term := string(ctx.FormValue("term"))
		redirection := "/docs/"+term+"/edit"
		if term == "" {
			redirection = "/docs"
		}
		ctx.Redirect(redirection, fasthttp.StatusMovedPermanently)
	})

	// /search find pages
	router.GET("/search", func(ctx *fasthttp.RequestCtx) {
		term := string(ctx.FormValue("term"))
		if term == "" {
			ctx.Redirect("/docs", fasthttp.StatusMovedPermanently)
			return
		}
		files, _ := ioutil.ReadDir("pages/")
		var pages []string
		for _, f := range files {
			title := f.Name()
			if strings.Contains(strings.ToLower(title), strings.ToLower(term)) {
				pages = append(pages, title)
			}
		}

		var content = map[string]string{}
		results, _ := exec.Command("bash", "-c", "cd pages; grep '"+term+"' *").Output() // TODO case insensitive search
		for _, result := range strings.Split(string(results), "\n") {
			matches := strings.Split(result, ":")
			page := matches[0]
			if page == "" {
				continue
			}
			line := strings.Join(matches[1:], "\n")
			content[page] += strings.TrimSpace(line) + "\n"
		}

		page := Page{"Main page", "", ""}
		render(ctx, "search", H{
			"page":    page,
			"pages":   pages,   // pages with search term in name
			"content": content, // pages with search term in content
			"term":    term,
			"title":   "Main page",
		})
	})

	// /docs display all pages
	router.GET("/docs", func(ctx *fasthttp.RequestCtx) {
		files, _ := ioutil.ReadDir("pages/")
		var pages []string
		for _, f := range files {
			title := f.Name()
			if title[0] != '.' && title != "Main_page" {
				pages = append(pages, title)
			}
		}

		page := Page{
			"All",
			"",
			"",
		}
		render(ctx, "show_all", H{
			"page":  page,
			"pages": pages,
			"title": "All",
		})
	})

	// /docs/:title display page
	router.GET("/docs/:title", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		if title == "All" {
			ctx.Redirect("/docs", fasthttp.StatusMovedPermanently)
			return
		}
		page := loadPage(title)
		term := ""
		if page.Source == EmptyPageText {
			term = title
		}
		render(ctx, "show", H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
			"term":  term,
		})
	})

	// /docs/:title/edit edit page
	router.GET("/docs/:title/edit", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		page := loadPage(title)
		render(ctx, "edit", H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
		})
	})

	// /docs/:title/edit edit page action
	router.POST("/docs/:title/edit", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		source := ctx.FormValue("source")
		ioutil.WriteFile("pages/"+title+".mw.html.md", []byte(source), 0644)

		ctx.Redirect("/docs/"+title, fasthttp.StatusMovedPermanently)
	})

	// /docs/:title/preview preview page action
	router.POST("/docs/:title/preview", func(ctx *fasthttp.RequestCtx) {
		title := pageTitle(ctx)
		source := ctx.FormValue("source")
		page := Page{
			title,
			string(source),
			template.HTML(github_flavored_markdown.Markdown(source)),
		}

		render(ctx, "edit", H{
			"page":  page,
			"title": strings.ReplaceAll(title, "_", " "),
		})
	})

	return router
}

func render(ctx *fasthttp.RequestCtx, view string, attributes H) {
	ctx.SetContentType("text/html")
	t := template.Must(template.ParseFiles("views/layout.html", "views/"+view+".html"))
	t.Execute(ctx, attributes)
}

func loadPage(title string) Page {
	source, err := ioutil.ReadFile("pages/" + title)
	if err != nil {
		source = []byte(EmptyPageText)
	}

	page := Page{
		title,
		string(source),
		template.HTML(github_flavored_markdown.Markdown(source)),
	}
	return page
}

func pageTitle(ctx *fasthttp.RequestCtx) string {
	title, _ := ctx.UserValue("title").(string)
	if title == "" {
		title = "Main_page"
	}
	return title
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

func slash(c *gin.Context) {
	var group string
	loginGroup := sessions.Default(c)
	groupCookie := loginGroup.Get("group")
	if groupCookie == nil {
		c.Redirect(302, "/login")
	} else {
		group = groupCookie.(string)
		c.Redirect(302, "/dashboard/"+group)
	}
}

func slashLogin(c *gin.Context) {
	loginGroup := sessions.Default(c)
	group := c.DefaultQuery("group", "noneasdf")
	if group == "noneasdf" {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{})
	} else {
		loginGroup.Set("group", group)
		loginGroup.Save()
		c.Redirect(302, "/dashboard/"+group)
	}
}

func slashLoginPOST(c *gin.Context) {
	loginGroup := sessions.Default(c)
	group := strings.ToLower(c.PostForm("group"))
	if _, err := os.Stat(path.Join("data", group+".db")); err == nil {
		loginGroup.Set("group", group)
		loginGroup.Save()
		c.Redirect(302, "/dashboard/"+group)
	} else {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "Incorrect login.",
		})
	}
}

func slashLogout(c *gin.Context) {
	var group string
	loginGroup := sessions.Default(c)
	groupCookie := loginGroup.Get("group")
	if groupCookie == nil {
		c.Redirect(302, "/login")
	} else {
		group = groupCookie.(string)
		fmt.Println(group)
		loginGroup.Clear()
		loginGroup.Save()
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"Message": "You are now logged out.",
		})
	}
}

func slashDashboard(c *gin.Context) {
	group := c.Param("group")
	ps, _ := openParameters(group)
	users := getUsers(group)
	people := make(map[string]UserPositionJSON)
	for _, user := range users {
		people[user] = getPositionBreakdown(group, user)
	}
	type DashboardData struct {
		Networks         []string
		Locations        map[string][]string
		LocationAccuracy map[string]int
		LocationCount    map[string]int
		Mixin            map[string]float64
		VarabilityCutoff map[string]float64
		Users            map[string]UserPositionJSON
	}
	var dash DashboardData
	dash.Networks = []string{}
	dash.Locations = make(map[string][]string)
	dash.LocationAccuracy = make(map[string]int)
	dash.LocationCount = make(map[string]int)
	dash.Mixin = make(map[string]float64)
	dash.VarabilityCutoff = make(map[string]float64)
	for n := range ps.NetworkLocs {
		dash.Mixin[n] = ps.Priors[n].Special["MixIn"]
		dash.VarabilityCutoff[n] = ps.Priors[n].Special["VarabilityCutoff"]
		dash.Networks = append(dash.Networks, n)
		dash.Locations[n] = []string{}
		for loc := range ps.NetworkLocs[n] {
			dash.Locations[n] = append(dash.Locations[n], loc)
			dash.LocationAccuracy[loc] = ps.Results[n].Accuracy[loc]
			dash.LocationCount[loc] = ps.Results[n].TotalLocations[loc]
		}
	}
	c.HTML(http.StatusOK, "dashboard.tmpl", gin.H{
		"Group": group,
		"Dash":  dash,
		"Users": people,
	})
}

func slashLocation(c *gin.Context) {
	group := c.Param("group")
	user := c.Param("user")
	userJSON := getPositionBreakdown(group, user)
	c.JSON(http.StatusOK, userJSON)
}

func slashExplore(c *gin.Context) {
	defer timeTrack(time.Now(), "Loading JSON")
	group := c.Param("group")
	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	// TODO: check if network and location exists in the ps, if not return 404
	datas := []template.JS{}
	names := []template.JS{}
	indexNames := []template.JS{}
	// Sort locations
	macs := []string{}
	for m := range ps.Priors[network].P[location] {
		if float64(ps.MacVariability[m]) > ps.Priors[network].Special["VarabilityCutoff"] {
			macs = append(macs, m)
		}
	}
	sort.Strings(macs)
	it := 0
	for _, m := range macs {
		n := ps.Priors[network].P[location][m]
		names = append(names, template.JS(string(m)))
		jsonByte, _ := json.Marshal(n)
		datas = append(datas, template.JS(string(jsonByte)))
		indexNames = append(indexNames, template.JS(strconv.Itoa(it)))
		it++
	}
	rsiRange, _ := json.Marshal(RssiRange)
	c.HTML(http.StatusOK, "plot.tmpl", gin.H{
		"RssiRange":  template.JS(string(rsiRange)),
		"Datas":      datas,
		"Names":      names,
		"IndexNames": indexNames,
	})
}

func slashExplore2(c *gin.Context) {
	defer timeTrack(time.Now(), "Loading JSON")
	group := c.Param("group")
	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	lookUpLocation := true
	if strings.Count(location, ":") > 4 {
		lookUpLocation = false // location is actuall mac
		Debug.Println("GOT LOCATION")
	}

	type macDatum struct {
		Name   string    `json:"name"`
		Points []float32 `json:"data"`
	}

	type macDatas struct {
		Macs []macDatum `json:"macs"`
	}

	var data macDatas
	data.Macs = []macDatum{}

	if lookUpLocation {
		// Sort locations
		macs := []string{}
		for m := range ps.Priors[network].P[location] {
			if float64(ps.MacVariability[m]) > ps.Priors[network].Special["VarabilityCutoff"] {
				macs = append(macs, m)
			}
		}
		sort.Strings(macs)

		for _, m := range macs {
			n := ps.Priors[network].P[location][m]
			data.Macs = append(data.Macs, macDatum{Name: m, Points: n})
		}
	} else {
		m := location
		for loc := range ps.Priors[network].P {
			Debug.Println(loc, m)
			n := ps.Priors[network].P[loc][m]
			data.Macs = append(data.Macs, macDatum{Name: strings.Replace(loc, " ", "%20", -1), Points: n})
		}
	}

	c.HTML(http.StatusOK, "plot2.tmpl", gin.H{
		"Data":    data,
		"Rssi":    RssiRange,
		"Title":   group + "/" + network + "/" + location,
		"Group":   strings.Replace(group, " ", "%20", -1),
		"Network": strings.Replace(network, " ", "%20", -1),
		"Legend":  !lookUpLocation,
	})
}

func slashPie(c *gin.Context) {
	group := c.Param("group")
	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	vals := []int{}
	names := []string{}
	fmt.Println(ps.Results[network].Guess[location])
	for guessloc, val := range ps.Results[network].Guess[location] {
		names = append(names, guessloc)
		vals = append(vals, val)
	}
	namesJSON, _ := json.Marshal(names)
	valsJSON, _ := json.Marshal(vals)
	c.HTML(http.StatusOK, "pie.tmpl", gin.H{
		"Names": template.JS(namesJSON),
		"Vals":  template.JS(valsJSON),
	})
}
<commit_msg>Fixed issue #24 https://github.com/schollz/find/issues/24<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
)

func slash(c *gin.Context) {
	var group string
	loginGroup := sessions.Default(c)
	groupCookie := loginGroup.Get("group")
	if groupCookie == nil {
		c.Redirect(302, "/login")
	} else {
		group = groupCookie.(string)
		c.Redirect(302, "/dashboard/"+group)
	}
}

func slashLogin(c *gin.Context) {
	loginGroup := sessions.Default(c)
	group := c.DefaultQuery("group", "noneasdf")
	if group == "noneasdf" {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{})
	} else {
		loginGroup.Set("group", group)
		loginGroup.Save()
		c.Redirect(302, "/dashboard/"+group)
	}
}

func slashLoginPOST(c *gin.Context) {
	loginGroup := sessions.Default(c)
	group := strings.ToLower(c.PostForm("group"))
	if _, err := os.Stat(path.Join("data", group+".db")); err == nil {
		loginGroup.Set("group", group)
		loginGroup.Save()
		c.Redirect(302, "/dashboard/"+group)
	} else {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "Incorrect login.",
		})
	}
}

func slashLogout(c *gin.Context) {
	var group string
	loginGroup := sessions.Default(c)
	groupCookie := loginGroup.Get("group")
	if groupCookie == nil {
		c.Redirect(302, "/login")
	} else {
		group = groupCookie.(string)
		fmt.Println(group)
		loginGroup.Clear()
		loginGroup.Save()
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"Message": "You are now logged out.",
		})
	}
}

func slashDashboard(c *gin.Context) {
	group := c.Param("group")
	if _, err := os.Stat(path.Join(RuntimeArgs.SourcePath, group+".db")); os.IsNotExist(err) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "First download the app or CLI program to insert some fingerprints.",
		})
		return
	}
	ps, _ := openParameters(group)
	users := getUsers(group)
	people := make(map[string]UserPositionJSON)
	for _, user := range users {
		people[user] = getPositionBreakdown(group, user)
	}
	type DashboardData struct {
		Networks         []string
		Locations        map[string][]string
		LocationAccuracy map[string]int
		LocationCount    map[string]int
		Mixin            map[string]float64
		VarabilityCutoff map[string]float64
		Users            map[string]UserPositionJSON
	}
	var dash DashboardData
	dash.Networks = []string{}
	dash.Locations = make(map[string][]string)
	dash.LocationAccuracy = make(map[string]int)
	dash.LocationCount = make(map[string]int)
	dash.Mixin = make(map[string]float64)
	dash.VarabilityCutoff = make(map[string]float64)
	for n := range ps.NetworkLocs {
		dash.Mixin[n] = ps.Priors[n].Special["MixIn"]
		dash.VarabilityCutoff[n] = ps.Priors[n].Special["VarabilityCutoff"]
		dash.Networks = append(dash.Networks, n)
		dash.Locations[n] = []string{}
		for loc := range ps.NetworkLocs[n] {
			dash.Locations[n] = append(dash.Locations[n], loc)
			dash.LocationAccuracy[loc] = ps.Results[n].Accuracy[loc]
			dash.LocationCount[loc] = ps.Results[n].TotalLocations[loc]
		}
	}
	c.HTML(http.StatusOK, "dashboard.tmpl", gin.H{
		"Group": group,
		"Dash":  dash,
		"Users": people,
	})
}

func slashLocation(c *gin.Context) {
	group := c.Param("group")
	if _, err := os.Stat(path.Join(RuntimeArgs.SourcePath, group+".db")); os.IsNotExist(err) {
		c.JSON(http.StatusOK, gin.H{"success": "false", "message": "First download the app or CLI program to insert some fingerprints."})
		return
	}
	user := c.Param("user")
	userJSON := getPositionBreakdown(group, user)
	c.JSON(http.StatusOK, userJSON)
}

func slashExplore(c *gin.Context) {
	group := c.Param("group")
	if _, err := os.Stat(path.Join(RuntimeArgs.SourcePath, group+".db")); os.IsNotExist(err) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "First download the app or CLI program to insert some fingerprints.",
		})
		return
	}
	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	// TODO: check if network and location exists in the ps, if not return 404
	datas := []template.JS{}
	names := []template.JS{}
	indexNames := []template.JS{}
	// Sort locations
	macs := []string{}
	for m := range ps.Priors[network].P[location] {
		if float64(ps.MacVariability[m]) > ps.Priors[network].Special["VarabilityCutoff"] {
			macs = append(macs, m)
		}
	}
	sort.Strings(macs)
	it := 0
	for _, m := range macs {
		n := ps.Priors[network].P[location][m]
		names = append(names, template.JS(string(m)))
		jsonByte, _ := json.Marshal(n)
		datas = append(datas, template.JS(string(jsonByte)))
		indexNames = append(indexNames, template.JS(strconv.Itoa(it)))
		it++
	}
	rsiRange, _ := json.Marshal(RssiRange)
	c.HTML(http.StatusOK, "plot.tmpl", gin.H{
		"RssiRange":  template.JS(string(rsiRange)),
		"Datas":      datas,
		"Names":      names,
		"IndexNames": indexNames,
	})
}

func slashExplore2(c *gin.Context) {
	group := c.Param("group")
	if _, err := os.Stat(path.Join(RuntimeArgs.SourcePath, group+".db")); os.IsNotExist(err) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "First download the app or CLI program to insert some fingerprints.",
		})
		return
	}

	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	lookUpLocation := true
	if strings.Count(location, ":") > 4 {
		lookUpLocation = false // location is actuall mac
		Debug.Println("GOT LOCATION")
	}

	type macDatum struct {
		Name   string    `json:"name"`
		Points []float32 `json:"data"`
	}

	type macDatas struct {
		Macs []macDatum `json:"macs"`
	}

	var data macDatas
	data.Macs = []macDatum{}

	if lookUpLocation {
		// Sort locations
		macs := []string{}
		for m := range ps.Priors[network].P[location] {
			if float64(ps.MacVariability[m]) > ps.Priors[network].Special["VarabilityCutoff"] {
				macs = append(macs, m)
			}
		}
		sort.Strings(macs)

		for _, m := range macs {
			n := ps.Priors[network].P[location][m]
			data.Macs = append(data.Macs, macDatum{Name: m, Points: n})
		}
	} else {
		m := location
		for loc := range ps.Priors[network].P {
			Debug.Println(loc, m)
			n := ps.Priors[network].P[loc][m]
			data.Macs = append(data.Macs, macDatum{Name: strings.Replace(loc, " ", "%20", -1), Points: n})
		}
	}

	c.HTML(http.StatusOK, "plot2.tmpl", gin.H{
		"Data":    data,
		"Rssi":    RssiRange,
		"Title":   group + "/" + network + "/" + location,
		"Group":   strings.Replace(group, " ", "%20", -1),
		"Network": strings.Replace(network, " ", "%20", -1),
		"Legend":  !lookUpLocation,
	})
}

func slashPie(c *gin.Context) {
	group := c.Param("group")
	if _, err := os.Stat(path.Join(RuntimeArgs.SourcePath, group+".db")); os.IsNotExist(err) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"ErrorMessage": "First download the app or CLI program to insert some fingerprints.",
		})
		return
	}

	network := c.Param("network")
	location := c.Param("location")
	ps, _ := openParameters(group)
	vals := []int{}
	names := []string{}
	fmt.Println(ps.Results[network].Guess[location])
	for guessloc, val := range ps.Results[network].Guess[location] {
		names = append(names, guessloc)
		vals = append(vals, val)
	}
	namesJSON, _ := json.Marshal(names)
	valsJSON, _ := json.Marshal(vals)
	c.HTML(http.StatusOK, "pie.tmpl", gin.H{
		"Names": template.JS(namesJSON),
		"Vals":  template.JS(valsJSON),
	})
}
<|endoftext|>


<commit_before>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, 0755); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, 0755); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, 0755); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<commit_msg>ラララララ ラー ララララー<commit_after>package lfs

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

const Version = "0.5.1"

//
// Setup permissions for the given directories used here.
//
const (
    TempDirPerms       = 0755
    LocalMediaDirPerms = 0755
    LocalLogDirPerms   = 0755
)

var (
	LargeSizeThreshold = 5 * 1024 * 1024
	TempDir            = filepath.Join(os.TempDir(), "git-lfs")
	UserAgent          string
	LocalWorkingDir    string
	LocalGitDir        string
	LocalMediaDir      string
	LocalLogDir        string
	checkedTempDir     string
)

func TempFile(prefix string) (*os.File, error) {
	if checkedTempDir != TempDir {
		if err := os.MkdirAll(TempDir, TempDirPerms); err != nil {
			return nil, err
		}
		checkedTempDir = TempDir
	}

	return ioutil.TempFile(TempDir, prefix)
}

func ResetTempDir() error {
	checkedTempDir = ""
	return os.RemoveAll(TempDir)
}

func LocalMediaPath(sha string) (string, error) {
	path := filepath.Join(LocalMediaDir, sha[0:2], sha[2:4])
	if err := os.MkdirAll(path, LocalMediaDirPerms); err != nil {
		return "", fmt.Errorf("Error trying to create local media directory in '%s': %s", path, err)
	}

	return filepath.Join(path, sha), nil
}

func Environ() []string {
	osEnviron := os.Environ()
	env := make([]string, 6, len(osEnviron)+6)
	env[0] = fmt.Sprintf("LocalWorkingDir=%s", LocalWorkingDir)
	env[1] = fmt.Sprintf("LocalGitDir=%s", LocalGitDir)
	env[2] = fmt.Sprintf("LocalMediaDir=%s", LocalMediaDir)
	env[3] = fmt.Sprintf("TempDir=%s", TempDir)
	env[4] = fmt.Sprintf("ConcurrentTransfers=%d", Config.ConcurrentTransfers())
	env[5] = fmt.Sprintf("BatchTransfer=%v", Config.BatchTransfer())

	for _, e := range osEnviron {
		if !strings.Contains(e, "GIT_") {
			continue
		}
		env = append(env, e)
	}

	return env
}

func InRepo() bool {
	return LocalWorkingDir != ""
}

func init() {
	var err error

	tracerx.DefaultKey = "GIT"
	tracerx.Prefix = "trace git-lfs: "

	LocalWorkingDir, LocalGitDir, err = resolveGitDir()
	if err == nil {
		LocalMediaDir = filepath.Join(LocalGitDir, "lfs", "objects")
		LocalLogDir = filepath.Join(LocalMediaDir, "logs")
		TempDir = filepath.Join(LocalGitDir, "lfs", "tmp")

		if err := os.MkdirAll(LocalMediaDir, LocalMediaDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create objects directory in '%s': %s", LocalMediaDir, err))
		}

		if err := os.MkdirAll(LocalLogDir, LocalLogDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create log directory in '%s': %s", LocalLogDir, err))
		}

		if err := os.MkdirAll(TempDir, TempDirPerms); err != nil {
			panic(fmt.Errorf("Error trying to create temp directory in '%s': %s", TempDir, err))
		}

	}

	UserAgent = fmt.Sprintf("git-lfs/%s (GitHub; %s %s; go %s)", Version,
		runtime.GOOS,
		runtime.GOARCH,
		strings.Replace(runtime.Version(), "go", "", 1))
}

func resolveGitDir() (string, string, error) {
	gitDir := Config.Getenv("GIT_DIR")
	workTree := Config.Getenv("GIT_WORK_TREE")

	if gitDir != "" {
		return processGitDirVar(gitDir, workTree)
	}

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	workTreeR, gitDirR, err := recursiveResolveGitDir(wd)
	if err != nil {
		return "", "", err
	}

	if workTree != "" {
		return processWorkTree(gitDirR, workTree)
	}

	return workTreeR, gitDirR, nil
}

func processGitDirVar(gitDir, workTree string) (string, string, error) {
	if workTree != "" {
		return processWorkTree(gitDir, workTree)
	}

	// See `core.worktree` in `man git-config`:
	// “If --git-dir or GIT_DIR is specified but none of --work-tree, GIT_WORK_TREE and
	// core.worktree is specified, the current working directory is regarded as the top
	// level of your working tree.”

	wd, err := os.Getwd()
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processWorkTree(gitDir, workTree string) (string, string, error) {
	// See `core.worktree` in `man git-config`:
	// “The value [of core.worktree, GIT_WORK_TREE, or --work-tree] can be an absolute path
	// or relative to the path to the .git directory, which is either specified
	// by --git-dir or GIT_DIR, or automatically discovered.”

	if filepath.IsAbs(workTree) {
		return workTree, gitDir, nil
	}

	base := filepath.Dir(filepath.Clean(gitDir))
	absWorkTree := filepath.Join(base, workTree)
	return absWorkTree, gitDir, nil
}

func recursiveResolveGitDir(dir string) (string, string, error) {
	var cleanDir = filepath.Clean(dir)
	if cleanDir[len(cleanDir)-1] == os.PathSeparator {
		return "", "", fmt.Errorf("Git repository not found")
	}

	if filepath.Base(dir) == gitExt {
		// We're in the `.git` directory.  Make no assumptions about the working directory.
		return "", dir, nil
	}

	gitDir := filepath.Join(dir, gitExt)
	info, err := os.Stat(gitDir)
	if err != nil {
		// Found neither a directory nor a file named `.git`.
		// Move one directory up.
		return recursiveResolveGitDir(filepath.Dir(dir))
	}

	if !info.IsDir() {
		// Found a file named `.git` (we're in a submodule).
		return resolveDotGitFile(gitDir)
	}

	// Found the `.git` directory.
	return dir, gitDir, nil
}

func resolveDotGitFile(file string) (string, string, error) {
	// The local working directory is the directory the `.git` file is located in.
	wd := filepath.Dir(file)

	// The `.git` file tells us where the submodules `.git` directory is.
	gitDir, err := processDotGitFile(file)
	if err != nil {
		return "", "", err
	}

	return wd, gitDir, nil
}

func processDotGitFile(file string) (string, error) {
	f, err := os.Open(file)
	if err != nil {
		return "", err
	}
	defer f.Close()

	data := make([]byte, 512)
	n, err := f.Read(data)
	if err != nil {
		return "", err
	}

	contents := string(data[0:n])

	if !strings.HasPrefix(contents, gitPtrPrefix) {
		// The `.git` file has no entry telling us about gitdir.
		return "", nil
	}

	dir := strings.TrimSpace(strings.Split(contents, gitPtrPrefix)[1])

	if filepath.IsAbs(dir) {
		// The .git file contains an absolute path.
		return dir, nil
	}

	// The .git file contains a relative path.
	// Create an absolute path based on the directory the .git file is located in.
	absDir := filepath.Join(filepath.Dir(file), dir)

	return absDir, nil
}

const (
	gitExt       = ".git"
	gitPtrPrefix = "gitdir: "
)
<|endoftext|>


<commit_before>package vault

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"

	"bytes"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/ieee0824/getenv"
	"github.com/jobtalk/pnzr/lib"
	"os"
	"os/exec"
)

func getEditor() string {
	if e := os.Getenv("PNZR_EDITOR"); e != "" {
		return e
	}

	if e := os.Getenv("EDITOR"); e != "" {
		return e
	}

	return "nano"
}

type mode struct {
	encrypt *bool
	decrypt *bool
	edit    *bool
	view    *bool
}

func (m *mode)checkMultiFlagSet() bool {
	return (*m.encrypt && *m.decrypt) ||
		(*m.encrypt && *m.edit) ||
		(*m.encrypt && *m.view) ||
		(*m.decrypt && *m.edit) ||
		(*m.decrypt && *m.view) ||
		(*m.edit && *m.view)
}

type VaultCommand struct {
	sess           *session.Session
	kmsKeyID       *string
	vaultMode      *mode
	file           *string
	profile        *string
	region         *string
	awsAccessKeyID *string
	awsSecretKeyID *string
}

func (v *VaultCommand) parseArgs(args []string) {
	var (
		flagSet = new(flag.FlagSet)
		f       *string
	)
	v.vaultMode = new(mode)

	v.kmsKeyID = flagSet.String("key_id", getenv.String("KMS_KEY_ID"), "Amazon KMS key ID")
	v.vaultMode.encrypt = flagSet.Bool("encrypt", getenv.Bool("ENCRYPT", false), "encrypt mode")
	v.vaultMode.decrypt = flagSet.Bool("decrypt", getenv.Bool("DECRYPT", false), "decrypt mode")
	v.vaultMode.view = flagSet.Bool("view", false, "view mode")
	v.vaultMode.edit = flagSet.Bool("edit", false, "edit mode")
	v.profile = flagSet.String("profile", getenv.String("AWS_PROFILE_NAME", "default"), "aws credentials profile name")
	v.region = flagSet.String("region", getenv.String("AWS_REGION", "ap-northeast-1"), "aws region")
	v.awsAccessKeyID = flagSet.String("aws-access-key-id", getenv.String("AWS_ACCESS_KEY_ID"), "aws access key id")
	v.awsSecretKeyID = flagSet.String("aws-secret-key-id", getenv.String("AWS_SECRET_KEY_ID"), "aws secret key id")
	v.file = flagSet.String("file", "", "target file")
	f = flagSet.String("f", "", "target file")

	if err := flagSet.Parse(args); err != nil {
		panic(err)
	}

	if *f == "" && *v.file == "" && len(flagSet.Args()) != 0 {
		targetName := flagSet.Args()[0]
		v.file = &targetName
	}

	if *v.file == "" {
		v.file = f
	}

	var awsConfig = aws.Config{}

	if *v.awsAccessKeyID != "" && *v.awsSecretKeyID != "" && *v.profile == "" {
		awsConfig.Credentials = credentials.NewStaticCredentials(*v.awsAccessKeyID, *v.awsSecretKeyID, "")
		awsConfig.Region = v.region
	}

	v.sess = session.Must(session.NewSessionWithOptions(session.Options{
		AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
		SharedConfigState:       session.SharedConfigEnable,
		Profile:                 *v.profile,
		Config:                  awsConfig,
	}))
}

func (v *VaultCommand) encrypt(keyID string, fileName string) error {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}
	kms := lib.NewKMS(v.sess)
	_, err = kms.SetKeyID(keyID).Encrypt(bin)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(fileName, []byte(kms.String()), 0644)
}

func (v *VaultCommand) decrypt(keyID string, fileName string) error {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}
	kms := lib.NewKMSFromBinary(bin, v.sess)
	if kms == nil {
		return errors.New(fmt.Sprintf("%v form is illegal", fileName))
	}
	plainText, err := kms.SetKeyID(keyID).Decrypt()
	if err != nil {
		return err
	}
	return ioutil.WriteFile(fileName, plainText, 0644)
}

func (v *VaultCommand) decryptTemporary(keyID string, fileName string) ([]byte, error) {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	kms := lib.NewKMSFromBinary(bin, v.sess)
	if kms == nil {
		return nil, errors.New(fmt.Sprintf("%v form is illegal", fileName))
	}
	plainText, err := kms.SetKeyID(keyID).Decrypt()
	if err != nil {
		return nil, err
	}
	return plainText, nil
}

func (c *VaultCommand) Help() string {
	var msg string
	msg += "usage: pnzr vault [options ...]\n"
	msg += "options:\n"
	msg += "    -key_id\n"
	msg += "        set kms key id\n"
	msg += "    -encrypt\n"
	msg += "        use encrypt mode\n"
	msg += "    -decrypt\n"
	msg += "        use decrypt mode\n"
	msg += "    -file\n"
	msg += "        setting target file\n"
	msg += "    -f"
	msg += "        setting target file\n"
	msg += "    -profile\n"
	msg += "        aws credential name\n"
	msg += "    -region\n"
	msg += "        aws region name\n"
	msg += "    -aws-access-key-id\n"
	msg += "        setting aws access key id\n"
	msg += "    -aws-secret-key-id\n"
	msg += "        setting aws secret key id\n"
	msg += "===================================================\n"
	return msg
}

func (v *VaultCommand) Run(args []string) int {
	v.parseArgs(args)

	if v.vaultMode.checkMultiFlagSet() {
		panic("Multiple vault options are selected.")
	} else if *v.vaultMode.encrypt {
		if err := v.encrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.decrypt {
		if err := v.decrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.edit {
		if err := v.decrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
		defer func() {
			if err := v.encrypt(*v.kmsKeyID, *v.file); err != nil {
				panic(err)
			}
		}()
		cmd := exec.Command(getEditor(), *v.file)

		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if err := cmd.Run(); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.view {
		plain, err := v.decryptTemporary(*v.kmsKeyID, *v.file)
		if err != nil {
			panic(err)
		}

		cmd := exec.Command("less")
		cmd.Stdin = bytes.NewReader(plain)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if err := cmd.Run(); err != nil {
			panic(err)
		}
	} else {
		panic("Vault mode is not selected.")
	}

	return 0
}

func (c *VaultCommand) Synopsis() string {
	return c.Help()
}
<commit_msg>fmtをかける<commit_after>package vault

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"

	"bytes"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/ieee0824/getenv"
	"github.com/jobtalk/pnzr/lib"
	"os"
	"os/exec"
)

func getEditor() string {
	if e := os.Getenv("PNZR_EDITOR"); e != "" {
		return e
	}

	if e := os.Getenv("EDITOR"); e != "" {
		return e
	}

	return "nano"
}

type mode struct {
	encrypt *bool
	decrypt *bool
	edit    *bool
	view    *bool
}

func (m *mode) checkMultiFlagSet() bool {
	return (*m.encrypt && *m.decrypt) ||
		(*m.encrypt && *m.edit) ||
		(*m.encrypt && *m.view) ||
		(*m.decrypt && *m.edit) ||
		(*m.decrypt && *m.view) ||
		(*m.edit && *m.view)
}

type VaultCommand struct {
	sess           *session.Session
	kmsKeyID       *string
	vaultMode      *mode
	file           *string
	profile        *string
	region         *string
	awsAccessKeyID *string
	awsSecretKeyID *string
}

func (v *VaultCommand) parseArgs(args []string) {
	var (
		flagSet = new(flag.FlagSet)
		f       *string
	)
	v.vaultMode = new(mode)

	v.kmsKeyID = flagSet.String("key_id", getenv.String("KMS_KEY_ID"), "Amazon KMS key ID")
	v.vaultMode.encrypt = flagSet.Bool("encrypt", getenv.Bool("ENCRYPT", false), "encrypt mode")
	v.vaultMode.decrypt = flagSet.Bool("decrypt", getenv.Bool("DECRYPT", false), "decrypt mode")
	v.vaultMode.view = flagSet.Bool("view", false, "view mode")
	v.vaultMode.edit = flagSet.Bool("edit", false, "edit mode")
	v.profile = flagSet.String("profile", getenv.String("AWS_PROFILE_NAME", "default"), "aws credentials profile name")
	v.region = flagSet.String("region", getenv.String("AWS_REGION", "ap-northeast-1"), "aws region")
	v.awsAccessKeyID = flagSet.String("aws-access-key-id", getenv.String("AWS_ACCESS_KEY_ID"), "aws access key id")
	v.awsSecretKeyID = flagSet.String("aws-secret-key-id", getenv.String("AWS_SECRET_KEY_ID"), "aws secret key id")
	v.file = flagSet.String("file", "", "target file")
	f = flagSet.String("f", "", "target file")

	if err := flagSet.Parse(args); err != nil {
		panic(err)
	}

	if *f == "" && *v.file == "" && len(flagSet.Args()) != 0 {
		targetName := flagSet.Args()[0]
		v.file = &targetName
	}

	if *v.file == "" {
		v.file = f
	}

	var awsConfig = aws.Config{}

	if *v.awsAccessKeyID != "" && *v.awsSecretKeyID != "" && *v.profile == "" {
		awsConfig.Credentials = credentials.NewStaticCredentials(*v.awsAccessKeyID, *v.awsSecretKeyID, "")
		awsConfig.Region = v.region
	}

	v.sess = session.Must(session.NewSessionWithOptions(session.Options{
		AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
		SharedConfigState:       session.SharedConfigEnable,
		Profile:                 *v.profile,
		Config:                  awsConfig,
	}))
}

func (v *VaultCommand) encrypt(keyID string, fileName string) error {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}
	kms := lib.NewKMS(v.sess)
	_, err = kms.SetKeyID(keyID).Encrypt(bin)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(fileName, []byte(kms.String()), 0644)
}

func (v *VaultCommand) decrypt(keyID string, fileName string) error {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}
	kms := lib.NewKMSFromBinary(bin, v.sess)
	if kms == nil {
		return errors.New(fmt.Sprintf("%v form is illegal", fileName))
	}
	plainText, err := kms.SetKeyID(keyID).Decrypt()
	if err != nil {
		return err
	}
	return ioutil.WriteFile(fileName, plainText, 0644)
}

func (v *VaultCommand) decryptTemporary(keyID string, fileName string) ([]byte, error) {
	bin, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	kms := lib.NewKMSFromBinary(bin, v.sess)
	if kms == nil {
		return nil, errors.New(fmt.Sprintf("%v form is illegal", fileName))
	}
	plainText, err := kms.SetKeyID(keyID).Decrypt()
	if err != nil {
		return nil, err
	}
	return plainText, nil
}

func (c *VaultCommand) Help() string {
	var msg string
	msg += "usage: pnzr vault [options ...]\n"
	msg += "options:\n"
	msg += "    -key_id\n"
	msg += "        set kms key id\n"
	msg += "    -encrypt\n"
	msg += "        use encrypt mode\n"
	msg += "    -decrypt\n"
	msg += "        use decrypt mode\n"
	msg += "    -file\n"
	msg += "        setting target file\n"
	msg += "    -f"
	msg += "        setting target file\n"
	msg += "    -profile\n"
	msg += "        aws credential name\n"
	msg += "    -region\n"
	msg += "        aws region name\n"
	msg += "    -aws-access-key-id\n"
	msg += "        setting aws access key id\n"
	msg += "    -aws-secret-key-id\n"
	msg += "        setting aws secret key id\n"
	msg += "===================================================\n"
	return msg
}

func (v *VaultCommand) Run(args []string) int {
	v.parseArgs(args)

	if v.vaultMode.checkMultiFlagSet() {
		panic("Multiple vault options are selected.")
	} else if *v.vaultMode.encrypt {
		if err := v.encrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.decrypt {
		if err := v.decrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.edit {
		if err := v.decrypt(*v.kmsKeyID, *v.file); err != nil {
			panic(err)
		}
		defer func() {
			if err := v.encrypt(*v.kmsKeyID, *v.file); err != nil {
				panic(err)
			}
		}()
		cmd := exec.Command(getEditor(), *v.file)

		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if err := cmd.Run(); err != nil {
			panic(err)
		}
	} else if *v.vaultMode.view {
		plain, err := v.decryptTemporary(*v.kmsKeyID, *v.file)
		if err != nil {
			panic(err)
		}

		cmd := exec.Command("less")
		cmd.Stdin = bytes.NewReader(plain)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		if err := cmd.Run(); err != nil {
			panic(err)
		}
	} else {
		panic("Vault mode is not selected.")
	}

	return 0
}

func (c *VaultCommand) Synopsis() string {
	return c.Help()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/alexjohnj/flasher/tbutils"
	"github.com/codegangsta/cli"
	"github.com/nsf/termbox-go"
	"log"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "flasher"
	app.Version = "0.3.0-DEV"
	app.Author = "Alex Jackson"
	app.Email = "alex@alexj.org"

	app.Commands = []cli.Command{
		{
			Name:      "flash",
			ShortName: "f",
			Usage:     "flasher flash [flashcard-file.json]",
			Action:    cliFlash,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "no-shuffle, n",
					Usage: "Presents flashcards in the order they are written in the source JSON file.",
				},
			},
		},
		{
			Name:      "info",
			ShortName: "i",
			Usage:     "flasher info [flashcard-file.json]",
			Action:    cliInfo,
		},
	}
	app.Run(os.Args)
}

func cliFlash(c *cli.Context) {
	// Load flashcards

	if len(c.Args()) != 1 {
		log.Printf("Incorrect usage\n")
		cli.ShowCommandHelp(c, "flash")
		os.Exit(1)
	}

	flashcardStack := new(cardStack)
	err := flashcardStack.loadFlashcardStack(c.Args()[0])

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

	if !c.Bool("no-shuffle") {
		flashcardStack.shuffle()
	}

	// Init termbox
	err = termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	drawAll(flashcardStack)

	//Main Run loop
mainloop:
	for {
		switch event := termbox.PollEvent(); event.Type {
		case termbox.EventKey:
			switch event.Key {
			case termbox.KeyEsc, termbox.KeyCtrlC:
				break mainloop
			case termbox.KeyEnter, termbox.KeyArrowRight:
				flashcardStack.advanceStack()
				drawAll(flashcardStack)
			case termbox.KeyBackspace2, termbox.KeyArrowLeft:
				flashcardStack.revertStack()
				drawAll(flashcardStack)
			}

			switch event.Ch {
			case 'q':
				break mainloop
			}

		case termbox.EventResize:
			drawAll(flashcardStack)
		}
		drawAll(flashcardStack)
	}
}

func cliInfo(c *cli.Context) {
	if len(c.Args()) != 1 {
		log.Printf("Incorrect usage\n")
		cli.ShowCommandHelp(c, "info")
		os.Exit(1)
	}

	flashcardStack := new(cardStack)
	err := flashcardStack.loadFlashcardStack(c.Args()[0])

	if err != nil {
		log.Fatalf("%s is an invalid file: %s", c.Args()[0], err.Error())
	}

	fmt.Printf("Deck Name: %s\nAuthor: %s\nNumber of Cards: %d\n", flashcardStack.Title, flashcardStack.Author, len(flashcardStack.Flashcards))
}

func drawAll(stack *cardStack) {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	w, h := termbox.Size()

	// Draw termbox border
	termbox.SetCell(0, 0, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w-1, 0, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(0, h-1, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w-1, h-1, '+', termbox.ColorDefault, termbox.ColorDefault)

	for x := 1; x < w-1; x++ {
		termbox.SetCell(x, 0, '-', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(x, h-1, '-', termbox.ColorDefault, termbox.ColorDefault)
	}

	// Draw the Stack's title
	titleXCoord := tbutils.CalculateXCenterCoord(stack.Title)
	tbutils.DrawText(titleXCoord, 1, stack.Title)

	// Draw the current card
	currentQuestion := stack.getCurrentFlashcard()
	currentQuestion.drawQuestion()
	if stack.ShowAnswer {
		currentQuestion.drawAnswer()
		// Draw the Q/A divider
		for x := 0; x < w; x++ {
			termbox.SetCell(x, (3 * h / 8), '-', termbox.ColorBlue, termbox.ColorDefault)
		}
	}

	// Draw end of stack message
	if stack.atEndOfStack() {
		endOfStackMessageLine1 := "End of Stack..."
		endOfStackMessageLine2 := "(q)Quit (r)Restart (x)Reshuffle & Restart."
		eosXCoord1, eosYCoord1 := tbutils.CalculateXCenterCoord(endOfStackMessageLine1), (3 * (h / 4))
		eosXCoord2, eosYCoord2 := tbutils.CalculateXCenterCoord(endOfStackMessageLine2), (3*h/4)+1
		tbutils.DrawText(eosXCoord1, eosYCoord1, endOfStackMessageLine1)
		tbutils.DrawText(eosXCoord2, eosYCoord2, endOfStackMessageLine2)
	}

	// Draw the current index
	indexStr := fmt.Sprintf("(%d/%d)", stack.StackIndex+1, len(stack.Flashcards))
	indexXCoord, indexYCoord := tbutils.CalculateXCenterCoord(indexStr), h-1
	tbutils.DrawText(indexXCoord, indexYCoord, indexStr)

	// Write out the back buffer
	termbox.Flush()
}
<commit_msg>Implemented end of stack functions<commit_after>package main

import (
	"fmt"
	"github.com/alexjohnj/flasher/tbutils"
	"github.com/codegangsta/cli"
	"github.com/nsf/termbox-go"
	"log"
	"os"
)

func main() {
	app := cli.NewApp()
	app.Name = "flasher"
	app.Version = "0.3.0-DEV"
	app.Author = "Alex Jackson"
	app.Email = "alex@alexj.org"

	app.Commands = []cli.Command{
		{
			Name:      "flash",
			ShortName: "f",
			Usage:     "flasher flash [flashcard-file.json]",
			Action:    cliFlash,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "no-shuffle, n",
					Usage: "Presents flashcards in the order they are written in the source JSON file.",
				},
			},
		},
		{
			Name:      "info",
			ShortName: "i",
			Usage:     "flasher info [flashcard-file.json]",
			Action:    cliInfo,
		},
	}
	app.Run(os.Args)
}

func cliFlash(c *cli.Context) {
	// Load flashcards

	if len(c.Args()) != 1 {
		log.Printf("Incorrect usage\n")
		cli.ShowCommandHelp(c, "flash")
		os.Exit(1)
	}

	flashcardStack := new(cardStack)
	err := flashcardStack.loadFlashcardStack(c.Args()[0])

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

	if !c.Bool("no-shuffle") {
		flashcardStack.shuffle()
	}

	// Init termbox
	err = termbox.Init()
	if err != nil {
		panic(err)
	}
	defer termbox.Close()
	drawAll(flashcardStack)

	//Main Run loop
mainloop:
	for {
		switch event := termbox.PollEvent(); event.Type {
		case termbox.EventKey:
			switch event.Key {
			case termbox.KeyEsc, termbox.KeyCtrlC:
				break mainloop
			case termbox.KeyEnter, termbox.KeyArrowRight:
				flashcardStack.advanceStack()
				drawAll(flashcardStack)
			case termbox.KeyBackspace2, termbox.KeyArrowLeft:
				flashcardStack.revertStack()
				drawAll(flashcardStack)
			}

			switch event.Ch {
			case 'q':
				break mainloop

			case 'r':
				if flashcardStack.atEndOfStack() {
					flashcardStack.StackIndex = 0
					flashcardStack.ShowAnswer = false
					drawAll(flashcardStack)
				}

			case 'x':
				if flashcardStack.atEndOfStack() {
					flashcardStack.shuffle()
					flashcardStack.StackIndex = 0
					flashcardStack.ShowAnswer = false
					drawAll(flashcardStack)
				}
			}

		case termbox.EventResize:
			drawAll(flashcardStack)
		}

		drawAll(flashcardStack)
	}
}

func cliInfo(c *cli.Context) {
	if len(c.Args()) != 1 {
		log.Printf("Incorrect usage\n")
		cli.ShowCommandHelp(c, "info")
		os.Exit(1)
	}

	flashcardStack := new(cardStack)
	err := flashcardStack.loadFlashcardStack(c.Args()[0])

	if err != nil {
		log.Fatalf("%s is an invalid file: %s", c.Args()[0], err.Error())
	}

	fmt.Printf("Deck Name: %s\nAuthor: %s\nNumber of Cards: %d\n", flashcardStack.Title, flashcardStack.Author, len(flashcardStack.Flashcards))
}

func drawAll(stack *cardStack) {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
	w, h := termbox.Size()

	// Draw termbox border
	termbox.SetCell(0, 0, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w-1, 0, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(0, h-1, '+', termbox.ColorDefault, termbox.ColorDefault)
	termbox.SetCell(w-1, h-1, '+', termbox.ColorDefault, termbox.ColorDefault)

	for x := 1; x < w-1; x++ {
		termbox.SetCell(x, 0, '-', termbox.ColorDefault, termbox.ColorDefault)
		termbox.SetCell(x, h-1, '-', termbox.ColorDefault, termbox.ColorDefault)
	}

	// Draw the Stack's title
	titleXCoord := tbutils.CalculateXCenterCoord(stack.Title)
	tbutils.DrawText(titleXCoord, 1, stack.Title)

	// Draw the current card
	currentQuestion := stack.getCurrentFlashcard()
	currentQuestion.drawQuestion()
	if stack.ShowAnswer {
		currentQuestion.drawAnswer()
		// Draw the Q/A divider
		for x := 0; x < w; x++ {
			termbox.SetCell(x, (3 * h / 8), '-', termbox.ColorBlue, termbox.ColorDefault)
		}
	}

	// Draw end of stack message
	if stack.atEndOfStack() {
		endOfStackMessageLine1 := "End of Stack..."
		endOfStackMessageLine2 := "(q)Quit (r)Restart (x)Reshuffle & Restart."
		eosXCoord1, eosYCoord1 := tbutils.CalculateXCenterCoord(endOfStackMessageLine1), (3 * (h / 4))
		eosXCoord2, eosYCoord2 := tbutils.CalculateXCenterCoord(endOfStackMessageLine2), (3*h/4)+1
		tbutils.DrawText(eosXCoord1, eosYCoord1, endOfStackMessageLine1)
		tbutils.DrawText(eosXCoord2, eosYCoord2, endOfStackMessageLine2)
	}

	// Draw the current index
	indexStr := fmt.Sprintf("(%d/%d)", stack.StackIndex+1, len(stack.Flashcards))
	indexXCoord, indexYCoord := tbutils.CalculateXCenterCoord(indexStr), h-1
	tbutils.DrawText(indexXCoord, indexYCoord, indexStr)

	// Write out the back buffer
	termbox.Flush()
}
<|endoftext|>


<commit_before>package tirion

import (
	"errors"
	"fmt"
	"math"
	"net"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/zimmski/tirion/shm"
)

const Version = "0.1"

type HighStockTag struct {
	X     int64  `json:"x"`
	Title string `json:"title"`
}

type Metric struct {
	Name string
	Type string
}

var MetricTypes = map[string]bool{
	"int":   true,
	"float": true,
}

type Program struct {
	Name string
}

type Run struct {
	Id            int32
	Name          string
	SubName       string
	Interval      int32
	Metrics       []Metric
	MetricCount   int32
	Prog          string
	ProgArguments string
	Start         *time.Time
	Stop          *time.Time
}

type Tag struct {
	Time time.Time
	Tag  string
}

type Tirion struct {
	fd        net.Conn
	Running   bool
	shm       *shm.Shm
	socket    string
	verbose   bool
	logPrefix string
}

func CheckMetrics(metrics []Metric) error {
	if len(metrics) == 0 {
		return errors.New("No metrics defined")
	} else if len(metrics) >= math.MaxInt32 {
		return errors.New(fmt.Sprintf("Maximum of %d metrics allowed", math.MaxInt32))
	}

	var metricNames = make(map[string]int32)

	for i, m := range metrics {
		if m.Name == "" {
			return errors.New(fmt.Sprintf("No name defined for metric[%d]", i))
		} else if v, ok := metricNames[m.Name]; ok {
			return errors.New(fmt.Sprintf("Name \"%s\" of metric[%d] alreay used for metric[%d]", m.Name, i, v))
		} else if m.Type == "" {
			return errors.New(fmt.Sprintf("No type defined for metric[%d]", i))
		} else if _, ok := MetricTypes[m.Type]; !ok {
			return errors.New(fmt.Sprintf("Unknown metric type \"%s\" for metric[%d]", m.Type, i))
		}

		metricNames[m.Name] = int32(i)
	}

	return nil
}

func (t *Tirion) initShm(filename string, create bool, count int32) error {
	var err error

	t.V("Open shared memory")
	t.shm, err = shm.NewShm(filename, create, count)

	if err != nil {
		return err
	}

	t.V("Read shared memory")
	err = t.shm.Read()

	if err != nil {
		panic(err)
	}

	return nil
}

func (t *Tirion) initSigHandler() {
	t.V("Create signal handler")
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	go func() {
		s := <-sig
		t.V("Catched signal %v", s)

		t.Running = false
	}()
}

func (t *Tirion) receive() (string, error) {
	var buf = make([]byte, 4096)

	nr, err := t.fd.Read(buf)

	if err != nil {
		return "", err
	}

	return strings.Trim(string(buf[0:nr]), "\n"), nil
}

func (t *Tirion) send(msg string) {
	_, err := t.fd.Write([]byte(msg + "\n"))

	if err != nil {
		panic(err)
	}
}

// TODO remove this or maybe we should put them in a logging package or use another logging package

func (t *Tirion) D(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[debug] "+format+"\n", a...)
}

func (t *Tirion) E(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[error] "+format+"\n", a...)
}

func (t *Tirion) V(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[verbose] "+format+"\n", a...)
}
<commit_msg>check metrics name for length and illegal characters<commit_after>package tirion

import (
	"errors"
	"fmt"
	"math"
	"net"
	"os"
	"os/signal"
	"regexp"
	"strings"
	"syscall"
	"time"

	"github.com/zimmski/tirion/shm"
)

const Version = "0.1"

type HighStockTag struct {
	X     int64  `json:"x"`
	Title string `json:"title"`
}

type Metric struct {
	Name string
	Type string
}

var MetricTypes = map[string]bool{
	"int":   true,
	"float": true,
}

type Program struct {
	Name string
}

type Run struct {
	Id            int32
	Name          string
	SubName       string
	Interval      int32
	Metrics       []Metric
	MetricCount   int32
	Prog          string
	ProgArguments string
	Start         *time.Time
	Stop          *time.Time
}

type Tag struct {
	Time time.Time
	Tag  string
}

type Tirion struct {
	fd        net.Conn
	Running   bool
	shm       *shm.Shm
	socket    string
	verbose   bool
	logPrefix string
}

func CheckMetrics(metrics []Metric) error {
	if len(metrics) == 0 {
		return errors.New("No metrics defined")
	} else if len(metrics) >= math.MaxInt32 {
		return errors.New(fmt.Sprintf("Maximum of %d metrics allowed", math.MaxInt32))
	}

	var metricNameRegex = regexp.MustCompile("[^a-zA-Z0-9.-_]")
	var metricNames = make(map[string]int32)

	for i, m := range metrics {
		if m.Name == "" {
			return errors.New(fmt.Sprintf("No name defined for metric[%d]", i))
		} else if len(m.Name) > 256 {
			return errors.New(fmt.Sprintf("Name of metric[%d] exceeds maximum of 256 characters", i))
		} else if metricNameRegex.MatchString(m.Name) {
			return errors.New(fmt.Sprintf("Name  of metric[%d] uses illegal characters. Only a-z, A-Z, 0-9, ., - and _ are allowed!", i))
		} else if v, ok := metricNames[m.Name]; ok {
			return errors.New(fmt.Sprintf("Name \"%s\" of metric[%d] alreay used for metric[%d]", m.Name, i, v))
		} else if m.Type == "" {
			return errors.New(fmt.Sprintf("No type defined for metric[%d]", i))
		} else if _, ok := MetricTypes[m.Type]; !ok {
			return errors.New(fmt.Sprintf("Unknown metric type \"%s\" for metric[%d]", m.Type, i))
		}

		metricNames[m.Name] = int32(i)
	}

	return nil
}

func (t *Tirion) initShm(filename string, create bool, count int32) error {
	var err error

	t.V("Open shared memory")
	t.shm, err = shm.NewShm(filename, create, count)

	if err != nil {
		return err
	}

	t.V("Read shared memory")
	err = t.shm.Read()

	if err != nil {
		panic(err)
	}

	return nil
}

func (t *Tirion) initSigHandler() {
	t.V("Create signal handler")
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	go func() {
		s := <-sig
		t.V("Catched signal %v", s)

		t.Running = false
	}()
}

func (t *Tirion) receive() (string, error) {
	var buf = make([]byte, 4096)

	nr, err := t.fd.Read(buf)

	if err != nil {
		return "", err
	}

	return strings.Trim(string(buf[0:nr]), "\n"), nil
}

func (t *Tirion) send(msg string) {
	_, err := t.fd.Write([]byte(msg + "\n"))

	if err != nil {
		panic(err)
	}
}

// TODO remove this or maybe we should put them in a logging package or use another logging package

func (t *Tirion) D(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[debug] "+format+"\n", a...)
}

func (t *Tirion) E(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[error] "+format+"\n", a...)
}

func (t *Tirion) V(format string, a ...interface{}) (n int, err error) {
	if !t.verbose {
		return
	}

	return fmt.Fprintf(os.Stderr, t.logPrefix+"[verbose] "+format+"\n", a...)
}
<|endoftext|>