<commit_before>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package sh

import (
	"fmt"
	"io"
	"strings"
)

func Fprint(w io.Writer, n Node) error {
	p := printer{
		w:       w,
		curLine: 1,
	}
	if f, ok := n.(File); ok {
		p.comments = f.Comments
	}
	p.node(n)
	return p.err
}

type printer struct {
	w   io.Writer
	err error

	contiguous bool

	curLine int
	level   int

	comments []Comment

	compactArithm bool
}

var (
	contiguousRight = map[Token]bool{
		DOLLPR:  true,
		LPAREN:  true,
		DLPAREN: true,
		BQUOTE:  true,
		CMDIN:   true,
		DOLLDP:  true,
	}
	contiguousLeft = map[Token]bool{
		SEMICOLON:  true,
		DSEMICOLON: true,
		RPAREN:     true,
		DRPAREN:    true,
		COMMA:      true,
	}
)

func (p *printer) space(b byte) {
	if p.err != nil {
		return
	}
	_, p.err = p.w.Write([]byte{b})
	p.contiguous = false
}

func (p *printer) nonSpaced(a ...interface{}) {
	for _, v := range a {
		if p.err != nil {
			break
		}
		switch x := v.(type) {
		case string:
			if len(x) > 0 {
				last := x[len(x)-1]
				p.contiguous = !space[last]
			}
			_, p.err = io.WriteString(p.w, x)
			p.curLine += strings.Count(x, "\n")
		case Comment:
			p.contiguous = true
			_, p.err = fmt.Fprint(p.w, HASH, x.Text)
		case Token:
			p.contiguous = !contiguousRight[x]
			_, p.err = fmt.Fprint(p.w, x)
		case Node:
			p.node(x)
		}
	}
}

func (p *printer) spaced(a ...interface{}) {
	for _, v := range a {
		if v == nil {
			continue
		}
		if t, ok := v.(Token); ok && contiguousLeft[t] {
		} else if p.contiguous {
			p.space(' ')
		}
		p.nonSpaced(v)
	}
}

func (p *printer) indent() {
	for i := 0; i < p.level; i++ {
		p.space('\t')
	}
}

func (p *printer) separate(pos Pos, fallback, allowTwo bool) {
	p.addComments(pos)
	if pos.Line > p.curLine {
		p.space('\n')
		if allowTwo && pos.Line > p.curLine+1 {
			// preserve single empty lines
			p.space('\n')
		}
		p.indent()
		p.curLine = pos.Line
	} else if fallback {
		p.nonSpaced(SEMICOLON)
	}
}

func (p *printer) sepSemicolon(v interface{}, pos Pos) {
	p.separate(pos, true, false)
	p.spaced(v)
}

func (p *printer) sepNewline(v interface{}, pos Pos) {
	p.separate(pos, false, true)
	p.spaced(v)
}

func (p *printer) addComments(pos Pos) {
	if len(p.comments) < 1 {
		return
	}
	c := p.comments[0]
	if c.Hash.Line >= pos.Line {
		return
	}
	p.sepNewline(c, c.Hash)
	p.comments = p.comments[1:]
	p.addComments(pos)
}

