<commit_before>package main

import (
	"fmt"
	"os"

	"../dos"
	"../interpreter"
	"../lua"
)

type LuaFunction struct {
	L            *lua.Lua
	registoryKey string
}

var LuaInstanceToCmd = map[uintptr]*interpreter.Interpreter{}

func (this LuaFunction) String() string {
	return "<<Lua-function>>"
}

func (this LuaFunction) Call(cmd *interpreter.Interpreter) (interpreter.NextT, error) {
	this.L.GetField(lua.LUA_REGISTRYINDEX, this.registoryKey)
	this.L.NewTable()
	for i, arg1 := range cmd.Args {
		this.L.PushString(arg1)
		this.L.RawSetI(-2, lua.Integer(i))
	}
	LuaInstanceToCmd[this.L.State()] = cmd
	err := this.L.Call(1, 0)
	return interpreter.CONTINUE, err
}

const original_io_lines = "original_io_lines"

func ioLines(this *lua.Lua) int {
	if this.IsString(1) {
		// io.lines("FILENAME") --> use original io.lines
		this.GetField(lua.LUA_REGISTRYINDEX, original_io_lines)
		this.PushValue(1)
		this.Call(1, 1)
	} else {
		// io.lines() --> use nyagos version
		this.PushGoFunction(ioLinesNext)
	}
	return 1
}

func ioLinesNext(this *lua.Lua) int {
	cmd := LuaInstanceToCmd[this.State()]

	line := make([]byte, 0, 256)
	var ch [1]byte
	for {
		n, err := cmd.Stdin.Read(ch[0:1])
		if n <= 0 || err != nil {
			if len(line) <= 0 {
				this.PushNil()
			} else {
				this.PushAnsiString(line)
			}
			return 1
		}
		if ch[0] == '\n' {
			this.PushAnsiString(line)
			return 1
		}
		line = append(line, ch[0])
	}
}

func SetLuaFunctions(this *lua.Lua) {
	stackPos := this.GetTop()
	defer this.SetTop(stackPos)
	this.NewTable()
	this.PushGoFunction(cmdAlias)
	this.SetField(-2, "alias")
	this.PushGoFunction(cmdSetEnv)
	this.SetField(-2, "setenv")
	this.PushGoFunction(cmdGetEnv)
	this.SetField(-2, "getenv")
	this.PushGoFunction(cmdExec)
	this.SetField(-2, "exec")
	this.PushGoFunction(cmdWrite)
	this.SetField(-2, "write")
	this.PushGoFunction(cmdAccess)
	this.SetField(-2, "access")
	this.PushGoFunction(cmdAtoU)
	this.SetField(-2, "atou")
	this.PushGoFunction(cmdUtoA)
	this.SetField(-2, "utoa")
	this.PushGoFunction(cmdGetwd)
	this.SetField(-2, "getwd")
	this.PushGoFunction(cmdWhich)
	this.SetField(-2, "which")
	this.PushGoFunction(cmdEval)
	this.SetField(-2, "eval")
	this.PushGoFunction(cmdGlob)
	this.SetField(-2, "glob")
	this.PushGoFunction(cmdBindKey)
	this.SetField(-2, "bindkey")
	this.PushGoFunction(cmdGetHistory)
	this.SetField(-2, "gethistory")
	this.PushGoFunction(cmdSetRuneWidth)
	this.SetField(-2, "setrunewidth")
	this.PushGoFunction(cmdShellExecute)
	this.SetField(-2, "shellexecute")
	this.PushGoFunction(cmdPathJoin)
	this.SetField(-2, "pathjoin")
	exeName, exeNameErr := dos.GetModuleFileName()
	if exeNameErr != nil {
		fmt.Fprintln(os.Stderr, exeNameErr)
	} else {
		this.PushString(exeName)
		this.SetField(-2, "exe")
	}
	this.SetGlobal("nyagos")

	// replace os.getenv
	this.GetGlobal("os")           // +1
	this.PushGoFunction(cmdGetEnv) // +2
	this.SetField(-2, "getenv")    // +1
	this.Pop(1)                    // 0

	// save io.lines as original_io_lines
	this.GetGlobal("io")                                    // +1
	this.GetField(-1, "lines")                              // +2
	this.SetField(lua.LUA_REGISTRYINDEX, original_io_lines) // +1
	this.Pop(1)                                             // 0

	// replace io.lines
	this.GetGlobal("io")         // +1
	this.PushGoFunction(ioLines) // +2
	this.SetField(-2, "lines")   // +1
	this.Pop(1)                  // 0

	var orgArgHook func([]string) []string
	orgArgHook = interpreter.SetArgsHook(func(args []string) []string {
		pos := this.GetTop()
		defer this.SetTop(pos)
		this.GetGlobal("nyagos")
		this.GetField(-1, "argsfilter")
		if !this.IsFunction(-1) {
			return orgArgHook(args)
		}
		this.NewTable()
		for i := 0; i < len(args); i++ {
			this.PushString(args[i])
			this.RawSetI(-2, lua.Integer(i))
		}
		if err := this.Call(1, 1); err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			return orgArgHook(args)
		}
		if this.GetType(-1) != lua.LUA_TTABLE {
			return orgArgHook(args)
		}
		newargs := []string{}
		for i := lua.Integer(0); true; i++ {
			this.PushInteger(i)
			this.GetTable(-2)
			if this.GetType(-1) == lua.LUA_TNIL {
				break
			}
			arg1, arg1err := this.ToString(-1)
			if arg1err == nil {
				newargs = append(newargs, arg1)
			} else {
				fmt.Fprintln(os.Stderr, arg1err.Error())
			}
			this.Pop(1)
		}
		return orgArgHook(newargs)
	})
}
<commit_msg>Simplefy initialize lua command table<commit_after>package main

import (
	"fmt"
	"os"

	"../dos"
	"../interpreter"
	"../lua"
)

type LuaFunction struct {
	L            *lua.Lua
	registoryKey string
}

var LuaInstanceToCmd = map[uintptr]*interpreter.Interpreter{}

func (this LuaFunction) String() string {
	return "<<Lua-function>>"
}

func (this LuaFunction) Call(cmd *interpreter.Interpreter) (interpreter.NextT, error) {
	this.L.GetField(lua.LUA_REGISTRYINDEX, this.registoryKey)
	this.L.NewTable()
	for i, arg1 := range cmd.Args {
		this.L.PushString(arg1)
		this.L.RawSetI(-2, lua.Integer(i))
	}
	LuaInstanceToCmd[this.L.State()] = cmd
	err := this.L.Call(1, 0)
	return interpreter.CONTINUE, err
}

const original_io_lines = "original_io_lines"

func ioLines(this *lua.Lua) int {
	if this.IsString(1) {
		// io.lines("FILENAME") --> use original io.lines
		this.GetField(lua.LUA_REGISTRYINDEX, original_io_lines)
		this.PushValue(1)
		this.Call(1, 1)
	} else {
		// io.lines() --> use nyagos version
		this.PushGoFunction(ioLinesNext)
	}
	return 1
}

func ioLinesNext(this *lua.Lua) int {
	cmd := LuaInstanceToCmd[this.State()]

	line := make([]byte, 0, 256)
	var ch [1]byte
	for {
		n, err := cmd.Stdin.Read(ch[0:1])
		if n <= 0 || err != nil {
			if len(line) <= 0 {
				this.PushNil()
			} else {
				this.PushAnsiString(line)
			}
			return 1
		}
		if ch[0] == '\n' {
			this.PushAnsiString(line)
			return 1
		}
		line = append(line, ch[0])
	}
}

func SetLuaFunctions(this *lua.Lua) {
	stackPos := this.GetTop()
	defer this.SetTop(stackPos)

	nyagos_table := map[string]interface{}{
		"access":       cmdAccess,
		"alias":        cmdAlias,
		"atou":         cmdAtoU,
		"bindkey":      cmdBindKey,
		"eval":         cmdEval,
		"exec":         cmdExec,
		"getenv":       cmdGetEnv,
		"gethistory":   cmdGetHistory,
		"getwd":        cmdGetwd,
		"glob":         cmdGlob,
		"pathjoin":     cmdPathJoin,
		"setenv":       cmdSetEnv,
		"setrunewidth": cmdSetRuneWidth,
		"shellexecute": cmdShellExecute,
		"utoa":         cmdUtoA,
		"which":        cmdWhich,
		"write":        cmdWrite,
	}
	if exeName, exeNameErr := dos.GetModuleFileName() ; exeNameErr != nil {
		fmt.Fprintln(os.Stderr, exeNameErr)
	} else {
		nyagos_table["exe"] = exeName
	}
	this.Push(nyagos_table)
	this.SetGlobal("nyagos")

	// replace os.getenv
	this.GetGlobal("os")           // +1
	this.PushGoFunction(cmdGetEnv) // +2
	this.SetField(-2, "getenv")    // +1
	this.Pop(1)                    // 0

	// save io.lines as original_io_lines
	this.GetGlobal("io")                                    // +1
	this.GetField(-1, "lines")                              // +2
	this.SetField(lua.LUA_REGISTRYINDEX, original_io_lines) // +1
	this.Pop(1)                                             // 0

	// replace io.lines
	this.GetGlobal("io")         // +1
	this.PushGoFunction(ioLines) // +2
	this.SetField(-2, "lines")   // +1
	this.Pop(1)                  // 0

	var orgArgHook func([]string) []string
	orgArgHook = interpreter.SetArgsHook(func(args []string) []string {
		pos := this.GetTop()
		defer this.SetTop(pos)
		this.GetGlobal("nyagos")
		this.GetField(-1, "argsfilter")
		if !this.IsFunction(-1) {
			return orgArgHook(args)
		}
		this.NewTable()
		for i := 0; i < len(args); i++ {
			this.PushString(args[i])
			this.RawSetI(-2, lua.Integer(i))
		}
		if err := this.Call(1, 1); err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			return orgArgHook(args)
		}
		if this.GetType(-1) != lua.LUA_TTABLE {
			return orgArgHook(args)
		}
		newargs := []string{}
		for i := lua.Integer(0); true; i++ {
			this.PushInteger(i)
			this.GetTable(-2)
			if this.GetType(-1) == lua.LUA_TNIL {
				break
			}
			arg1, arg1err := this.ToString(-1)
			if arg1err == nil {
				newargs = append(newargs, arg1)
			} else {
				fmt.Fprintln(os.Stderr, arg1err.Error())
			}
			this.Pop(1)
		}
		return orgArgHook(newargs)
	})
}
<|endoftext|>


<commit_before>package snmp

import (
	"bytes"
	"io"
)

// GetResponse represents an SNMP GET-RESPONSE.
type GetResponse struct {
	rawSequence []DataType
	requestID   int
	err         int
	errIndex    int
	Varbinds    []Varbind
}

// Encode encodes a GetResponse with the proper header.
func (s GetResponse) Encode() ([]byte, error) {
	buf := &bytes.Buffer{}

	for _, entry := range s.rawSequence {
		encodedEntry, err := entry.Encode()
		if err != nil {
			return nil, err
		}

		_, err = buf.Write(encodedEntry)
		if err != nil {
			return nil, err
		}
	}

	seqLength := buf.Len()

	return append(encodeHeaderSequence(0xa2, seqLength), buf.Bytes()...), nil
}

// decodeGetResponse decodes a GetResponse up to length bytes from r.
// It returns the SNMP data type, the number of bytes read, and an error.
// For convenience, individual fields values are copied directly into
// the GetResponse struct.
func decodeGetResponse(length int, r io.Reader) (GetResponse, int, error) {
	res := GetResponse{}
	seqBytes := 0
	bytesRead := 0

	for seqBytes < length {
		item, read, err := decode(r)
		if read > 0 && item != nil {
			res.rawSequence = append(res.rawSequence, item)
			bytesRead += read
			seqBytes += read
		}

		if err != nil {
			return res, bytesRead, err
		}
	}

	reqID, ok := res.rawSequence[0].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.requestID = int(reqID)

	errorCode, ok := res.rawSequence[1].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.err = int(errorCode)

	errIndex, ok := res.rawSequence[2].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.errIndex = int(errIndex)

	varbindSeq, ok := res.rawSequence[3].(Sequence)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	for _, varbindElem := range varbindSeq {
		varbindPair, ok := varbindElem.(Sequence)
		if !ok {
			return res, bytesRead, ErrDecodingType
		}

		oid, ok := varbindPair[0].(ObjectIdentifier)
		if ok {
			val := varbindPair[1]
			res.Varbinds = append(res.Varbinds, NewVarbind(oid, val))
		}
	}

	return res, bytesRead, nil
}
<commit_msg>Update comment<commit_after>package snmp

import (
	"bytes"
	"io"
)

