<commit_before>// docgo is a [Go](http://golang.org) implementation of [Jeremy Ashkenas]
// (http://github.com/jashkenas)'s [docco] (http://jashkenas.github.com/docco/),
// a literate-programming-style documentation generator.  Running docgo on your
// Go source files produces HTML with comments and code side-by-side.
//
// Comments are processed by [Markdown]
// (http://daringfireball.net/projects/markdown) using [Russ Ross]
// (http://github.com/russross)'s [BlackFriday]
// (http://github.com/russross/blackfriday) library, and code is
// syntax-highlighted using [litebrite](http://dhconnelly.github.com/litebrite),
// a Go syntax highlighting library.
//
// The source is available on [GitHub](http://github.com/dhconnelly/docgo).
//
// With a recent Go weekly build (I'm using `weekly.2012-2-07`), you can get,
// install, and run docgo by doing the following at a command line:
//
// `go get github.com/dhconnelly/docgo`

// `go install github.com/dhconnelly/docgo`

// `docgo file.go`
//
// This will create `file.html` in the current directory.
//
// There are two command-line flags:
//
// - `resdir`: a path to the directory containing the CSS styles and HTML
//   templates (this is usually the docgo source directory)
// - `outdir`: the directory to which the generated HTML should be writen

// docgo is copyright 2012 Daniel Connelly.  All rights reserved.  Use of
// this source code is governed by a BSD-style license that can be found in
// the `LICENSE` file.

// ## Imports and globals

package main

import (
	"bytes"
	"flag"
	"go/build"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"

	"github.com/dhconnelly/litebrite"
	"github.com/russross/blackfriday"
)

var (
	templ       *template.Template                // html template for generated docs
	match       = regexp.MustCompile(`^\s*//\s?`) // pattern for extracted comments
	sep         = "/*[docgoseparator]*/"          // replacement for comment groups
	unsep       = regexp.MustCompile(`<div class="comment">/\*\[docgoseparator\]\*/</div>`)
	outdir      = flag.String("outdir", ".", "output directory for html & css")
	resdir      = flag.String("resdir", "", "directory containing CSS and templates")
	csspath     = flag.String("csspath", "", "relative path to CSS file, for use with the <link> element")
	cssfilename = "doc.css"
	tplfilename = "doc.templ"
	pkg         = "github.com/christophberger/docgo" // for locating the resources if not specified
)

// ## Generating documentation

type docs struct {
	Filename string
	Sections []*section
	CssPath  string
}

type section struct {
	Doc  string
	Code string
}

// Extract comments from source code, pass them through markdown, highlight the
// code, and render to a string.
func GenerateDocs(title, src string) string {
	sections := extractSections(src)
	highlightCode(sections)
	markdownComments(sections)

	var b bytes.Buffer
	cleanCssPath := ""
	if len(*csspath) > 0 {
		cleanCssPath = path.Clean(*csspath) + string(os.PathSeparator)
	}
	err := templ.Execute(&b, docs{title, sections, cleanCssPath + cssfilename})
	if err != nil {
		panic(err.Error())
	}
	return b.String()
}

// ## Processing sections

// Split the source into sections, where each section contains a comment group
// (consecutive leading-line // comments) and the code that follows that group.
func extractSections(source string) []*section {
	sections := make([]*section, 0)
	current := new(section)

	for _, line := range strings.Split(source, "\n") {
		// When a candidate comment line is found, add it to the current
		// comment group (or create a new section if code has already been
		// added to the current section).
		if match.FindString(line) != "" {
			if current.Code != "" {
				sections = append(sections, current)
				current = new(section)
			}
			// Strip out the comment delimiters
			current.Doc += match.ReplaceAllString(line, "") + "\n"
		} else {
			current.Code += line + "\n"
		}
	}

	return append(sections, current)
}

// Apply markdown to each section's documentation.
func markdownComments(sections []*section) {
	for _, section := range sections {
		// IMHO BlackFriday should use a string interface, since it
		// operates on text (not arbitrary binary) data...
		section.Doc = string(blackfriday.MarkdownCommon([]byte(section.Doc)))
	}
}

// Apply syntax highlighting to each section's code.
func highlightCode(sections []*section) {
	// Rejoin the source code fragments, using sep as delimiter
	segments := make([]string, 0)
	for _, section := range sections {
		segments = append(segments, section.Code)
	}
	code := strings.Join(segments, sep)

	// Highlight the joined source
	h := litebrite.Highlighter{"operator", "ident", "literal", "keyword", "comment"}
	hlcode := h.Highlight(code)

	// Collect the code between subsequent `unsep`s
	matches := append(unsep.FindAllStringIndex(hlcode, -1), []int{len(hlcode), 0})
	lastend := 0
	for i, match := range matches {
		sections[i].Code = hlcode[lastend:match[0]]
		lastend = match[1]
	}
}

// ## Setup and running

// Locate the HTML template and CSS.
func findResources() string {
	if *resdir != "" {
		return *resdir
	}

	// find the path to the package root to locate the resource files
	p, err := build.Default.Import(pkg, "", build.FindOnly)
	if err != nil {
		panic(err.Error())
	}
	return p.Dir
}

// Load the HTML template
func loadTemplate(path string) {
	templ = template.Must(template.ParseFiles(path + string(os.PathSeparator) + tplfilename))
}

// copyFile copies the contents of src to dst atomically.
// Copied from github.com/pkg/fileutils/copy.go.
// (c) Dave Cheney - see LICENSE_CopyFile.txt.
func copyFile(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	tmp, err := ioutil.TempFile(filepath.Dir(dst), "copyfile")
	if err != nil {
		return err
	}
	_, err = io.Copy(tmp, in)
	if err != nil {
		tmp.Close()
		os.Remove(tmp.Name())
		return err
	}
	if err := tmp.Close(); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	const perm = 0644
	if err := os.Chmod(tmp.Name(), perm); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	if err := os.Rename(tmp.Name(), dst); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	return nil
}

// copyCssFile() copies
func copyCssFile() {
	// Copy only if dest path != source path
	src := path.Clean(*resdir)
	dst := path.Clean(*outdir + *csspath)
	if dst != src {
		err := copyFile(dst+string(os.PathSeparator)+cssfilename, src+string(os.PathSeparator)+cssfilename)
		if err != nil {
			panic(err.Error())
		}
	}
}

// Generate documentation for a source file.
func processFile(filename string) {
	src, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err.Error())
	}
	name := filepath.Base(filename)
	outname := filepath.Join(*outdir, name[:len(name)-2]) + "html"
	docs := GenerateDocs(name, string(src))
	err = ioutil.WriteFile(outname, []byte(docs), 0666)
	if err != nil {
		panic(err.Error())
	}
	copyCssFile()
}

func main() {
	flag.Parse()
	loadTemplate(findResources())
	for _, filename := range flag.Args() {
		processFile(filename)
	}
}
<commit_msg>Changed: Cleared up a few comments in extractSections for my own understanding.<commit_after>// docgo is a [Go](http://golang.org) implementation of [Jeremy Ashkenas]
// (http://github.com/jashkenas)'s [docco] (http://jashkenas.github.com/docco/),
// a literate-programming-style documentation generator.  Running docgo on your
// Go source files produces HTML with comments and code side-by-side.
//
// Comments are processed by [Markdown]
// (http://daringfireball.net/projects/markdown) using [Russ Ross]
// (http://github.com/russross)'s [BlackFriday]
// (http://github.com/russross/blackfriday) library, and code is
// syntax-highlighted using [litebrite](http://dhconnelly.github.com/litebrite),
// a Go syntax highlighting library.
//
// The source is available on [GitHub](http://github.com/dhconnelly/docgo).
//
// With a recent Go weekly build (I'm using `weekly.2012-2-07`), you can get,
// install, and run docgo by doing the following at a command line:
//
// `go get github.com/dhconnelly/docgo`

// `go install github.com/dhconnelly/docgo`

// `docgo file.go`
//
// This will create `file.html` in the current directory.
//
// There are two command-line flags:
//
// - `resdir`: a path to the directory containing the CSS styles and HTML
//   templates (this is usually the docgo source directory)
// - `outdir`: the directory to which the generated HTML should be writen

// docgo is copyright 2012 Daniel Connelly.  All rights reserved.  Use of
// this source code is governed by a BSD-style license that can be found in
// the `LICENSE` file.

// ## Imports and globals

package main

import (
	"bytes"
	"flag"
	"go/build"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"

	"github.com/dhconnelly/litebrite"
	"github.com/russross/blackfriday"
)

var (
	templ       *template.Template                // html template for generated docs
	match       = regexp.MustCompile(`^\s*//\s?`) // pattern for extracted comments
	sep         = "/*[docgoseparator]*/"          // replacement for comment groups
	unsep       = regexp.MustCompile(`<div class="comment">/\*\[docgoseparator\]\*/</div>`)
	outdir      = flag.String("outdir", ".", "output directory for html & css")
	resdir      = flag.String("resdir", "", "directory containing CSS and templates")
	csspath     = flag.String("csspath", "", "relative path to CSS file, for use with the <link> element")
	cssfilename = "doc.css"
	tplfilename = "doc.templ"
	pkg         = "github.com/christophberger/docgo" // for locating the resources if not specified
)

// ## Generating documentation

type docs struct {
	Filename string
	Sections []*section
	CssPath  string
}

type section struct {
	Doc  string
	Code string
}

// Extract comments from source code, pass them through markdown, highlight the
// code, and render to a string.
func GenerateDocs(title, src string) string {
	sections := extractSections(src)
	highlightCode(sections)
	markdownComments(sections)

	var b bytes.Buffer
	cleanCssPath := ""
	if len(*csspath) > 0 {
		cleanCssPath = path.Clean(*csspath) + string(os.PathSeparator)
	}
	err := templ.Execute(&b, docs{title, sections, cleanCssPath + cssfilename})
	if err != nil {
		panic(err.Error())
	}
	return b.String()
}

// ## Processing sections

// Split the source into sections, where each section contains a comment group
// (consecutive leading-line // comments) and the code that follows that group.
func extractSections(source string) []*section {
	sections := make([]*section, 0)
	current := new(section)

	for _, line := range strings.Split(source, "\n") {
		// When a candidate comment line is found, first test if we're currently
		// in a Code group. If so, switch to a new section. Add the comment line
		// to the section's Doc group.
		if match.FindString(line) != "" {
			if current.Code != "" {
				sections = append(sections, current)
				current = new(section)
			}
			// Strip out the comment delimiters and add the line to the
			// current doc section.
			current.Doc += match.ReplaceAllString(line, "") + "\n"
		} else {
			// No comment line found, so add the current line to the Code group.
			current.Code += line + "\n"
		}
	}

	return append(sections, current)
}

// Apply markdown to each section's documentation.
func markdownComments(sections []*section) {
	for _, section := range sections {
		// IMHO BlackFriday should use a string interface, since it
		// operates on text (not arbitrary binary) data...
		section.Doc = string(blackfriday.MarkdownCommon([]byte(section.Doc)))
	}
}

// Apply syntax highlighting to each section's code.
func highlightCode(sections []*section) {
	// Rejoin the source code fragments, using sep as delimiter
	segments := make([]string, 0)
	for _, section := range sections {
		segments = append(segments, section.Code)
	}
	code := strings.Join(segments, sep)

	// Highlight the joined source
	h := litebrite.Highlighter{"operator", "ident", "literal", "keyword", "comment"}
	hlcode := h.Highlight(code)

	// Collect the code between subsequent `unsep`s
	matches := append(unsep.FindAllStringIndex(hlcode, -1), []int{len(hlcode), 0})
	lastend := 0
	for i, match := range matches {
		sections[i].Code = hlcode[lastend:match[0]]
		lastend = match[1]
	}
}

// ## Setup and running

// Locate the HTML template and CSS.
func findResources() string {
	if *resdir != "" {
		return *resdir
	}

	// find the path to the package root to locate the resource files
	p, err := build.Default.Import(pkg, "", build.FindOnly)
	if err != nil {
		panic(err.Error())
	}
	return p.Dir
}

// Load the HTML template
func loadTemplate(path string) {
	templ = template.Must(template.ParseFiles(path + string(os.PathSeparator) + tplfilename))
}