func (p *printer) node(n Node) {
	switch x := n.(type) {
	case File:
		p.progStmts(x.Stmts)
		p.space('\n')
	case Stmt:
		if x.Negated {
			p.spaced(NOT)
		}
		for _, a := range x.Assigns {
			p.spaced(a)
		}
		p.spaced(x.Node)
		for _, r := range x.Redirs {
			p.spaced(r.N)
			p.nonSpaced(r.Op, r.Word)
		}
		if x.Background {
			p.spaced(AND)
		}
	case Assign:
		if x.Name != nil {
			p.spaced(x.Name)
			if x.Append {
				p.nonSpaced(ADD_ASSIGN)
			} else {
				p.nonSpaced(ASSIGN)
			}
		}
		p.nonSpaced(x.Value)
	case Command:
		p.wordJoin(x.Args, true)
	case Subshell:
		p.spaced(LPAREN)
		if len(x.Stmts) == 0 {
			// avoid conflict with ()
			p.space(' ')
		}
		p.stmtJoin(x.Stmts)
		p.sepNewline(RPAREN, x.Rparen)
	case Block:
		p.spaced(LBRACE)
		p.stmtJoin(x.Stmts)
		p.sepSemicolon(RBRACE, x.Rbrace)
	case IfStmt:
		p.spaced(IF, x.Cond, SEMICOLON, THEN)
		p.stmtJoin(x.ThenStmts)
		for _, el := range x.Elifs {
			p.sepSemicolon(ELIF, el.Elif)
			p.spaced(el.Cond, SEMICOLON, THEN)
			p.stmtJoin(el.ThenStmts)
		}
		if len(x.ElseStmts) > 0 {
			p.sepSemicolon(ELSE, x.Else)
			p.stmtJoin(x.ElseStmts)
		}
		p.sepSemicolon(FI, x.Fi)
	case StmtCond:
		p.stmtJoin(x.Stmts)
	case CStyleCond:
		p.spaced(DLPAREN, x.Cond, DRPAREN)
	case WhileStmt:
		p.spaced(WHILE, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case UntilStmt:
		p.spaced(UNTIL, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case ForStmt:
		p.spaced(FOR, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case WordIter:
		p.spaced(x.Name)
		if len(x.List) > 0 {
			p.spaced(IN)
			p.wordJoin(x.List, false)
		}
	case CStyleLoop:
		p.spaced(DLPAREN, x.Init, SEMICOLON, x.Cond,
			SEMICOLON, x.Post, DRPAREN)
	case UnaryExpr:
		if x.Post {
			p.nonSpaced(x.X, x.Op)
		} else {
			p.nonSpaced(x.Op)
			p.contiguous = false
			p.nonSpaced(x.X)
		}
	case BinaryExpr:
		if p.compactArithm {
			p.nonSpaced(x.X, x.Op, x.Y)
		} else {
			p.spaced(x.X, x.Op, x.Y)
		}
	case FuncDecl:
		if x.BashStyle {
			p.spaced(FUNCTION)
		}
		p.spaced(x.Name)
		if !x.BashStyle {
			p.nonSpaced(LPAREN, RPAREN)
		}
		p.spaced(x.Body)
	case Word:
		for _, n := range x.Parts {
			p.nonSpaced(n)
		}
	case Lit:
		p.nonSpaced(x.Value)
	case SglQuoted:
		p.nonSpaced(SQUOTE, x.Value, SQUOTE)
	case Quoted:
		p.nonSpaced(x.Quote)
		for _, n := range x.Parts {
			p.nonSpaced(n)
		}
		p.nonSpaced(quotedStop(x.Quote))
	case CmdSubst:
		if x.Backquotes {
			p.nonSpaced(BQUOTE)
		} else {
			p.nonSpaced(DOLLPR)
		}
		p.stmtJoin(x.Stmts)
		if x.Backquotes {
			p.nonSpaced(BQUOTE)
		} else {
			p.nonSpaced(RPAREN)
		}
	case ParamExp:
		if x.Short {
			p.nonSpaced(DOLLAR, x.Param)
			return
		}
		p.nonSpaced(DOLLBR)
		if x.Length {
			p.nonSpaced(HASH)
		}
		p.nonSpaced(x.Param)
		if x.Ind != nil {
			p.nonSpaced(LBRACK, x.Ind.Word, RBRACK)
		}
		if x.Repl != nil {
			if x.Repl.All {
				p.nonSpaced(QUO)
			}
			p.nonSpaced(QUO, x.Repl.Orig, QUO, x.Repl.With)
		} else if x.Exp != nil {
			p.nonSpaced(x.Exp.Op, x.Exp.Word)
		}
		p.nonSpaced(RBRACE)
	case ArithmExpr:
		p.nonSpaced(DOLLDP, x.X, DRPAREN)
	case ParenExpr:
		p.nonSpaced(LPAREN)
		oldCompact := p.compactArithm
		p.compactArithm = false
		p.nonSpaced(x.X)
		p.compactArithm = oldCompact
		p.nonSpaced(RPAREN)
	case CaseStmt:
		p.spaced(CASE, x.Word, IN)
		for _, pl := range x.List {
			p.separate(wordFirstPos(pl.Patterns), false, true)
			for i, w := range pl.Patterns {
				if i > 0 {
					p.spaced(OR)
				}
				p.spaced(w)
			}
			p.nonSpaced(RPAREN)
			p.stmtJoin(pl.Stmts)
			p.level++
			p.sepNewline(DSEMICOLON, pl.Dsemi)
			p.level--
		}
		if len(x.List) == 0 {
			p.sepSemicolon(ESAC, x.Esac)
		} else {
			p.sepNewline(ESAC, x.Esac)
		}
	case DeclStmt:
		if x.Local {
			p.spaced(LOCAL)
		} else {
			p.spaced(DECLARE)
		}
		for _, w := range x.Opts {
			p.spaced(w)
		}
		for _, a := range x.Assigns {
			p.spaced(a)
		}
	case ArrayExpr:
		p.nonSpaced(LPAREN)
		p.wordJoin(x.List, false)
		p.nonSpaced(RPAREN)
	case CmdInput:
		// avoid conflict with <<
		p.spaced(CMDIN)
		p.stmtJoin(x.Stmts)
		p.nonSpaced(RPAREN)
	case EvalStmt:
		p.spaced(EVAL, x.Stmt)
	case LetStmt:
		p.spaced(LET)
		p.compactArithm = true
		for _, n := range x.Exprs {
			p.spaced(n)
		}
		p.compactArithm = false
	}
}

func (p *printer) wordJoin(ws []Word, keepNewlines bool) {
	anyNewline := false
	for _, w := range ws {
		if keepNewlines && w.Pos().Line > p.curLine {
			p.spaced("\\\n")
			if !anyNewline {
				p.level++
				anyNewline = true
			}
			p.indent()
		}
		p.spaced(w)
	}
	if anyNewline {
		p.level--
	}
}

func (p *printer) progStmts(stmts []Stmt) {
	for i, s := range stmts {
		p.separate(s.Pos(), i > 0, true)
		p.node(s)
	}
}

func (p *printer) stmtJoin(stmts []Stmt) {
	p.level++
	for i, s := range stmts {
		p.separate(s.Pos(), i > 0, i > 0)
		p.node(s)
	}
	p.level--
}
<commit_msg>print: don't forget about trailing comments<commit_after>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package sh

import (
	"fmt"
	"io"
	"strings"
)

func Fprint(w io.Writer, n Node) error {
	p := printer{
		w:       w,
		curLine: 1,
	}
	if f, ok := n.(File); ok {
		p.comments = f.Comments
	}
	p.node(n)
	return p.err
}

type printer struct {
	w   io.Writer
	err error

	contiguous bool

	curLine int
	level   int

	comments []Comment

	compactArithm bool
}

var (
	contiguousRight = map[Token]bool{
		DOLLPR:  true,
		LPAREN:  true,
		DLPAREN: true,
		BQUOTE:  true,
		CMDIN:   true,
		DOLLDP:  true,
	}
	contiguousLeft = map[Token]bool{
		SEMICOLON:  true,
		DSEMICOLON: true,
		RPAREN:     true,
		DRPAREN:    true,
		COMMA:      true,
	}
)

func (p *printer) space(b byte) {
	if p.err != nil {
		return
	}
	_, p.err = p.w.Write([]byte{b})
	p.contiguous = false
}

func (p *printer) nonSpaced(a ...interface{}) {
	for _, v := range a {
		if p.err != nil {
			break
		}
		switch x := v.(type) {
		case string:
			if len(x) > 0 {
				last := x[len(x)-1]
				p.contiguous = !space[last]
			}
			_, p.err = io.WriteString(p.w, x)
			p.curLine += strings.Count(x, "\n")
		case Comment:
			p.contiguous = true
			_, p.err = fmt.Fprint(p.w, HASH, x.Text)
		case Token:
			p.contiguous = !contiguousRight[x]
			_, p.err = fmt.Fprint(p.w, x)
		case Node:
			p.node(x)
		}
	}
}

func (p *printer) spaced(a ...interface{}) {
	for _, v := range a {
		if v == nil {
			continue
		}
		if t, ok := v.(Token); ok && contiguousLeft[t] {
		} else if p.contiguous {
			p.space(' ')
		}
		p.nonSpaced(v)
	}
}

func (p *printer) indent() {
	for i := 0; i < p.level; i++ {
		p.space('\t')
	}
}

func (p *printer) separate(pos Pos, fallback, allowTwo bool) {
	p.commentsUpTo(pos.Line)
	if pos.Line > p.curLine {
		p.space('\n')
		if allowTwo && pos.Line > p.curLine+1 {
			// preserve single empty lines
			p.space('\n')
		}
		p.indent()
		p.curLine = pos.Line
	} else if fallback {
		p.nonSpaced(SEMICOLON)
	}
}

func (p *printer) sepSemicolon(v interface{}, pos Pos) {
	p.separate(pos, true, false)
	p.spaced(v)
}

func (p *printer) sepNewline(v interface{}, pos Pos) {
	p.separate(pos, false, true)
	p.spaced(v)
}

func (p *printer) commentsUpTo(line int) {
	if len(p.comments) < 1 {
		return
	}
	c := p.comments[0]
	if line > 0 && c.Hash.Line >= line {
		return
	}
	p.sepNewline(c, c.Hash)
	p.comments = p.comments[1:]
	p.commentsUpTo(line)
}

func (p *printer) node(n Node) {
	switch x := n.(type) {
	case File:
		p.progStmts(x.Stmts)
		p.commentsUpTo(0)
		p.space('\n')
	case Stmt:
		if x.Negated {
			p.spaced(NOT)
		}
		for _, a := range x.Assigns {
			p.spaced(a)
		}
		p.spaced(x.Node)
		for _, r := range x.Redirs {
			p.spaced(r.N)
			p.nonSpaced(r.Op, r.Word)
		}
		if x.Background {
			p.spaced(AND)
		}
	case Assign:
		if x.Name != nil {
			p.spaced(x.Name)
			if x.Append {
				p.nonSpaced(ADD_ASSIGN)
			} else {
				p.nonSpaced(ASSIGN)
			}
		}
		p.nonSpaced(x.Value)
	case Command:
		p.wordJoin(x.Args, true)
	case Subshell:
		p.spaced(LPAREN)
		if len(x.Stmts) == 0 {
			// avoid conflict with ()
			p.space(' ')
		}
		p.stmtJoin(x.Stmts)
		p.sepNewline(RPAREN, x.Rparen)
	case Block:
		p.spaced(LBRACE)
		p.stmtJoin(x.Stmts)
		p.sepSemicolon(RBRACE, x.Rbrace)
	case IfStmt:
		p.spaced(IF, x.Cond, SEMICOLON, THEN)
		p.stmtJoin(x.ThenStmts)
		for _, el := range x.Elifs {
			p.sepSemicolon(ELIF, el.Elif)
			p.spaced(el.Cond, SEMICOLON, THEN)
			p.stmtJoin(el.ThenStmts)
		}
		if len(x.ElseStmts) > 0 {
			p.sepSemicolon(ELSE, x.Else)
			p.stmtJoin(x.ElseStmts)
		}
		p.sepSemicolon(FI, x.Fi)
	case StmtCond:
		p.stmtJoin(x.Stmts)
	case CStyleCond:
		p.spaced(DLPAREN, x.Cond, DRPAREN)
	case WhileStmt:
		p.spaced(WHILE, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case UntilStmt:
		p.spaced(UNTIL, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case ForStmt:
		p.spaced(FOR, x.Cond, SEMICOLON, DO)
		p.stmtJoin(x.DoStmts)
		p.sepSemicolon(DONE, x.Done)
	case WordIter:
		p.spaced(x.Name)
		if len(x.List) > 0 {
			p.spaced(IN)
			p.wordJoin(x.List, false)
		}
	case CStyleLoop:
		p.spaced(DLPAREN, x.Init, SEMICOLON, x.Cond,
			SEMICOLON, x.Post, DRPAREN)
	case UnaryExpr:
		if x.Post {
			p.nonSpaced(x.X, x.Op)
		} else {
			p.nonSpaced(x.Op)
			p.contiguous = false
			p.nonSpaced(x.X)
		}
	case BinaryExpr:
		if p.compactArithm {
			p.nonSpaced(x.X, x.Op, x.Y)
		} else {
			p.spaced(x.X, x.Op, x.Y)
		}
	case FuncDecl:
		if x.BashStyle {
			p.spaced(FUNCTION)
		}
		p.spaced(x.Name)
		if !x.BashStyle {
			p.nonSpaced(LPAREN, RPAREN)
		}
		p.spaced(x.Body)
	case Word:
		for _, n := range x.Parts {
			p.nonSpaced(n)
		}
	case Lit:
		p.nonSpaced(x.Value)
	case SglQuoted:
		p.nonSpaced(SQUOTE, x.Value, SQUOTE)
	case Quoted:
		p.nonSpaced(x.Quote)
		for _, n := range x.Parts {
			p.nonSpaced(n)
		}
		p.nonSpaced(quotedStop(x.Quote))
	case CmdSubst:
		if x.Backquotes {
			p.nonSpaced(BQUOTE)
		} else {
			p.nonSpaced(DOLLPR)
		}
		p.stmtJoin(x.Stmts)
		if x.Backquotes {
			p.nonSpaced(BQUOTE)
		} else {
			p.nonSpaced(RPAREN)
		}
	case ParamExp:
		if x.Short {
			p.nonSpaced(DOLLAR, x.Param)
			return
		}
		p.nonSpaced(DOLLBR)
		if x.Length {
			p.nonSpaced(HASH)
		}
		p.nonSpaced(x.Param)
		if x.Ind != nil {
			p.nonSpaced(LBRACK, x.Ind.Word, RBRACK)
		}
		if x.Repl != nil {
			if x.Repl.All {
				p.nonSpaced(QUO)
			}
			p.nonSpaced(QUO, x.Repl.Orig, QUO, x.Repl.With)
		} else if x.Exp != nil {
			p.nonSpaced(x.Exp.Op, x.Exp.Word)
		}
		p.nonSpaced(RBRACE)
	case ArithmExpr:
		p.nonSpaced(DOLLDP, x.X, DRPAREN)
	case ParenExpr:
		p.nonSpaced(LPAREN)
		oldCompact := p.compactArithm
		p.compactArithm = false
		p.nonSpaced(x.X)
		p.compactArithm = oldCompact
		p.nonSpaced(RPAREN)
	case CaseStmt:
		p.spaced(CASE, x.Word, IN)
		for _, pl := range x.List {
			p.separate(wordFirstPos(pl.Patterns), false, true)
			for i, w := range pl.Patterns {
				if i > 0 {
					p.spaced(OR)
				}
				p.spaced(w)
			}
			p.nonSpaced(RPAREN)
			p.stmtJoin(pl.Stmts)
			p.level++
			p.sepNewline(DSEMICOLON, pl.Dsemi)
			p.level--
		}
		if len(x.List) == 0 {
			p.sepSemicolon(ESAC, x.Esac)
		} else {
			p.sepNewline(ESAC, x.Esac)
		}
	case DeclStmt:
		if x.Local {
			p.spaced(LOCAL)
		} else {
			p.spaced(DECLARE)
		}
		for _, w := range x.Opts {
			p.spaced(w)
		}
		for _, a := range x.Assigns {
			p.spaced(a)
		}
	case ArrayExpr:
		p.nonSpaced(LPAREN)
		p.wordJoin(x.List, false)
		p.nonSpaced(RPAREN)
	case CmdInput:
		// avoid conflict with <<
		p.spaced(CMDIN)
		p.stmtJoin(x.Stmts)
		p.nonSpaced(RPAREN)
	case EvalStmt:
		p.spaced(EVAL, x.Stmt)
	case LetStmt:
		p.spaced(LET)
		p.compactArithm = true
		for _, n := range x.Exprs {
			p.spaced(n)
		}
		p.compactArithm = false
	}
}

func (p *printer) wordJoin(ws []Word, keepNewlines bool) {
	anyNewline := false
	for _, w := range ws {
		if keepNewlines && w.Pos().Line > p.curLine {
			p.spaced("\\\n")
			if !anyNewline {
				p.level++
				anyNewline = true
			}
			p.indent()
		}
		p.spaced(w)
	}
	if anyNewline {
		p.level--
	}
}

func (p *printer) progStmts(stmts []Stmt) {
	for i, s := range stmts {
		p.separate(s.Pos(), i > 0, true)
		p.node(s)
	}
}

func (p *printer) stmtJoin(stmts []Stmt) {
	p.level++
	for i, s := range stmts {
		p.separate(s.Pos(), i > 0, i > 0)
		p.node(s)
	}
	p.level--
}
<|endoftext|>


<commit_before>package terminal

import (
	"fmt"
	"os"
	"regexp"
	"runtime"
)

type Color uint

const (
	red    Color = 31
	green        = 32
	yellow       = 33
	//	blue          = 34
	magenta = 35
	cyan    = 36
	grey    = 37
	white   = 38
)

func colorize(message string, color Color, bold bool) string {
	if runtime.GOOS == "windows" || os.Getenv("CF_COLOR") != "true" {
		return message
	}

	attr := 0
	if bold {
		attr = 1
	}

	return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color, message)
}

func decolorize(message string) string {
	reg, err := regexp.Compile(`\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]`)
	if err != nil {
		panic(err)
	}
	return string(reg.ReplaceAll([]byte(message), []byte("")))
}

func HeaderColor(message string) string {
	return colorize(message, white, true)
}

func CommandColor(message string) string {
	return colorize(message, yellow, true)
}

func StoppedColor(message string) string {
	return colorize(message, grey, true)
}

func AdvisoryColor(message string) string {
	return colorize(message, yellow, true)
}

func CrashedColor(message string) string {
	return colorize(message, red, true)
}

func FailureColor(message string) string {
	return colorize(message, red, true)
}

func SuccessColor(message string) string {
	return colorize(message, green, true)
}

func EntityNameColor(message string) string {
	return colorize(message, cyan, true)
}

func PromptColor(message string) string {
	return colorize(message, cyan, true)
}

func TableContentHeaderColor(message string) string {
	return colorize(message, cyan, true)
}

func WarningColor(message string) string {
	return colorize(message, magenta, true)
}

func LogStdoutColor(message string) string {
	return colorize(message, white, false)
}

func LogStderrColor(message string) string {
	return colorize(message, red, false)
}

func LogAppHeaderColor(message string) string {
	return colorize(message, yellow, true)
}

func LogSysHeaderColor(message string) string {
	return colorize(message, cyan, true)
}
<commit_msg>Change command and advisory color.<commit_after>package terminal

import (
	"fmt"
	"os"
	"regexp"
	"runtime"
)

type Color uint

const (
	red    Color = 31
	green        = 32
	yellow       = 33
	blue         = 34
	magenta      = 35
	cyan         = 36
	grey         = 37
	white        = 38
)

func colorize(message string, color Color, bold bool) string {
	if runtime.GOOS == "windows" || os.Getenv("CF_COLOR") != "true" {
		return message
	}

	attr := 0
	if bold {
		attr = 1
	}

	return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color, message)
}

func decolorize(message string) string {
	reg, err := regexp.Compile(`\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]`)
	if err != nil {
		panic(err)
	}
	return string(reg.ReplaceAll([]byte(message), []byte("")))
}

func HeaderColor(message string) string {
	return colorize(message, white, true)
}

func CommandColor(message string) string {
	return colorize(message, cyan, true)
}

func StoppedColor(message string) string {
	return colorize(message, grey, true)
}

func AdvisoryColor(message string) string {
	return colorize(message, cyan, true)
}

func CrashedColor(message string) string {
	return colorize(message, red, true)
}

func FailureColor(message string) string {
	return colorize(message, red, true)
}

func SuccessColor(message string) string {
	return colorize(message, green, true)
}

func EntityNameColor(message string) string {
	return colorize(message, cyan, true)
}

func PromptColor(message string) string {
	return colorize(message, cyan, true)
}

func TableContentHeaderColor(message string) string {
	return colorize(message, cyan, true)
}

func WarningColor(message string) string {
	return colorize(message, magenta, true)
}

func LogStdoutColor(message string) string {
	return colorize(message, white, false)
}

func LogStderrColor(message string) string {
	return colorize(message, red, false)
}

func LogAppHeaderColor(message string) string {
	return colorize(message, yellow, true)
}

func LogSysHeaderColor(message string) string {
	return colorize(message, cyan, true)
}
<|endoftext|>


<commit_before>package http3

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/quicvarint"
)

type frame interface{}

func parseNextFrame(r io.Reader) (frame, error) {
	qr := quicvarint.NewReader(r)
	for {
		t, err := quicvarint.Read(qr)
		if err != nil {
			return nil, err
		}
		l, err := quicvarint.Read(qr)
		if err != nil {
			return nil, err
		}

		switch t {
		case 0x0:
			return &dataFrame{Length: l}, nil
		case 0x1:
			return &headersFrame{Length: l}, nil
		case 0x4:
			return parseSettingsFrame(r, l)
		case 0x3: // CANCEL_PUSH
			fallthrough
		case 0x5: // PUSH_PROMISE
			fallthrough
		case 0x7: // GOAWAY
			fallthrough
		case 0xd: // MAX_PUSH_ID
			fallthrough
		case 0xe: // DUPLICATE_PUSH
			fallthrough
		default:
			// skip over unknown frames
			if _, err := io.CopyN(ioutil.Discard, qr, int64(l)); err != nil {
				return nil, err
			}
		}
	}
}

type dataFrame struct {
	Length uint64
}

func (f *dataFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x0)
	quicvarint.Write(b, f.Length)
}

type headersFrame struct {
	Length uint64
}

func (f *headersFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x1)
	quicvarint.Write(b, f.Length)
}