// GetResponse represents an SNMP GetResponse-PDU.
type GetResponse struct {
	rawSequence []DataType
	requestID   int
	err         int
	errIndex    int
	Varbinds    []Varbind
}

// Encode encodes a GetResponse with the proper header.
func (s GetResponse) Encode() ([]byte, error) {
	buf := &bytes.Buffer{}

	for _, entry := range s.rawSequence {
		encodedEntry, err := entry.Encode()
		if err != nil {
			return nil, err
		}

		_, err = buf.Write(encodedEntry)
		if err != nil {
			return nil, err
		}
	}

	seqLength := buf.Len()

	return append(encodeHeaderSequence(0xa2, seqLength), buf.Bytes()...), nil
}

// decodeGetResponse decodes a GetResponse up to length bytes from r.
// It returns the SNMP data type, the number of bytes read, and an error.
// For convenience, individual fields values are copied directly into
// the GetResponse struct.
func decodeGetResponse(length int, r io.Reader) (GetResponse, int, error) {
	res := GetResponse{}
	seqBytes := 0
	bytesRead := 0

	for seqBytes < length {
		item, read, err := decode(r)
		if read > 0 && item != nil {
			res.rawSequence = append(res.rawSequence, item)
			bytesRead += read
			seqBytes += read
		}

		if err != nil {
			return res, bytesRead, err
		}
	}

	reqID, ok := res.rawSequence[0].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.requestID = int(reqID)

	errorCode, ok := res.rawSequence[1].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.err = int(errorCode)

	errIndex, ok := res.rawSequence[2].(Int)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	res.errIndex = int(errIndex)

	varbindSeq, ok := res.rawSequence[3].(Sequence)
	if !ok {
		return res, bytesRead, ErrDecodingType
	}
	for _, varbindElem := range varbindSeq {
		varbindPair, ok := varbindElem.(Sequence)
		if !ok {
			return res, bytesRead, ErrDecodingType
		}

		oid, ok := varbindPair[0].(ObjectIdentifier)
		if ok {
			val := varbindPair[1]
			res.Varbinds = append(res.Varbinds, NewVarbind(oid, val))
		}
	}

	return res, bytesRead, nil
}
<|endoftext|>


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

package main

import (
	"code.google.com/p/log4go"
	"flag"
	"fmt"
	"github.com/limetext/gopy/lib"
	"github.com/limetext/lime/backend"
	_ "github.com/limetext/lime/backend/commands"
	"github.com/limetext/lime/backend/keys"
	"github.com/limetext/lime/backend/render"
	"github.com/limetext/lime/backend/sublime"
	"github.com/limetext/lime/backend/textmate"
	"github.com/limetext/lime/backend/util"
	. "github.com/quarnster/util/text"
	"io"
	"net/http"
	"runtime/debug"
	"strconv"
	"sync"
	"time"
	"unicode"
)

var (
	scheme   *textmate.Theme
	blink    bool
	port   = flag.Int("port", 8080, "Configures which port to host lime on")
)

const (
	console_height  = 20
	render_chan_len = 2
)

type layout struct {
	x, y          int
	width, height int
	visible       Region
	lastUpdate    int
}
type tbfe struct {
	layout         map[*backend.View]layout
	status_message string
	dorender       chan bool
	lock           sync.Mutex
	dirty          bool
}

func htmlcol(c render.Colour) string {
	return fmt.Sprintf("%02X%02X%02X", c.R, c.G, c.B)
}

func (t *tbfe) renderView(wr io.Writer, v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	recipie := v.Transform(scheme, vr).Transcribe()
	highlight_line := false
	if b, ok := v.Settings().Get("highlight_line", highlight_line).(bool); ok {
		highlight_line = b
	}
	lastEnd := 0
	for _, reg := range recipie {
		if lastEnd != reg.Region.Begin() {
			io.WriteString(wr, runes[lastEnd:reg.Region.Begin()])
		}
		fmt.Fprintf(wr, "%s", htmlcol(reg.Flavour.Foreground), htmlcol(reg.Flavour.Background), runes[reg.Region.Begin():reg.Region.End()])
		lastEnd = reg.Region.End()
	}
	if lastEnd != vr.End() {
		io.WriteString(wr, v.Buffer().Substr(Region{lastEnd, vr.End()}))
	}
}

func (t *tbfe) clip(v *backend.View, s, e int) Region {
	p := util.Prof.Enter("clip")
	defer p.Exit()
	h := t.layout[v].height
	if e-s > h {
		e = s + h
	} else if e-s < h {
		s = e - h
	}
	if e2, _ := v.Buffer().RowCol(v.Buffer().TextPoint(e, 0)); e2 < e {
		e = e2
	}
	if s < 0 {
		s = 0
	}
	e = s + h
	r := Region{v.Buffer().TextPoint(s, 0), v.Buffer().TextPoint(e, 0)}
	return v.Buffer().LineR(r)
}

func (t *tbfe) Show(v *backend.View, r Region) {
	t.lock.Lock()
	l := t.layout[v]
	t.lock.Unlock()
	if l.visible.Covers(r) {
		return
	}
	p := util.Prof.Enter("show")
	defer p.Exit()

	lv := l.visible

	s1, _ := v.Buffer().RowCol(lv.Begin())
	e1, _ := v.Buffer().RowCol(lv.End())
	s2, _ := v.Buffer().RowCol(r.Begin())
	e2, _ := v.Buffer().RowCol(r.End())

	r1 := Region{s1, e1}
	r2 := Region{s2, e2}

	r3 := r1.Cover(r2)
	diff := 0
	if d1, d2 := Abs(r1.Begin()-r3.Begin()), Abs(r1.End()-r3.End()); d1 > d2 {
		diff = r3.Begin() - r1.Begin()
	} else {
		diff = r3.End() - r1.End()
	}
	r3.A = r1.Begin() + diff
	r3.B = r1.End() + diff

	r3 = t.clip(v, r3.A, r3.B)
	l.visible = r3
	t.lock.Lock()
	t.layout[v] = l
	t.lock.Unlock()
}

func (t *tbfe) VisibleRegion(v *backend.View) Region {
	t.lock.Lock()
	r, ok := t.layout[v]
	t.lock.Unlock()
	if !ok || r.lastUpdate != v.Buffer().ChangeCount() {
		t.Show(v, r.visible)
		t.lock.Lock()
		r = t.layout[v]
		t.lock.Unlock()
	}
	return r.visible
}

func (t *tbfe) StatusMessage(msg string) {
	t.lock.Lock()
	defer t.lock.Unlock()
	t.status_message = msg
}

func (t *tbfe) ErrorMessage(msg string) {
	log4go.Error(msg)
}

// TODO(q): Actually show a dialog
func (t *tbfe) MessageDialog(msg string) {
	log4go.Info(msg)
}

// TODO(q): Actually show a dialog
func (t *tbfe) OkCancelDialog(msg, ok string) bool {
	log4go.Info(msg, ok)
	return false
}

func (t *tbfe) scroll(b Buffer, pos, delta int) {
	t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}

var pc = 0

func (t *tbfe) render(w io.Writer) {
	defer func() {
		if r := recover(); r != nil {
			log4go.Error("Panic in renderthread: %v\n%s", r, string(debug.Stack()))
			if pc > 1 {
				panic(r)
			}
			pc++
		}
	}()
	vs := make([]*backend.View, 0, len(t.layout))
	l := make([]layout, 0, len(t.layout))
	for k, v := range t.layout {
		vs = append(vs, k)
		l = append(l, v)
	}
	for i, v := range vs {
		t.renderView(w, v, l[i])
	}
	//	runes := []rune(t.status_message)
}
func (t *tbfe) key(w http.ResponseWriter, req *http.Request) {
	log4go.Debug("key: %s", req)
	kc := req.FormValue("keyCode")
	var kp keys.KeyPress
	v, _ := strconv.ParseInt(kc, 10, 32)

	if req.FormValue("altKey") == "true" {
		kp.Alt = true
	}
	if req.FormValue("ctrlKey") == "true" {
		kp.Ctrl = true
	}
	if req.FormValue("metaKey") == "true" {
		kp.Super = true
	}
	if req.FormValue("shiftKey") == "true" {
		kp.Shift = true
	}
	if !kp.Shift {
		v = int64(unicode.ToLower(rune(v)))
	}
	kp.Key = keys.Key(v)
	backend.GetEditor().HandleInput(kp)
}

func (t *tbfe) view(w http.ResponseWriter, req *http.Request) {
	log4go.Debug("view: %s", req)
	if t.dirty {
		t.dirty = false
		t.render(w)
	} else {
		w.WriteHeader(404)
	}
}

func (t *tbfe) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s := time.Now()
	w.Header().Set("Content-Type", "text/html")
	log4go.Debug("Serving client: %s", req)

	c := scheme.Spice(&render.ViewRegions{})

	fmt.Fprintf(w, `

`, htmlcol(c.Foreground), htmlcol(c.Background))
	io.WriteString(w, "")
	log4go.Debug("Done serving client: %s", time.Since(s))
}

func (t *tbfe) loop() {
	backend.OnNew.Add(func(v *backend.View) {
		v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { t.dirty = true })
	})
	backend.OnModified.Add(func(v *backend.View) {
		t.dirty = true
	})
	backend.OnSelectionModified.Add(func(v *backend.View) {
		t.dirty = true
	})

	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)
	c := ed.Console()
	if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil {
		log4go.Error(err)
	} else {
		scheme = sc
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	w := ed.NewWindow()
	v := w.OpenFile("main.go", 0)
	v.Settings().Set("trace", true)
	v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage")
	c.Buffer().AddCallback(t.scroll)

	sel := v.Sel()
	sel.Clear()
	//	end := v.Buffer().Size() - 2
	sel.Add(Region{0, 0})
	// sel.Add(Region{end - 22, end - 22})
	// sel.Add(Region{end - 16, end - 20})
	// sel.Add(Region{end - 13, end - 10})

	{
		w, h := 800, 600
		t.lock.Lock()
		t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0}
		t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0}
		t.lock.Unlock()
		t.Show(v, Region{1, 1})
	}
	t.Show(v, Region{100, 100})
	t.Show(v, Region{1, 1})

	go func() {
		ed.Init()
		sublime.Init()
	}()
	log4go.Debug("serving")
	http.HandleFunc("/key", t.key)
	http.HandleFunc("/", t.ServeHTTP)
	http.HandleFunc("/view", t.view)
	if err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *port), nil); err != nil {
		log4go.Error("Error serving: %s", err)
	}
	log4go.Debug("Done")
}

func main() {
	flag.Parse()
	log4go.AddFilter("file", log4go.FINEST, log4go.NewConsoleLogWriter())
	defer func() {
		py.NewLock()
		py.Finalize()
	}()

	var t tbfe
	t.dorender = make(chan bool, render_chan_len)
	t.layout = make(map[*backend.View]layout)
	t.loop()
}
<commit_msg>fmt fix<commit_after>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package main

import (
	"code.google.com/p/log4go"
	"flag"
	"fmt"
	"github.com/limetext/gopy/lib"
	"github.com/limetext/lime/backend"
	_ "github.com/limetext/lime/backend/commands"
	"github.com/limetext/lime/backend/keys"
	"github.com/limetext/lime/backend/render"
	"github.com/limetext/lime/backend/sublime"
	"github.com/limetext/lime/backend/textmate"
	"github.com/limetext/lime/backend/util"
	. "github.com/quarnster/util/text"
	"io"
	"net/http"
	"runtime/debug"
	"strconv"
	"sync"
	"time"
	"unicode"
)

var (
	scheme *textmate.Theme
	blink  bool
	port   = flag.Int("port", 8080, "Configures which port to host lime on")
)

const (
	console_height  = 20
	render_chan_len = 2
)

type layout struct {
	x, y          int
	width, height int
	visible       Region
	lastUpdate    int
}
type tbfe struct {
	layout         map[*backend.View]layout
	status_message string
	dorender       chan bool
	lock           sync.Mutex
	dirty          bool
}

func htmlcol(c render.Colour) string {
	return fmt.Sprintf("%02X%02X%02X", c.R, c.G, c.B)
}

func (t *tbfe) renderView(wr io.Writer, v *backend.View, lay layout) {
	p := util.Prof.Enter("render")
	defer p.Exit()

	vr := lay.visible
	runes := v.Buffer().Substr(vr)
	recipie := v.Transform(scheme, vr).Transcribe()
	highlight_line := false
	if b, ok := v.Settings().Get("highlight_line", highlight_line).(bool); ok {
		highlight_line = b
	}
	lastEnd := 0
	for _, reg := range recipie {
		if lastEnd != reg.Region.Begin() {
			io.WriteString(wr, runes[lastEnd:reg.Region.Begin()])
		}
		fmt.Fprintf(wr, "%s", htmlcol(reg.Flavour.Foreground), htmlcol(reg.Flavour.Background), runes[reg.Region.Begin():reg.Region.End()])
		lastEnd = reg.Region.End()
	}
	if lastEnd != vr.End() {
		io.WriteString(wr, v.Buffer().Substr(Region{lastEnd, vr.End()}))
	}
}