// copyFile copies the contents of src to dst atomically.
// Copied from github.com/pkg/fileutils/copy.go.
// (c) Dave Cheney - see LICENSE_CopyFile.txt.
func copyFile(dst, src string) error {
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	tmp, err := ioutil.TempFile(filepath.Dir(dst), "copyfile")
	if err != nil {
		return err
	}
	_, err = io.Copy(tmp, in)
	if err != nil {
		tmp.Close()
		os.Remove(tmp.Name())
		return err
	}
	if err := tmp.Close(); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	const perm = 0644
	if err := os.Chmod(tmp.Name(), perm); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	if err := os.Rename(tmp.Name(), dst); err != nil {
		os.Remove(tmp.Name())
		return err
	}
	return nil
}

// copyCssFile() copies
func copyCssFile() {
	// Copy only if dest path != source path
	src := path.Clean(*resdir)
	dst := path.Clean(*outdir + *csspath)
	if dst != src {
		err := copyFile(dst+string(os.PathSeparator)+cssfilename, src+string(os.PathSeparator)+cssfilename)
		if err != nil {
			panic(err.Error())
		}
	}
}

// Generate documentation for a source file.
func processFile(filename string) {
	src, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err.Error())
	}
	name := filepath.Base(filename)
	outname := filepath.Join(*outdir, name[:len(name)-2]) + "html"
	docs := GenerateDocs(name, string(src))
	err = ioutil.WriteFile(outname, []byte(docs), 0666)
	if err != nil {
		panic(err.Error())
	}
	copyCssFile()
}

func main() {
	flag.Parse()
	loadTemplate(findResources())
	for _, filename := range flag.Args() {
		processFile(filename)
	}
}
<|endoftext|>


<commit_before>// Package openfec implements a client library for OpenFEC
//
// See https://api.open.fec.gov
package openfec
<commit_msg>improve documentation<commit_after>// Package openfec implements a client library for OpenFEC
//
// See https://api.open.fec.gov
//
// Overview
//
// Endpoints are classified in the following groups: Candidate, Committee, Financial, Filings and Schedules.
//
// Candidate
//
// Candidate endpoints give you access to information about the people running for office.
// This information is organized by candidate_id. If you're unfamiliar with candidate IDs,
// using `/candidates/search` will help you locate a particular candidate.
//
// Officially, a candidate is an individual seeking nomination for election to a federal
// office. People become candidates when they (or agents working on their behalf)
// raise contributions or make expenditures that exceed $5,000.
//
// The candidate endpoints primarily use data from FEC registration
// [Form 1](http://www.fec.gov/pdf/forms/fecfrm1.pdf), for candidate information, and
// [Form 2](http://www.fec.gov/pdf/forms/fecfrm2.pdf), for committee information.
//
//
// Committee
//
// Committees are entities that spend and raise money in an election. Their characteristics and
// relationships with candidates can change over time.
//
// You might want to use filters or search endpoints to find the committee you're looking
// for. Then you can use other committee endpoints to explore information about the committee
// that interests you.
//
// Financial information is organized by `committee_id`, so finding the committee you're interested in
// will lead you to more granular financial information.
//
// The committee endpoints include all FEC filers, even if they aren't registered as a committee.
//
// Officially, committees include the committees and organizations that file with the FEC.
// Several different types of organizations file financial reports with the FEC:
//
// * Campaign committees authorized by particular candidates to raise and spend funds in
// their campaigns
// * Non-party committees (e.g., PACs), some of which may be sponsored by corporations,
// unions, trade or membership groups, etc.
// * Political party committees at the national, state, and local levels
// * Groups and individuals making only independent expenditures
// * Corporations, unions, and other organizations making internal communications
//
// The committee endpoints primarily use data from FEC registration Form 1 and Form 2.
//
// Financial
//
// Fetch key information about a committee's Form 3, Form 3X, or Form 3P financial reports.
//
// Most committees are required to summarize their financial activity in each filing; those summaries
// are included in these files. Generally, committees file reports on a quarterly or monthly basis, but
// some must also submit a report 12 days before primary elections. Therefore, during the primary
// season, the period covered by this file may be different for different committees. These totals
// also incorporate any changes made by committees, if any report covering the period is amended.
//
// Information is made available on the API as soon as it's processed. Keep in mind, complex
// paper filings take longer to process.
//
// The financial endpoints use data from FEC [form 5](http://www.fec.gov/pdf/forms/fecfrm5.pdf),
// for independent expenditors; or the summary and detailed summary pages of the FEC
// [form 3](http://www.fec.gov/pdf/forms/fecfrm3.pdf), for House and Senate committees;
// [form 3X](http://www.fec.gov/pdf/forms/fecfrm3x.pdf), for PACs and parties;
// and [form 3P](http://www.fec.gov/pdf/forms/fecfrm3p.pdf), for presidential committees.
//
// Filings
//
// All official records and reports filed by or delivered to the FEC.
//
// Note: because the filings data includes many records, counts for large
// result sets are approximate.
//
// Schedules
//
// Schedules come from particular sections on forms and contain detailed transactional data.
//
// Schedule A explains where contributions come from. If you are interested in
// individual donors, this will be the endpoint you use.
//
// For the Schedule A aggregates, "memoed" items are not included to avoid double counting.
//
// Schedule B explains how money is spent.
package openfec
<|endoftext|>


<commit_before>package next

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"reflect"
	"runtime"
	"time"
)

type Duo struct {
	Conn       map[string]*net.TCPConn
	Config     *Config
	Logger     *log.Logger
	routes     *Routes
	middleware []reflect.Value
}

const (
	DuoHead       = 0xEF
	DuoSec        = 0x01
	DuoMaxContent = 2 << 10
)

func NewDuo() *Duo {
	duo := &Duo{
		Conn:       make(map[string]*net.TCPConn),
		Config:     NewConfig(),
		Logger:     log.New(os.Stdout, "", log.Ldate|log.Ltime),
		routes:     NewRoutes(),
		middleware: make([]reflect.Value, 0),
	}

	// Load default config if exists
	file := "config.json"
	if fileExists(file) {
		duo.Config.Load(file)
	}

	return duo
}

// Pack is a utility function to read from the supplied Writer
// according to the Next protocol spec:
//
//    EF01[x][x][x][x][x][x][x][x][x]
//        |  | (binary)          |
//        |1-byte                | 1-byte
//      ---------------------------
//    head size       data        crc
func (t *Duo) Pack(w io.Writer, data []byte) error {
	// Head
	out := []byte{DuoHead, DuoSec}
	// Size
	out = append(out, byte(len(data)+2))
	// Data
	out = append(out, data...)
	// Tail
	out = append(out, t.crc(data))
	if _, err := w.Write(out); err != nil {
		return errors.New("write fail")
	}

	return nil
}

// CRC data code
// 100-(EF+01+X)%FF
func (t *Duo) crc(data []byte) byte {
	sum := DuoHead + DuoSec + len(data) + 2
	for _, d := range data {
		sum += int(d)
	}

	return byte(0x100 - sum%0xFF)
}

// Unpack is a utility function to read from the supplied Reader
// according to the Next protocol spec:
//
//    EF01[x][x][x][x][x][x][x][x][x]
//        |  | (binary)          |
//        |1-byte                | 1-byte
//      ---------------------------
//    head size       data        crc
func (t *Duo) Unpack(r io.Reader) ([]byte, error) {
	// Check head
	head := make([]byte, 2)
	_, err := r.Read(head)
	if err != nil {
		return nil, err
	}
	if int32(head[0]) != DuoHead && int32(head[1]) != DuoSec {
		return nil, errors.New("data head is error")
	}

	// message size
	s := make([]byte, 1)
	_, err = r.Read(s)
	if err != nil {
		return nil, err
	}
	size := int32(uint32(s[0]))
	size = size - 2
	if size <= 0 || size > TcpMaxContent {
		return nil, errors.New("data size is error")
	}

	// message binary data
	buf := make([]byte, size)
	_, err = r.Read(buf)
	if err != nil {
		return nil, err
	}

	// Check head
	tail := make([]byte, 1)
	_, err = r.Read(tail)
	if err != nil {
		return nil, err
	}
	if tail[0] != t.crc(buf) {
		// TODO
		//		return nil, errors.New("data tail is error")
	}

	//t.Logger.Printf("Head: %v, size: %v, buf: %v, Tail: %v", head, size, buf, tail)

	return buf, nil
}

func (t *Duo) handler(conn *net.TCPConn, body []byte) {
	requestPath := "device" // Hack for device sever

	ctx := DuoContext{
		Method: body[0],
		Params: body,
		Duo:    t,
		Fd:     t.Fd(conn),
		conn:   conn,
	}
	tm := time.Now().UTC()
	defer t.logRequest(ctx, tm)

	route := t.routes.Match(requestPath, "VIA")
	if route == nil {
		//ctx.WriteJSON("404", "request method not found")
		return
	}

	cr := route.cr

	var args []reflect.Value
	handlerType := route.handler.Type()
	if requiresDuoContext(handlerType) {
		args = append(args, reflect.ValueOf(&ctx))
	}

	match := cr.FindStringSubmatch(requestPath)
	for _, arg := range match[1:] {
		args = append(args, reflect.ValueOf(arg))
	}

	t.safelyCall(route.handler, args)
}

// Get the integer Unix file descriptor referencing the open file
func (t *Duo) Fd(conn *net.TCPConn) string {
	return conn.RemoteAddr().String()
}

func (t *Duo) Pipe(conn *net.TCPConn) {
	fd := t.Fd(conn)
	defer func() {
		t.Logger.Printf("disconnected: %s\n", fd)
		conn.Close()
		delete(t.Conn, fd)
	}()

	// Save in map
	t.Conn[fd] = conn

	// Read data
	reader := bufio.NewReader(conn)
	for {
		body, err := t.Unpack(reader)
		if err != nil {
			if err == io.EOF {
				return
			}
			t.Logger.Print(err)
		}
		if len(body) == 0 {
			continue
		}

		t.handler(conn, body)
		reader.Reset(conn)
	}
}

func (t *Duo) Run(addr string) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp", addr)
	tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
	defer tcpListener.Close()

	t.Logger.Printf("next duo serving %s\n", addr)

	// Run middleware
	go func() {
		for _, v := range t.middleware {
			var args []reflect.Value
			args = append(args, reflect.ValueOf(t))
			t.safelyCall(v, args)
		}
	}()

	// Run tcp listener
	for {
		tcpConn, err := tcpListener.AcceptTCP()
		if err != nil {
			continue
		}

		t.Logger.Printf("connected: %s\n", tcpConn.RemoteAddr().String())
		go t.Pipe(tcpConn)
	}
}

// Post adds a handler for the 'Via' TCP method for tcp.
func (t *Duo) Middleware(handler interface{}) {
	switch handler.(type) {
	case reflect.Value:
		fv := handler.(reflect.Value)
		t.middleware = append(t.middleware, fv)
	default:
		fv := reflect.ValueOf(handler)
		t.middleware = append(t.middleware, fv)
	}
}

// Post adds a handler for the 'Via' TCP method for tcp.
func (t *Duo) Via(route string, handler interface{}) {
	t.routes.Add(route, "VIA", handler)
}

func (t *Duo) Write(conn *net.TCPConn, code byte, data ...[]byte) {
	out := make([]byte, 0)

	out = append(out, code)
	if len(data) > 0 {
		out = append(out, data[0]...)
	}

	t.Pack(conn, out)
}

// safelyCall invokes `function` in recover block
func (t *Duo) safelyCall(function reflect.Value, args []reflect.Value) (resp []reflect.Value, e interface{}) {
	defer func() {
		if err := recover(); err != nil {
			if t.Config.Bool("panic") {
				// go back to panic
				panic(err)
			} else {
				e = err
				resp = nil
				t.Logger.Println("Handler crashed with error", err)
				for i := 1; ; i += 1 {
					_, file, line, ok := runtime.Caller(i)
					if !ok {
						break
					}
					t.Logger.Println(file, line)
				}
			}
		}
	}()
	return function.Call(args), nil
}

func (t *Duo) logRequest(ctx DuoContext, sTime time.Time) {
	//log the request
	var logEntry bytes.Buffer

	duration := time.Now().Sub(sTime)

	fmt.Fprintf(&logEntry, "%s - \033[32;1m TCP %x\033[0m - %v", ctx.Fd, ctx.Method, duration)

	if len(ctx.Params) > 0 {
		fmt.Fprintf(&logEntry, " - \033[37;1mParams: %v\033[0m\n", ctx.Params)
	}

	ctx.Duo.Logger.Print(logEntry.String())
}