const settingDatagram = 0x276

type settingsFrame struct {
	Datagram bool
	other    map[uint64]uint64 // all settings that we don't explicitly recognize
}

func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
	if l > 8*(1<<10) {
		return nil, fmt.Errorf("unexpected size for SETTINGS frame: %d", l)
	}
	buf := make([]byte, l)
	if _, err := io.ReadFull(r, buf); err != nil {
		if err == io.ErrUnexpectedEOF {
			return nil, io.EOF
		}
		return nil, err
	}
	frame := &settingsFrame{}
	b := bytes.NewReader(buf)
	var readDatagram bool
	for b.Len() > 0 {
		id, err := quicvarint.Read(b)
		if err != nil { // should not happen. We allocated the whole frame already.
			return nil, err
		}
		val, err := quicvarint.Read(b)
		if err != nil { // should not happen. We allocated the whole frame already.
			return nil, err
		}

		switch id {
		case settingDatagram:
			if readDatagram {
				return nil, fmt.Errorf("duplicate setting: %d", id)
			}
			readDatagram = true
			if val != 0 && val != 1 {
				return nil, fmt.Errorf("invalid value for H3_DATAGRAM: %d", val)
			}
			frame.Datagram = val == 1
		default:
			if _, ok := frame.other[id]; ok {
				return nil, fmt.Errorf("duplicate setting: %d", id)
			}
			if frame.other == nil {
				frame.other = make(map[uint64]uint64)
			}
			frame.other[id] = val
		}
	}
	return frame, nil
}

func (f *settingsFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x4)
	var l protocol.ByteCount
	for id, val := range f.other {
		l += quicvarint.Len(id) + quicvarint.Len(val)
	}
	if f.Datagram {
		l += quicvarint.Len(settingDatagram) + quicvarint.Len(1)
	}
	quicvarint.Write(b, uint64(l))
	if f.Datagram {
		quicvarint.Write(b, settingDatagram)
		quicvarint.Write(b, 1)
	}
	for id, val := range f.other {
		quicvarint.Write(b, id)
		quicvarint.Write(b, val)
	}
}
<commit_msg>remove parser logic for HTTP/3 DUPLICATE_PUSH frame (#3356)<commit_after>package http3

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/quicvarint"
)

type frame interface{}

func parseNextFrame(r io.Reader) (frame, error) {
	qr := quicvarint.NewReader(r)
	for {
		t, err := quicvarint.Read(qr)
		if err != nil {
			return nil, err
		}
		l, err := quicvarint.Read(qr)
		if err != nil {
			return nil, err
		}

		switch t {
		case 0x0:
			return &dataFrame{Length: l}, nil
		case 0x1:
			return &headersFrame{Length: l}, nil
		case 0x4:
			return parseSettingsFrame(r, l)
		case 0x3: // CANCEL_PUSH
			fallthrough
		case 0x5: // PUSH_PROMISE
			fallthrough
		case 0x7: // GOAWAY
			fallthrough
		case 0xd: // MAX_PUSH_ID
			fallthrough
		default:
			// skip over unknown frames
			if _, err := io.CopyN(ioutil.Discard, qr, int64(l)); err != nil {
				return nil, err
			}
		}
	}
}

type dataFrame struct {
	Length uint64
}

func (f *dataFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x0)
	quicvarint.Write(b, f.Length)
}

type headersFrame struct {
	Length uint64
}

func (f *headersFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x1)
	quicvarint.Write(b, f.Length)
}

const settingDatagram = 0x276

type settingsFrame struct {
	Datagram bool
	other    map[uint64]uint64 // all settings that we don't explicitly recognize
}

func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
	if l > 8*(1<<10) {
		return nil, fmt.Errorf("unexpected size for SETTINGS frame: %d", l)
	}
	buf := make([]byte, l)
	if _, err := io.ReadFull(r, buf); err != nil {
		if err == io.ErrUnexpectedEOF {
			return nil, io.EOF
		}
		return nil, err
	}
	frame := &settingsFrame{}
	b := bytes.NewReader(buf)
	var readDatagram bool
	for b.Len() > 0 {
		id, err := quicvarint.Read(b)
		if err != nil { // should not happen. We allocated the whole frame already.
			return nil, err
		}
		val, err := quicvarint.Read(b)
		if err != nil { // should not happen. We allocated the whole frame already.
			return nil, err
		}

		switch id {
		case settingDatagram:
			if readDatagram {
				return nil, fmt.Errorf("duplicate setting: %d", id)
			}
			readDatagram = true
			if val != 0 && val != 1 {
				return nil, fmt.Errorf("invalid value for H3_DATAGRAM: %d", val)
			}
			frame.Datagram = val == 1
		default:
			if _, ok := frame.other[id]; ok {
				return nil, fmt.Errorf("duplicate setting: %d", id)
			}
			if frame.other == nil {
				frame.other = make(map[uint64]uint64)
			}
			frame.other[id] = val
		}
	}
	return frame, nil
}