func (t *tbfe) clip(v *backend.View, s, e int) Region {
	p := util.Prof.Enter("clip")
	defer p.Exit()
	h := t.layout[v].height
	if e-s > h {
		e = s + h
	} else if e-s < h {
		s = e - h
	}
	if e2, _ := v.Buffer().RowCol(v.Buffer().TextPoint(e, 0)); e2 < e {
		e = e2
	}
	if s < 0 {
		s = 0
	}
	e = s + h
	r := Region{v.Buffer().TextPoint(s, 0), v.Buffer().TextPoint(e, 0)}
	return v.Buffer().LineR(r)
}

func (t *tbfe) Show(v *backend.View, r Region) {
	t.lock.Lock()
	l := t.layout[v]
	t.lock.Unlock()
	if l.visible.Covers(r) {
		return
	}
	p := util.Prof.Enter("show")
	defer p.Exit()

	lv := l.visible

	s1, _ := v.Buffer().RowCol(lv.Begin())
	e1, _ := v.Buffer().RowCol(lv.End())
	s2, _ := v.Buffer().RowCol(r.Begin())
	e2, _ := v.Buffer().RowCol(r.End())

	r1 := Region{s1, e1}
	r2 := Region{s2, e2}

	r3 := r1.Cover(r2)
	diff := 0
	if d1, d2 := Abs(r1.Begin()-r3.Begin()), Abs(r1.End()-r3.End()); d1 > d2 {
		diff = r3.Begin() - r1.Begin()
	} else {
		diff = r3.End() - r1.End()
	}
	r3.A = r1.Begin() + diff
	r3.B = r1.End() + diff

	r3 = t.clip(v, r3.A, r3.B)
	l.visible = r3
	t.lock.Lock()
	t.layout[v] = l
	t.lock.Unlock()
}

func (t *tbfe) VisibleRegion(v *backend.View) Region {
	t.lock.Lock()
	r, ok := t.layout[v]
	t.lock.Unlock()
	if !ok || r.lastUpdate != v.Buffer().ChangeCount() {
		t.Show(v, r.visible)
		t.lock.Lock()
		r = t.layout[v]
		t.lock.Unlock()
	}
	return r.visible
}

func (t *tbfe) StatusMessage(msg string) {
	t.lock.Lock()
	defer t.lock.Unlock()
	t.status_message = msg
}

func (t *tbfe) ErrorMessage(msg string) {
	log4go.Error(msg)
}

// TODO(q): Actually show a dialog
func (t *tbfe) MessageDialog(msg string) {
	log4go.Info(msg)
}

// TODO(q): Actually show a dialog
func (t *tbfe) OkCancelDialog(msg, ok string) bool {
	log4go.Info(msg, ok)
	return false
}

func (t *tbfe) scroll(b Buffer, pos, delta int) {
	t.Show(backend.GetEditor().Console(), Region{b.Size(), b.Size()})
}

var pc = 0

func (t *tbfe) render(w io.Writer) {
	defer func() {
		if r := recover(); r != nil {
			log4go.Error("Panic in renderthread: %v\n%s", r, string(debug.Stack()))
			if pc > 1 {
				panic(r)
			}
			pc++
		}
	}()
	vs := make([]*backend.View, 0, len(t.layout))
	l := make([]layout, 0, len(t.layout))
	for k, v := range t.layout {
		vs = append(vs, k)
		l = append(l, v)
	}
	for i, v := range vs {
		t.renderView(w, v, l[i])
	}
	//	runes := []rune(t.status_message)
}
func (t *tbfe) key(w http.ResponseWriter, req *http.Request) {
	log4go.Debug("key: %s", req)
	kc := req.FormValue("keyCode")
	var kp keys.KeyPress
	v, _ := strconv.ParseInt(kc, 10, 32)

	if req.FormValue("altKey") == "true" {
		kp.Alt = true
	}
	if req.FormValue("ctrlKey") == "true" {
		kp.Ctrl = true
	}
	if req.FormValue("metaKey") == "true" {
		kp.Super = true
	}
	if req.FormValue("shiftKey") == "true" {
		kp.Shift = true
	}
	if !kp.Shift {
		v = int64(unicode.ToLower(rune(v)))
	}
	kp.Key = keys.Key(v)
	backend.GetEditor().HandleInput(kp)
}

func (t *tbfe) view(w http.ResponseWriter, req *http.Request) {
	log4go.Debug("view: %s", req)
	if t.dirty {
		t.dirty = false
		t.render(w)
	} else {
		w.WriteHeader(404)
	}
}

func (t *tbfe) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	s := time.Now()
	w.Header().Set("Content-Type", "text/html")
	log4go.Debug("Serving client: %s", req)

	c := scheme.Spice(&render.ViewRegions{})

	fmt.Fprintf(w, `

`, htmlcol(c.Foreground), htmlcol(c.Background))
	io.WriteString(w, "")
	log4go.Debug("Done serving client: %s", time.Since(s))
}

func (t *tbfe) loop() {
	backend.OnNew.Add(func(v *backend.View) {
		v.Settings().AddOnChange("lime.frontend.html.render", func(name string) { t.dirty = true })
	})
	backend.OnModified.Add(func(v *backend.View) {
		t.dirty = true
	})
	backend.OnSelectionModified.Add(func(v *backend.View) {
		t.dirty = true
	})

	ed := backend.GetEditor()
	ed.SetFrontend(t)
	ed.LogInput(false)
	ed.LogCommands(false)
	c := ed.Console()
	if sc, err := textmate.LoadTheme("../../3rdparty/bundles/TextMate-Themes/GlitterBomb.tmTheme"); err != nil {
		log4go.Error(err)
	} else {
		scheme = sc
	}

	defer func() {
		fmt.Println(util.Prof)
	}()

	w := ed.NewWindow()
	v := w.OpenFile("main.go", 0)
	v.Settings().Set("trace", true)
	v.Settings().Set("syntax", "../../3rdparty/bundles/go.tmbundle/Syntaxes/Go.tmLanguage")
	c.Buffer().AddCallback(t.scroll)

	sel := v.Sel()
	sel.Clear()
	//	end := v.Buffer().Size() - 2
	sel.Add(Region{0, 0})
	// sel.Add(Region{end - 22, end - 22})
	// sel.Add(Region{end - 16, end - 20})
	// sel.Add(Region{end - 13, end - 10})

	{
		w, h := 800, 600
		t.lock.Lock()
		t.layout[v] = layout{0, 0, w, h - console_height - 1, Region{}, 0}
		t.layout[c] = layout{0, h - console_height + 1, w, console_height - 5, Region{}, 0}
		t.lock.Unlock()
		t.Show(v, Region{1, 1})
	}
	t.Show(v, Region{100, 100})
	t.Show(v, Region{1, 1})

	go func() {
		ed.Init()
		sublime.Init()
	}()
	log4go.Debug("serving")
	http.HandleFunc("/key", t.key)
	http.HandleFunc("/", t.ServeHTTP)
	http.HandleFunc("/view", t.view)
	if err := http.ListenAndServe(fmt.Sprintf("localhost:%d", *port), nil); err != nil {
		log4go.Error("Error serving: %s", err)
	}
	log4go.Debug("Done")
}

func main() {
	flag.Parse()
	log4go.AddFilter("file", log4go.FINEST, log4go.NewConsoleLogWriter())
	defer func() {
		py.NewLock()
		py.Finalize()
	}()

	var t tbfe
	t.dorender = make(chan bool, render_chan_len)
	t.layout = make(map[*backend.View]layout)
	t.loop()
}
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2017 Shinya Yagyu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/alecthomas/kingpin"
	"github.com/iotaledger/giota"
)

func main() {
	var (
		app = kingpin.New("giotan", "giota CLI Tool")

		send      = app.Command("send", "Send token")
		seed      = send.Flag("seed", "seed").Required().String()
		recipient = send.Flag("recipient", "recipient address").Required().String()
		sender    = send.Flag("sender", "sender addresses, separated with comma").String()
		amount    = send.Flag("amount", "amount to send").Required().Int64()
		mwm       = send.Flag("mwm", "MinWeightMagnituce").Default("18").Int64()

		addresses = app.Command("addresses", "List used/unused addresses")
		seedA     = addresses.Flag("seed", "seed").Required().String()

		newseed = app.Command("new", "create a new seed")
	)
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case send.FullCommand():
		Send(*seed, *recipient, *sender, *amount, *mwm)
	case addresses.FullCommand():
		handleAddresses(*seedA)
	case newseed.FullCommand():
		seed := giota.NewSeed()
		fmt.Println("New seed: ", seed)
		fmt.Printf("To display an address, run\n\t%s addresses --seed=%s\n", os.Args[0], seed)
	}
}

func handleAddresses(seed string) {
	server := giota.RandomNode()
	fmt.Printf("using IRI server: %s\n", server)
	seedT, err := giota.ToTrytes(seed)
	if err != nil {
		fmt.Fprintf(os.Stderr, "You must specify valid seed")
		os.Exit(-1)
	}
	api := giota.NewAPI(server, nil)
	adr, adrs, err := giota.GetUsedAddress(api, seedT, 2)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot get addresses: %s\n", err.Error())
		os.Exit(-1)
	}
	fmt.Println("address info:")
	for _, a := range adrs {
		fmt.Printf("\t%s (used)\n", a)
	}
	fmt.Printf("\n\t%s (unused)\n", adr)
}

func check(seed, recipient, sender string, amount int64) (giota.Trytes, giota.Address, []giota.Address) {
	if amount <= 0 {
		fmt.Fprintln(os.Stderr, "You must specify the amount with positive value.")
		os.Exit(-1)
	}
	seedT, err := giota.ToTrytes(seed)
	if err != nil {
		fmt.Fprintln(os.Stderr, "You must specify valid seed")
		os.Exit(-1)
	}
	recipientT, err := giota.ToAddress(recipient)
	if err != nil {
		fmt.Fprintln(os.Stderr, "You must specify valid recipient")
		os.Exit(-1)
	}
	var senderT []giota.Address
	if sender != "" {
		senders := strings.Split(sender, ",")
		senderT = make([]giota.Address, len(senders))
		for i, s := range senders {
			senderT[i], err = giota.ToAddress(s)
			if err != nil {
				fmt.Fprintln(os.Stderr, "You must specify valid sender")
				os.Exit(-1)
			}
		}
	}
	return seedT, recipientT, senderT
}

func sendToSender(api *giota.API, trs []giota.Transfer, sender []giota.Address, seedT giota.Trytes, mwm int64) (giota.Bundle, error) {
	_, adrs, err := giota.GetUsedAddress(api, seedT, 2)
	if err != nil {
		return nil, err
	}
	adrinfo := make([]giota.AddressInfo, len(sender))
	for i, s := range sender {
		for j, a := range adrs {
			if s == a {
				adrinfo[i] = giota.AddressInfo{
					Seed:     seedT,
					Index:    j,
					Security: 2,
				}
				break
			}
		}
		return nil, fmt.Errorf("cannot found address %s from seed", s)
	}
	bdl, err := giota.PrepareTransfers(api, seedT, trs, adrinfo, "", 2)
	if err != nil {
		return nil, err
	}
	name, pow := giota.GetBestPoW()
	fmt.Fprintf(os.Stderr, "using PoW:%s\n", name)
	err = giota.SendTrytes(api, giota.Depth, []giota.Transaction(bdl), mwm, pow)
	return bdl, err
}