// requiresContext determines whether 'handlerType' contains
// an argument to 'web.Ctx' as its first argument
func requiresDuoContext(handlerType reflect.Type) bool {
	//if the method doesn't take arguments, no
	if handlerType.NumIn() == 0 {
		return false
	}

	//if the first argument is not a pointer, no
	a0 := handlerType.In(0)
	if a0.Kind() != reflect.Ptr {
		return false
	}
	//if the first argument is a context, yes
	if a0.Elem() == reflect.TypeOf(DuoContext{}) {
		return true
	}

	return false
}

// --------
// Duo Context
// --------
type DuoContext struct {
	Method byte
	Params []byte
	Duo    *Duo
	Fd     string
	conn   *net.TCPConn
}

// Writes data into the response object.
func (ctx *DuoContext) Write(out []byte) {
	ctx.Duo.Pack(ctx.conn, out)
}
<commit_msg>add close when no ready from client<commit_after>package next

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"reflect"
	"runtime"
	"time"
)

type Duo struct {
	Conn       map[string]*net.TCPConn
	Config     *Config
	Logger     *log.Logger
	routes     *Routes
	middleware []reflect.Value
}

const (
	DuoHead       = 0xEF
	DuoSec        = 0x01
	DuoMaxContent = 2 << 10
)

func NewDuo() *Duo {
	duo := &Duo{
		Conn:       make(map[string]*net.TCPConn),
		Config:     NewConfig(),
		Logger:     log.New(os.Stdout, "", log.Ldate|log.Ltime),
		routes:     NewRoutes(),
		middleware: make([]reflect.Value, 0),
	}

	// Load default config if exists
	file := "config.json"
	if fileExists(file) {
		duo.Config.Load(file)
	}

	return duo
}

// Pack is a utility function to read from the supplied Writer
// according to the Next protocol spec:
//
//    EF01[x][x][x][x][x][x][x][x][x]
//        |  | (binary)          |
//        |1-byte                | 1-byte
//      ---------------------------
//    head size       data        crc
func (t *Duo) Pack(w io.Writer, data []byte) error {
	// Head
	out := []byte{DuoHead, DuoSec}
	// Size
	out = append(out, byte(len(data)+2))
	// Data
	out = append(out, data...)
	// Tail
	out = append(out, t.crc(data))
	if _, err := w.Write(out); err != nil {
		return errors.New("write fail")
	}

	return nil
}

// CRC data code
// 100-(EF+01+X)%FF
func (t *Duo) crc(data []byte) byte {
	sum := DuoHead + DuoSec + len(data) + 2
	for _, d := range data {
		sum += int(d)
	}

	return byte(0x100 - sum%0xFF)
}

// Unpack is a utility function to read from the supplied Reader
// according to the Next protocol spec:
//
//    EF01[x][x][x][x][x][x][x][x][x]
//        |  | (binary)          |
//        |1-byte                | 1-byte
//      ---------------------------
//    head size       data        crc
func (t *Duo) Unpack(r io.Reader) ([]byte, error) {
	// Check head
	head := make([]byte, 2)
	_, err := r.Read(head)
	if err != nil {
		return nil, err
	}
	if int32(head[0]) != DuoHead && int32(head[1]) != DuoSec {
		return nil, errors.New("data head is error")
	}

	// message size
	s := make([]byte, 1)
	_, err = r.Read(s)
	if err != nil {
		return nil, err
	}
	size := int32(uint32(s[0]))
	size = size - 2
	if size <= 0 || size > TcpMaxContent {
		return nil, errors.New("data size is error")
	}

	// message binary data
	buf := make([]byte, size)
	_, err = r.Read(buf)
	if err != nil {
		return nil, err
	}

	// Check head
	tail := make([]byte, 1)
	_, err = r.Read(tail)
	if err != nil {
		return nil, err
	}
	if tail[0] != t.crc(buf) {
		// TODO
		//		return nil, errors.New("data tail is error")
	}

	//t.Logger.Printf("Head: %v, size: %v, buf: %v, Tail: %v", head, size, buf, tail)

	return buf, nil
}

func (t *Duo) handler(conn *net.TCPConn, body []byte) {
	requestPath := "device" // Hack for device sever

	ctx := DuoContext{
		Method: body[0],
		Params: body,
		Duo:    t,
		Fd:     t.Fd(conn),
		conn:   conn,
	}
	tm := time.Now().UTC()
	defer t.logRequest(ctx, tm)

	route := t.routes.Match(requestPath, "VIA")
	if route == nil {
		//ctx.WriteJSON("404", "request method not found")
		return
	}

	cr := route.cr

	var args []reflect.Value
	handlerType := route.handler.Type()
	if requiresDuoContext(handlerType) {
		args = append(args, reflect.ValueOf(&ctx))
	}

	match := cr.FindStringSubmatch(requestPath)
	for _, arg := range match[1:] {
		args = append(args, reflect.ValueOf(arg))
	}

	t.safelyCall(route.handler, args)
}

// Get the integer Unix file descriptor referencing the open file
func (t *Duo) Fd(conn *net.TCPConn) string {
	return conn.RemoteAddr().String()
}

func (t *Duo) Pipe(conn *net.TCPConn) {
	fd := t.Fd(conn)
	defer func() {
		t.Logger.Printf("disconnected: %s\n", fd)
		conn.Close()
		delete(t.Conn, fd)
	}()

	// Save in map
	t.Conn[fd] = conn

	// Read data
	reader := bufio.NewReader(conn)
	for {
		body, err := t.Unpack(reader)
		if err != nil {
			if err == io.EOF {
				return
			}
			if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
				return
			}
			t.Logger.Print(err)
		}

		conn.SetReadDeadline(time.Now().Add(20 * time.Second))

		if len(body) == 0 {
			continue
		}

		t.handler(conn, body)
		reader.Reset(conn)
	}
}

func (t *Duo) Run(addr string) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp", addr)
	tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
	defer tcpListener.Close()

	t.Logger.Printf("next duo serving %s\n", addr)

	// Run middleware
	go func() {
		for _, v := range t.middleware {
			var args []reflect.Value
			args = append(args, reflect.ValueOf(t))
			t.safelyCall(v, args)
		}
	}()

	// Run tcp listener
	for {
		tcpConn, err := tcpListener.AcceptTCP()
		if err != nil {
			continue
		}

		t.Logger.Printf("connected: %s\n", tcpConn.RemoteAddr().String())
		go t.Pipe(tcpConn)
	}
}

// Post adds a handler for the 'Via' TCP method for tcp.
func (t *Duo) Middleware(handler interface{}) {
	switch handler.(type) {
	case reflect.Value:
		fv := handler.(reflect.Value)
		t.middleware = append(t.middleware, fv)
	default:
		fv := reflect.ValueOf(handler)
		t.middleware = append(t.middleware, fv)
	}
}

// Post adds a handler for the 'Via' TCP method for tcp.
func (t *Duo) Via(route string, handler interface{}) {
	t.routes.Add(route, "VIA", handler)
}

func (t *Duo) Write(conn *net.TCPConn, code byte, data ...[]byte) {
	out := make([]byte, 0)

	out = append(out, code)
	if len(data) > 0 {
		out = append(out, data[0]...)
	}

	t.Pack(conn, out)
}

// safelyCall invokes `function` in recover block
func (t *Duo) safelyCall(function reflect.Value, args []reflect.Value) (resp []reflect.Value, e interface{}) {
	defer func() {
		if err := recover(); err != nil {
			if t.Config.Bool("panic") {
				// go back to panic
				panic(err)
			} else {
				e = err
				resp = nil
				t.Logger.Println("Handler crashed with error", err)
				for i := 1; ; i += 1 {
					_, file, line, ok := runtime.Caller(i)
					if !ok {
						break
					}
					t.Logger.Println(file, line)
				}
			}
		}
	}()
	return function.Call(args), nil
}

func (t *Duo) logRequest(ctx DuoContext, sTime time.Time) {
	//log the request
	var logEntry bytes.Buffer

	duration := time.Now().Sub(sTime)

	fmt.Fprintf(&logEntry, "%s - \033[32;1m TCP %x\033[0m - %v", ctx.Fd, ctx.Method, duration)

	if len(ctx.Params) > 0 {
		fmt.Fprintf(&logEntry, " - \033[37;1mParams: %v\033[0m\n", ctx.Params)
	}

	ctx.Duo.Logger.Print(logEntry.String())
}

// requiresContext determines whether 'handlerType' contains
// an argument to 'web.Ctx' as its first argument
func requiresDuoContext(handlerType reflect.Type) bool {
	//if the method doesn't take arguments, no
	if handlerType.NumIn() == 0 {
		return false
	}

	//if the first argument is not a pointer, no
	a0 := handlerType.In(0)
	if a0.Kind() != reflect.Ptr {
		return false
	}
	//if the first argument is a context, yes
	if a0.Elem() == reflect.TypeOf(DuoContext{}) {
		return true
	}

	return false
}

// --------
// Duo Context
// --------
type DuoContext struct {
	Method byte
	Params []byte
	Duo    *Duo
	Fd     string
	conn   *net.TCPConn
}

// Writes data into the response object.
func (ctx *DuoContext) Write(out []byte) {
	ctx.Duo.Pack(ctx.conn, out)
}
<|endoftext|>


<commit_before>package main

import "bufio"
import "fmt"
import "encoding/csv"
import "io"
import "os"

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func parse_file(filename string) ([]string, []string, []string) {
	f, err := os.Open(filename)
	check(err)
	defer f.Close()

	var column_names []string
	var units []string
	var descriptions []string

	r := csv.NewReader(bufio.NewReader(f))
	r.Comma = ';'
RECORDS:
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}

		headers := []*[]string{
			&column_names,
			&units,
			&descriptions,
		}

		for _, target := range headers {
			if *target == nil {
				*target = make([]string, len(record))
				copy(*target, record)
				continue RECORDS
			}
		}
	}

	return column_names, units, descriptions
}

func main() {
	column_names, units, descriptions := parse_file("example_headers")
	fmt.Println(column_names)
	fmt.Println(units)
	fmt.Println(descriptions)
}
<commit_msg>Add command-line argument to choose filename.<commit_after>package main

import "bufio"
import "gopkg.in/alecthomas/kingpin.v2"
import "fmt"
import "encoding/csv"
import "io"
import "os"

var (
	filename = kingpin.Arg("filename", "Filename to load").Required().String()
)

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func parse_file(filename string) ([]string, []string, []string) {
	f, err := os.Open(filename)
	check(err)
	defer f.Close()

	var column_names []string
	var units []string
	var descriptions []string

	r := csv.NewReader(bufio.NewReader(f))
	r.Comma = ';'
RECORDS:
	for {
		record, err := r.Read()
		if err == io.EOF {
			break
		}

		headers := []*[]string{
			&column_names,
			&units,
			&descriptions,
		}

		for _, target := range headers {
			if *target == nil {
				*target = make([]string, len(record))
				copy(*target, record)
				continue RECORDS
			}
		}
	}

	return column_names, units, descriptions
}

func main() {
	kingpin.Parse()
	column_names, units, descriptions := parse_file(*filename)
	fmt.Println(column_names)
	fmt.Println(units)
	fmt.Println(descriptions)
}
<|endoftext|>


<commit_before>package sgload

import (
	"bytes"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
)

type SGDataStore struct {
	MaxConcurrentHttpClients chan struct{} // TODO: currenty ignored
	SyncGatewayUrl           string
}

func NewSGDataStore(sgUrl string, maxConcurrentHttpClients chan struct{}) *SGDataStore {

	return &SGDataStore{
		MaxConcurrentHttpClients: maxConcurrentHttpClients,
		SyncGatewayUrl:           sgUrl,
	}
}

func (s SGDataStore) CreateUser(u UserCred) error {

	return nil
}

func (s SGDataStore) CreateDocument(d Document) error {

	// TODO: need to add BasicAuth header for user?

	docBytes, err := json.Marshal(d)
	if err != nil {
		return err
	}
	buf := bytes.NewBuffer(docBytes)
	resp, err := http.Post(s.SyncGatewayUrl, "application/json", buf)
	if err != nil {
		return err
	}
	io.Copy(ioutil.Discard, resp.Body)
	resp.Body.Close()

	return nil
}
<commit_msg>Successfully posts to sync gw<commit_after>package sgload

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

type SGDataStore struct {
	MaxConcurrentHttpClients chan struct{} // TODO: currenty ignored
	SyncGatewayUrl           string
}

func NewSGDataStore(sgUrl string, maxConcurrentHttpClients chan struct{}) *SGDataStore {

	return &SGDataStore{
		MaxConcurrentHttpClients: maxConcurrentHttpClients,
		SyncGatewayUrl:           sgUrl,
	}
}