func (f *settingsFrame) Write(b *bytes.Buffer) {
	quicvarint.Write(b, 0x4)
	var l protocol.ByteCount
	for id, val := range f.other {
		l += quicvarint.Len(id) + quicvarint.Len(val)
	}
	if f.Datagram {
		l += quicvarint.Len(settingDatagram) + quicvarint.Len(1)
	}
	quicvarint.Write(b, uint64(l))
	if f.Datagram {
		quicvarint.Write(b, settingDatagram)
		quicvarint.Write(b, 1)
	}
	for id, val := range f.other {
		quicvarint.Write(b, id)
		quicvarint.Write(b, val)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Adam Tauber
//
// 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 colly

import (
	"crypto/sha1"
	"encoding/gob"
	"encoding/hex"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"

	"compress/gzip"

	"github.com/gobwas/glob"
)

type httpBackend struct {
	LimitRules []*LimitRule
	Client     *http.Client
	lock       *sync.RWMutex
}

type checkHeadersFunc func(req *http.Request, statusCode int, header http.Header) bool

// LimitRule provides connection restrictions for domains.
// Both DomainRegexp and DomainGlob can be used to specify
// the included domains patterns, but at least one is required.
// There can be two kind of limitations:
//  - Parallelism: Set limit for the number of concurrent requests to matching domains
//  - Delay: Wait specified amount of time between requests (parallelism is 1 in this case)
type LimitRule struct {
	// DomainRegexp is a regular expression to match against domains
	DomainRegexp string
	// DomainGlob is a glob pattern to match against domains
	DomainGlob string
	// Delay is the duration to wait before creating a new request to the matching domains
	Delay time.Duration
	// RandomDelay is the extra randomized duration to wait added to Delay before creating a new request
	RandomDelay time.Duration
	// Parallelism is the number of the maximum allowed concurrent requests of the matching domains
	Parallelism    int
	waitChan       chan bool
	compiledRegexp *regexp.Regexp
	compiledGlob   glob.Glob
}

// Init initializes the private members of LimitRule
func (r *LimitRule) Init() error {
	waitChanSize := 1
	if r.Parallelism > 1 {
		waitChanSize = r.Parallelism
	}
	r.waitChan = make(chan bool, waitChanSize)
	hasPattern := false
	if r.DomainRegexp != "" {
		c, err := regexp.Compile(r.DomainRegexp)
		if err != nil {
			return err
		}
		r.compiledRegexp = c
		hasPattern = true
	}
	if r.DomainGlob != "" {
		c, err := glob.Compile(r.DomainGlob)
		if err != nil {
			return err
		}
		r.compiledGlob = c
		hasPattern = true
	}
	if !hasPattern {
		return ErrNoPattern
	}
	return nil
}

func (h *httpBackend) Init(jar http.CookieJar) {
	rand.Seed(time.Now().UnixNano())
	h.Client = &http.Client{
		Jar:     jar,
		Timeout: 10 * time.Second,
	}
	h.lock = &sync.RWMutex{}
}

// Match checks that the domain parameter triggers the rule
func (r *LimitRule) Match(domain string) bool {
	match := false
	if r.compiledRegexp != nil && r.compiledRegexp.MatchString(domain) {
		match = true
	}
	if r.compiledGlob != nil && r.compiledGlob.Match(domain) {
		match = true
	}
	return match
}

func (h *httpBackend) GetMatchingRule(domain string) *LimitRule {
	if h.LimitRules == nil {
		return nil
	}
	h.lock.RLock()
	defer h.lock.RUnlock()
	for _, r := range h.LimitRules {
		if r.Match(domain) {
			return r
		}
	}
	return nil
}

func (h *httpBackend) Cache(request *http.Request, bodySize int, checkHeadersFunc checkHeadersFunc, cacheDir string) (*Response, error) {
	if cacheDir == "" || request.Method != "GET" {
		return h.Do(request, bodySize, checkHeadersFunc)
	}
	sum := sha1.Sum([]byte(request.URL.String()))
	hash := hex.EncodeToString(sum[:])
	dir := path.Join(cacheDir, hash[:2])
	filename := path.Join(dir, hash)
	if file, err := os.Open(filename); err == nil {
		resp := new(Response)
		err := gob.NewDecoder(file).Decode(resp)
		file.Close()
		if resp.StatusCode < 500 {
			return resp, err
		}
	}
	resp, err := h.Do(request, bodySize, checkHeadersFunc)
	if err != nil || resp.StatusCode >= 500 {
		return resp, err
	}
	if _, err := os.Stat(dir); err != nil {
		if err := os.MkdirAll(dir, 0750); err != nil {
			return resp, err
		}
	}
	file, err := os.Create(filename + "~")
	if err != nil {
		return resp, err
	}
	if err := gob.NewEncoder(file).Encode(resp); err != nil {
		file.Close()
		return resp, err
	}
	file.Close()
	return resp, os.Rename(filename+"~", filename)
}

func (h *httpBackend) Do(request *http.Request, bodySize int, checkHeadersFunc checkHeadersFunc) (*Response, error) {
	r := h.GetMatchingRule(request.URL.Host)
	if r != nil {
		r.waitChan <- true
		defer func(r *LimitRule) {
			randomDelay := time.Duration(0)
			if r.RandomDelay != 0 {
				randomDelay = time.Duration(rand.Int63n(int64(r.RandomDelay)))
			}
			time.Sleep(r.Delay + randomDelay)
			<-r.waitChan
		}(r)
	}

	res, err := h.Client.Do(request)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.Request != nil {
		*request = *res.Request
	}
	if !checkHeadersFunc(request, res.StatusCode, res.Header) {
		// closing res.Body (see defer above) without reading it aborts
		// the download
		return nil, ErrAbortedAfterHeaders
	}

	var bodyReader io.Reader = res.Body
	if bodySize > 0 {
		bodyReader = io.LimitReader(bodyReader, int64(bodySize))
	}
	contentEncoding := strings.ToLower(res.Header.Get("Content-Encoding"))
	if !res.Uncompressed && (strings.Contains(contentEncoding, "gzip") || (contentEncoding == "" && strings.Contains(strings.ToLower(res.Header.Get("Content-Type")), "gzip")) || strings.HasSuffix(strings.ToLower(request.URL.Path), ".xml.gz")) {
		bodyReader, err = gzip.NewReader(bodyReader)
		if err != nil {
			return nil, err
		}
		defer bodyReader.(*gzip.Reader).Close()
	}
	body, err := ioutil.ReadAll(bodyReader)
	if err != nil {
		return nil, err
	}
	return &Response{
		StatusCode: res.StatusCode,
		Body:       body,
		Headers:    &res.Header,
	}, nil
}

func (h *httpBackend) Limit(rule *LimitRule) error {
	h.lock.Lock()
	if h.LimitRules == nil {
		h.LimitRules = make([]*LimitRule, 0, 8)
	}
	h.LimitRules = append(h.LimitRules, rule)
	h.lock.Unlock()
	return rule.Init()
}

func (h *httpBackend) Limits(rules []*LimitRule) error {
	for _, r := range rules {
		if err := h.Limit(r); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Add httpBackend cache response callback<commit_after>// Copyright 2018 Adam Tauber
//
// 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 colly

import (
	"crypto/sha1"
	"encoding/gob"
	"encoding/hex"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"

	"compress/gzip"

	"github.com/gobwas/glob"
)

type httpBackend struct {
	LimitRules []*LimitRule
	Client     *http.Client
	lock       *sync.RWMutex
}

type checkHeadersFunc func(req *http.Request, statusCode int, header http.Header) bool

// LimitRule provides connection restrictions for domains.
// Both DomainRegexp and DomainGlob can be used to specify
// the included domains patterns, but at least one is required.
// There can be two kind of limitations:
//  - Parallelism: Set limit for the number of concurrent requests to matching domains
//  - Delay: Wait specified amount of time between requests (parallelism is 1 in this case)
type LimitRule struct {
	// DomainRegexp is a regular expression to match against domains
	DomainRegexp string
	// DomainGlob is a glob pattern to match against domains
	DomainGlob string
	// Delay is the duration to wait before creating a new request to the matching domains
	Delay time.Duration
	// RandomDelay is the extra randomized duration to wait added to Delay before creating a new request
	RandomDelay time.Duration
	// Parallelism is the number of the maximum allowed concurrent requests of the matching domains
	Parallelism    int
	waitChan       chan bool
	compiledRegexp *regexp.Regexp
	compiledGlob   glob.Glob
}

// Init initializes the private members of LimitRule
func (r *LimitRule) Init() error {
	waitChanSize := 1
	if r.Parallelism > 1 {
		waitChanSize = r.Parallelism
	}
	r.waitChan = make(chan bool, waitChanSize)
	hasPattern := false
	if r.DomainRegexp != "" {
		c, err := regexp.Compile(r.DomainRegexp)
		if err != nil {
			return err
		}
		r.compiledRegexp = c
		hasPattern = true
	}
	if r.DomainGlob != "" {
		c, err := glob.Compile(r.DomainGlob)
		if err != nil {
			return err
		}
		r.compiledGlob = c
		hasPattern = true
	}
	if !hasPattern {
		return ErrNoPattern
	}
	return nil
}

func (h *httpBackend) Init(jar http.CookieJar) {
	rand.Seed(time.Now().UnixNano())
	h.Client = &http.Client{
		Jar:     jar,
		Timeout: 10 * time.Second,
	}
	h.lock = &sync.RWMutex{}
}

// Match checks that the domain parameter triggers the rule
func (r *LimitRule) Match(domain string) bool {
	match := false
	if r.compiledRegexp != nil && r.compiledRegexp.MatchString(domain) {
		match = true
	}
	if r.compiledGlob != nil && r.compiledGlob.Match(domain) {
		match = true
	}
	return match
}

func (h *httpBackend) GetMatchingRule(domain string) *LimitRule {
	if h.LimitRules == nil {
		return nil
	}
	h.lock.RLock()
	defer h.lock.RUnlock()
	for _, r := range h.LimitRules {
		if r.Match(domain) {
			return r
		}
	}
	return nil
}

func (h *httpBackend) Cache(request *http.Request, bodySize int, checkHeadersFunc checkHeadersFunc, cacheDir string) (*Response, error) {
	if cacheDir == "" || request.Method != "GET" || request.Header.Get("Cache-Control") == "no-cache" {
		return h.Do(request, bodySize, checkHeadersFunc)
	}
	sum := sha1.Sum([]byte(request.URL.String()))
	hash := hex.EncodeToString(sum[:])
	dir := path.Join(cacheDir, hash[:2])
	filename := path.Join(dir, hash)
	if file, err := os.Open(filename); err == nil {
		resp := new(Response)
		err := gob.NewDecoder(file).Decode(resp)
		file.Close()
		checkHeadersFunc(request, resp.StatusCode, *resp.Headers)
		if resp.StatusCode < 500 {
			return resp, err
		}
	}
	resp, err := h.Do(request, bodySize, checkHeadersFunc)
	if err != nil || resp.StatusCode >= 500 {
		return resp, err
	}
	if _, err := os.Stat(dir); err != nil {
		if err := os.MkdirAll(dir, 0750); err != nil {
			return resp, err
		}
	}
	file, err := os.Create(filename + "~")
	if err != nil {
		return resp, err
	}
	if err := gob.NewEncoder(file).Encode(resp); err != nil {
		file.Close()
		return resp, err
	}
	file.Close()
	return resp, os.Rename(filename+"~", filename)
}

func (h *httpBackend) Do(request *http.Request, bodySize int, checkHeadersFunc checkHeadersFunc) (*Response, error) {
	r := h.GetMatchingRule(request.URL.Host)
	if r != nil {
		r.waitChan <- true
		defer func(r *LimitRule) {
			randomDelay := time.Duration(0)
			if r.RandomDelay != 0 {
				randomDelay = time.Duration(rand.Int63n(int64(r.RandomDelay)))
			}
			time.Sleep(r.Delay + randomDelay)
			<-r.waitChan
		}(r)
	}

	res, err := h.Client.Do(request)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	if res.Request != nil {
		*request = *res.Request
	}
	if !checkHeadersFunc(request, res.StatusCode, res.Header) {
		// closing res.Body (see defer above) without reading it aborts
		// the download
		return nil, ErrAbortedAfterHeaders
	}

	var bodyReader io.Reader = res.Body
	if bodySize > 0 {
		bodyReader = io.LimitReader(bodyReader, int64(bodySize))
	}
	contentEncoding := strings.ToLower(res.Header.Get("Content-Encoding"))
	if !res.Uncompressed && (strings.Contains(contentEncoding, "gzip") || (contentEncoding == "" && strings.Contains(strings.ToLower(res.Header.Get("Content-Type")), "gzip")) || strings.HasSuffix(strings.ToLower(request.URL.Path), ".xml.gz")) {
		bodyReader, err = gzip.NewReader(bodyReader)
		if err != nil {
			return nil, err
		}
		defer bodyReader.(*gzip.Reader).Close()
	}
	body, err := ioutil.ReadAll(bodyReader)
	if err != nil {
		return nil, err
	}
	return &Response{
		StatusCode: res.StatusCode,
		Body:       body,
		Headers:    &res.Header,
	}, nil
}

func (h *httpBackend) Limit(rule *LimitRule) error {
	h.lock.Lock()
	if h.LimitRules == nil {
		h.LimitRules = make([]*LimitRule, 0, 8)
	}
	h.LimitRules = append(h.LimitRules, rule)
	h.lock.Unlock()
	return rule.Init()
}

func (h *httpBackend) Limits(rules []*LimitRule) error {
	for _, r := range rules {
		if err := h.Limit(r); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// -*- coding: utf-8-unix -*-
package main

import (
	"./process"
	"fmt"
	"os"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"code.google.com/p/go-uuid/uuid"
)

type BootJSON struct {
	Name      string        `json:"name"      binding:"required"`
	Param     interface{}   `json:"parameter" binding:"required"`
}

type JubatusServer struct {
	Filename string
	Proc process.JubatusProcess
}

func (j *JubatusServer) Call(method string, arg []interface{}) (interface{}, error) {
	return j.Proc.Call(method, arg)
}

func (j *JubatusServer) Kill() {
	os.Remove(j.Filename)
}

func NewJubatusServer(jubatype string, arg interface{}) (*JubatusServer, error) {
	jtype := jubatype
	filename := uuid.New() + ".json"
	data, _ := json.Marshal(arg)
	filepath := "/tmp/" + filename

	fp, err := os.Create(filepath)
	if err != nil {
		return nil, err
	}
	fp.Write(data)
	fp.Close()
	fmt.Println(arg)

	new_process, err := process.NewJubatusProcess("juba" + jtype, filepath)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	return &JubatusServer{filename, *new_process}, err
}

func main() {
	router := gin.Default()

	servers := make(map[string]map[string]*JubatusServer)
	modules := []string{"classifier", "recommender", "regression"}

	for _, module := range modules {
		local_module := module

		router.POST("/" + local_module, func(c *gin.Context) {
			/*
        Create new jubatus model
        Name => unique name of new model
        Param => jubatus boot parameter passed with -f option
      */

			fmt.Println("" + local_module)
			var arg BootJSON
			c.Bind(&arg)
			if _, ok := servers[local_module][arg.Name]; ok {
				c.String(409, local_module + "/" + arg.Name + " is already exists\n")
				return
			}
			newServer, err := NewJubatusServer(local_module, arg.Param)
			if err != nil {
				fmt.Println(err)
				c.String(500, err.Error())
				return
			}

			if servers[local_module] == nil {
				servers[local_module] = make(map[string]*JubatusServer)
			}
			servers[local_module][arg.Name] = newServer

			c.String(200, "ok")
		})

		router.POST("/" + local_module + "/:name/:method", func(c *gin.Context) {
			/*
        Do machine learning
        you can use Jubatus via HTTP rpc
      */
			var argument []interface{}
			c.Bind(&argument)

			name := c.Params.ByName("name")
			method := c.Params.ByName("method")

			if server, ok := servers[local_module][name]; ok {
				fmt.Println(argument)
				ret, err := server.Call(method, argument)
				fmt.Println("return: ", ret, err)
				c.JSON(200, gin.H{"result": ret})
			} else {
				c.String(404, "target " + name + " not found")
			}
		})

		router.GET("/" + local_module, func(c *gin.Context) {
			/*
        get list of names of machine learning models
      */
			ret := []string{}
			for _, local_module := range modules {
				for name, _ := range servers[local_module] {
					ret = append(ret, local_module + "/" + name)
				}
			}
			c.JSON(200, gin.H{"servers": "hoge"})
		})

		router.DELETE("/" + local_module + "/:name", func(c *gin.Context) {
			/*
        delete machine learning model
      */
			name := c.Params.ByName("name")
			if server, ok := servers[local_module][name]; ok {
				server.Kill()
				delete(servers, name)
				c.String(200, "deleted")
			} else {
				c.String(404, "target " + name + " not found")
			}
		})
	}

	port := os.Getenv("PORT")
	if len(port) == 0 {
		port = "3000"
	}

	router.Run(":" + port)
}
<commit_msg>go fmt<commit_after>// -*- coding: utf-8-unix -*-
package main

import (
	"./process"
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"os"
)

type BootJSON struct {
	Name  string      `json:"name"      binding:"required"`
	Param interface{} `json:"parameter" binding:"required"`
}

type JubatusServer struct {
	Filename string
	Proc     process.JubatusProcess
}

func (j *JubatusServer) Call(method string, arg []interface{}) (interface{}, error) {
	return j.Proc.Call(method, arg)
}

func (j *JubatusServer) Kill() {
	os.Remove(j.Filename)
}

func NewJubatusServer(jubatype string, arg interface{}) (*JubatusServer, error) {
	jtype := jubatype
	filename := uuid.New() + ".json"
	data, _ := json.Marshal(arg)
	filepath := "/tmp/" + filename

	fp, err := os.Create(filepath)
	if err != nil {
		return nil, err
	}
	fp.Write(data)
	fp.Close()
	fmt.Println(arg)

	new_process, err := process.NewJubatusProcess("juba"+jtype, filepath)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}

	return &JubatusServer{filename, *new_process}, err
}

func main() {
	router := gin.Default()

	servers := make(map[string]map[string]*JubatusServer)
	modules := []string{"classifier", "recommender", "regression"}

	for _, module := range modules {
		local_module := module

		router.POST("/"+local_module, func(c *gin.Context) {
			/*
			   Create new jubatus model
			   Name => unique name of new model
			   Param => jubatus boot parameter passed with -f option
			*/

			fmt.Println("" + local_module)
			var arg BootJSON
			c.Bind(&arg)
			if _, ok := servers[local_module][arg.Name]; ok {
				c.String(409, local_module+"/"+arg.Name+" is already exists\n")
				return
			}
			newServer, err := NewJubatusServer(local_module, arg.Param)
			if err != nil {
				fmt.Println(err)
				c.String(500, err.Error())
				return
			}

			if servers[local_module] == nil {
				servers[local_module] = make(map[string]*JubatusServer)
			}
			servers[local_module][arg.Name] = newServer

			c.String(200, "ok")
		})

		router.POST("/"+local_module+"/:name/:method", func(c *gin.Context) {
			/*
			   Do machine learning
			   you can use Jubatus via HTTP rpc
			*/
			var argument []interface{}
			c.Bind(&argument)

			name := c.Params.ByName("name")
			method := c.Params.ByName("method")

			if server, ok := servers[local_module][name]; ok {
				fmt.Println(argument)
				ret, err := server.Call(method, argument)
				fmt.Println("return: ", ret, err)
				c.JSON(200, gin.H{"result": ret})
			} else {
				c.String(404, "target "+name+" not found")
			}
		})

		router.GET("/"+local_module, func(c *gin.Context) {
			/*
			   get list of names of machine learning models
			*/
			ret := []string{}
			for _, local_module := range modules {
				for name, _ := range servers[local_module] {
					ret = append(ret, local_module+"/"+name)
				}
			}
			c.JSON(200, gin.H{"servers": "hoge"})
		})

		router.DELETE("/"+local_module+"/:name", func(c *gin.Context) {
			/*
			   delete machine learning model
			*/
			name := c.Params.ByName("name")
			if server, ok := servers[local_module][name]; ok {
				server.Kill()
				delete(servers, name)
				c.String(200, "deleted")
			} else {
				c.String(404, "target "+name+" not found")
			}
		})
	}

	port := os.Getenv("PORT")
	if len(port) == 0 {
		port = "3000"
	}

	router.Run(":" + port)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
	"github.com/pachyderm/pachyderm/src/pkg/cobramainutil"
	"github.com/pachyderm/pachyderm/src/pkg/mainutil"
	"github.com/spf13/cobra"
)

var (
	defaultEnv = map[string]string{}
)

type appEnv struct{}

func main() {
	mainutil.Main(do, &appEnv{}, defaultEnv)
}

func do(appEnvObj interface{}) error {
	appEnv := appEnvObj.(*appEnv)

	runCmd := cobramainutil.Command{
		Use:  "run",
		Long: "run",
		Run: func(cmd *cobra.Command, args []string) error {
			return run(appEnv, args)
		},
	}.ToCobraCommand()

	rootCmd := &cobra.Command{
		Use:  "pachkube",
		Long: `pachkube`,
	}

	rootCmd.AddCommand(runCmd)
	return rootCmd.Execute()
}

func run(appEnv *appEnv, args []string) error {
	clientConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{},
	).ClientConfig()
	if err != nil {
		return err
	}
	client, err := client.New(clientConfig)
	if err != nil {
		return err
	}
	versionInfo, err := client.ServerVersion()
	if err != nil {
		return err
	}
	fmt.Printf("%+v\n", versionInfo)
	return nil
}
<commit_msg>Changes the import used for k8s.<commit_after>package main

import (
	"fmt"

	"github.com/pachyderm/pachyderm/src/pkg/cobramainutil"
	"github.com/pachyderm/pachyderm/src/pkg/mainutil"
	"github.com/spf13/cobra"
	"k8s.io/kubernetes/pkg/client"
	"k8s.io/kubernetes/pkg/client/clientcmd"
)

var (
	defaultEnv = map[string]string{}
)

type appEnv struct{}

func main() {
	mainutil.Main(do, &appEnv{}, defaultEnv)
}

func do(appEnvObj interface{}) error {
	appEnv := appEnvObj.(*appEnv)

	runCmd := cobramainutil.Command{
		Use:  "run",
		Long: "run",
		Run: func(cmd *cobra.Command, args []string) error {
			return run(appEnv, args)
		},
	}.ToCobraCommand()

	rootCmd := &cobra.Command{
		Use:  "pachkube",
		Long: `pachkube`,
	}

	rootCmd.AddCommand(runCmd)
	return rootCmd.Execute()
}

func run(appEnv *appEnv, args []string) error {
	clientConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		clientcmd.NewDefaultClientConfigLoadingRules(),
		&clientcmd.ConfigOverrides{},
	).ClientConfig()
	if err != nil {
		return err
	}
	client, err := client.New(clientConfig)
	if err != nil {
		return err
	}
	versionInfo, err := client.ServerVersion()
	if err != nil {
		return err
	}
	fmt.Printf("%+v\n", versionInfo)
	return nil
}
<|endoftext|>


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

// This file contains the test for unkeyed struct literals.

package main

import (
	"cmd/vet/internal/whitelist"
	"flag"
	"go/ast"
	"go/types"
	"strings"
)

var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")

func init() {
	register("composites",
		"check that composite literals used field-keyed elements",
		checkUnkeyedLiteral,
		compositeLit)
}

// checkUnkeyedLiteral checks if a composite literal is a struct literal with
// unkeyed fields.
func checkUnkeyedLiteral(f *File, node ast.Node) {
	cl := node.(*ast.CompositeLit)

	typ := f.pkg.types[cl].Type
	if typ == nil {
		// cannot determine composite literals' type, skip it
		return
	}
	typeName := typ.String()
	if *compositeWhiteList && whitelist.UnkeyedLiteral[typeName] {
		// skip whitelisted types
		return
	}
	under := typ.Underlying()
	for {
		ptr, ok := under.(*types.Pointer)
		if !ok {
			break
		}
		under = ptr.Elem().Underlying()
	}
	if _, ok := under.(*types.Struct); !ok {
		// skip non-struct composite literals
		return
	}
	if isLocalType(f, typ) {
		// allow unkeyed locally defined composite literal
		return
	}

	// check if the CompositeLit contains an unkeyed field
	allKeyValue := true
	for _, e := range cl.Elts {
		if _, ok := e.(*ast.KeyValueExpr); !ok {
			allKeyValue = false
			break
		}
	}
	if allKeyValue {
		// all the composite literal fields are keyed
		return
	}

	f.Badf(cl.Pos(), "%s composite literal uses unkeyed fields", typeName)
}

func isLocalType(f *File, typ types.Type) bool {
	switch x := typ.(type) {
	case *types.Struct:
		// struct literals are local types
		return true
	case *types.Pointer:
		return isLocalType(f, x.Elem())
	case *types.Named:
		// names in package foo are local to foo_test too
		return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(f.pkg.path, "_test")
	}
	return false
}
<commit_msg>cmd/vet: -composites only checks imported types<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains the test for unkeyed struct literals.

package main

import (
	"cmd/vet/internal/whitelist"
	"flag"
	"go/ast"
	"go/types"
	"strings"
)

var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")

func init() {
	register("composites",
		"check that composite literals of types from imported packages use field-keyed elements",
		checkUnkeyedLiteral,
		compositeLit)
}

// checkUnkeyedLiteral checks if a composite literal is a struct literal with
// unkeyed fields.
func checkUnkeyedLiteral(f *File, node ast.Node) {
	cl := node.(*ast.CompositeLit)

	typ := f.pkg.types[cl].Type
	if typ == nil {
		// cannot determine composite literals' type, skip it
		return
	}
	typeName := typ.String()
	if *compositeWhiteList && whitelist.UnkeyedLiteral[typeName] {
		// skip whitelisted types
		return
	}
	under := typ.Underlying()
	for {
		ptr, ok := under.(*types.Pointer)
		if !ok {
			break
		}
		under = ptr.Elem().Underlying()
	}
	if _, ok := under.(*types.Struct); !ok {
		// skip non-struct composite literals
		return
	}
	if isLocalType(f, typ) {
		// allow unkeyed locally defined composite literal
		return
	}

	// check if the CompositeLit contains an unkeyed field
	allKeyValue := true
	for _, e := range cl.Elts {
		if _, ok := e.(*ast.KeyValueExpr); !ok {
			allKeyValue = false
			break
		}
	}
	if allKeyValue {
		// all the composite literal fields are keyed
		return
	}

	f.Badf(cl.Pos(), "%s composite literal uses unkeyed fields", typeName)
}

func isLocalType(f *File, typ types.Type) bool {
	switch x := typ.(type) {
	case *types.Struct:
		// struct literals are local types
		return true
	case *types.Pointer:
		return isLocalType(f, x.Elem())
	case *types.Named:
		// names in package foo are local to foo_test too
		return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(f.pkg.path, "_test")
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2015 Alex Browne.  All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

// package prtty is a small go library for logging things with color.
package prtty

import (
	"fmt"
	"github.com/wsxiaoys/terminal/color"
	"io"
	"log"
	"os"
)

const (
	// Color settings for the different logging functions
	// See: https://godoc.org/github.com/wsxiaoys/terminal/color
	defaultColor = "@w" // white
	infoColor    = "@c" // cyan
	warnColor    = "@y" // yellow
	successColor = "@g" // green
	errorColor   = "@r" // red
)

var (
	Default = NewLogger(os.Stdout, defaultColor)
	Info    = NewLogger(os.Stdout, infoColor)
	Warn    = NewLogger(os.Stdout, warnColor)
	Success = NewLogger(os.Stdout, successColor)
	Error   = NewLogger(os.Stderr, errorColor)
)

type Logger struct {
	out   io.Writer
	color string
}

func NewLogger(out io.Writer, color string) *Logger {
	return &Logger{
		out:   out,
		color: color,
	}
}

func (l *Logger) Print(v ...interface{}) {
	log.SetOutput(l.out)
	log.Print(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Println(v ...interface{}) {
	log.SetOutput(l.out)
	log.Println(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Printf(format string, v ...interface{}) {
	log.SetOutput(l.out)
	log.Printf(color.Sprint(l.color + fmt.Sprintf(format, v...)))
}

func (l *Logger) Panic(v ...interface{}) {
	log.SetOutput(l.out)
	log.Panic(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Panicln(v ...interface{}) {
	log.SetOutput(l.out)
	log.Panicln(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Panicf(format string, v ...interface{}) {
	log.SetOutput(l.out)
	log.Panicf(color.Sprint(l.color + fmt.Sprintf(format, v...)))
}

func (l *Logger) Fatal(v ...interface{}) {
	log.SetOutput(l.out)
	log.Fatal(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Fatalln(v ...interface{}) {
	log.SetOutput(l.out)
	log.Fatalln(color.Sprint(l.color + fmt.Sprint(v...)))
}

func (l *Logger) Fatalf(format string, v ...interface{}) {
	log.SetOutput(l.out)
	log.Fatalf(color.Sprint(l.color + fmt.Sprintf(format, v...)))
}
<commit_msg>Make Output and Color exported so users can configure each default Logger<commit_after>// Copyright 2015 Alex Browne.  All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

// package prtty is a small go library for logging things with color.
package prtty

import (
	"fmt"
	"github.com/wsxiaoys/terminal/color"
	"io"
	"log"
	"os"
)

const (
	// Color settings for the different logging functions
	// See: https://godoc.org/github.com/wsxiaoys/terminal/color
	defaultColor = "@w" // white
	infoColor    = "@c" // cyan
	warnColor    = "@y" // yellow
	successColor = "@g" // green
	errorColor   = "@r" // red
)

var (
	Default = NewLogger(os.Stdout, defaultColor)
	Info    = NewLogger(os.Stdout, infoColor)
	Warn    = NewLogger(os.Stdout, warnColor)
	Success = NewLogger(os.Stdout, successColor)
	Error   = NewLogger(os.Stderr, errorColor)
)

type Logger struct {
	Output io.Writer
	Color  string
}

func NewLogger(out io.Writer, color string) *Logger {
	return &Logger{
		Output: out,
		Color:  color,
	}
}

func (l *Logger) Print(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Print(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Println(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Println(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Printf(format string, v ...interface{}) {
	log.SetOutput(l.Output)
	log.Printf(color.Sprint(l.Color + fmt.Sprintf(format, v...)))
}

func (l *Logger) Panic(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Panic(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Panicln(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Panicln(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Panicf(format string, v ...interface{}) {
	log.SetOutput(l.Output)
	log.Panicf(color.Sprint(l.Color + fmt.Sprintf(format, v...)))
}

func (l *Logger) Fatal(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Fatal(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Fatalln(v ...interface{}) {
	log.SetOutput(l.Output)
	log.Fatalln(color.Sprint(l.Color + fmt.Sprint(v...)))
}

func (l *Logger) Fatalf(format string, v ...interface{}) {
	log.SetOutput(l.Output)
	log.Fatalf(color.Sprint(l.Color + fmt.Sprintf(format, v...)))
}
<|endoftext|>


<commit_before>// A framework that allows you to create your own web robots!
package gobot

import (
	"io/ioutil"
	"net/http"
    "net/url"
    "os"
    "log"
	"regexp"
    "runtime"
)

var (
	tagRe  = regexp.MustCompilePOSIX("<a[^>]*>")
	attrRe = regexp.MustCompilePOSIX("href=\"[^\"]*\"")
	urlRe  = regexp.MustCompilePOSIX("http://[^\"]*")
)

type VisitAction func(*http.Response)

type ErrorAction func(*http.Request)

type VisitDecision func(string)(bool)

type GoBot struct {
	http.Client
    OnVisit VisitAction
    OnError ErrorAction
    ShouldVisit VisitDecision
    visited map[string]bool
}

func NewGoBot() *GoBot {
    bot := new(GoBot)
    bot.OnVisit = defaultVisitAction
    bot.OnError = defaultErrorAction
    bot.ShouldVisit = defaultVisitDecision
    bot.Jar = NewBotCookieJar()
    bot.visited = make(map[string]bool)
    return bot
}

func (bot *GoBot) StartCrawl(seed string) {
    resp, err := bot.Get(seed)
    ncpu := runtime.NumCPU()
    runtime.GOMAXPROCS(ncpu)
    if err != nil {
        log.Printf("StartCrawl: ERROR\n")
    }
    urls := ExtractLinks(resp)
    for i, u := range urls {
        if i == (ncpu - 1) {
            break
        }
        go bot.Crawl(u)
    }
    bot.Crawl(seed)
}

func (bot *GoBot) Crawl(seed string) {
    queue := make([]string, 0)
    currUrl := seed

    for {
        resp, err := bot.Get(currUrl)
        for err != nil {
            go bot.OnError(resp.Request)
            if len(queue) > 0 {
                currUrl = queue[0]
                queue = queue[1:]
                resp, err = bot.Get(currUrl)
            } else {
                os.Exit(1) // TODO: Should find a better way to exit.
            }
        }

        go bot.OnVisit(resp)

        urls := ExtractLinks(resp)
        for _, url := range urls {
            _, present := bot.visited[url]
            if !present {
                queue = append(queue, url)
                bot.visited[url] = true
            }
        }

        if len(queue) > 0 {
            currUrl = queue[0]
            queue = queue[1:]
        } else {
            break
        }

    }
}

// Extracts all the links from the body of an http response.
func ExtractLinks(resp *http.Response) []string {
	urls := make([]string, 0)
	body := ResponseBodyToString(resp)
	tags := tagRe.FindAllString(body, -1)

	for _, tag := range tags {
		url := urlRe.FindString(attrRe.FindString(tag))
		if url != "" {
			urls = append(urls, url)
		}
	}
	return urls
}

// Returns a string of the body of an http response.
func ResponseBodyToString(resp *http.Response) string {
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}
	return string(body)
}

func defaultVisitAction(resp *http.Response) {
    request := resp.Request
    log.Printf("%s\n", request.URL.String())
}

func defaultErrorAction(resp *http.Request) {
}

func defaultVisitDecision(url string) bool {
    return true
}

type BotCookieJar struct {
    cookies map[string][]*http.Cookie
}

func NewBotCookieJar() *BotCookieJar {
    jar := new(BotCookieJar)
    jar.cookies = make(map[string][]*http.Cookie)
    return jar
}

func (jar *BotCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.cookies[u.Host] = cookies
}

func (jar *BotCookieJar) Cookies(u *url.URL) []*http.Cookie {
    return jar.cookies[u.Host]
}
<commit_msg>Fix code formating issues<commit_after>// A framework that allows you to create your own web robots!
package gobot

import (
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"runtime"
)

var (
	tagRe  = regexp.MustCompilePOSIX("<a[^>]*>")
	attrRe = regexp.MustCompilePOSIX("href=\"[^\"]*\"")
	urlRe  = regexp.MustCompilePOSIX("http://[^\"]*")
)

type VisitAction func(*http.Response)

type ErrorAction func(*http.Request)

type VisitDecision func(string) bool

type GoBot struct {
	http.Client
	OnVisit     VisitAction
	OnError     ErrorAction
	ShouldVisit VisitDecision
	visited     map[string]bool
}

func NewGoBot() *GoBot {
	bot := new(GoBot)
	bot.OnVisit = defaultVisitAction
	bot.OnError = defaultErrorAction
	bot.ShouldVisit = defaultVisitDecision
	bot.Jar = NewBotCookieJar()
	bot.visited = make(map[string]bool)
	return bot
}

func (bot *GoBot) StartCrawl(seed string) {
	resp, err := bot.Get(seed)
	ncpu := runtime.NumCPU()
	runtime.GOMAXPROCS(ncpu)
	if err != nil {
		log.Printf("StartCrawl: ERROR\n")
	}
	urls := ExtractLinks(resp)
	for i, u := range urls {
		if i == (ncpu - 1) {
			break
		}
		go bot.Crawl(u)
	}
	bot.Crawl(seed)
}

func (bot *GoBot) Crawl(seed string) {
	queue := make([]string, 0)
	currUrl := seed

	for {
		resp, err := bot.Get(currUrl)
		for err != nil {
			go bot.OnError(resp.Request)
			if len(queue) > 0 {
				currUrl = queue[0]
				queue = queue[1:]
				resp, err = bot.Get(currUrl)
			} else {
				os.Exit(1) // TODO: Should find a better way to exit.
			}
		}

		go bot.OnVisit(resp)

		urls := ExtractLinks(resp)
		for _, url := range urls {
			_, present := bot.visited[url]
			if !present {
				queue = append(queue, url)
				bot.visited[url] = true
			}
		}

		if len(queue) > 0 {
			currUrl = queue[0]
			queue = queue[1:]
		} else {
			break
		}

	}
}

// Extracts all the links from the body of an http response.
func ExtractLinks(resp *http.Response) []string {
	urls := make([]string, 0)
	body := ResponseBodyToString(resp)
	tags := tagRe.FindAllString(body, -1)

	for _, tag := range tags {
		url := urlRe.FindString(attrRe.FindString(tag))
		if url != "" {
			urls = append(urls, url)
		}
	}
	return urls
}

// Returns a string of the body of an http response.
func ResponseBodyToString(resp *http.Response) string {
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return ""
	}
	return string(body)
}

func defaultVisitAction(resp *http.Response) {
	request := resp.Request
	log.Printf("%s\n", request.URL.String())
}

func defaultErrorAction(resp *http.Request) {
}

func defaultVisitDecision(url string) bool {
	return true
}

type BotCookieJar struct {
	cookies map[string][]*http.Cookie
}

func NewBotCookieJar() *BotCookieJar {
	jar := new(BotCookieJar)
	jar.cookies = make(map[string][]*http.Cookie)
	return jar
}

func (jar *BotCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
	jar.cookies[u.Host] = cookies
}

func (jar *BotCookieJar) Cookies(u *url.URL) []*http.Cookie {
	return jar.cookies[u.Host]
}
<|endoftext|>


<commit_before>package main

var authTopic = &Topic{
	Name:        "auth",
	Description: "authentication (login/logout)",
}

var whoamiCmd = &Command{
	Topic:       "auth",
	Command:     "whoami",
	Description: "display your Heroku login",
	Default:     true,
	Help: `Example:

  $ heroku auth:whoami
	email@example.com`,
	Run: func(ctx *Context) {
		// don't use needsToken since this should fail if
		// not logged in. Should not show a login prompt.
		ctx.APIToken = apiToken()

		if ctx.APIToken == "" {
			Println("not logged in")
			Exit(100)
		}

		req := apiRequest(ctx.APIToken)
		req.Method = "GET"
		req.Uri = req.Uri + "/account"
		res, err := req.Do()
		ExitIfError(err)
		var doc map[string]interface{}
		res.Body.FromJsonTo(&doc)
		Println(doc["email"])
	},
}
<commit_msg>fixed auth:whoami for invalid api keys<commit_after>package main

var authTopic = &Topic{
	Name:        "auth",
	Description: "authentication (login/logout)",
}

var whoamiCmd = &Command{
	Topic:       "auth",
	Command:     "whoami",
	Description: "display your Heroku login",
	Default:     true,
	Help: `Example:

  $ heroku auth:whoami
	email@example.com`,
	Run: func(ctx *Context) {
		// don't use needsToken since this should fail if
		// not logged in. Should not show a login prompt.
		ctx.APIToken = apiToken()

		if ctx.APIToken == "" {
			Println("not logged in")
			Exit(100)
		}

		req := apiRequest(ctx.APIToken)
		req.Method = "GET"
		req.Uri = req.Uri + "/account"
		res, err := req.Do()
		ExitIfError(err)
		if res.StatusCode != 200 {
			Println("not logged in")
			Exit(100)
		}
		var doc map[string]interface{}
		res.Body.FromJsonTo(&doc)
		Println(doc["email"])
	},
}
<|endoftext|>


<commit_before>package widget

import (
	"fmt"
	"html/template"
	"os"
	"path/filepath"

	"github.com/jinzhu/gorm"
	"github.com/qor/admin"
	"github.com/qor/assetfs"
	"github.com/qor/qor/resource"
	"github.com/qor/roles"
)

var (
	root, _                = os.Getwd()
	viewPaths              []string
	registeredWidgets      []*Widget
	registeredWidgetsGroup []*WidgetsGroup
)

// Config widget config
type Config struct {
	DB            *gorm.DB
	Admin         *admin.Admin
	PreviewAssets []string
}

func init() {
	if path := os.Getenv("WEB_ROOT"); path != "" {
		root = path
	}
}

// New new widgets container
func New(config *Config) *Widgets {
	widgets := &Widgets{Config: config, funcMaps: template.FuncMap{}, AssetFS: assetfs.AssetFS().NameSpace("widgets")}

	if root != "" {
		widgets.RegisterViewPath(filepath.Join(root, "app/views/widgets"))
	}
	widgets.RegisterViewPath("app/views/widgets")
	return widgets
}

// Widgets widgets container
type Widgets struct {
	funcMaps              template.FuncMap
	Config                *Config
	Resource              *admin.Resource
	AssetFS               assetfs.Interface
	WidgetSettingResource *admin.Resource
}

// SetAssetFS set asset fs for render
func (widgets *Widgets) SetAssetFS(assetFS assetfs.Interface) {
	for _, viewPath := range viewPaths {
		assetFS.RegisterPath(viewPath)
	}

	widgets.AssetFS = assetFS
}

// RegisterWidget register a new widget
func (widgets *Widgets) RegisterWidget(w *Widget) {
	registeredWidgets = append(registeredWidgets, w)
}

// RegisterWidgetsGroup register widgets group
func (widgets *Widgets) RegisterWidgetsGroup(group *WidgetsGroup) {
	registeredWidgetsGroup = append(registeredWidgetsGroup, group)
}

// RegisterFuncMap register view funcs, it could be used when render templates
func (widgets *Widgets) RegisterFuncMap(name string, fc interface{}) {
	widgets.funcMaps[name] = fc
}

// ConfigureQorResourceBeforeInitialize a method used to config Widget for qor admin
func (widgets *Widgets) ConfigureQorResourceBeforeInitialize(res resource.Resourcer) {
	if res, ok := res.(*admin.Resource); ok {
		// register view paths
		res.GetAdmin().RegisterViewPath("github.com/qor/widget/views")

		// set resources
		widgets.Resource = res

		// set setting resource
		if widgets.WidgetSettingResource == nil {
			widgets.WidgetSettingResource = res.GetAdmin().NewResource(&QorWidgetSetting{}, &admin.Config{Name: res.Name})
		}

		res.Name = widgets.WidgetSettingResource.Name

		for funcName, fc := range funcMap {
			res.GetAdmin().RegisterFuncMap(funcName, fc)
		}

		// configure routes
		controller := widgetController{Widgets: widgets}
		router := res.GetAdmin().GetRouter()
		router.Get(widgets.WidgetSettingResource.ToParam(), controller.Index, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/new", widgets.WidgetSettingResource.ToParam()), controller.New, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/!setting", widgets.WidgetSettingResource.ToParam()), controller.Setting, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Edit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v/!preview", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Preview, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v/edit", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Edit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Put(fmt.Sprintf("%v/%v", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Update, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Post(widgets.WidgetSettingResource.ToParam(), controller.Update, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/inline-edit", res.ToParam()), controller.InlineEdit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
	}
}

// Widget widget struct
type Widget struct {
	Name          string
	PreviewIcon   string
	Group         string
	Templates     []string
	Setting       *admin.Resource
	Permission    *roles.Permission
	InlineEditURL func(*Context) string
	Context       func(context *Context, setting interface{}) *Context
}

// WidgetsGroup widgets Group
type WidgetsGroup struct {
	Name    string
	Widgets []string
}

// GetWidget get widget by name
func GetWidget(name string) *Widget {
	for _, w := range registeredWidgets {
		if w.Name == name {
			return w
		}
	}

	for _, g := range registeredWidgetsGroup {
		if g.Name == name {
			for _, widgetName := range g.Widgets {
				return GetWidget(widgetName)
			}
		}
	}
	return nil
}
<commit_msg>Use utils.AppRoot<commit_after>package widget

import (
	"fmt"
	"html/template"
	"path/filepath"

	"github.com/jinzhu/gorm"
	"github.com/qor/admin"
	"github.com/qor/assetfs"
	"github.com/qor/qor/resource"
	"github.com/qor/qor/utils"
	"github.com/qor/roles"
)

var (
	viewPaths              []string
	registeredWidgets      []*Widget
	registeredWidgetsGroup []*WidgetsGroup
)

// Config widget config
type Config struct {
	DB            *gorm.DB
	Admin         *admin.Admin
	PreviewAssets []string
}

// New new widgets container
func New(config *Config) *Widgets {
	widgets := &Widgets{Config: config, funcMaps: template.FuncMap{}, AssetFS: assetfs.AssetFS().NameSpace("widgets")}

	if utils.AppRoot != "" {
		widgets.RegisterViewPath(filepath.Join(utils.AppRoot, "app/views/widgets"))
	}
	widgets.RegisterViewPath("app/views/widgets")
	return widgets
}

// Widgets widgets container
type Widgets struct {
	funcMaps              template.FuncMap
	Config                *Config
	Resource              *admin.Resource
	AssetFS               assetfs.Interface
	WidgetSettingResource *admin.Resource
}

// SetAssetFS set asset fs for render
func (widgets *Widgets) SetAssetFS(assetFS assetfs.Interface) {
	for _, viewPath := range viewPaths {
		assetFS.RegisterPath(viewPath)
	}

	widgets.AssetFS = assetFS
}

// RegisterWidget register a new widget
func (widgets *Widgets) RegisterWidget(w *Widget) {
	registeredWidgets = append(registeredWidgets, w)
}

// RegisterWidgetsGroup register widgets group
func (widgets *Widgets) RegisterWidgetsGroup(group *WidgetsGroup) {
	registeredWidgetsGroup = append(registeredWidgetsGroup, group)
}

// RegisterFuncMap register view funcs, it could be used when render templates
func (widgets *Widgets) RegisterFuncMap(name string, fc interface{}) {
	widgets.funcMaps[name] = fc
}

// ConfigureQorResourceBeforeInitialize a method used to config Widget for qor admin
func (widgets *Widgets) ConfigureQorResourceBeforeInitialize(res resource.Resourcer) {
	if res, ok := res.(*admin.Resource); ok {
		// register view paths
		res.GetAdmin().RegisterViewPath("github.com/qor/widget/views")

		// set resources
		widgets.Resource = res

		// set setting resource
		if widgets.WidgetSettingResource == nil {
			widgets.WidgetSettingResource = res.GetAdmin().NewResource(&QorWidgetSetting{}, &admin.Config{Name: res.Name})
		}

		res.Name = widgets.WidgetSettingResource.Name

		for funcName, fc := range funcMap {
			res.GetAdmin().RegisterFuncMap(funcName, fc)
		}

		// configure routes
		controller := widgetController{Widgets: widgets}
		router := res.GetAdmin().GetRouter()
		router.Get(widgets.WidgetSettingResource.ToParam(), controller.Index, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/new", widgets.WidgetSettingResource.ToParam()), controller.New, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/!setting", widgets.WidgetSettingResource.ToParam()), controller.Setting, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Edit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v/!preview", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Preview, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/%v/edit", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Edit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Put(fmt.Sprintf("%v/%v", widgets.WidgetSettingResource.ToParam(), widgets.WidgetSettingResource.ParamIDName()), controller.Update, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Post(widgets.WidgetSettingResource.ToParam(), controller.Update, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
		router.Get(fmt.Sprintf("%v/inline-edit", res.ToParam()), controller.InlineEdit, &admin.RouteConfig{Resource: widgets.WidgetSettingResource})
	}
}

// Widget widget struct
type Widget struct {
	Name          string
	PreviewIcon   string
	Group         string
	Templates     []string
	Setting       *admin.Resource
	Permission    *roles.Permission
	InlineEditURL func(*Context) string
	Context       func(context *Context, setting interface{}) *Context
}

// WidgetsGroup widgets Group
type WidgetsGroup struct {
	Name    string
	Widgets []string
}

// GetWidget get widget by name
func GetWidget(name string) *Widget {
	for _, w := range registeredWidgets {
		if w.Name == name {
			return w
		}
	}

	for _, g := range registeredWidgetsGroup {
		if g.Name == name {
			for _, widgetName := range g.Widgets {
				return GetWidget(widgetName)
			}
		}
	}
	return nil
}
<|endoftext|>


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

package net

import (
	"errors"
	"os"
)

func query(filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, 0)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query("/net/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("net: bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(addr string, typ string) (res []string, err error) {
	return query("/net/dns", addr+" "+typ, 1024)
}

// toLower returns a lower-case version of in. Restricting us to
// ASCII is sufficient to handle the IP protocol names and allow
// us to not depend on the strings and unicode packages.
func toLower(in string) string {
	isAlreadyLowerCase := true
	for _, c := range in {
		if 'A' <= c && c <= 'Z' {
			isAlreadyLowerCase = false
			break
		}
	}
	if isAlreadyLowerCase {
		return in
	}
	out := []byte(in)
	for i, c := range out {
		if 'A' <= c && c <= 'Z' {
			out[i] += 'a' - 'A'
		}
	}
	return string(out)
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
	lines, err := query("/net/cs", "!protocol="+toLower(name), 128)
	if err != nil {
		return 0, err
	}
	unknownProtoError := errors.New("unknown IP protocol specified: " + name)
	if len(lines) == 0 {
		return 0, unknownProtoError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownProtoError
	}
	s := f[1]
	if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
		return n, nil
	}
	return 0, unknownProtoError
}

func lookupHost(host string) (addrs []string, err error) {
	// Use /net/cs instead of /net/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS("net", host, "1")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		addrs = append(addrs, addr)
	}
	return
}

func lookupIP(host string) (ips []IP, err error) {
	addrs, err := LookupHost(host)
	if err != nil {
		return
	}
	for _, addr := range addrs {
		if ip := ParseIP(addr); ip != nil {
			ips = append(ips, ip)
		}
	}
	return
}

func lookupPort(network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(network, "127.0.0.1", service)
	if err != nil {
		return
	}
	unknownPortError := &AddrError{"unknown port", network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s, 0); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func lookupCNAME(name string) (cname string, err error) {
	lines, err := queryDNS(name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("net: bad response from ndb/dns")
}

func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4], 0)
		priority, _, priorityOk := dtoi(f[3], 0)
		weight, _, weightOk := dtoi(f[2], 0)
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
		cname = f[0]
	}
	byPriorityWeight(addrs).sort()
	return
}

func lookupMX(name string) (mx []*MX, err error) {
	lines, err := queryDNS(name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2], 0); ok {
			mx = append(mx, &MX{f[3], uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func lookupNS(name string) (ns []*NS, err error) {
	lines, err := queryDNS(name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{f[2]})
	}
	return
}

func lookupTXT(name string) (txt []string, err error) {
	lines, err := queryDNS(name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, line[i+1:])
		}
	}
	return
}

func lookupAddr(addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, f[2])
	}
	return
}
<commit_msg>net: rewrite toLower more clearly<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
	"errors"
	"os"
)

func query(filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, 0)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query("/net/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("net: bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(addr string, typ string) (res []string, err error) {
	return query("/net/dns", addr+" "+typ, 1024)
}

// toLower returns a lower-case version of in. Restricting us to
// ASCII is sufficient to handle the IP protocol names and allow
// us to not depend on the strings and unicode packages.
func toLower(in string) string {
	for _, c := range in {
		if 'A' <= c && c <= 'Z' {
			// Has upper case; need to fix.
			out := []byte(in)
			for i := 0; i < len(in); i++ {
				c := in[i]
				if 'A' <= c && c <= 'Z' {
					c += 'a' - 'A'
				}
				out[i] = c
			}
			return string(out)
		}
	}
	return in
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(name string) (proto int, err error) {
	lines, err := query("/net/cs", "!protocol="+toLower(name), 128)
	if err != nil {
		return 0, err
	}
	unknownProtoError := errors.New("unknown IP protocol specified: " + name)
	if len(lines) == 0 {
		return 0, unknownProtoError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownProtoError
	}
	s := f[1]
	if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
		return n, nil
	}
	return 0, unknownProtoError
}

func lookupHost(host string) (addrs []string, err error) {
	// Use /net/cs instead of /net/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS("net", host, "1")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		addrs = append(addrs, addr)
	}
	return
}

func lookupIP(host string) (ips []IP, err error) {
	addrs, err := LookupHost(host)
	if err != nil {
		return
	}
	for _, addr := range addrs {
		if ip := ParseIP(addr); ip != nil {
			ips = append(ips, ip)
		}
	}
	return
}

func lookupPort(network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(network, "127.0.0.1", service)
	if err != nil {
		return
	}
	unknownPortError := &AddrError{"unknown port", network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s, 0); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func lookupCNAME(name string) (cname string, err error) {
	lines, err := queryDNS(name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("net: bad response from ndb/dns")
}

func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4], 0)
		priority, _, priorityOk := dtoi(f[3], 0)
		weight, _, weightOk := dtoi(f[2], 0)
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
		cname = f[0]
	}
	byPriorityWeight(addrs).sort()
	return
}

func lookupMX(name string) (mx []*MX, err error) {
	lines, err := queryDNS(name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2], 0); ok {
			mx = append(mx, &MX{f[3], uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func lookupNS(name string) (ns []*NS, err error) {
	lines, err := queryDNS(name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{f[2]})
	}
	return
}

func lookupTXT(name string) (txt []string, err error) {
	lines, err := queryDNS(name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, line[i+1:])
		}
	}
	return
}

func lookupAddr(addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, f[2])
	}
	return
}
<|endoftext|>


<commit_before>/*
This tool recursively searches $SRCSEARCHROOT for the directory queried and will return the path
of the most shallow result. Directories are searched in lexicographic order.
*/

package main

import (
	"container/list"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

const envRootVar = "SRCSEARCHROOT"

var (
	errNotFound = errors.New("could not find directory")

	ignoreHidden = flag.Bool("ignorehidden", true, "ignore hidden directories")
	maxDepth     = flag.Int("maxdepth", 5, "maximum search depth")
)

type location struct {
	path  string
	depth int
}

func search(dir string, names []string, startdepth int) (path string, err error) {
	q := list.New()
	q.PushBack(location{dir, startdepth})
	for q.Len() > 0 {
		front := q.Front()
		cloc := q.Remove(front).(location)
		entries, err := ioutil.ReadDir(cloc.path)
		if err != nil {
			return "", err
		}
		for _, e := range entries {
			if !e.IsDir() || (*ignoreHidden && strings.HasPrefix(e.Name(), ".")) {
				continue
			}
			absPath := cloc.path + "/" + e.Name()
			if e.Name() == names[0] {
				if len(names) == 1 {
					return absPath, nil
				} else if subPath, err := search(absPath, names[1:], cloc.depth+1); err == nil {
					return subPath, nil
				}
			}
			if cloc.depth < *maxDepth {
				q.PushBack(location{absPath, cloc.depth + 1})
			}
		}
	}
	return "", errNotFound
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s dirname[/subdir/...]\n", os.Args[0])
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	if len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(1)
	}
	searchpath := flag.Arg(0)
	root := os.Getenv(envRootVar)
	if root == "" {
		fmt.Fprintln(os.Stderr, envRootVar+" must be set.")
		os.Exit(2)
	}
	names := strings.Split(searchpath, string(os.PathSeparator))
	p, err := search(root, names, 0)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(3)
	}
	fmt.Println(p)
}
<commit_msg>Update docs<commit_after>/*
This tool recursively searches $SRCSEARCHROOT for the directory queried and will return the path
of the most shallow result. Directories are searched in lexicographic order.

A bash include file is included with this tool that adds a scd command which uses srcsearch to
quickly cd into a workspace.
*/

package main

import (
	"container/list"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

const envRootVar = "SRCSEARCHROOT"

var (
	errNotFound = errors.New("could not find directory")

	ignoreHidden = flag.Bool("ignorehidden", true, "ignore hidden directories")
	maxDepth     = flag.Int("maxdepth", 5, "maximum search depth")
)

type location struct {
	path  string
	depth int
}

func search(dir string, names []string, startdepth int) (path string, err error) {
	q := list.New()
	q.PushBack(location{dir, startdepth})
	for q.Len() > 0 {
		front := q.Front()
		cloc := q.Remove(front).(location)
		entries, err := ioutil.ReadDir(cloc.path)
		if err != nil {
			return "", err
		}
		for _, e := range entries {
			if !e.IsDir() || (*ignoreHidden && strings.HasPrefix(e.Name(), ".")) {
				continue
			}
			absPath := cloc.path + "/" + e.Name()
			if e.Name() == names[0] {
				if len(names) == 1 {
					return absPath, nil
				} else if subPath, err := search(absPath, names[1:], cloc.depth+1); err == nil {
					return subPath, nil
				}
			}
			if cloc.depth < *maxDepth {
				q.PushBack(location{absPath, cloc.depth + 1})
			}
		}
	}
	return "", errNotFound
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: %s dirname[/subdir/...]\n", os.Args[0])
	flag.PrintDefaults()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	if len(flag.Args()) == 0 {
		flag.Usage()
		os.Exit(1)
	}
	searchpath := flag.Arg(0)
	root := os.Getenv(envRootVar)
	if root == "" {
		fmt.Fprintln(os.Stderr, envRootVar+" must be set.")
		os.Exit(2)
	}
	names := strings.Split(searchpath, string(os.PathSeparator))
	p, err := search(root, names, 0)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(3)
	}
	fmt.Println(p)
}
<|endoftext|>