//Send handles send command.
func Send(seed, recipient, sender string, amount int64, mwm int64) {
	seedT, recipientT, senderT := check(seed, recipient, sender, amount)

	trs := []giota.Transfer{
		giota.Transfer{
			Address: recipientT,
			Value:   amount,
			Tag:     "PRETTYGIOTAN",
		},
	}

	var bdl giota.Bundle
	var err error
	server := giota.RandomNode()
	fmt.Printf("using IRI server: %s\n", server)

	api := giota.NewAPI(server, nil)
	name, pow := giota.GetBestPoW()
	fmt.Fprintf(os.Stderr, "using PoW:%s\n", name)
	if senderT == nil {
		bdl, err = giota.PrepareTransfers(api, seedT, trs, nil, "", 2)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(-1)
		}
		err = giota.SendTrytes(api, giota.Depth, []giota.Transaction(bdl), mwm, pow)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(-1)
		}
	} else {
		bdl, err = sendToSender(api, trs, senderT, seedT, mwm)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot send: %s\n", err.Error())
		os.Exit(-1)
	}

	fmt.Println("transactions info:")
	for i, tx := range bdl {
		fmt.Printf(`
		No: %d/%d
		Hash : %s
		Address:%s
		Value:%d
		Timestamp:%s
`,
			i, len(bdl), tx.Hash(), tx.Address, tx.Value, tx.Timestamp)
	}
}
<commit_msg>for tutorial<commit_after>/*
MIT License

Copyright (c) 2017 Shinya Yagyu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"fmt"
	"os"
	"strings"
	"syscall"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/alecthomas/kingpin"
	"github.com/iotaledger/giota"
)

func main() {
	var (
		app = kingpin.New("giotan", "giota CLI Tool")

		send      = app.Command("send", "Send token")
		recipient = send.Flag("recipient", "recipient address").Required().String()
		sender    = send.Flag("sender", "sender addresses, separated with comma").String()
		amount    = send.Flag("amount", "amount to send").Required().Int64()
		tag       = send.Flag("tag", "tag to send").Default("PRETTYGIOTAN").String()
		mwm       = send.Flag("mwm", "MinWeightMagnituce").Default("18").Int64()

		addresses = app.Command("addresses", "List used/unused addresses")

		newseed = app.Command("new", "create a new seed")
	)
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case send.FullCommand():
		fmt.Print("input your seed:")
		seed, err := terminal.ReadPassword(int(syscall.Stdin))
		fmt.Println("")
		if err != nil {
			panic(err)
		}
		Send(string(seed), *recipient, *sender, *amount, *mwm, *tag)
	case addresses.FullCommand():
		fmt.Print("input your seed:")
		seedA, err := terminal.ReadPassword(int(syscall.Stdin))
		fmt.Println("")
		if err != nil {
			panic(err)
		}
		handleAddresses(string(seedA))
	case newseed.FullCommand():
		seed := giota.NewSeed()
		fmt.Println("New seed: ", seed)
		fmt.Printf("To display addresses, run\n\t%s addresses\n", os.Args[0])
		fmt.Println("and input the seed above.")
	}
}

func handleAddresses(seed string) {
	server := giota.RandomNode()
	fmt.Printf("using IRI server: %s\n", server)
	seedT, err := giota.ToTrytes(seed)
	if err != nil {
		fmt.Fprintf(os.Stderr, "You must specify valid seed")
		os.Exit(-1)
	}
	api := giota.NewAPI(server, nil)
	adr, adrs, err := giota.GetUsedAddress(api, seedT, 2)
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot get addresses: %s\n", err.Error())
		os.Exit(-1)
	}
	var resp *giota.GetBalancesResponse
	if len(adrs) > 0 {
		resp, err = api.GetBalances(adrs, 100)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cannot get balance: %s\n", err.Error())
			os.Exit(-1)
		}
	}
	fmt.Println("address info:")
	fmt.Println("used:")
	for i, a := range adrs {
		fmt.Printf("\t%s (balance=%d)\n", a, resp.Balances[i])
	}
	fmt.Println("\nunused:")
	fmt.Printf("\t%s\n", adr)
}

func check(seed, recipient, sender string, amount int64) (giota.Trytes, giota.Address, []giota.Address) {
	if amount <= 0 {
		fmt.Fprintln(os.Stderr, "You must specify the amount with positive value.")
		os.Exit(-1)
	}
	seedT, err := giota.ToTrytes(seed)
	if err != nil {
		fmt.Fprintln(os.Stderr, "You must specify valid seed")
		os.Exit(-1)
	}
	recipientT, err := giota.ToAddress(recipient)
	if err != nil {
		fmt.Fprintln(os.Stderr, "You must specify valid recipient")
		os.Exit(-1)
	}
	var senderT []giota.Address
	if sender != "" {
		senders := strings.Split(sender, ",")
		senderT = make([]giota.Address, len(senders))
		for i, s := range senders {
			senderT[i], err = giota.ToAddress(s)
			if err != nil {
				fmt.Fprintln(os.Stderr, "You must specify valid sender")
				os.Exit(-1)
			}
		}
	}
	return seedT, recipientT, senderT
}

func sendToSender(api *giota.API, trs []giota.Transfer, sender []giota.Address, seedT giota.Trytes, mwm int64) (giota.Bundle, error) {
	_, adrs, err := giota.GetUsedAddress(api, seedT, 2)
	if err != nil {
		return nil, err
	}
	adrinfo := make([]giota.AddressInfo, len(sender))
	for i, s := range sender {
		for j, a := range adrs {
			if s == a {
				adrinfo[i] = giota.AddressInfo{
					Seed:     seedT,
					Index:    j,
					Security: 2,
				}
				break
			}
		}
		return nil, fmt.Errorf("cannot found address %s from seed", s)
	}
	bdl, err := giota.PrepareTransfers(api, seedT, trs, adrinfo, "", 2)
	if err != nil {
		return nil, err
	}
	name, pow := giota.GetBestPoW()
	fmt.Fprintf(os.Stderr, "using PoW:%s\n", name)
	err = giota.SendTrytes(api, giota.Depth, []giota.Transaction(bdl), mwm, pow)
	return bdl, err
}

//Send handles send command.
func Send(seed, recipient, sender string, amount int64, mwm int64, tag string) {
	seedT, recipientT, senderT := check(seed, recipient, sender, amount)
	ttag, err := giota.ToTrytes(tag)
	if err != nil {
		panic(err)
	}
	trs := []giota.Transfer{
		giota.Transfer{
			Address: recipientT,
			Value:   amount,
			Tag:     ttag,
		},
	}

	var bdl giota.Bundle
	server := giota.RandomNode()
	fmt.Printf("using IRI server: %s\n", server)

	api := giota.NewAPI(server, nil)
	name, pow := giota.GetBestPoW()
	fmt.Fprintf(os.Stderr, "using PoW:%s\n", name)
	if senderT == nil {
		bdl, err = giota.PrepareTransfers(api, seedT, trs, nil, "", 2)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(-1)
		}
		err = giota.SendTrytes(api, giota.Depth, []giota.Transaction(bdl), mwm, pow)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(-1)
		}
	} else {
		bdl, err = sendToSender(api, trs, senderT, seedT, mwm)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "cannot send: %s\n", err.Error())
		os.Exit(-1)
	}

	fmt.Println("bundle info:")
	fmt.Println("bundle hash: ", bdl.Hash())
	for i, tx := range bdl {
		fmt.Printf(`
		No: %d/%d
		Hash : %s
		Address:%s
		Value:%d
		Timestamp:%s
`,
			i, len(bdl), tx.Hash(), tx.Address, tx.Value, tx.Timestamp)
	}
}
<|endoftext|>


<commit_before><commit_msg>internal/etl: change derrors.InvalidArgument to terminal error<commit_after><|endoftext|>


<commit_before><commit_msg>internal/jsre: ensure Stop can be called more than once<commit_after><|endoftext|>


<commit_before><commit_msg>ensure etl not used in views/indicies/virtual tables<commit_after><|endoftext|>


<commit_before>package nss

import (
	"bytes"
	"net"
)

func Fuzz(data []byte) int {
	if net.ParseNSSConf(bytes.NewReader(data)) == nil {
		return 0
	}
	return 1
}
<commit_msg>disable build of nss example it won't build as is<commit_after>// This example won't build as is, because ParseNSSConf function is not exported
// from net package. To build this example, you need to patch net package to
// rename parseNSSConf to ParseNSSConf first.
// +build never

package nss

import (
	"bytes"
	"net"
)

func Fuzz(data []byte) int {
	if net.ParseNSSConf(bytes.NewReader(data)) == nil {
		return 0
	}
	return 1
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import (
	`sort`
)

type MoveWithScore struct {
	move  Move
	score int
}

type MoveGen struct {
	p      *Position
	list   [256]MoveWithScore
	phase  int
	head   int
	tail   int
	ply    int
}

// Pre-allocate move generator array (one entry per ply) to avoid garbage
// collection overhead.
var moveList [MaxPly]MoveGen

// Returns "new" move generator for the given ply. Since move generator array
// has been pre-allocated already we simply return a pointer to the existing
// array element re-initializing all its data.
func NewGen(p *Position, ply int) (gen *MoveGen) {
	gen = &moveList[ply]
	gen.p = p
	gen.phase = p.phase()
	gen.list = [256]MoveWithScore{}
	gen.head, gen.tail = 0, 0
	gen.ply = ply
	return gen
}

// Returns "new" move generator for the initial step of iterative deepening
// (depth == 1) and existing one for subsequent iterations (depth > 1). This
// is used in iterative deepening search when all the moves are being generated
// at depth one, and reused later as the search deepens.
func NewRootGen(p *Position, depth int) (gen *MoveGen) {
	if depth > 1 {
		return moveList[0].reset().rank(p.cachedMove())
	}

	gen = NewGen(p, 0).generateAllMoves()
	if gen.onlyMove() {
		return gen
	}
	//
	// Get rid of invalid moves so that we don't do it on each iteration.
	//
	return gen.validOnly(p).rank(p.cachedMove())
}

func (gen *MoveGen) reset() *MoveGen {
	gen.head = 0
	return gen
}

func (gen *MoveGen) size() int {
	return gen.tail - gen.head
}

func (gen *MoveGen) onlyMove() bool {
	return gen.size() == 1
}

func (gen *MoveGen) NextMove() (move Move) {
	if gen.head < gen.tail {
		move = gen.list[gen.head].move
		gen.head++
	}
	return
}

// Removes invalid moves from the generated list. We use in iterative deepening
// to avoid stumbling upon invalid moves on each iteration.
func (gen *MoveGen) validOnly(p *Position) *MoveGen {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position == nil {
			gen.remove()
		} else {
			position.TakeBack(move)
		}
	}
	return gen.reset()
}

// Probes a list of generated moves and returns true if it contains at least
// one valid move.
func (gen *MoveGen) anyValid(p *Position) bool {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position != nil {
			position.TakeBack(move)
			return true
		}
	}
	return false
}

func (gen *MoveGen) rank(bestMove Move) *MoveGen {
	if gen.size() < 2 {
		return gen
	}
	//
	// If the cache is disabled or we couldn't determine best move so far
	// then use principal variation table as backup.
	//
	game := gen.p.game
	if len(game.cache) == 0 && bestMove == Move(0) {
		bestMove = game.bestLine[0][gen.ply]
	}

	for i := gen.head; i < gen.tail; i++ {
		move := gen.list[i].move
		if move == bestMove {
			gen.list[i].score = 0xFFFF
		} else if move & isCapture != 0 {
			gen.list[i].score = 8192 + move.value()
		} else if move == game.killers[gen.ply][0] {
			gen.list[i].score = 4096
		} else if move == game.killers[gen.ply][1] {
			gen.list[i].score = 2048
		} else {
			gen.list[i].score = game.good(move)
		}
	}

	sort.Sort(byScore{gen.list[gen.head:gen.tail]})
	return gen
}

func (gen *MoveGen) quickRank() *MoveGen {
	if gen.size() < 2 {
		return gen
	}

	game := gen.p.game
	for i := gen.head; i < gen.tail; i++ {
		if move := gen.list[i].move; move & isCapture != 0 {
			gen.list[i].score = 8192 + move.value()
		} else {
			gen.list[i].score = game.good(move)
		}
	}

	sort.Sort(byScore{gen.list[gen.head:gen.tail]})
	return gen
}

func (gen *MoveGen) add(move Move) *MoveGen {
	gen.list[gen.tail].move = move
	gen.tail++
	return gen
}

// Removes current move from the list by copying over the ramaining moves. Head and
// tail pointers get decremented so that calling NexMove() works as expected.
func (gen *MoveGen) remove() *MoveGen {
	copy(gen.list[gen.head-1:], gen.list[gen.head:])
	gen.head--
	gen.tail--
	return gen
}

// Returns an array of generated moves by continuously appending the NextMove()
// until the list is empty.
func (gen *MoveGen) allMoves() (moves []Move) {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		moves = append(moves, move)
	}
	return
}

// Sorting moves by their relative score based on piece/square for regular moves
// or least valuaeable attacker/most valueable victim for captures.
type byScore struct {
	list []MoveWithScore
}

func (her byScore) Len() int           { return len(her.list) }
func (her byScore) Swap(i, j int)      { her.list[i], her.list[j] = her.list[j], her.list[i] }
func (her byScore) Less(i, j int) bool { return her.list[i].score > her.list[j].score }
<commit_msg>No immediate need for game phase calculation when generating moves<commit_after>// Copyright (c) 2013-2014 by Michael Dvorkin. All Rights Reserved.
// Use of this source code is governed by a MIT-style license that can
// be found in the LICENSE file.

package donna

import (
	`sort`
)

type MoveWithScore struct {
	move  Move
	score int
}

type MoveGen struct {
	p      *Position
	list   [256]MoveWithScore
	head   int
	tail   int
	ply    int
}

// Pre-allocate move generator array (one entry per ply) to avoid garbage
// collection overhead.
var moveList [MaxPly]MoveGen

// Returns "new" move generator for the given ply. Since move generator array
// has been pre-allocated already we simply return a pointer to the existing
// array element re-initializing all its data.
func NewGen(p *Position, ply int) (gen *MoveGen) {
	gen = &moveList[ply]
	gen.p = p
	gen.list = [256]MoveWithScore{}
	gen.head, gen.tail = 0, 0
	gen.ply = ply
	return gen
}

// Returns "new" move generator for the initial step of iterative deepening
// (depth == 1) and existing one for subsequent iterations (depth > 1). This
// is used in iterative deepening search when all the moves are being generated
// at depth one, and reused later as the search deepens.
func NewRootGen(p *Position, depth int) (gen *MoveGen) {
	if depth > 1 {
		return moveList[0].reset().rank(p.cachedMove())
	}

	gen = NewGen(p, 0).generateAllMoves()
	if gen.onlyMove() {
		return gen
	}
	//
	// Get rid of invalid moves so that we don't do it on each iteration.
	//
	return gen.validOnly(p).rank(p.cachedMove())
}

func (gen *MoveGen) reset() *MoveGen {
	gen.head = 0
	return gen
}

func (gen *MoveGen) size() int {
	return gen.tail - gen.head
}

func (gen *MoveGen) onlyMove() bool {
	return gen.size() == 1
}

func (gen *MoveGen) NextMove() (move Move) {
	if gen.head < gen.tail {
		move = gen.list[gen.head].move
		gen.head++
	}
	return
}

// Removes invalid moves from the generated list. We use in iterative deepening
// to avoid stumbling upon invalid moves on each iteration.
func (gen *MoveGen) validOnly(p *Position) *MoveGen {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position == nil {
			gen.remove()
		} else {
			position.TakeBack(move)
		}
	}
	return gen.reset()
}

// Probes a list of generated moves and returns true if it contains at least
// one valid move.
func (gen *MoveGen) anyValid(p *Position) bool {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		if position := p.MakeMove(move); position != nil {
			position.TakeBack(move)
			return true
		}
	}
	return false
}

func (gen *MoveGen) rank(bestMove Move) *MoveGen {
	if gen.size() < 2 {
		return gen
	}
	//
	// If the cache is disabled or we couldn't determine best move so far
	// then use principal variation table as backup.
	//
	game := gen.p.game
	if len(game.cache) == 0 && bestMove == Move(0) {
		bestMove = game.bestLine[0][gen.ply]
	}

	for i := gen.head; i < gen.tail; i++ {
		move := gen.list[i].move
		if move == bestMove {
			gen.list[i].score = 0xFFFF
		} else if move & isCapture != 0 {
			gen.list[i].score = 8192 + move.value()
		} else if move == game.killers[gen.ply][0] {
			gen.list[i].score = 4096
		} else if move == game.killers[gen.ply][1] {
			gen.list[i].score = 2048
		} else {
			gen.list[i].score = game.good(move)
		}
	}

	sort.Sort(byScore{gen.list[gen.head:gen.tail]})
	return gen
}

func (gen *MoveGen) quickRank() *MoveGen {
	if gen.size() < 2 {
		return gen
	}

	game := gen.p.game
	for i := gen.head; i < gen.tail; i++ {
		if move := gen.list[i].move; move & isCapture != 0 {
			gen.list[i].score = 8192 + move.value()
		} else {
			gen.list[i].score = game.good(move)
		}
	}

	sort.Sort(byScore{gen.list[gen.head:gen.tail]})
	return gen
}

func (gen *MoveGen) add(move Move) *MoveGen {
	gen.list[gen.tail].move = move
	gen.tail++
	return gen
}

// Removes current move from the list by copying over the ramaining moves. Head and
// tail pointers get decremented so that calling NexMove() works as expected.
func (gen *MoveGen) remove() *MoveGen {
	copy(gen.list[gen.head-1:], gen.list[gen.head:])
	gen.head--
	gen.tail--
	return gen
}

// Returns an array of generated moves by continuously appending the NextMove()
// until the list is empty.
func (gen *MoveGen) allMoves() (moves []Move) {
	for move := gen.NextMove(); move != 0; move = gen.NextMove() {
		moves = append(moves, move)
	}
	return
}

// Sorting moves by their relative score based on piece/square for regular moves
// or least valuaeable attacker/most valueable victim for captures.
type byScore struct {
	list []MoveWithScore
}

func (her byScore) Len() int           { return len(her.list) }
func (her byScore) Swap(i, j int)      { her.list[i], her.list[j] = her.list[j], her.list[i] }
func (her byScore) Less(i, j int) bool { return her.list[i].score > her.list[j].score }
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"net/http"
)

// TODO: add the missing methods
const (
	// HTTP GET request
	MethodGet = "GET"
	// HTTP Post request
	MethodPost = "POST"
)

// ServeMux is a safe HTTP request multiplexer that wraps http.ServeMux.
// It matches the URL of each incoming request against a list of registered
// patterns and calls the handler for the pattern that most closely matches the
// URL.
//
// The multiplexer contains a list of allowed domains that will be matched
// against each incoming request. A different handler can be specified for every
// HTTP method supported at a registered pattern.
type ServeMux struct {
	mux        *http.ServeMux
	domains    map[string]bool
	dispatcher Dispatcher

	// Maps user-provided patterns to combined handlers which encapsulate
	// multiple handlers, each one associated with an HTTP method.
	handlers map[string]methodHandler
}

// NewServeMux allocates and returns a new ServeMux
// TODO(@mattias, @mara): make domains a variadic of string **literals**.
func NewServeMux(dispatcher Dispatcher, domains ...string) *ServeMux {
	d := map[string]bool{}
	for _, host := range domains {
		d[host] = true
	}
	return &ServeMux{
		mux:        http.NewServeMux(),
		domains:    d,
		dispatcher: dispatcher,
		handlers:   map[string]methodHandler{},
	}
}

// Handle registers a handler for the given pattern and method. If another
// handler is already registered for the same pattern and method, Handle panics.
func (m *ServeMux) Handle(pattern string, method string, h Handler) {
	ch, ok := m.handlers[pattern]
	if !ok {
		ch := methodHandler{
			h:       map[string]Handler{method: h},
			domains: m.domains,
			d:       m.dispatcher,
		}

		m.handlers[pattern] = ch
		m.mux.Handle(pattern, ch)
		return
	}

	if _, ok := ch.h[method]; ok {
		panic("method already registered")
	}
	ch.h[method] = h
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// methodHandler is collection of handlers based on the request method.
type methodHandler struct {
	// Maps an HTTP method to its handler
	h       map[string]Handler
	domains map[string]bool
	d       Dispatcher
}

// ServeHTTP dispatches the request to the handler associated with
// the incoming request's method.
func (c methodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !c.domains[r.Host] {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	h, ok := c.h[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(newResponseWriter(c.d, w), newIncomingRequest(r))
}
<commit_msg>Rename structure fields and rephrase documentation<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 safehttp

import (
	"net/http"
)

// TODO: add the missing methods
const (
	// HTTP GET request
	MethodGet = "GET"
	// HTTP Post request
	MethodPost = "POST"
)

// ServeMux is an HTTP request multiplexer. It matches the URL of each incoming
// request against a list of registered patterns and calls the handler for
// the pattern that most closely matches the URL.
//
// Patterns name are fixed, rooted paths, like "/favicon.ico", or rooted
// subtrees like "/images/" (note the trailing slash). Longer patterns take
// precedence over shorter ones, so that if there are handlers registered for
// both "/images/" and "/images/thumbnails/", the latter handler will be called
// for paths beginning "/images/thumbnails/" and the former will receive
// requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted subtree, the
// pattern "/" matches all paths not matched by other registered patterns,
// not just the URL with Path == "/".
//
// If a subtree has been registered and a request is received naming the subtree root without its trailing slash, ServeMux redirects that request to
// the subtree root (adding the trailing slash). This behavior can be overridden
// with a separate registration for the path without the trailing slash. For
// example, registering "/images/" causes ServeMux to redirect a request for
// "/images" to "/images/", unless "/images" has been registered separately.
//
// Patterns may optionally begin with a host name, restricting matches to URLs
// on that host only. Host-specific patterns take precedence over general
// patterns, so that a handler might register for the two patterns "/codesearch"
// and "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// ServeMux also takes care of sanitizing the URL request path and the Host
// header, stripping the port number and redirecting any request containing . or
// .. elements or repeated slashes to an equivalent, cleaner URL.
//
// Multiple HTTP methods can be served for one pattern and the user is expected
// to register a handler for each method supported. These will be combined
// into one handler per pattern. The framework will then match each
// incoming request to its underlying handler according to its HTTP method.
type ServeMux struct {
	mux     *http.ServeMux
	domains map[string]bool
	disp    Dispatcher

	// Maps user-provided patterns to combined handlers which encapsulate
	// multiple handlers, each one associated with an HTTP method.
	handlers map[string]methodHandler
}

// NewServeMux allocates and returns a new ServeMux
// TODO(@mattiasgrenfeldt, @mihalimara22): make domains a variadic of string ..//**literals**.
func NewServeMux(dispatcher Dispatcher, domains ...string) *ServeMux {
	d := map[string]bool{}
	for _, host := range domains {
		d[host] = true
	}
	return &ServeMux{
		mux:      http.NewServeMux(),
		domains:  d,
		disp:     dispatcher,
		handlers: map[string]methodHandler{},
	}
}

// Handle registers a handler for the given pattern and method. If another
// handler is already registered for the same pattern and method, Handle panics.
func (m *ServeMux) Handle(pattern string, method string, h Handler) {
	ch, ok := m.handlers[pattern]
	if !ok {
		ch := methodHandler{
			methodMap: map[string]Handler{method: h},
			domains:   m.domains,
			disp:      m.disp,
		}

		m.handlers[pattern] = ch
		m.mux.Handle(pattern, ch)
		return
	}

	if _, ok := ch.methodMap[method]; ok {
		panic("method already registered")
	}
	ch.methodMap[method] = h
}

// ServeHTTP dispatches the request to the handler whose method matches the
// incoming request and whose pattern most closely matches the request URL.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	m.mux.ServeHTTP(w, r)
}

// methodHandler is collection of handlers based on the request method.
type methodHandler struct {
	// Maps an HTTP method to its handler
	methodMap map[string]Handler
	domains   map[string]bool
	disp      Dispatcher
}

// ServeHTTP dispatches the request to the handler associated with
// the incoming request's method.
func (m methodHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !m.domains[r.Host] {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
		return
	}

	h, ok := m.methodMap[r.Method]
	if !ok {
		http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
		return
	}

	h.ServeHTTP(newResponseWriter(m.disp, w), newIncomingRequest(r))
}
<|endoftext|>


<commit_before>package client

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"io"

	"github.com/flynn/go-discoverd"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
)

func New() (*Client, error) {
	services, err := discoverd.Services("flynn-sampi", discoverd.DefaultTimeout)
	if err != nil {
		return nil, err
	}
	if len(services) == 0 {
		return nil, errors.New("sampi: no servers found")
	}
	c, err := rpcplus.DialHTTP("tcp", services[0].Addr)
	return &Client{c}, err
}

type Client struct {
	c *rpcplus.Client
}

func (c *Client) State() (map[string]sampi.Host, error) {
	var state map[string]sampi.Host
	err := c.c.Call("Scheduler.State", struct{}{}, &state)
	return state, err
}

func (c *Client) Schedule(req *sampi.ScheduleReq) (*sampi.ScheduleRes, error) {
	var res sampi.ScheduleRes
	err := c.c.Call("Scheduler.Schedule", req, &res)
	return &res, err
}

func (c *Client) RegisterHost(host *sampi.Host, stream chan *sampi.Job) *error {
	return &c.c.StreamGo("Scheduler.RegisterHost", host, stream).Error
}

func (c *Client) RemoveJobs(jobIDs []string) error {
	return c.c.Call("Scheduler.RemoveJobs", jobIDs, &struct{}{})
}

func RandomJobID(prefix string) string { return prefix + randomID() }

func randomID() string {
	b := make([]byte, 16)
	enc := make([]byte, 24)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err) // This shouldn't ever happen, right?
	}
	base64.URLEncoding.Encode(enc, b)
	return string(bytes.TrimRight(enc, "="))
}
<commit_msg>sampi: using explicit leader api<commit_after>package client

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"io"
	"time"

	"github.com/flynn/go-discoverd"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
)

func New() (*Client, error) {
	services, err := discoverd.NewServiceSet("flynn-sampi")
	if err != nil {
		return nil, err
	}
	select {
	case <-services.Watch(true, true):
	case <-time.After(time.Second):
		return nil, errors.New("sampi: no servers found")
	}
	c, err := rpcplus.DialHTTP("tcp", services.Leader().Addr)
	return &Client{c}, err
}

type Client struct {
	c *rpcplus.Client
}

func (c *Client) State() (map[string]sampi.Host, error) {
	var state map[string]sampi.Host
	err := c.c.Call("Scheduler.State", struct{}{}, &state)
	return state, err
}

func (c *Client) Schedule(req *sampi.ScheduleReq) (*sampi.ScheduleRes, error) {
	var res sampi.ScheduleRes
	err := c.c.Call("Scheduler.Schedule", req, &res)
	return &res, err
}

func (c *Client) RegisterHost(host *sampi.Host, stream chan *sampi.Job) *error {
	return &c.c.StreamGo("Scheduler.RegisterHost", host, stream).Error
}

func (c *Client) RemoveJobs(jobIDs []string) error {
	return c.c.Call("Scheduler.RemoveJobs", jobIDs, &struct{}{})
}

func RandomJobID(prefix string) string { return prefix + randomID() }

func randomID() string {
	b := make([]byte, 16)
	enc := make([]byte, 24)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err) // This shouldn't ever happen, right?
	}
	base64.URLEncoding.Encode(enc, b)
	return string(bytes.TrimRight(enc, "="))
}
<|endoftext|>


<commit_before>package client

import (
	"errors"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
)

func New() (*Client, error) {
	disc, err := discover.NewClient()
	if err != nil {
		return nil, err
	}
	services, err := disc.Services("flynn-sampi")
	if err != nil {
		return nil, err
	}
	addrs := services.OnlineAddrs()
	if len(addrs) == 0 {
		return nil, errors.New("sampi: no servers found")
	}
	c, err := rpcplus.DialHTTP("tcp", addrs[0])
	return &Client{c}, err
}

type Client struct {
	c *rpcplus.Client
}

func (c *Client) State() (map[string]sampi.Host, error) {
	var state map[string]sampi.Host
	err := c.c.Call("Scheduler.State", struct{}{}, &state)
	return state, err
}

func (c *Client) Schedule(req *sampi.ScheduleReq) (*sampi.ScheduleRes, error) {
	var res sampi.ScheduleRes
	err := c.c.Call("Scheduler.Schedule", req, &res)
	return &res, err
}

func (c *Client) RegisterHost(host *sampi.Host, stream chan *sampi.Job) *error {
	return &c.c.StreamGo("Scheduler.RegisterHost", host, stream).Error
}

func (c *Client) RemoveJobs(jobIDs []string) error {
	return c.c.Call("Scheduler.RemoveJobs", jobIDs, &struct{}{})
}
<commit_msg>sampi: Add random job ID generation<commit_after>package client

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"errors"
	"io"

	"github.com/flynn/go-discover/discover"
	"github.com/flynn/rpcplus"
	"github.com/flynn/sampi/types"
)

func New() (*Client, error) {
	disc, err := discover.NewClient()
	if err != nil {
		return nil, err
	}
	services, err := disc.Services("flynn-sampi")
	if err != nil {
		return nil, err
	}
	addrs := services.OnlineAddrs()
	if len(addrs) == 0 {
		return nil, errors.New("sampi: no servers found")
	}
	c, err := rpcplus.DialHTTP("tcp", addrs[0])
	return &Client{c}, err
}

type Client struct {
	c *rpcplus.Client
}

func (c *Client) State() (map[string]sampi.Host, error) {
	var state map[string]sampi.Host
	err := c.c.Call("Scheduler.State", struct{}{}, &state)
	return state, err
}

func (c *Client) Schedule(req *sampi.ScheduleReq) (*sampi.ScheduleRes, error) {
	var res sampi.ScheduleRes
	err := c.c.Call("Scheduler.Schedule", req, &res)
	return &res, err
}

func (c *Client) RegisterHost(host *sampi.Host, stream chan *sampi.Job) *error {
	return &c.c.StreamGo("Scheduler.RegisterHost", host, stream).Error
}

func (c *Client) RemoveJobs(jobIDs []string) error {
	return c.c.Call("Scheduler.RemoveJobs", jobIDs, &struct{}{})
}

func RandomJobID(prefix string) string { return prefix + randomID() }

func randomID() string {
	b := make([]byte, 16)
	enc := make([]byte, 24)
	_, err := io.ReadFull(rand.Reader, b)
	if err != nil {
		panic(err) // This shouldn't ever happen, right?
	}
	base64.URLEncoding.Encode(enc, b)
	return string(bytes.TrimRight(enc, "="))
}
<|endoftext|>


<commit_before>package git

import (
	"bufio"
	"os"
	"path/filepath"
	"strings"

	"github.com/git-lfs/git-lfs/tools"
	"github.com/rubyist/tracerx"
)

const (
	LockableAttrib = "lockable"
)

// AttributePath is a path entry in a gitattributes file which has the LFS filter
type AttributePath struct {
	// Path entry in the attribute file
	Path string
	// The attribute file which was the source of this entry
	Source string
	// Path also has the 'lockable' attribute
	Lockable bool
}

// GetAttributePaths returns a list of entries in .gitattributes which are
// configured with the filter=lfs attribute
// workingDIr is the root of the working copy
// gitDir is the root of the git repo
func GetAttributePaths(workingDir, gitDir string) []AttributePath {
	paths := make([]AttributePath, 0)

	for _, path := range findAttributeFiles(workingDir, gitDir) {
		attributes, err := os.Open(path)
		if err != nil {
			continue
		}

		scanner := bufio.NewScanner(attributes)

		for scanner.Scan() {
			line := scanner.Text()
			if strings.Contains(line, "filter=lfs") {
				fields := strings.Fields(line)
				relfile, _ := filepath.Rel(workingDir, path)
				pattern := fields[0]
				if reldir := filepath.Dir(relfile); len(reldir) > 0 {
					pattern = filepath.Join(reldir, pattern)
				}
				lockable := strings.Contains(line, LockableAttrib)
				paths = append(paths, AttributePath{Path: pattern, Source: relfile, Lockable: lockable})
			}
		}
	}

	return paths
}

func findAttributeFiles(workingDir, gitDir string) []string {
	var paths []string

	repoAttributes := filepath.Join(gitDir, "info", "attributes")
	if info, err := os.Stat(repoAttributes); err == nil && !info.IsDir() {
		paths = append(paths, repoAttributes)
	}

	tools.FastWalkGitRepo(workingDir, func(parentDir string, info os.FileInfo, err error) {
		if err != nil {
			tracerx.Printf("Error finding .gitattributes: %v", err)
			return
		}

		if info.IsDir() || info.Name() != ".gitattributes" {
			return
		}
		paths = append(paths, filepath.Join(parentDir, info.Name()))
	})

	// reverse the order of the files so more specific entries are found first
	// when iterating from the front (respects precedence)
	for i, j := 0, len(paths)-1; i < j; i, j = i+1, j-1 {
		paths[i], paths[j] = paths[j], paths[i]
	}

	return paths
}
<commit_msg>Deal with edge case of file pattern which includes the word “lockable”<commit_after>package git

import (
	"bufio"
	"os"
	"path/filepath"
	"strings"

	"github.com/git-lfs/git-lfs/tools"
	"github.com/rubyist/tracerx"
)

const (
	LockableAttrib = "lockable"
)

// AttributePath is a path entry in a gitattributes file which has the LFS filter
type AttributePath struct {
	// Path entry in the attribute file
	Path string
	// The attribute file which was the source of this entry
	Source string
	// Path also has the 'lockable' attribute
	Lockable bool
}

// GetAttributePaths returns a list of entries in .gitattributes which are
// configured with the filter=lfs attribute
// workingDIr is the root of the working copy
// gitDir is the root of the git repo
func GetAttributePaths(workingDir, gitDir string) []AttributePath {
	paths := make([]AttributePath, 0)

	for _, path := range findAttributeFiles(workingDir, gitDir) {
		attributes, err := os.Open(path)
		if err != nil {
			continue
		}

		scanner := bufio.NewScanner(attributes)

		for scanner.Scan() {
			line := scanner.Text()
			if strings.Contains(line, "filter=lfs") {
				fields := strings.Fields(line)
				relfile, _ := filepath.Rel(workingDir, path)
				pattern := fields[0]
				if reldir := filepath.Dir(relfile); len(reldir) > 0 {
					pattern = filepath.Join(reldir, pattern)
				}
				// Find lockable flag in any position after pattern to avoid
				// edge case of matching "lockable" to a file pattern
				lockable := false
				for _, f := range fields[1:] {
					if f == LockableAttrib {
						lockable = true
						break
					}
				}
				paths = append(paths, AttributePath{Path: pattern, Source: relfile, Lockable: lockable})
			}
		}
	}

	return paths
}

func findAttributeFiles(workingDir, gitDir string) []string {
	var paths []string

	repoAttributes := filepath.Join(gitDir, "info", "attributes")
	if info, err := os.Stat(repoAttributes); err == nil && !info.IsDir() {
		paths = append(paths, repoAttributes)
	}

	tools.FastWalkGitRepo(workingDir, func(parentDir string, info os.FileInfo, err error) {
		if err != nil {
			tracerx.Printf("Error finding .gitattributes: %v", err)
			return
		}

		if info.IsDir() || info.Name() != ".gitattributes" {
			return
		}
		paths = append(paths, filepath.Join(parentDir, info.Name()))
	})

	// reverse the order of the files so more specific entries are found first
	// when iterating from the front (respects precedence)
	for i, j := 0, len(paths)-1; i < j; i, j = i+1, j-1 {
		paths[i], paths[j] = paths[j], paths[i]
	}

	return paths
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"
)

var NO_RESPONSE string = ""

var listen *string = flag.String("listen", ":8000", "\"[address]:<port>\" to bind to. [default: \":8000\"]")
var username *string = flag.String("username", "", "GitHub username to fetch keys for. [required]")
var ttl *int64 = flag.Int64("ttl", 86400, "Time in seconds to cache GitHub keys for. [default: 86400 (one day)]")

var cache []string = make([]string, 0)
var expire int64 = 0

func fetchKeys() error {
	fmt.Fprintf(os.Stderr, "Fetching keys for GitHub user \"%s\"\n", *username)
	var resp *http.Response
	var err error
	var uri string = fmt.Sprintf("https://api.github.com/users/%s/keys", *username)
	resp, err = http.Get(uri)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	var keys []map[string]interface{} = make([]map[string]interface{}, 0)
	err = json.Unmarshal(body, &keys)
	if err != nil {
		return err
	}

	var newCache []string = make([]string, 0)
	for _, key := range keys {
		newCache = append(newCache, key["key"].(string))
	}
	var newExpire int64 = time.Now().UTC().Unix() + *ttl
	cache = newCache
	expire = newExpire

	return nil
}

func getResponse(r *http.Request) (int, string) {
	if r.Method != "GET" {
		return http.StatusMethodNotAllowed, NO_RESPONSE
	}

	var err error
	var now int64 = time.Now().UTC().Unix()
	if now >= expire {
		err = fetchKeys()
		if err != nil {
			return http.StatusInternalServerError, NO_RESPONSE
		}
	}

	if len(cache) > 0 {
		var response string = ""
		for _, key := range cache {
			response += fmt.Sprintf("%s\n", key)
		}
		return http.StatusOK, response
	}

	return http.StatusNoContent, NO_RESPONSE
}

func handle(w http.ResponseWriter, r *http.Request) {
	var status int
	var response string
	status, response = getResponse(r)
	w.WriteHeader(status)
	fmt.Fprintf(w, response)

	fmt.Fprintf(
		os.Stdout,
		"\"%d\"\t\"%d\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\n",
		status, len(response), r.Method, r.URL, r.Proto, r.Host, r.RemoteAddr, r.UserAgent(),
	)
}

func main() {
	flag.Parse()
	if *username == "" {
		log.Fatal("Must provide `-username` parameter. e.g. `github-keys -username \"github-username\"`")
	}

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

	fmt.Fprintf(os.Stderr, "Starting server on \"%s\" for GitHub user \"%s\"\n", *listen, *username)
	http.HandleFunc("/", handle)
	err = http.ListenAndServe(*listen, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>use log package<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

var NO_RESPONSE string = ""

var listen *string = flag.String("listen", ":8000", "\"[address]:<port>\" to bind to. [default: \":8000\"]")
var username *string = flag.String("username", "", "GitHub username to fetch keys for. [required]")
var ttl *int64 = flag.Int64("ttl", 86400, "Time in seconds to cache GitHub keys for. [default: 86400 (one day)]")

var cache []string = make([]string, 0)
var expire int64 = 0

func fetchKeys() error {
	log.Printf("Fetching keys for GitHub user \"%s\"\n", *username)
	var resp *http.Response
	var err error
	var uri string = fmt.Sprintf("https://api.github.com/users/%s/keys", *username)
	resp, err = http.Get(uri)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	var body []byte
	body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}

	var keys []map[string]interface{} = make([]map[string]interface{}, 0)
	err = json.Unmarshal(body, &keys)
	if err != nil {
		return err
	}

	var newCache []string = make([]string, 0)
	for _, key := range keys {
		newCache = append(newCache, key["key"].(string))
	}
	var newExpire int64 = time.Now().UTC().Unix() + *ttl
	cache = newCache
	expire = newExpire

	return nil
}

func getResponse(r *http.Request) (int, string) {
	if r.Method != "GET" {
		return http.StatusMethodNotAllowed, NO_RESPONSE
	}

	var err error
	var now int64 = time.Now().UTC().Unix()
	if now >= expire {
		err = fetchKeys()
		if err != nil {
			return http.StatusInternalServerError, NO_RESPONSE
		}
	}

	if len(cache) > 0 {
		var response string = ""
		for _, key := range cache {
			response += fmt.Sprintf("%s\n", key)
		}
		return http.StatusOK, response
	}

	return http.StatusNoContent, NO_RESPONSE
}

func handle(w http.ResponseWriter, r *http.Request) {
	var status int
	var response string
	status, response = getResponse(r)
	w.WriteHeader(status)
	fmt.Fprintf(w, response)

	log.Printf(
		"\"%d\"\t\"%d\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\t\"%s\"\n",
		status, len(response), r.Method, r.URL, r.Proto, r.Host, r.RemoteAddr, r.UserAgent(),
	)
}

func main() {
	flag.Parse()
	if *username == "" {
		log.Fatal("Must provide `-username` parameter. e.g. `github-keys -username \"github-username\"`")
	}

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

	log.Printf("Starting server on \"%s\" for GitHub user \"%s\"\n", *listen, *username)
	http.HandleFunc("/", handle)
	err = http.ListenAndServe(*listen, nil)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/boltdb/bolt"
)

var (
	QuotaError = errors.New("payment required")

	bucketName = []byte("cache")
)

type Cache struct {
	db *bolt.DB
}

func NewCache(dir string) (*Cache, error) {
	db, err := bolt.Open(dir, 0666, nil)
	if err != nil {
		return nil, err
	}
	tx, err := db.Begin(true)
	if err != nil {
		return nil, err
	}
	_, err = tx.CreateBucketIfNotExists(bucketName)
	if err != nil {
		return nil, err
	}
	err = tx.Commit()
	if err != nil {
		return nil, err
	}
	return &Cache{
		db: db,
	}, nil
}

func (c *Cache) Close() error {
	return c.db.Close()
}

func (c *Cache) Put(key string, data []byte) error {
	tx, err := c.db.Begin(true)
	if err != nil {
		return err
	}
	defer func() {
		if tx != nil {
			tx.Rollback()
		}
	}()
	bucket := tx.Bucket(bucketName)
	err = bucket.Put([]byte(key), data)
	if err != nil {
		return err
	}
	err = tx.Commit()
	tx = nil
	return err
}

func (c *Cache) Get(key string) ([]byte, error) {
	tx, err := c.db.Begin(false)
	if err != nil {
		return nil, err
	}
	defer tx.Rollback()
	bucket := tx.Bucket(bucketName)
	temp := bucket.Get([]byte(key))
	data := make([]byte, len(temp))
	copy(data, temp)
	return data, nil
}

type Geocoder struct {
	key   string
	cache *Cache
}

func NewGeocoder(key, cacheDir string) (*Geocoder, error) {
	cache, err := NewCache(cacheDir)
	if err != nil {
		return nil, err
	}
	return &Geocoder{
		key:   key,
		cache: cache,
	}, nil
}

func (g *Geocoder) Close() error {
	return g.cache.Close()
}

type LocRate struct {
	Limit     int `json:"limit"`
	Remaining int `json:"remaining"`
}

type LocComponent struct {
	City        string `json:"city"`
	PostCode    string `json:"postcode"`
	County      string `json:"county"`
	State       string `json:"state"`
	Country     string `json:"country"`
	CountryCode string `json:"country_code"`
}

func (c *LocComponent) String() string {
	values := []struct {
		Field string
		Value string
	}{
		{"city", c.City},
		{"postcode", c.PostCode},
		{"county", c.County},
		{"state", c.State},
		{"country", c.Country},
	}
	s := ""
	written := false
	for _, v := range values {
		if v.Value == "" {
			continue
		}
		if written {
			s += ", "
		}
		s += fmt.Sprintf("%s: %s", v.Field, v.Value)
		written = true
	}
	return s
}

type LocResult struct {
	Component LocComponent `json:"components"`
}

type Location struct {
	Cached  bool
	Rate    LocRate     `json:"rate"`
	Results []LocResult `json:"results"`
}

func makeKeyAndCountryCode(q, code string) (string, string) {
	code = strings.ToLower(code)
	if code == "" {
		code = "unk"
	}
	return q + "-" + code, code
}

func (g *Geocoder) GeocodeFromCache(q, countryCode string) (*Location, error) {
	key, countryCode := makeKeyAndCountryCode(q, countryCode)
	data, err := g.cache.Get(key)
	if err != nil {
		return nil, err
	}
	if len(data) == 0 {
		return nil, nil
	}
	res := &Location{}
	err = json.Unmarshal(data, res)
	res.Cached = true
	return res, err
}

func (g *Geocoder) Geocode(q, countryCode string, offline bool) (*Location, error) {
	res, err := g.GeocodeFromCache(q, countryCode)
	if err != nil || res != nil || offline {
		return res, err
	}
	r, err := g.rawGeocode(q, countryCode)
	if err != nil {
		return nil, err
	}
	defer r.Close()
	data, err := ioutil.ReadAll(&io.LimitedReader{
		R: r,
		N: 4 * 1024 * 1024,
	})
	if err != nil {
		return nil, err
	}
	res = &Location{}
	err = json.Unmarshal(data, res)
	if err != nil {
		return nil, err
	}
	key, _ := makeKeyAndCountryCode(q, countryCode)
	err = g.cache.Put(key, data)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, res)
	return res, err
}

func (g *Geocoder) rawGeocode(q, countryCode string) (io.ReadCloser, error) {
	u := fmt.Sprintf("http://api.opencagedata.com/geocode/v1/json?q=%s&key=%s",
		url.QueryEscape(q), url.QueryEscape(g.key))
	if countryCode != "" {
		u += "&countrycode=" + url.QueryEscape(countryCode)
	}
	rsp, err := http.Get(u)
	if err != nil {
		return nil, err
	}
	if rsp.StatusCode != 200 {
		rsp.Body.Close()
		if rsp.StatusCode == 402 {
			return nil, QuotaError
		}
		return nil, fmt.Errorf("geocoding failed with %s", rsp.Status)
	}
	return rsp.Body, nil
}

var (
	geocodeCmd   = app.Command("geocode", "geocode location with OpenCage")
	geocodeQuery = geocodeCmd.Arg("query", "geocoding query").Required().String()
)

func geocode(cfg *Config) error {
	key := cfg.GeocodingKey()
	if key == "" {
		return fmt.Errorf("geocoding key is not set, please configure APEC_GEOCODING_KEY")
	}
	geocoder, err := NewGeocoder(key, cfg.Geocoder())
	if err != nil {
		return err
	}
	defer geocoder.Close()
	loc, err := geocoder.Geocode(*geocodeQuery, "fr", false)
	if err != nil {
		return err
	}
	if loc.Cached {
		fmt.Printf("cached: true\n")
	}
	fmt.Printf("remaining: %d\n", loc.Rate.Remaining)
	for _, res := range loc.Results {
		comp := res.Component
		fmt.Printf("%s\n", comp.String())
	}
	return nil
}
<commit_msg>geocoder: rewrite using bolt Update/View API<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"

	"github.com/boltdb/bolt"
)

var (
	QuotaError = errors.New("payment required")

	bucketName = []byte("cache")
)

type Cache struct {
	db *bolt.DB
}

func NewCache(dir string) (*Cache, error) {
	db, err := bolt.Open(dir, 0666, nil)
	if err != nil {
		return nil, err
	}
	err = db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists(bucketName)
		return err
	})
	if err != nil {
		return nil, err
	}
	return &Cache{
		db: db,
	}, nil
}

func (c *Cache) Close() error {
	return c.db.Close()
}

func (c *Cache) Put(key string, data []byte) error {
	return c.db.Update(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(bucketName)
		return bucket.Put([]byte(key), data)
	})
}

func (c *Cache) Get(key string) ([]byte, error) {
	var data []byte
	err := c.db.View(func(tx *bolt.Tx) error {
		bucket := tx.Bucket(bucketName)
		temp := bucket.Get([]byte(key))
		data = make([]byte, len(temp))
		copy(data, temp)
		return nil
	})
	return data, err
}

type Geocoder struct {
	key   string
	cache *Cache
}

func NewGeocoder(key, cacheDir string) (*Geocoder, error) {
	cache, err := NewCache(cacheDir)
	if err != nil {
		return nil, err
	}
	return &Geocoder{
		key:   key,
		cache: cache,
	}, nil
}

func (g *Geocoder) Close() error {
	return g.cache.Close()
}

type LocRate struct {
	Limit     int `json:"limit"`
	Remaining int `json:"remaining"`
}

type LocComponent struct {
	City        string `json:"city"`
	PostCode    string `json:"postcode"`
	County      string `json:"county"`
	State       string `json:"state"`
	Country     string `json:"country"`
	CountryCode string `json:"country_code"`
}

func (c *LocComponent) String() string {
	values := []struct {
		Field string
		Value string
	}{
		{"city", c.City},
		{"postcode", c.PostCode},
		{"county", c.County},
		{"state", c.State},
		{"country", c.Country},
	}
	s := ""
	written := false
	for _, v := range values {
		if v.Value == "" {
			continue
		}
		if written {
			s += ", "
		}
		s += fmt.Sprintf("%s: %s", v.Field, v.Value)
		written = true
	}
	return s
}

type LocResult struct {
	Component LocComponent `json:"components"`
}

type Location struct {
	Cached  bool
	Rate    LocRate     `json:"rate"`
	Results []LocResult `json:"results"`
}

func makeKeyAndCountryCode(q, code string) (string, string) {
	code = strings.ToLower(code)
	if code == "" {
		code = "unk"
	}
	return q + "-" + code, code
}

func (g *Geocoder) GeocodeFromCache(q, countryCode string) (*Location, error) {
	key, countryCode := makeKeyAndCountryCode(q, countryCode)
	data, err := g.cache.Get(key)
	if err != nil {
		return nil, err
	}
	if len(data) == 0 {
		return nil, nil
	}
	res := &Location{}
	err = json.Unmarshal(data, res)
	res.Cached = true
	return res, err
}

func (g *Geocoder) Geocode(q, countryCode string, offline bool) (*Location, error) {
	res, err := g.GeocodeFromCache(q, countryCode)
	if err != nil || res != nil || offline {
		return res, err
	}
	r, err := g.rawGeocode(q, countryCode)
	if err != nil {
		return nil, err
	}
	defer r.Close()
	data, err := ioutil.ReadAll(&io.LimitedReader{
		R: r,
		N: 4 * 1024 * 1024,
	})
	if err != nil {
		return nil, err
	}
	res = &Location{}
	err = json.Unmarshal(data, res)
	if err != nil {
		return nil, err
	}
	key, _ := makeKeyAndCountryCode(q, countryCode)
	err = g.cache.Put(key, data)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, res)
	return res, err
}

func (g *Geocoder) rawGeocode(q, countryCode string) (io.ReadCloser, error) {
	u := fmt.Sprintf("http://api.opencagedata.com/geocode/v1/json?q=%s&key=%s",
		url.QueryEscape(q), url.QueryEscape(g.key))
	if countryCode != "" {
		u += "&countrycode=" + url.QueryEscape(countryCode)
	}
	rsp, err := http.Get(u)
	if err != nil {
		return nil, err
	}
	if rsp.StatusCode != 200 {
		rsp.Body.Close()
		if rsp.StatusCode == 402 {
			return nil, QuotaError
		}
		return nil, fmt.Errorf("geocoding failed with %s", rsp.Status)
	}
	return rsp.Body, nil
}

var (
	geocodeCmd   = app.Command("geocode", "geocode location with OpenCage")
	geocodeQuery = geocodeCmd.Arg("query", "geocoding query").Required().String()
)

func geocode(cfg *Config) error {
	key := cfg.GeocodingKey()
	if key == "" {
		return fmt.Errorf("geocoding key is not set, please configure APEC_GEOCODING_KEY")
	}
	geocoder, err := NewGeocoder(key, cfg.Geocoder())
	if err != nil {
		return err
	}
	defer geocoder.Close()
	loc, err := geocoder.Geocode(*geocodeQuery, "fr", false)
	if err != nil {
		return err
	}
	if loc.Cached {
		fmt.Printf("cached: true\n")
	}
	fmt.Printf("remaining: %d\n", loc.Rate.Remaining)
	for _, res := range loc.Results {
		comp := res.Component
		fmt.Printf("%s\n", comp.String())
	}
	return nil
}
<|endoftext|>


<commit_before>package reviewdog

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/xanzy/go-gitlab"
)

const noGitlabTokenSkipTestMes = "skipping test (requires actual Personal access tokens. export REVIEWDOG_TEST_GITHUB_API_TOKEN=<GitLab Personal Access Token>)"

func setupGitLabClient() *gitlab.Client {
	token := os.Getenv("REVIEWDOG_TEST_GITLAB_API_TOKEN")
	if token == "" {
		return nil
	}
	cli := gitlab.NewClient(nil, token)
	cli.SetBaseURL("https://gitlab.com/api/v4")
	return cli
}

func TestGitLabMergeRequest_Post(t *testing.T) {
	t.Skip("skipping test which post comments actually")
	client := setupGitLabClient()
	if client == nil {
		t.Skip(noGitlabTokenSkipTestMes)
	}

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	sha := "bc328521a974c23acb24e8ebf51c1c2dcdb4fe6a"

	g, err := NewGitLabMergeReqest(client, owner, repo, pr, sha)
	if err != nil {
		t.Fatal(err)
	}
	comment := &Comment{
		CheckResult: &CheckResult{
			Path: "diff.go",
			Lnum: 22,
		},
		LnumDiff: 11,
		Body:     "[reviewdog] test",
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	if err := g.Post(context.Background(), comment); err != nil {
		t.Error(err)
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
}

func TestGitLabMergeRequest_Diff(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}

	want := `diff --git a/diff.go b/diff.go
index 496d0d8..f06d633 100644
--- a/diff.go
+++ b/diff.go
@@ -13,14 +13,15 @@ type DiffString struct {
 	strip int
 }

-func NewDiffString(diff string, strip int) DiffService {
-	return &DiffString{b: []byte(diff), strip: strip}
-}

 func (d *DiffString) Diff(_ context.Context) ([]byte, error) {
 	return d.b, nil
 }

+func NewDiffString(diff string, strip int) DiffService {
+	return &DiffString{b: []byte(diff), strip: strip}
+}
+
 func (d *DiffString) Strip() int {
 	return d.strip
 }
`

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	b, err := g.Diff(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	if got := string(b); got != want {
		t.Errorf("got:\n%v\nwant:\n%v", got, want)
	}
}

func TestGitLabMergeRequest_comment(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	comments, err := g.comment(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	for _, c := range comments {
		t.Log("---")
		t.Log(c.Note)
		t.Log(c.Path)
		t.Log(c.Line)
	}
}

func TestGitLabPullRequest_Post_Flush_review_api(t *testing.T) {
	apiCalled := 0
	mux := http.NewServeMux()
	mux.HandleFunc("/api/v4/projects/o/r/merge_requests/14/commits", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.Commit{
			{
				ID:      "0123456789abcdef",
				ShortID: "012345678",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/0123456789abcdef/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.CommitComment{
			{
				Path: "notExistFile.go",
				Line: 1,
				Note: bodyPrefix + "\nalready commented",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/sha/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "POST" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		var req gitlab.CommitComment
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			t.Error(err)
		}
		want := gitlab.CommitComment{
			Path:     "notExistFile.go",
			Line:     14,
			Note:     bodyPrefix + "\nnew comment",
			LineType: "new",
		}
		if diff := pretty.Compare(want, req); diff != "" {
			t.Errorf("req.Comments diff: (-got +want)\n%s", diff)
		}
		if err := json.NewEncoder(w).Encode(req); err != nil {
			t.Fatal(err)
		}
	})
	ts := httptest.NewServer(mux)
	defer ts.Close()

	cli := gitlab.NewClient(nil, "")
	cli.SetBaseURL(ts.URL)
	g, err := NewGitLabMergeReqest(cli, "o", "r", 14, "sha")
	if err != nil {
		t.Fatal(err)
	}
	// Path is set to notExistFile path for mock-up test.
	// If setting exists file path, sha is changed by last commit id.
	comments := []*Comment{
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 1,
			},
			Body: "already commented",
		},
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 14,
			},
			Body: "new comment",
		},
	}
	for _, c := range comments {
		if err := g.Post(context.Background(), c); err != nil {
			t.Error(err)
		}
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
	if want := 3; apiCalled != want {
		t.Errorf("GitLab API is called %d times, want %d times", apiCalled, want)
	}
}

func TestGitLabPullReqest_workdir(t *testing.T) {
	cwd, _ := os.Getwd()
	defer os.Chdir(cwd)

	g, err := NewGitLabMergeReqest(nil, "", "", 0, "")
	if err != nil {
		t.Fatal(err)
	}
	if g.wd != "" {
		t.Fatalf("g.wd = %q, want empty", g.wd)
	}
	ctx := context.Background()
	want := "a/b/c"
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: want}})
	if got := g.postComments[0].Path; got != want {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, want)
	}

	subDir := "cmd/"
	if err := os.Chdir(subDir); err != nil {
		t.Fatal(err)
	}
	g, _ = NewGitLabMergeReqest(nil, "", "", 0, "")
	if g.wd != subDir {
		t.Fatalf("gitRelWorkdir() = %q, want %q", g.wd, subDir)
	}
	path := "a/b/c"
	wantPath := "cmd/" + path
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: path}})
	if got := g.postComments[0].Path; got != wantPath {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, wantPath)
	}
}
<commit_msg>reword: comment<commit_after>package reviewdog

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/kylelemons/godebug/pretty"
	"github.com/xanzy/go-gitlab"
)

const noGitlabTokenSkipTestMes = "skipping test (requires actual Personal access tokens. export REVIEWDOG_TEST_GITHUB_API_TOKEN=<GitLab Personal Access Token>)"

func setupGitLabClient() *gitlab.Client {
	token := os.Getenv("REVIEWDOG_TEST_GITLAB_API_TOKEN")
	if token == "" {
		return nil
	}
	cli := gitlab.NewClient(nil, token)
	cli.SetBaseURL("https://gitlab.com/api/v4")
	return cli
}

func TestGitLabMergeRequest_Post(t *testing.T) {
	t.Skip("skipping test which post comments actually")
	client := setupGitLabClient()
	if client == nil {
		t.Skip(noGitlabTokenSkipTestMes)
	}

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	sha := "bc328521a974c23acb24e8ebf51c1c2dcdb4fe6a"

	g, err := NewGitLabMergeReqest(client, owner, repo, pr, sha)
	if err != nil {
		t.Fatal(err)
	}
	comment := &Comment{
		CheckResult: &CheckResult{
			Path: "diff.go",
			Lnum: 22,
		},
		LnumDiff: 11,
		Body:     "[reviewdog] test",
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	if err := g.Post(context.Background(), comment); err != nil {
		t.Error(err)
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
}

func TestGitLabMergeRequest_Diff(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}

	want := `diff --git a/diff.go b/diff.go
index 496d0d8..f06d633 100644
--- a/diff.go
+++ b/diff.go
@@ -13,14 +13,15 @@ type DiffString struct {
 	strip int
 }

-func NewDiffString(diff string, strip int) DiffService {
-	return &DiffString{b: []byte(diff), strip: strip}
-}

 func (d *DiffString) Diff(_ context.Context) ([]byte, error) {
 	return d.b, nil
 }

+func NewDiffString(diff string, strip int) DiffService {
+	return &DiffString{b: []byte(diff), strip: strip}
+}
+
 func (d *DiffString) Strip() int {
 	return d.strip
 }
`

	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	b, err := g.Diff(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	if got := string(b); got != want {
		t.Errorf("got:\n%v\nwant:\n%v", got, want)
	}
}

func TestGitLabMergeRequest_comment(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test which contains actual API requests in short mode")
	}
	client := setupGitLabClient()
	if client == nil {
		t.Skip(notokenSkipTestMes)
	}
	// https://gitlab.com/nakatanakatana/reviewdog/merge_requests/1
	owner := "nakatanakatana"
	repo := "reviewdog"
	pr := 1
	g, err := NewGitLabMergeReqest(client, owner, repo, pr, "")
	if err != nil {
		t.Fatal(err)
	}
	comments, err := g.comment(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	for _, c := range comments {
		t.Log("---")
		t.Log(c.Note)
		t.Log(c.Path)
		t.Log(c.Line)
	}
}

func TestGitLabPullRequest_Post_Flush_review_api(t *testing.T) {
	apiCalled := 0
	mux := http.NewServeMux()
	mux.HandleFunc("/api/v4/projects/o/r/merge_requests/14/commits", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.Commit{
			{
				ID:      "0123456789abcdef",
				ShortID: "012345678",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/0123456789abcdef/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "GET" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		cs := []*gitlab.CommitComment{
			{
				Path: "notExistFile.go",
				Line: 1,
				Note: bodyPrefix + "\nalready commented",
			},
		}
		if err := json.NewEncoder(w).Encode(cs); err != nil {
			t.Fatal(err)
		}
	})
	mux.HandleFunc("/api/v4/projects/o/r/repository/commits/sha/comments", func(w http.ResponseWriter, r *http.Request) {
		apiCalled++
		if r.Method != "POST" {
			t.Errorf("unexpected access: %v %v", r.Method, r.URL)
		}
		var req gitlab.CommitComment
		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
			t.Error(err)
		}
		want := gitlab.CommitComment{
			Path:     "notExistFile.go",
			Line:     14,
			Note:     bodyPrefix + "\nnew comment",
			LineType: "new",
		}
		if diff := pretty.Compare(want, req); diff != "" {
			t.Errorf("req.Comments diff: (-got +want)\n%s", diff)
		}
		if err := json.NewEncoder(w).Encode(req); err != nil {
			t.Fatal(err)
		}
	})
	ts := httptest.NewServer(mux)
	defer ts.Close()

	cli := gitlab.NewClient(nil, "")
	cli.SetBaseURL(ts.URL)
	g, err := NewGitLabMergeReqest(cli, "o", "r", 14, "sha")
	if err != nil {
		t.Fatal(err)
	}
	// Path is set to non existing file path for mock test not to use last commit id of the line.
	// If setting exists file path, sha is changed by last commit id.
	comments := []*Comment{
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 1,
			},
			Body: "already commented",
		},
		{
			CheckResult: &CheckResult{
				Path: "notExistFile.go",
				Lnum: 14,
			},
			Body: "new comment",
		},
	}
	for _, c := range comments {
		if err := g.Post(context.Background(), c); err != nil {
			t.Error(err)
		}
	}
	if err := g.Flush(context.Background()); err != nil {
		t.Error(err)
	}
	if want := 3; apiCalled != want {
		t.Errorf("GitLab API is called %d times, want %d times", apiCalled, want)
	}
}

func TestGitLabPullReqest_workdir(t *testing.T) {
	cwd, _ := os.Getwd()
	defer os.Chdir(cwd)

	g, err := NewGitLabMergeReqest(nil, "", "", 0, "")
	if err != nil {
		t.Fatal(err)
	}
	if g.wd != "" {
		t.Fatalf("g.wd = %q, want empty", g.wd)
	}
	ctx := context.Background()
	want := "a/b/c"
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: want}})
	if got := g.postComments[0].Path; got != want {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, want)
	}

	subDir := "cmd/"
	if err := os.Chdir(subDir); err != nil {
		t.Fatal(err)
	}
	g, _ = NewGitLabMergeReqest(nil, "", "", 0, "")
	if g.wd != subDir {
		t.Fatalf("gitRelWorkdir() = %q, want %q", g.wd, subDir)
	}
	path := "a/b/c"
	wantPath := "cmd/" + path
	g.Post(ctx, &Comment{CheckResult: &CheckResult{Path: path}})
	if got := g.postComments[0].Path; got != wantPath {
		t.Errorf("wd=%q path=%q, want %q", g.wd, got, wantPath)
	}
}
<|endoftext|>