func (s SGDataStore) CreateUser(u UserCred) error {

	return nil
}

func (s SGDataStore) CreateDocument(d Document) error {

	// TODO: need to add BasicAuth header for user?

	docBytes, err := json.Marshal(d)
	if err != nil {
		return err
	}
	buf := bytes.NewBuffer(docBytes)
	resp, err := http.Post(s.SyncGatewayUrl, "application/json", buf)
	if err != nil {
		return err
	}
	if resp.StatusCode < 200 || resp.StatusCode > 201 {
		return fmt.Errorf("Unexpected response status for POST request: %d", resp.StatusCode)
	}

	io.Copy(ioutil.Discard, resp.Body)
	resp.Body.Close()

	return nil
}
<|endoftext|>


<commit_before>package instana

import (
	"bytes"
	"io/ioutil"
	"sort"
	"strings"
)

const eumTemplate string = "eum.js"

// EumSnippet generates javascript code to initialize JavaScript agent
func EumSnippet(apiKey string, traceID string, meta map[string]string) string {

	if len(apiKey) == 0 || len(traceID) == 0 {
		return ""
	}

	b, err := ioutil.ReadFile(eumTemplate)
	if err != nil {
		return ""
	}

	snippet := strings.Replace(string(b), "$apiKey", apiKey, -1)
	snippet = strings.Replace(snippet, "$traceId", traceID, -1)

	var keys []string
	for k := range meta {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var metaBuffer bytes.Buffer
	for _, k := range keys {
		metaBuffer.WriteString("ineum('meta','" + k + "','" + meta[k] + "');")
	}

	snippet = strings.Replace(snippet, "$meta", metaBuffer.String(), -1)

	return snippet
}
<commit_msg>Deprecate instana.EumSnippet()<commit_after>package instana

import (
	"bytes"
	"io/ioutil"
	"sort"
	"strings"
)

const eumTemplate string = "eum.js"

// EumSnippet generates javascript code to initialize JavaScript agent
//
// Deprecated: this snippet is outdated and this method will be removed in
// the next major version. To learn about the way to install Instana EUM snippet
// please refer to https://docs.instana.io/products/website_monitoring/#installation
func EumSnippet(apiKey string, traceID string, meta map[string]string) string {

	if len(apiKey) == 0 || len(traceID) == 0 {
		return ""
	}

	b, err := ioutil.ReadFile(eumTemplate)
	if err != nil {
		return ""
	}

	snippet := strings.Replace(string(b), "$apiKey", apiKey, -1)
	snippet = strings.Replace(snippet, "$traceId", traceID, -1)

	var keys []string
	for k := range meta {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var metaBuffer bytes.Buffer
	for _, k := range keys {
		metaBuffer.WriteString("ineum('meta','" + k + "','" + meta[k] + "');")
	}

	snippet = strings.Replace(snippet, "$meta", metaBuffer.String(), -1)

	return snippet
}
<|endoftext|>


<commit_before>package main

import (
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var cmdFix = &Command{
	UsageLine: "fix",
	Short:     "fix the beego application to compatibel with beego 1.6",
	Long: `
As from beego1.6, there's some incompatible code with the old version.

bee fix help to upgrade the application to beego 1.6
`,
}

func init() {
	cmdFix.Run = runFix
}

func runFix(cmd *Command, args []string) int {
	dir, err := os.Getwd()
	if err != nil {
		ColorLog("GetCurrent Path:%s\n", err)
	}
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if strings.HasPrefix(info.Name(), ".") {
				return filepath.SkipDir
			}
			return nil
		}
		if err != nil {
			return err
		}
		if strings.HasSuffix(info.Name(), ".exe") {
			return nil
		}
		ColorLog("%s\n", path)
		err = fixFile(path)
		if err != nil {
			ColorLog("fixFile:%s\n", err)
		}
		return err
	})
	return 0
}

var rules = []string{
	"beego.AppName", "beego.BConfig.AppName",
	"beego.RunMode", "beego.BConfig.RunMode",
	"beego.RecoverPanic", "beego.BConfig.RecoverPanic",
	"beego.RouterCaseSensitive", "beego.BConfig.RouterCaseSensitive",
	"beego.BeegoServerName", "beego.BConfig.ServerName",
	"beego.EnableGzip", "beego.BConfig.EnableGzip",
	"beego.ErrorsShow", "beego.BConfig.EnableErrorsShow",
	"beego.CopyRequestBody", "beego.BConfig.CopyRequestBody",
	"beego.MaxMemory", "beego.BConfig.MaxMemory",
	"beego.Graceful", "beego.BConfig.Listen.Graceful",
	"beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr",
	"beego.HttpPort", "beego.BConfig.Listen.HTTPPort",
	"beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4",
	"beego.EnableHttpListen", "beego.BConfig.Listen.HTTPEnable",
	"beego.EnableHttpTLS", "beego.BConfig.Listen.HTTPSEnable",
	"beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr",
	"beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort",
	"beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile",
	"beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile",
	"beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable",
	"beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr",
	"beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort",
	"beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi",
	"beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut",
	"beego.AutoRender", "beego.BConfig.WebConfig.AutoRender",
	"beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath",
	"beego.StaticDir", "beego.BConfig.WebConfig.StaticDir",
	"beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip",
	"beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex",
	"beego.FlashName", "beego.BConfig.WebConfig.FlashName",
	"beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeparator",
	"beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs",
	"beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKey",
	"beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF",
	"beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire",
	"beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft",
	"beego.TemplateRight", "beego.BConfig.WebConfig.TemplateRight",
	"beego.SessionOn", "beego.BConfig.WebConfig.Session.SessionOn",
	"beego.SessionProvider", "beego.BConfig.WebConfig.Session.SessionProvider",
	"beego.SessionName", "beego.BConfig.WebConfig.Session.SessionName",
	"beego.SessionGCMaxLifetime", "beego.BConfig.WebConfig.Session.SessionGCMaxLifetime",
	"beego.SessionSavePath", "beego.BConfig.WebConfig.Session.SessionProviderConfig",
	"beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime",
	"beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie",
	"beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain",
	"Ctx.Input.CopyBody(", "Ctx.Input.CopyBody(beego.BConfig.MaxMemory",
	".UrlFor(", ".URLFor(",
	".ServeJson(", ".ServeJSON(",
	".ServeXml(", ".ServeXML(",
	".ServeJsonp(", ".ServeJSONP(",
	".XsrfToken(", ".XSRFToken(",
	".CheckXsrfCookie(", ".CheckXSRFCookie(",
	".XsrfFormHtml(", ".XSRFFormHTML(",
	"beego.UrlFor(", "beego.URLFor(",
	"beego.GlobalDocApi", "beego.GlobalDocAPI",
	"beego.Errorhandler", "beego.ErrorHandler",
	"Output.Jsonp(", "Output.JSONP(",
	"Output.Json(", "Output.JSON(",
	"Output.Xml(", "Output.XML(",
	"Input.Uri()", "Input.URI()",
	"Input.Url()", "Input.URL()",
	"Input.AcceptsHtml()", "Input.AcceptsHTML()",
	"Input.AcceptsXml()", "Input.AcceptsXML()",
	"Input.AcceptsJson()", "Input.AcceptsJSON()",
	"Ctx.XsrfToken()", "Ctx.XSRFToken()",
	"Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()",
	"session.SessionStore", "session.Store",
	".TplNames", ".TplName",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.ApiDeclaration", "swagger.APIDeclaration",
	"swagger.Api", "swagger.API",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.Infomation", "swagger.Information",
	"toolbox.UrlMap", "toolbox.URLMap",
	"logs.LoggerInterface", "logs.Logger",
	"Input.Request", "Input.Context.Request",
	"Input.Params)", "Input.Params())",
	"httplib.BeegoHttpSettings", "httplib.BeegoHTTPSettings",
	"httplib.BeegoHttpRequest", "httplib.BeegoHTTPRequest",
	".TlsClientConfig", ".TLSClientConfig",
	".JsonBody", ".JSONBody",
	".ToJson", ".ToJSON",
	".ToXml", ".ToXML",
	"beego.Html2str", "beego.HTML2str",
	"beego.AssetsCss", "beego.AssetsCSS",
	"orm.DR_Sqlite", "orm.DRSqlite",
	"orm.DR_Postgres", "orm.DRPostgres",
	"orm.DR_MySQL", "orm.DRMySQL",
	"orm.DR_Oracle", "orm.DROracle",
	"orm.Col_Add", "orm.ColAdd",
	"orm.Col_Minus", "orm.ColMinus",
	"orm.Col_Multiply", "orm.ColMultiply",
	"orm.Col_Except", "orm.ColExcept",
	"GenerateOperatorSql", "GenerateOperatorSQL",
	"OperatorSql", "OperatorSQL",
	"orm.Debug_Queries", "orm.DebugQueries",
	"orm.COMMA_SPACE", "orm.CommaSpace",
	".SendOut()", ".DoRequest()",
	"validation.ValidationError", "validation.Error",
}

func fixFile(file string) error {
	rp := strings.NewReplacer(rules...)
	content, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	fixed := rp.Replace(string(content))

	// forword the RequestBody from the replace
	// "Input.Request", "Input.Context.Request",
	fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1)

	// regexp replace
	pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`)
	fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")")
	// fix the cache object Put method
	pareg = regexp.MustCompile(`(\.Put\(\")(.*)(\",)(\s)(.*)(,\s*)([^\*.]*)(\))`)
	if pareg.MatchString(fixed) && strings.HasSuffix(file, ".go") {
		fixed = pareg.ReplaceAllString(fixed, ".Put(\"$2\", $5, $7*time.Second)")
		fset := token.NewFileSet() // positions are relative to fset
		f, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly)
		if err != nil {
			panic(err)
		}
		// Print the imports from the file's AST.
		hasTimepkg := false
		for _, s := range f.Imports {
			if s.Path.Value == `"time"` {
				hasTimepkg = true
				break
			}
		}
		if !hasTimepkg {
			fixed = strings.Replace(fixed, "import (", "import (\n\t\"time\"", 1)
		}
	}
	// replace the v.Apis in docs.go
	if strings.Contains(file, "docs.go") {
		fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1)
	}
	// replace the config file
	if strings.HasSuffix(file, ".conf") {
		fixed = strings.Replace(fixed, "HttpCertFile", "HTTPSCertFile", -1)
		fixed = strings.Replace(fixed, "HttpKeyFile", "HTTPSKeyFile", -1)
		fixed = strings.Replace(fixed, "EnableHttpListen", "HTTPEnable", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "BeegoServerName", "ServerName", -1)
		fixed = strings.Replace(fixed, "AdminHttpAddr", "AdminAddr", -1)
		fixed = strings.Replace(fixed, "AdminHttpPort", "AdminPort", -1)
		fixed = strings.Replace(fixed, "HttpServerTimeOut", "ServerTimeOut", -1)
	}
	err = os.Truncate(file, 0)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, []byte(fixed), 0666)
}
<commit_msg>fix #1663<commit_after>package main

import (
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var cmdFix = &Command{
	UsageLine: "fix",
	Short:     "fix the beego application to compatibel with beego 1.6",
	Long: `
As from beego1.6, there's some incompatible code with the old version.

bee fix help to upgrade the application to beego 1.6
`,
}

func init() {
	cmdFix.Run = runFix
}

func runFix(cmd *Command, args []string) int {
	dir, err := os.Getwd()
	if err != nil {
		ColorLog("GetCurrent Path:%s\n", err)
	}
	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if strings.HasPrefix(info.Name(), ".") {
				return filepath.SkipDir
			}
			return nil
		}
		if err != nil {
			return err
		}
		if strings.HasSuffix(info.Name(), ".exe") {
			return nil
		}
		ColorLog("%s\n", path)
		err = fixFile(path)
		if err != nil {
			ColorLog("fixFile:%s\n", err)
		}
		return err
	})
	return 0
}

var rules = []string{
	"beego.AppName", "beego.BConfig.AppName",
	"beego.RunMode", "beego.BConfig.RunMode",
	"beego.RecoverPanic", "beego.BConfig.RecoverPanic",
	"beego.RouterCaseSensitive", "beego.BConfig.RouterCaseSensitive",
	"beego.BeegoServerName", "beego.BConfig.ServerName",
	"beego.EnableGzip", "beego.BConfig.EnableGzip",
	"beego.ErrorsShow", "beego.BConfig.EnableErrorsShow",
	"beego.CopyRequestBody", "beego.BConfig.CopyRequestBody",
	"beego.MaxMemory", "beego.BConfig.MaxMemory",
	"beego.Graceful", "beego.BConfig.Listen.Graceful",
	"beego.HttpAddr", "beego.BConfig.Listen.HTTPAddr",
	"beego.HttpPort", "beego.BConfig.Listen.HTTPPort",
	"beego.ListenTCP4", "beego.BConfig.Listen.ListenTCP4",
	"beego.EnableHttpListen", "beego.BConfig.Listen.EnableHTTP",
	"beego.EnableHttpTLS", "beego.BConfig.Listen.EnableHTTPS",
	"beego.HttpsAddr", "beego.BConfig.Listen.HTTPSAddr",
	"beego.HttpsPort", "beego.BConfig.Listen.HTTPSPort",
	"beego.HttpCertFile", "beego.BConfig.Listen.HTTPSCertFile",
	"beego.HttpKeyFile", "beego.BConfig.Listen.HTTPSKeyFile",
	"beego.EnableAdmin", "beego.BConfig.Listen.AdminEnable",
	"beego.AdminHttpAddr", "beego.BConfig.Listen.AdminAddr",
	"beego.AdminHttpPort", "beego.BConfig.Listen.AdminPort",
	"beego.UseFcgi", "beego.BConfig.Listen.EnableFcgi",
	"beego.HttpServerTimeOut", "beego.BConfig.Listen.ServerTimeOut",
	"beego.AutoRender", "beego.BConfig.WebConfig.AutoRender",
	"beego.ViewsPath", "beego.BConfig.WebConfig.ViewsPath",
	"beego.StaticDir", "beego.BConfig.WebConfig.StaticDir",
	"beego.StaticExtensionsToGzip", "beego.BConfig.WebConfig.StaticExtensionsToGzip",
	"beego.DirectoryIndex", "beego.BConfig.WebConfig.DirectoryIndex",
	"beego.FlashName", "beego.BConfig.WebConfig.FlashName",
	"beego.FlashSeperator", "beego.BConfig.WebConfig.FlashSeparator",
	"beego.EnableDocs", "beego.BConfig.WebConfig.EnableDocs",
	"beego.XSRFKEY", "beego.BConfig.WebConfig.XSRFKey",
	"beego.EnableXSRF", "beego.BConfig.WebConfig.EnableXSRF",
	"beego.XSRFExpire", "beego.BConfig.WebConfig.XSRFExpire",
	"beego.TemplateLeft", "beego.BConfig.WebConfig.TemplateLeft",
	"beego.TemplateRight", "beego.BConfig.WebConfig.TemplateRight",
	"beego.SessionOn", "beego.BConfig.WebConfig.Session.SessionOn",
	"beego.SessionProvider", "beego.BConfig.WebConfig.Session.SessionProvider",
	"beego.SessionName", "beego.BConfig.WebConfig.Session.SessionName",
	"beego.SessionGCMaxLifetime", "beego.BConfig.WebConfig.Session.SessionGCMaxLifetime",
	"beego.SessionSavePath", "beego.BConfig.WebConfig.Session.SessionProviderConfig",
	"beego.SessionCookieLifeTime", "beego.BConfig.WebConfig.Session.SessionCookieLifeTime",
	"beego.SessionAutoSetCookie", "beego.BConfig.WebConfig.Session.SessionAutoSetCookie",
	"beego.SessionDomain", "beego.BConfig.WebConfig.Session.SessionDomain",
	"Ctx.Input.CopyBody(", "Ctx.Input.CopyBody(beego.BConfig.MaxMemory",
	".UrlFor(", ".URLFor(",
	".ServeJson(", ".ServeJSON(",
	".ServeXml(", ".ServeXML(",
	".ServeJsonp(", ".ServeJSONP(",
	".XsrfToken(", ".XSRFToken(",
	".CheckXsrfCookie(", ".CheckXSRFCookie(",
	".XsrfFormHtml(", ".XSRFFormHTML(",
	"beego.UrlFor(", "beego.URLFor(",
	"beego.GlobalDocApi", "beego.GlobalDocAPI",
	"beego.Errorhandler", "beego.ErrorHandler",
	"Output.Jsonp(", "Output.JSONP(",
	"Output.Json(", "Output.JSON(",
	"Output.Xml(", "Output.XML(",
	"Input.Uri()", "Input.URI()",
	"Input.Url()", "Input.URL()",
	"Input.AcceptsHtml()", "Input.AcceptsHTML()",
	"Input.AcceptsXml()", "Input.AcceptsXML()",
	"Input.AcceptsJson()", "Input.AcceptsJSON()",
	"Ctx.XsrfToken()", "Ctx.XSRFToken()",
	"Ctx.CheckXsrfCookie()", "Ctx.CheckXSRFCookie()",
	"session.SessionStore", "session.Store",
	".TplNames", ".TplName",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.ApiDeclaration", "swagger.APIDeclaration",
	"swagger.Api", "swagger.API",
	"swagger.ApiRef", "swagger.APIRef",
	"swagger.Infomation", "swagger.Information",
	"toolbox.UrlMap", "toolbox.URLMap",
	"logs.LoggerInterface", "logs.Logger",
	"Input.Request", "Input.Context.Request",
	"Input.Params)", "Input.Params())",
	"httplib.BeegoHttpSettings", "httplib.BeegoHTTPSettings",
	"httplib.BeegoHttpRequest", "httplib.BeegoHTTPRequest",
	".TlsClientConfig", ".TLSClientConfig",
	".JsonBody", ".JSONBody",
	".ToJson", ".ToJSON",
	".ToXml", ".ToXML",
	"beego.Html2str", "beego.HTML2str",
	"beego.AssetsCss", "beego.AssetsCSS",
	"orm.DR_Sqlite", "orm.DRSqlite",
	"orm.DR_Postgres", "orm.DRPostgres",
	"orm.DR_MySQL", "orm.DRMySQL",
	"orm.DR_Oracle", "orm.DROracle",
	"orm.Col_Add", "orm.ColAdd",
	"orm.Col_Minus", "orm.ColMinus",
	"orm.Col_Multiply", "orm.ColMultiply",
	"orm.Col_Except", "orm.ColExcept",
	"GenerateOperatorSql", "GenerateOperatorSQL",
	"OperatorSql", "OperatorSQL",
	"orm.Debug_Queries", "orm.DebugQueries",
	"orm.COMMA_SPACE", "orm.CommaSpace",
	".SendOut()", ".DoRequest()",
	"validation.ValidationError", "validation.Error",
}

func fixFile(file string) error {
	rp := strings.NewReplacer(rules...)
	content, err := ioutil.ReadFile(file)
	if err != nil {
		return err
	}
	fixed := rp.Replace(string(content))

	// forword the RequestBody from the replace
	// "Input.Request", "Input.Context.Request",
	fixed = strings.Replace(fixed, "Input.Context.RequestBody", "Input.RequestBody", -1)

	// regexp replace
	pareg := regexp.MustCompile(`(Input.Params\[")(.*)("])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Param(\"$2\")")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])(\s)(=)(\s)(.*)`)
	fixed = pareg.ReplaceAllString(fixed, "Input.SetData(\"$2\", $7)")
	pareg = regexp.MustCompile(`(Input.Data\[\")(.*)(\"\])`)
	fixed = pareg.ReplaceAllString(fixed, "Input.Data(\"$2\")")
	// fix the cache object Put method
	pareg = regexp.MustCompile(`(\.Put\(\")(.*)(\",)(\s)(.*)(,\s*)([^\*.]*)(\))`)
	if pareg.MatchString(fixed) && strings.HasSuffix(file, ".go") {
		fixed = pareg.ReplaceAllString(fixed, ".Put(\"$2\", $5, $7*time.Second)")
		fset := token.NewFileSet() // positions are relative to fset
		f, err := parser.ParseFile(fset, file, nil, parser.ImportsOnly)
		if err != nil {
			panic(err)
		}
		// Print the imports from the file's AST.
		hasTimepkg := false
		for _, s := range f.Imports {
			if s.Path.Value == `"time"` {
				hasTimepkg = true
				break
			}
		}
		if !hasTimepkg {
			fixed = strings.Replace(fixed, "import (", "import (\n\t\"time\"", 1)
		}
	}
	// replace the v.Apis in docs.go
	if strings.Contains(file, "docs.go") {
		fixed = strings.Replace(fixed, "v.Apis", "v.APIs", -1)
	}
	// replace the config file
	if strings.HasSuffix(file, ".conf") {
		fixed = strings.Replace(fixed, "HttpCertFile", "HTTPSCertFile", -1)
		fixed = strings.Replace(fixed, "HttpKeyFile", "HTTPSKeyFile", -1)
		fixed = strings.Replace(fixed, "EnableHttpListen", "HTTPEnable", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "EnableHttpTLS", "EnableHTTPS", -1)
		fixed = strings.Replace(fixed, "BeegoServerName", "ServerName", -1)
		fixed = strings.Replace(fixed, "AdminHttpAddr", "AdminAddr", -1)
		fixed = strings.Replace(fixed, "AdminHttpPort", "AdminPort", -1)
		fixed = strings.Replace(fixed, "HttpServerTimeOut", "ServerTimeOut", -1)
	}
	err = os.Truncate(file, 0)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(file, []byte(fixed), 0666)
}
<|endoftext|>


<commit_before>package notifiers

import (
	"encoding/json"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/alerting"
)

func init() {
	alerting.RegisterNotifier(&alerting.NotifierPlugin{
		Type:        "teams",
		Name:        "Microsoft Teams",
		Description: "Sends notifications using Incomming Webhook connector to Microsoft Teams",
		Factory:     NewTeamsNotifier,
		OptionsTemplate: `

Teams settings

        Url
        <input type="text" required class="gf-form-input max-width-30" ng-model="ctrl.model.settings.url" placeholder="Teams incoming webhook url"></input>

    `,
	})

}

func NewTeamsNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
	url := model.Settings.Get("url").MustString()
	if url == "" {
		return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
	}

	return &TeamsNotifier{
		NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
		Url:          url,
		log:          log.New("alerting.notifier.teams"),
	}, nil
}

type TeamsNotifier struct {
	NotifierBase
	Url       string
	Recipient string
	Mention   string
	log       log.Logger
}

func (this *TeamsNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Executing teams notification", "ruleId", evalContext.Rule.Id, "notification", this.Name)

	ruleUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed get rule link", "error", err)
		return err
	}

	fields := make([]map[string]interface{}, 0)
	fieldLimitCount := 4
	for index, evt := range evalContext.EvalMatches {
		fields = append(fields, map[string]interface{}{
			"name":  evt.Metric,
			"value": evt.Value,
		})
		if index > fieldLimitCount {
			break
		}
	}

	if evalContext.Error != nil {
		fields = append(fields, map[string]interface{}{
			"name":  "Error message",
			"value": evalContext.Error.Error(),
		})
	}

	message := this.Mention
	if evalContext.Rule.State != m.AlertStateOK { //dont add message when going back to alert state ok.
		message += " " + evalContext.Rule.Message
	}

	body := map[string]interface{}{
		"@type":      "MessageCard",
		"@context":   "http://schema.org/extensions",
		"summary":    message,
		"title":      evalContext.GetNotificationTitle(),
		"themeColor": evalContext.GetStateModel().Color,
		"sections": []map[string]interface{}{
			{
				"title": "Details",
				"facts": fields,
				"images": []map[string]interface{}{
					{
						"image": evalContext.ImagePublicUrl,
					},
				},
				"text": message,
				"potentialAction": []map[string]interface{}{
					{
						"@context": "http://schema.org",
						"@type":    "ViewAction",
						"name":     "View Rule",
						"target": []string{
							ruleUrl,
						},
					},
				},
			},
		},
	}

	data, _ := json.Marshal(&body)
	print(string(data))
	cmd := &m.SendWebhookSync{Url: this.Url, Body: string(data)}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send teams notification", "error", err, "webhook", this.Name)
		return err
	}

	return nil
}
<commit_msg>teams: removes print statement<commit_after>package notifiers

import (
	"encoding/json"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/alerting"
)

func init() {
	alerting.RegisterNotifier(&alerting.NotifierPlugin{
		Type:        "teams",
		Name:        "Microsoft Teams",
		Description: "Sends notifications using Incomming Webhook connector to Microsoft Teams",
		Factory:     NewTeamsNotifier,
		OptionsTemplate: `

Teams settings

        Url
        <input type="text" required class="gf-form-input max-width-30" ng-model="ctrl.model.settings.url" placeholder="Teams incoming webhook url"></input>

    `,
	})

}

func NewTeamsNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
	url := model.Settings.Get("url").MustString()
	if url == "" {
		return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
	}

	return &TeamsNotifier{
		NotifierBase: NewNotifierBase(model.Id, model.IsDefault, model.Name, model.Type, model.Settings),
		Url:          url,
		log:          log.New("alerting.notifier.teams"),
	}, nil
}

type TeamsNotifier struct {
	NotifierBase
	Url       string
	Recipient string
	Mention   string
	log       log.Logger
}

func (this *TeamsNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Executing teams notification", "ruleId", evalContext.Rule.Id, "notification", this.Name)

	ruleUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed get rule link", "error", err)
		return err
	}

	fields := make([]map[string]interface{}, 0)
	fieldLimitCount := 4
	for index, evt := range evalContext.EvalMatches {
		fields = append(fields, map[string]interface{}{
			"name":  evt.Metric,
			"value": evt.Value,
		})
		if index > fieldLimitCount {
			break
		}
	}

	if evalContext.Error != nil {
		fields = append(fields, map[string]interface{}{
			"name":  "Error message",
			"value": evalContext.Error.Error(),
		})
	}

	message := this.Mention
	if evalContext.Rule.State != m.AlertStateOK { //dont add message when going back to alert state ok.
		message += " " + evalContext.Rule.Message
	}

	body := map[string]interface{}{
		"@type":      "MessageCard",
		"@context":   "http://schema.org/extensions",
		"summary":    message,
		"title":      evalContext.GetNotificationTitle(),
		"themeColor": evalContext.GetStateModel().Color,
		"sections": []map[string]interface{}{
			{
				"title": "Details",
				"facts": fields,
				"images": []map[string]interface{}{
					{
						"image": evalContext.ImagePublicUrl,
					},
				},
				"text": message,
				"potentialAction": []map[string]interface{}{
					{
						"@context": "http://schema.org",
						"@type":    "ViewAction",
						"name":     "View Rule",
						"target": []string{
							ruleUrl,
						},
					},
				},
			},
		},
	}

	data, _ := json.Marshal(&body)
	cmd := &m.SendWebhookSync{Url: this.Url, Body: string(data)}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send teams notification", "error", err, "webhook", this.Name)
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Skaffold Authors

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

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

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

package fsnotify

import (
	"context"
	"io"
	"path/filepath"
	"time"

	"github.com/rjeczalik/notify"
	"github.com/sirupsen/logrus"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
)

// For testing
var (
	Watch = notify.Watch
)

func New(workspaces map[string]struct{}, isActive func() bool, duration int) *Trigger {
	return &Trigger{
		Interval:   time.Duration(duration) * time.Millisecond,
		workspaces: workspaces,
		isActive:   isActive,
		watchFunc:  Watch,
	}
}

// Trigger watches for changes with fsnotify
type Trigger struct {
	Interval   time.Duration
	workspaces map[string]struct{}
	isActive   func() bool
	watchFunc  func(path string, c chan<- notify.EventInfo, events ...notify.Event) error
}

// IsActive returns the function to run if Trigger is active.
func (t *Trigger) IsActive() func() bool {
	return t.isActive
}

// Debounce tells the watcher to not debounce rapid sequence of changes.
func (t *Trigger) Debounce() bool {
	// This trigger has built-in debouncing.
	return false
}

func (t *Trigger) LogWatchToUser(out io.Writer) {
	if t.isActive() {
		output.Yellow.Fprintln(out, "Watching for changes...")
	} else {
		output.Yellow.Fprintln(out, "Not watching for changes...")
	}
}

// Start listening for file system changes
func (t *Trigger) Start(ctx context.Context) (<-chan bool, error) {
	c := make(chan notify.EventInfo, 100)

	// Workaround https://github.com/rjeczalik/notify/issues/96
	wd, err := util.RealWorkDir()
	if err != nil {
		return nil, err
	}

	// Watch current directory recursively
	if err := t.watchFunc(filepath.Join(wd, "..."), c, notify.All); err != nil {
		return nil, err
	}

	// Watch all workspaces recursively
	for w := range t.workspaces {
		if w == "." {
			continue
		}

		if err := t.watchFunc(filepath.Join(wd, w, "..."), c, notify.All); err != nil {
			return nil, err
		}
	}

	// Since the file watcher runs in a separate go routine
	// and can take some time to start, it can lose the very first change.
	// As a mitigation, we act as if a change was detected.
	go func() { c <- nil }()

	trigger := make(chan bool)
	go func() {
		timer := time.NewTimer(1<<63 - 1) // Forever

		for {
			select {
			case e := <-c:

				// Ignore detected changes if not active or to be ignore.
				if !t.isActive() && t.Ignore(e) {
					continue
				}
				logrus.Debugln("Change detected", e)

				// Wait t.Ienterval before triggering.
				// This way, rapid stream of events will be grouped.
				timer.Reset(t.Interval)
			case <-timer.C:
				trigger <- true
			case <-ctx.Done():
				timer.Stop()
				return
			}
		}
	}()

	return trigger, nil
}

// Ignore checks if the change detected is to be ignored or not.
// Currently, returns false i.e Allows all files changed.
func (t *Trigger) Ignore(_ notify.EventInfo) bool {
	return false
}
<commit_msg>Fix couldn't start notify trigger in multi-config projects (#6114)<commit_after>/*
Copyright 2020 The Skaffold Authors

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

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

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

package fsnotify

import (
	"context"
	"io"
	"path/filepath"
	"time"

	"github.com/rjeczalik/notify"
	"github.com/sirupsen/logrus"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
)

// For testing
var (
	Watch = notify.Watch
)

func New(workspaces map[string]struct{}, isActive func() bool, duration int) *Trigger {
	return &Trigger{
		Interval:   time.Duration(duration) * time.Millisecond,
		workspaces: workspaces,
		isActive:   isActive,
		watchFunc:  Watch,
	}
}

// Trigger watches for changes with fsnotify
type Trigger struct {
	Interval   time.Duration
	workspaces map[string]struct{}
	isActive   func() bool
	watchFunc  func(path string, c chan<- notify.EventInfo, events ...notify.Event) error
}

// IsActive returns the function to run if Trigger is active.
func (t *Trigger) IsActive() func() bool {
	return t.isActive
}

// Debounce tells the watcher to not debounce rapid sequence of changes.
func (t *Trigger) Debounce() bool {
	// This trigger has built-in debouncing.
	return false
}

func (t *Trigger) LogWatchToUser(out io.Writer) {
	if t.isActive() {
		output.Yellow.Fprintln(out, "Watching for changes...")
	} else {
		output.Yellow.Fprintln(out, "Not watching for changes...")
	}
}

// Start listening for file system changes
func (t *Trigger) Start(ctx context.Context) (<-chan bool, error) {
	c := make(chan notify.EventInfo, 100)

	// Workaround https://github.com/rjeczalik/notify/issues/96
	wd, err := util.RealWorkDir()
	if err != nil {
		return nil, err
	}

	// Watch current directory recursively
	if err := t.watchFunc(filepath.Join(wd, "..."), c, notify.All); err != nil {
		return nil, err
	}

	// Watch all workspaces recursively
	for w := range t.workspaces {
		if w == "." {
			continue
		}

		// Workspace paths may already have been converted to absolute paths (e.g. in a multi-config project).
		var path string
		if filepath.IsAbs(w) {
			path = w
		} else {
			path = filepath.Join(wd, w)
		}

		if err := t.watchFunc(filepath.Join(path, "..."), c, notify.All); err != nil {
			return nil, err
		}
	}

	// Since the file watcher runs in a separate go routine
	// and can take some time to start, it can lose the very first change.
	// As a mitigation, we act as if a change was detected.
	go func() { c <- nil }()

	trigger := make(chan bool)
	go func() {
		timer := time.NewTimer(1<<63 - 1) // Forever

		for {
			select {
			case e := <-c:

				// Ignore detected changes if not active or to be ignore.
				if !t.isActive() && t.Ignore(e) {
					continue
				}
				logrus.Debugln("Change detected", e)

				// Wait t.Ienterval before triggering.
				// This way, rapid stream of events will be grouped.
				timer.Reset(t.Interval)
			case <-timer.C:
				trigger <- true
			case <-ctx.Done():
				timer.Stop()
				return
			}
		}
	}()

	return trigger, nil
}

// Ignore checks if the change detected is to be ignored or not.
// Currently, returns false i.e Allows all files changed.
func (t *Trigger) Ignore(_ notify.EventInfo) bool {
	return false
}
<|endoftext|>


<commit_before><commit_msg>sql: added a test for distsql index backfill<commit_after><|endoftext|>


<commit_before>package cache

import (
	"encoding/xml"
	"github.com/rgbkrk/libvirt-go"
	kubeapi "k8s.io/client-go/pkg/api"
	kubev1 "k8s.io/client-go/pkg/api/v1"
	metav1 "k8s.io/client-go/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/runtime"
	"k8s.io/client-go/pkg/types"
	"k8s.io/client-go/pkg/watch"
	"k8s.io/client-go/tools/cache"
	kubevirt "kubevirt.io/kubevirt/pkg/virt-handler/virtwrap"
)

// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace and field selector.
func NewListWatchFromClient(c kubevirt.Connection, events ...int) *cache.ListWatch {
	if len(events) == 0 {
		events = []int{libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE}
	}
	listFunc := func(options kubev1.ListOptions) (runtime.Object, error) {
		doms, err := c.ListAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE | libvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE)
		if err != nil {
			return nil, err
		}
		list := kubevirt.DomainList{
			Items: []kubevirt.Domain{},
		}
		for _, dom := range doms {
			domain, err := NewDomain(dom)
			if err != nil {
				return nil, err
			}
			spec, err := NewDomainSpec(dom)
			if err != nil {
				return nil, err
			}
			domain.Spec = *spec
			status, err := dom.GetState()
			if err != nil {
				return nil, err
			}
			domain.Status.Status = kubevirt.LifeCycleTranslationMap[status[0]]
			list.Items = append(list.Items, *domain)
		}

		return &list, nil
	}
	watchFunc := func(options kubev1.ListOptions) (watch.Interface, error) {
		return NewDomainWatcher(c, events...)
	}
	return &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
}

type DomainWatcher struct {
	C chan watch.Event
}

func (d *DomainWatcher) Stop() {

}

func (d *DomainWatcher) ResultChan() <-chan watch.Event {
	return d.C
}

func NewDomainWatcher(c kubevirt.Connection, events ...int) (watch.Interface, error) {
	watcher := &DomainWatcher{C: make(chan watch.Event)}
	callback := libvirt.DomainEventCallback(
		func(c *libvirt.VirConnection, d *libvirt.VirDomain, eventDetails interface{}, _ func()) int {
			domain, err := NewDomain(d)
			if err != nil {
				// TODO proper logging
				// FIXME like described below libvirt needs to send the xml along side with the event. When this is done we can return an error
				// watcher.C <- watch.Event{Type: watch.Error, Object: &Domain{}}
				return 0
			}
			// TODO In case of other events, it might not be enough to just send state and domainxml, maybe we have to embed the event and the details too
			//      Think about device removal: First event is a DEFINED/UPDATED event and then we get the REMOVED event when it is done (is it that way?)
			e, ok := eventDetails.(libvirt.DomainLifecycleEvent)
			if ok {
				switch e.Event {

				case libvirt.VIR_DOMAIN_EVENT_STOPPED,
					libvirt.VIR_DOMAIN_EVENT_SHUTDOWN,
					libvirt.VIR_DOMAIN_EVENT_CRASHED,
					libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
					// We can't count on a domain xml in these cases, but let's try it
					if e.Event != libvirt.VIR_DOMAIN_EVENT_UNDEFINED {
						spec, err := NewDomainSpec(d)
						if err != nil {
							// TODO proper logging
						} else {
							domain.Spec = *spec
						}
					}
					status, err := d.GetState()
					if err != nil {
						// TODO proper logging
						domain.Status.Status = kubevirt.NoState
					} else {
						domain.Status.Status = kubevirt.LifeCycleTranslationMap[status[0]]
					}
				default:
					// TODO libvirt is racy there, between an event and fetching a domain xml everything can happen
					//      that is why we can't just report an error here, on the next resync we can compensate this missed event
					// TODO Fix libvirt regarding to event order and domain xml availability. Sometimes when a VM is defined the domainxml can't yet be fetched
					//      Libvirt is inherently inconsistent, see https://www.redhat.com/archives/libvir-list/2016-November/msg01318.html
					//      To fix this, an event should send its state and the current domain xml
					spec, err := NewDomainSpec(d)
					if err != nil {
						// TODO proper logging
						return 0
					}
					domain.Spec = *spec
					status, err := d.GetState()
					if err != nil {
						// TODO proper logging
						return 0
					}
					domain.Status.Status = kubevirt.LifeCycleTranslationMap[status[0]]
				}

				switch e.Event {
				case libvirt.VIR_DOMAIN_EVENT_DEFINED:
					if e.Detail == libvirt.VIR_DOMAIN_EVENT_DEFINED_ADDED {
						watcher.C <- watch.Event{Type: watch.Added, Object: domain}
					} else {
						watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
					}
				case libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
					watcher.C <- watch.Event{Type: watch.Deleted, Object: domain}
				default:
					watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
				}
			} else {
				watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
			}
			return 0
		})
	for _, event := range events {
		c.DomainEventRegister(libvirt.VirDomain{}, event, &callback, nil)
	}
	return watcher, nil
}

func NewDomainSpec(dom kubevirt.VirDomain) (*kubevirt.DomainSpec, error) {
	domain := kubevirt.DomainSpec{}
	domxml, err := dom.GetXMLDesc(libvirt.VIR_DOMAIN_XML_MIGRATABLE)
	if err != nil {
		return nil, err
	}
	err = xml.Unmarshal([]byte(domxml), &domain)
	if err != nil {
		return nil, err
	}

	return &domain, nil
}

func NewDomain(dom kubevirt.VirDomain) (*kubevirt.Domain, error) {
	name, err := dom.GetName()
	if err != nil {
		return nil, err
	}
	uuid, err := dom.GetUUIDString()
	if err != nil {
		return nil, err
	}
	return &kubevirt.Domain{
		Spec: kubevirt.DomainSpec{},
		ObjectMeta: kubeapi.ObjectMeta{
			Name:      name,
			UID:       types.UID(uuid),
			Namespace: kubeapi.NamespaceDefault,
		},
		Status: kubevirt.DomainStatus{},
		TypeMeta: metav1.TypeMeta{
			APIVersion: "1.2.2",
			Kind:       "Domain",
		},
	}, nil
}

func NewDomainCache(c kubevirt.Connection) (cache.SharedInformer, error) {
	domainCacheSource := NewListWatchFromClient(c, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE)
	informer := cache.NewSharedInformer(domainCacheSource, &kubevirt.Domain{}, 0)
	return informer, nil
}
<commit_msg>change kubevirt to virtwrap in cache.go<commit_after>package cache

import (
	"encoding/xml"
	"github.com/rgbkrk/libvirt-go"
	kubeapi "k8s.io/client-go/pkg/api"
	kubev1 "k8s.io/client-go/pkg/api/v1"
	metav1 "k8s.io/client-go/pkg/apis/meta/v1"
	"k8s.io/client-go/pkg/runtime"
	"k8s.io/client-go/pkg/types"
	"k8s.io/client-go/pkg/watch"
	"k8s.io/client-go/tools/cache"
	"kubevirt.io/kubevirt/pkg/virt-handler/virtwrap"
)

// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace and field selector.
func NewListWatchFromClient(c virtwrap.Connection, events ...int) *cache.ListWatch {
	if len(events) == 0 {
		events = []int{libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE}
	}
	listFunc := func(options kubev1.ListOptions) (runtime.Object, error) {
		doms, err := c.ListAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE | libvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE)
		if err != nil {
			return nil, err
		}
		list := virtwrap.DomainList{
			Items: []virtwrap.Domain{},
		}
		for _, dom := range doms {
			domain, err := NewDomain(dom)
			if err != nil {
				return nil, err
			}
			spec, err := NewDomainSpec(dom)
			if err != nil {
				return nil, err
			}
			domain.Spec = *spec
			status, err := dom.GetState()
			if err != nil {
				return nil, err
			}
			domain.Status.Status = virtwrap.LifeCycleTranslationMap[status[0]]
			list.Items = append(list.Items, *domain)
		}

		return &list, nil
	}
	watchFunc := func(options kubev1.ListOptions) (watch.Interface, error) {
		return NewDomainWatcher(c, events...)
	}
	return &cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
}

type DomainWatcher struct {
	C chan watch.Event
}

func (d *DomainWatcher) Stop() {

}

func (d *DomainWatcher) ResultChan() <-chan watch.Event {
	return d.C
}

func NewDomainWatcher(c virtwrap.Connection, events ...int) (watch.Interface, error) {
	watcher := &DomainWatcher{C: make(chan watch.Event)}
	callback := libvirt.DomainEventCallback(
		func(c *libvirt.VirConnection, d *libvirt.VirDomain, eventDetails interface{}, _ func()) int {
			domain, err := NewDomain(d)
			if err != nil {
				// TODO proper logging
				// FIXME like described below libvirt needs to send the xml along side with the event. When this is done we can return an error
				// watcher.C <- watch.Event{Type: watch.Error, Object: &Domain{}}
				return 0
			}
			// TODO In case of other events, it might not be enough to just send state and domainxml, maybe we have to embed the event and the details too
			//      Think about device removal: First event is a DEFINED/UPDATED event and then we get the REMOVED event when it is done (is it that way?)
			e, ok := eventDetails.(libvirt.DomainLifecycleEvent)
			if ok {
				switch e.Event {

				case libvirt.VIR_DOMAIN_EVENT_STOPPED,
					libvirt.VIR_DOMAIN_EVENT_SHUTDOWN,
					libvirt.VIR_DOMAIN_EVENT_CRASHED,
					libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
					// We can't count on a domain xml in these cases, but let's try it
					if e.Event != libvirt.VIR_DOMAIN_EVENT_UNDEFINED {
						spec, err := NewDomainSpec(d)
						if err != nil {
							// TODO proper logging
						} else {
							domain.Spec = *spec
						}
					}
					status, err := d.GetState()
					if err != nil {
						// TODO proper logging
						domain.Status.Status = virtwrap.NoState
					} else {
						domain.Status.Status = virtwrap.LifeCycleTranslationMap[status[0]]
					}
				default:
					// TODO libvirt is racy there, between an event and fetching a domain xml everything can happen
					//      that is why we can't just report an error here, on the next resync we can compensate this missed event
					// TODO Fix libvirt regarding to event order and domain xml availability. Sometimes when a VM is defined the domainxml can't yet be fetched
					//      Libvirt is inherently inconsistent, see https://www.redhat.com/archives/libvir-list/2016-November/msg01318.html
					//      To fix this, an event should send its state and the current domain xml
					spec, err := NewDomainSpec(d)
					if err != nil {
						// TODO proper logging
						return 0
					}
					domain.Spec = *spec
					status, err := d.GetState()
					if err != nil {
						// TODO proper logging
						return 0
					}
					domain.Status.Status = virtwrap.LifeCycleTranslationMap[status[0]]
				}

				switch e.Event {
				case libvirt.VIR_DOMAIN_EVENT_DEFINED:
					if e.Detail == libvirt.VIR_DOMAIN_EVENT_DEFINED_ADDED {
						watcher.C <- watch.Event{Type: watch.Added, Object: domain}
					} else {
						watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
					}
				case libvirt.VIR_DOMAIN_EVENT_UNDEFINED:
					watcher.C <- watch.Event{Type: watch.Deleted, Object: domain}
				default:
					watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
				}
			} else {
				watcher.C <- watch.Event{Type: watch.Modified, Object: domain}
			}
			return 0
		})
	for _, event := range events {
		c.DomainEventRegister(libvirt.VirDomain{}, event, &callback, nil)
	}
	return watcher, nil
}

func NewDomainSpec(dom virtwrap.VirDomain) (*virtwrap.DomainSpec, error) {
	domain := virtwrap.DomainSpec{}
	domxml, err := dom.GetXMLDesc(libvirt.VIR_DOMAIN_XML_MIGRATABLE)
	if err != nil {
		return nil, err
	}
	err = xml.Unmarshal([]byte(domxml), &domain)
	if err != nil {
		return nil, err
	}

	return &domain, nil
}

func NewDomain(dom virtwrap.VirDomain) (*virtwrap.Domain, error) {
	name, err := dom.GetName()
	if err != nil {
		return nil, err
	}
	uuid, err := dom.GetUUIDString()
	if err != nil {
		return nil, err
	}
	return &virtwrap.Domain{
		Spec: virtwrap.DomainSpec{},
		ObjectMeta: kubeapi.ObjectMeta{
			Name:      name,
			UID:       types.UID(uuid),
			Namespace: kubeapi.NamespaceDefault,
		},
		Status: virtwrap.DomainStatus{},
		TypeMeta: metav1.TypeMeta{
			APIVersion: "1.2.2",
			Kind:       "Domain",
		},
	}, nil
}

func NewDomainCache(c virtwrap.Connection) (cache.SharedInformer, error) {
	domainCacheSource := NewListWatchFromClient(c, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE)
	informer := cache.NewSharedInformer(domainCacheSource, &virtwrap.Domain{}, 0)
	return informer, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

const (
	ansiEraseDisplay = "\033[2J"
	ansiResetCursor  = "\033[H"
	carriageReturn   = "\015"
)

var originalSttyState bytes.Buffer
var winRows uint16
var winCols uint16

func getSttyState(state *bytes.Buffer) (err error) {
	cmd := exec.Command("stty", "-g")
	cmd.Stdin = os.Stdin
	cmd.Stdout = state
	return cmd.Run()
}

func setSttyState(state *bytes.Buffer) (err error) {
	cmd := exec.Command("stty", state.String())
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func drawInitialScreen() (err error) {
	_, err = io.WriteString(os.Stdout, ansiEraseDisplay)
	if err != nil {
		return err
	}
	_, err = io.WriteString(os.Stdout, ansiResetCursor)

	return err
}

func setCursorPos(line int, col int) (err error) {
	str := fmt.Sprintf("\033[%d;%dH", line+1, col+1)
	_, err = io.WriteString(os.Stdout, str)
	return err
}

type winsize struct {
	rows, cols, xpixel, ypixel uint16
}

func getWinsize() winsize {
	ws := winsize{}
	syscall.Syscall(syscall.SYS_IOCTL,
		uintptr(0), uintptr(syscall.TIOCGWINSZ),
		uintptr(unsafe.Pointer(&ws)))
	return ws
}

func init() {
	ws := getWinsize()
	winRows = ws.rows
	winCols = ws.cols
}

func main() {
	err := getSttyState(&originalSttyState)
	if err != nil {
		log.Fatal(err)
	}
	defer setSttyState(&originalSttyState)

	setSttyState(bytes.NewBufferString("cbreak"))
	setSttyState(bytes.NewBufferString("-echo"))

	var input []byte = make([]byte, 0)
	var b []byte = make([]byte, 1)

	// TODO: Do not print results and input to STDOUT, only to TTY, only print
	// selected result to STDOUT

	// TODO: Run command in the background, draw as long as no new input given
	// if input is given, cancel command in background

	// TODO: Only print as many result lines as we have lines on the screen

	for {
		// Clear screen and set cursor to first row, first col
		err = drawInitialScreen()
		if err != nil {
			log.Fatal(err)
		}

		// Print prompt with already typed input
		prompt := fmt.Sprintf(">> %s", input[:len(input)])
		fmt.Printf("%s", prompt)

		fmt.Printf("\n")

		// Print results
		// TODO: move this in a goroutine, give it a quit-channel, stream the output
		// to the current position (line after prompt)
		iname := fmt.Sprintf("*%s*", input[:len(input)])
		out, err := exec.Command("find", ".", "-iname", iname).Output()
		if err != nil {
			log.Fatal(err)
		}
		outb := bytes.NewBuffer(out)
		outr := bufio.NewReader(outb)
		for i := 0; i < int(winRows)-2; i++ {
			line, err := outr.ReadBytes('\n')
			if err != nil && err != io.EOF {
				log.Fatal(err)
			}
			fmt.Printf("%s", line)
		}

		// Jump back to last typing position
		setCursorPos(0, len(prompt))

		os.Stdin.Read(b)
		switch b[0] {
		case 127:
			// Backspace
			if len(input) > 0 {
				input = input[:len(input)-1]
			}
		case 4, 13:
			// Return or Ctrl-D
			fmt.Println("Result:")
			fmt.Printf("%s%s\n", carriageReturn, string(input[:len(input)]))
			return
		default:
			// TODO: Default is wrong here. Only append printable characters to
			// input

			// TODO: Send a signal through the quit channel to the command in the background,
			// to cancel it
			// Everything else
			input = append(input, b...)
		}
	}
}
<commit_msg>Only run command when input is given<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"syscall"
	"unsafe"
)

const (
	ansiEraseDisplay = "\033[2J"
	ansiResetCursor  = "\033[H"
	carriageReturn   = "\015"
)

var originalSttyState bytes.Buffer
var winRows uint16
var winCols uint16

func getSttyState(state *bytes.Buffer) (err error) {
	cmd := exec.Command("stty", "-g")
	cmd.Stdin = os.Stdin
	cmd.Stdout = state
	return cmd.Run()
}

func setSttyState(state *bytes.Buffer) (err error) {
	cmd := exec.Command("stty", state.String())
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func drawInitialScreen() (err error) {
	_, err = io.WriteString(os.Stdout, ansiEraseDisplay)
	if err != nil {
		return err
	}
	_, err = io.WriteString(os.Stdout, ansiResetCursor)

	return err
}

func setCursorPos(line int, col int) (err error) {
	str := fmt.Sprintf("\033[%d;%dH", line+1, col+1)
	_, err = io.WriteString(os.Stdout, str)
	return err
}

type winsize struct {
	rows, cols, xpixel, ypixel uint16
}

func getWinsize() winsize {
	ws := winsize{}
	syscall.Syscall(syscall.SYS_IOCTL,
		uintptr(0), uintptr(syscall.TIOCGWINSZ),
		uintptr(unsafe.Pointer(&ws)))
	return ws
}

func init() {
	ws := getWinsize()
	winRows = ws.rows
	winCols = ws.cols
}

func main() {
	err := getSttyState(&originalSttyState)
	if err != nil {
		log.Fatal(err)
	}
	defer setSttyState(&originalSttyState)

	setSttyState(bytes.NewBufferString("cbreak"))
	setSttyState(bytes.NewBufferString("-echo"))

	var input []byte = make([]byte, 0)
	var b []byte = make([]byte, 1)

	// TODO: Do not print results and input to STDOUT, only to TTY, only print
	// selected result to STDOUT

	// TODO: Run command in the background, draw as long as no new input given
	// if input is given, cancel command in background

	// TODO: Only print as many result lines as we have lines on the screen

	for {
		// Clear screen and set cursor to first row, first col
		err = drawInitialScreen()
		if err != nil {
			log.Fatal(err)
		}

		// Print prompt with already typed input
		prompt := fmt.Sprintf(">> %s", input[:len(input)])
		fmt.Printf("%s", prompt)

		if len(input) > 0 {
			fmt.Printf("\n")

			// Print results
			// TODO: move this in a goroutine, give it a quit-channel, stream the output
			// to the current position (line after prompt)
			arg := fmt.Sprintf("%s", input[:len(input)])
			out, err := exec.Command("ag", arg).Output()
			if err != nil {
				log.Fatal(err)
			}
			outb := bytes.NewBuffer(out)
			outr := bufio.NewReader(outb)
			for i := 0; i < int(winRows)-2; i++ {
				line, err := outr.ReadBytes('\n')
				if err != nil && err != io.EOF {
					log.Fatal(err)
				}
				fmt.Printf("%s", line)
			}

			// Jump back to last typing position
			setCursorPos(0, len(prompt))
		}

		os.Stdin.Read(b)
		switch b[0] {
		case 127:
			// Backspace
			if len(input) > 0 {
				input = input[:len(input)-1]
			}
		case 4, 13:
			// Return or Ctrl-D
			fmt.Println("Result:")
			fmt.Printf("%s%s\n", carriageReturn, string(input[:len(input)]))
			return
		default:
			// TODO: Default is wrong here. Only append printable characters to
			// input

			// TODO: Send a signal through the quit channel to the command in the background,
			// to cancel it
			// Everything else
			input = append(input, b...)
		}
	}
}
<|endoftext|>


<commit_before>// 27 september 2014

package main

import (
	// ...
)

type GCC struct {
	CC		string
	CXX		string
	LD		string
	LDCXX	string
	RC		string
	ArchFlag	string
}

func (g *GCC) buildRegularFile(cc string, std string, cflags []string, filename string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		cc,
		filename,
		"-c",
		std,
		"-Wall",
		"-Wextra",
		// for the case where we are implementing an interface and are not using some parameter
		"-Wno-unused-parameter",
		g.ArchFlag,
	}, cflags...)
	if *debug {
		line = append(line, "-g")
	}
	line = append(line, "-o", object)
	e := &Executor{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		nil,
		Stage{e},
		nil,
	}
	return stages, object
}

func (g *GCC) BuildCFile(filename string, cflags []string) (stages []Stage, object string) {
	return g.buildRegularFile(
		g.CC,
		"--std=c99",		// I refuse to support C11.
		cflags,
		filename)
}

func (g *GCC) BuildCXXFile(filename string, cflags []string) (stages []Stage, object string) {
	g.LD = g.LDCXX
	return g.buildRegularFile(
		g.CXX,
		"--std=c++11",
		cflags,
		filename)
}

// TODO .m, .mm

func (g *GCC) BuildRCFile(filename string, cflags []string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		g.RC,
		filename,
		object,
	}, cflags...)
	e := &Executor{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		nil,
		Stage{e},
		nil,
	}
	return stages, object
}

func (g *GCC) Link(objects []string, ldflags []string, libs []string) *Executor {
	target := targetName()
	for i := 0; i < len(libs); i++ {
		libs[i] = "-l" + libs[i]
	}
	line := append([]string{
		g.LD,
		g.ArchFlag,
	}, objects...)
	line = append(line, ldflags...)
	line = append(line, libs...)
	if *debug {
		line = append(line, "-g")
	}
	line = append(line, "-o", target)
	return &Executor{
		Name:	"Linking " + target,
		Line:		line,
	}
}

// TODO:
// - MinGW static libgcc/libsjlj/libwinpthread/etc.

func init() {
	toolchains["gcc"] = make(map[string]Toolchain)
	toolchains["gcc"]["386"] = &GCC{
		CC:			"gcc",
		CXX:			"g++",
		LD:			"gcc",
		LDCXX:		"g++",
		RC:			"windres",		// TODO arch flag?
		ArchFlag:		"-m32",
	}
	toolchains["gcc"]["amd64"] = &GCC{
		CC:			"gcc",
		CXX:			"g++",
		LD:			"gcc",
		LDCXX:		"g++",
		RC:			"windres",		// TODO arch flag?
		ArchFlag:		"-m64",
	}
	toolchains["clang"] = make(map[string]Toolchain)
	toolchains["clang"]["386"] = &GCC{
		CC:			"clang",
		CXX:			"clang++",
		LD:			"clang",
		LDCXX:		"clang++",
		// TODO RC
		ArchFlag:		"-m32",
	}
	toolchains["clang"]["amd64"] = &GCC{
		CC:			"clang",
		CXX:			"clang++",
		LD:			"clang",
		LDCXX:		"clang++",
		// TODO RC
		ArchFlag:		"-m64",
	}
	toolchains["mingwcc"] = make(map[string]Toolchain)
	toolchains["mingwcc"]["386"] = &GCC{
		CC:			"i686-w64-mingw32-gcc",
		CXX:			"i686-w64-mingw32-g++",
		LD:			"i686-w64-mingw32-gcc",
		LDCXX:		"i686-w64-mingw32-g++",
		RC:			"i686-w64-mingw32-windres",
		ArchFlag:		"-m32",
	}
	toolchains["mingwcc"]["amd64"] = &GCC{
		CC:			"x86_64-w64-mingw32-gcc",
		CXX:			"x86_64-w64-mingw32-g++",
		LD:			"x86_64-w64-mingw32-gcc",
		LDCXX:		"x86_64-w64-mingw32-g++",
		RC:			"x86_64-w64-mingw32-windres",
		ArchFlag:		"-m64",
	}
}
<commit_msg>More TODOs.<commit_after>// 27 september 2014

package main

import (
	// ...
)

type GCC struct {
	CC		string
	CXX		string
	LD		string
	LDCXX	string
	RC		string
	ArchFlag	string
}

func (g *GCC) buildRegularFile(cc string, std string, cflags []string, filename string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		cc,
		filename,
		"-c",
		std,
		"-Wall",
		"-Wextra",
		// for the case where we are implementing an interface and are not using some parameter
		"-Wno-unused-parameter",
		g.ArchFlag,
	}, cflags...)
	if *debug {
		line = append(line, "-g")
	}
	line = append(line, "-o", object)
	e := &Executor{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		nil,
		Stage{e},
		nil,
	}
	return stages, object
}

func (g *GCC) BuildCFile(filename string, cflags []string) (stages []Stage, object string) {
	return g.buildRegularFile(
		g.CC,
		"--std=c99",		// I refuse to support C11.
		cflags,
		filename)
}

func (g *GCC) BuildCXXFile(filename string, cflags []string) (stages []Stage, object string) {
	g.LD = g.LDCXX
	return g.buildRegularFile(
		g.CXX,
		"--std=c++11",
		cflags,
		filename)
}

// TODO .m, .mm
// apart from needing -lobjc at link time, this is identical to C/C++; the --std flags are the same (thanks Beelsebob in irc.freenode.net/#macdev)

func (g *GCC) BuildRCFile(filename string, cflags []string) (stages []Stage, object string) {
	object = objectName(filename, ".o")
	line := append([]string{
		g.RC,
		filename,
		object,
	}, cflags...)
	e := &Executor{
		Name:	"Compiled " + filename,
		Line:		line,
	}
	stages = []Stage{
		nil,
		Stage{e},
		nil,
	}
	return stages, object
}

func (g *GCC) Link(objects []string, ldflags []string, libs []string) *Executor {
	target := targetName()
	for i := 0; i < len(libs); i++ {
		libs[i] = "-l" + libs[i]
	}
	line := append([]string{
		g.LD,
		g.ArchFlag,
	}, objects...)
	line = append(line, ldflags...)
	line = append(line, libs...)
	if *debug {
		line = append(line, "-g")
	}
	line = append(line, "-o", target)
	return &Executor{
		Name:	"Linking " + target,
		Line:		line,
	}
}

// TODO:
// - MinGW static libgcc/libsjlj/libwinpthread/etc.

func init() {
	toolchains["gcc"] = make(map[string]Toolchain)
	toolchains["gcc"]["386"] = &GCC{
		CC:			"gcc",
		CXX:			"g++",
		LD:			"gcc",
		LDCXX:		"g++",
		RC:			"windres",		// TODO arch flag?
		ArchFlag:		"-m32",
	}
	toolchains["gcc"]["amd64"] = &GCC{
		CC:			"gcc",
		CXX:			"g++",
		LD:			"gcc",
		LDCXX:		"g++",
		RC:			"windres",		// TODO arch flag?
		ArchFlag:		"-m64",
	}
	toolchains["clang"] = make(map[string]Toolchain)
	toolchains["clang"]["386"] = &GCC{
		CC:			"clang",
		CXX:			"clang++",
		LD:			"clang",
		LDCXX:		"clang++",
		// TODO RC
		ArchFlag:		"-m32",
	}
	toolchains["clang"]["amd64"] = &GCC{
		CC:			"clang",
		CXX:			"clang++",
		LD:			"clang",
		LDCXX:		"clang++",
		// TODO RC
		ArchFlag:		"-m64",
	}
	toolchains["mingwcc"] = make(map[string]Toolchain)
	toolchains["mingwcc"]["386"] = &GCC{
		CC:			"i686-w64-mingw32-gcc",
		CXX:			"i686-w64-mingw32-g++",
		LD:			"i686-w64-mingw32-gcc",
		LDCXX:		"i686-w64-mingw32-g++",
		RC:			"i686-w64-mingw32-windres",
		ArchFlag:		"-m32",
	}
	toolchains["mingwcc"]["amd64"] = &GCC{
		CC:			"x86_64-w64-mingw32-gcc",
		CXX:			"x86_64-w64-mingw32-g++",
		LD:			"x86_64-w64-mingw32-gcc",
		LDCXX:		"x86_64-w64-mingw32-g++",
		RC:			"x86_64-w64-mingw32-windres",
		ArchFlag:		"-m64",
	}
}
<|endoftext|>