<commit_before>package base

import (
	"net/http"

	"github.com/webx-top/echo"
	X "github.com/webx-top/webx"
	"github.com/webx-top/webx/lib/codec"
	"github.com/webx-top/webx/lib/htmlcache"
	"github.com/webx-top/webx/lib/i18n"
)

func NewController() *Controller {
	return &Controller{
		tmplField: `Tmpl`,
		dataField: `Data`,
		Codec:     codec.Default,
	}
}

type Controller struct {
	tmplField     string //模板名称字段名称
	dataField     string //模板数据字段名称
	CookiePrefix  string
	CookieSecret  bool
	CookieAuthkey string
	CookieExpires int64
	CookieDomain  string
	codec.Codec
}

//设置退出标记
func (a *Controller) Exit(c echo.Context) {
	c.Set(`web:exit`, true)
}

//获取模板名称字段名
func (a *Controller) TmplField() string {
	return a.tmplField
}

//获取模板数据字段名
func (a *Controller) DataField() string {
	return a.dataField
}

//指定模板
func (a *Controller) Tmpl(tmpl string, c echo.Context) {
	c.Set(a.tmplField, tmpl)
}

//模板数据赋值
func (a *Controller) Assign(data interface{}, c echo.Context) {
	switch data.(type) {
	case map[string]interface{}:
		d := data.(map[string]interface{})
		v, ok := c.Get(a.dataField).(map[string]interface{})
		if ok {
			for key, val := range d {
				v[key] = val
			}
		} else {
			v = d
		}
		c.Set(a.dataField, v)
	default:
		c.Set(a.dataField, data)
	}
}

//渲染模板
func (a *Controller) Render(c echo.Context) error {
	if ignore, _ := c.Get(`webx:ignoreRender`).(bool); ignore {
		return nil
	}
	return htmlcache.Render(c, http.StatusOK)
}

func (a *Controller) Before(c echo.Context) error {
	Xsrf.Register(c)
	c.SetFunc("Query", c.Query)
	c.SetFunc("Form", c.Form)
	a.Assign(map[string]interface{}{"Status": 1, "Message": "", "Path": c.Path()}, c)
	return nil
}

func (a *Controller) After(c echo.Context) error {
	return a.Render(c)
}

func (a *Controller) Lang(c echo.Context) string {
	lang, _ := c.Get(`webx:language`).(string)
	if lang == `` {
		lang = DefaultLang
	}
	return lang
}

//TODO: 移到echo.Context中
func (a *Controller) T(c echo.Context, key string, args ...interface{}) string {
	return i18n.T(a.Lang(c), key, args...)
}

func (a *Controller) X(c echo.Context) *X.Context {
	return c.(*X.Context)
}
<commit_msg>update<commit_after>package base

import (
	"net/http"

	"github.com/webx-top/echo"
	X "github.com/webx-top/webx"
	"github.com/webx-top/webx/lib/htmlcache"
	"github.com/webx-top/webx/lib/i18n"
)

func NewController() *Controller {
	return &Controller{
		tmplField: `Tmpl`,
		dataField: `Data`,
	}
}

type Controller struct {
	tmplField string //模板名称字段名称
	dataField string //模板数据字段名称
}

//设置退出标记
func (a *Controller) Exit(c echo.Context) {
	c.Set(`web:exit`, true)
}

//获取模板名称字段名
func (a *Controller) TmplField() string {
	return a.tmplField
}

//获取模板数据字段名
func (a *Controller) DataField() string {
	return a.dataField
}

//指定模板
func (a *Controller) Tmpl(tmpl string, c echo.Context) {
	c.Set(a.tmplField, tmpl)
}

//模板数据赋值
func (a *Controller) Assign(data interface{}, c echo.Context) {
	switch data.(type) {
	case map[string]interface{}:
		d := data.(map[string]interface{})
		v, ok := c.Get(a.dataField).(map[string]interface{})
		if ok {
			for key, val := range d {
				v[key] = val
			}
		} else {
			v = d
		}
		c.Set(a.dataField, v)
	default:
		c.Set(a.dataField, data)
	}
}

//渲染模板
func (a *Controller) Render(c echo.Context) error {
	if ignore, _ := c.Get(`webx:ignoreRender`).(bool); ignore {
		return nil
	}
	return htmlcache.Render(c, http.StatusOK)
}

func (a *Controller) Before(c echo.Context) error {
	Xsrf.Register(c)
	c.SetFunc("Query", c.Query)
	c.SetFunc("Form", c.Form)
	a.Assign(map[string]interface{}{"Status": 1, "Message": "", "Path": c.Path()}, c)
	return nil
}

func (a *Controller) After(c echo.Context) error {
	return a.Render(c)
}

func (a *Controller) Lang(c echo.Context) string {
	lang, _ := c.Get(`webx:language`).(string)
	if lang == `` {
		lang = DefaultLang
	}
	return lang
}

//TODO: 移到echo.Context中
func (a *Controller) T(c echo.Context, key string, args ...interface{}) string {
	return i18n.T(a.Lang(c), key, args...)
}

func (a *Controller) X(c echo.Context) *X.Context {
	return c.(*X.Context)
}
<|endoftext|>


<commit_before>// +build windows

package jibber_jabber

import (
	"errors"
	"fmt"
	"syscall"
	"unsafe"
)

const LOCALE_NAME_MAX_LENGTH uint32 = 85

var SUPPORTED_LOCALES = map[uintptr]string{
	0x0407: "de-DE",
	0x0409: "en-US",
	0x0c0a: "es-ES", //or is it 0x040a
	0x040c: "fr-FR",
	0x0410: "it-IT",
	0x0411: "ja-JA",
	//0x0412: "ko_KO", - Will add support for Korean when nicksnyder/go-i18n supports Korean
	0x0416: "pt-BR",
	//0x0419: "ru_RU", - Will add support for Russian when nicksnyder/go-i18n supports Russian
	0x0804: "zh-CN",
	0x0c04: "zh-CK",
}

func getWindowsLocaleFrom(sysCall string) (locale string, err error) {
	buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH)

	dll := syscall.MustLoadDLL("kernel32")
	proc := dll.MustFindProc(sysCall)
	r, _, dllError := proc.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(LOCALE_NAME_MAX_LENGTH))
	if r == 0 {
		err = errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
		return
	}

	locale = syscall.UTF16ToString(buffer)

	return
}

func getAllWindowsLocaleFrom(sysCall string) (string, error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc(sysCall)
	if err != nil {
		return "", err
	}

	r, locale, dllError := proc.Call()
	if r == 0 {
		return "", errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
	}

	return SUPPORTED_LOCALES[locale], nil
}

func getWindowsLocale() (locale string, err error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc("IsWindowsVistaOrGreater")
	if err != nil {
		return "", err
	}

	r, isVistaOrGreater, dllError := proc.Call()
	if r == 0 {
		return "", errors.New("Could not determine if the version of Windows is Vista or later:\n" + dllError.Error())
	}

	if isVistaOrGreater == 1 {
		locale, err = getWindowsLocaleFrom("GetUserDefaultLocaleName")
		if err != nil {
			locale, err = getWindowsLocaleFrom("GetSystemDefaultLocaleName")
		}
	} else if isVistaOrGreater == 0 {
		locale, err = getAllWindowsLocaleFrom("GetUserDefaultLCID")
		if err != nil {
			locale, err = getAllWindowsLocaleFrom("GetSystemDefaultLCID")
		}
	} else {
		panic(isVistaOrGreater)
	}
	return
}
func DetectIETF() (locale string, err error) {
	locale, err = getWindowsLocale()
	return
}

func DetectLanguage() (language string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		language, _ = splitLocale(windows_locale)
	}

	return
}

func DetectTerritory() (territory string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		_, territory = splitLocale(windows_locale)
	}

	return
}
<commit_msg>Remove unused import<commit_after>// +build windows

package jibber_jabber

import (
	"errors"
	"syscall"
	"unsafe"
)

const LOCALE_NAME_MAX_LENGTH uint32 = 85

var SUPPORTED_LOCALES = map[uintptr]string{
	0x0407: "de-DE",
	0x0409: "en-US",
	0x0c0a: "es-ES", //or is it 0x040a
	0x040c: "fr-FR",
	0x0410: "it-IT",
	0x0411: "ja-JA",
	//0x0412: "ko_KO", - Will add support for Korean when nicksnyder/go-i18n supports Korean
	0x0416: "pt-BR",
	//0x0419: "ru_RU", - Will add support for Russian when nicksnyder/go-i18n supports Russian
	0x0804: "zh-CN",
	0x0c04: "zh-CK",
}

func getWindowsLocaleFrom(sysCall string) (locale string, err error) {
	buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH)

	dll := syscall.MustLoadDLL("kernel32")
	proc := dll.MustFindProc(sysCall)
	r, _, dllError := proc.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(LOCALE_NAME_MAX_LENGTH))
	if r == 0 {
		err = errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
		return
	}

	locale = syscall.UTF16ToString(buffer)

	return
}

func getAllWindowsLocaleFrom(sysCall string) (string, error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc(sysCall)
	if err != nil {
		return "", err
	}

	r, locale, dllError := proc.Call()
	if r == 0 {
		return "", errors.New(COULD_NOT_DETECT_PACKAGE_ERROR_MESSAGE + ":\n" + dllError.Error())
	}

	return SUPPORTED_LOCALES[locale], nil
}

func getWindowsLocale() (locale string, err error) {
	dll, err := syscall.LoadDLL("kernel32")
	if err != nil {
		return "", errors.New("Could not find kernel32 dll")
	}

	proc, err := dll.FindProc("IsWindowsVistaOrGreater")
	if err != nil {
		return "", err
	}

	r, isVistaOrGreater, dllError := proc.Call()
	if r == 0 {
		return "", errors.New("Could not determine if the version of Windows is Vista or later:\n" + dllError.Error())
	}

	if isVistaOrGreater == 1 {
		locale, err = getWindowsLocaleFrom("GetUserDefaultLocaleName")
		if err != nil {
			locale, err = getWindowsLocaleFrom("GetSystemDefaultLocaleName")
		}
	} else if isVistaOrGreater == 0 {
		locale, err = getAllWindowsLocaleFrom("GetUserDefaultLCID")
		if err != nil {
			locale, err = getAllWindowsLocaleFrom("GetSystemDefaultLCID")
		}
	} else {
		panic(isVistaOrGreater)
	}
	return
}
func DetectIETF() (locale string, err error) {
	locale, err = getWindowsLocale()
	return
}

func DetectLanguage() (language string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		language, _ = splitLocale(windows_locale)
	}

	return
}

func DetectTerritory() (territory string, err error) {
	windows_locale, err := getWindowsLocale()
	if err == nil {
		_, territory = splitLocale(windows_locale)
	}

	return
}
<|endoftext|>


<commit_before>package services

import (
	"github.com/gtarcea/1DevDayTalk2014/app"
	"github.com/gtarcea/1DevDayTalk2014/schema"
)

type usersDB struct {
	users map[string]schema.User
}

func NewUsersDB() app.UserDBService {
	return &usersDB{
		users: make(map[string]schema.User),
	}
}

func (db *usersDB) GetByEmail(email string) (schema.User, error) {
	user, ok := db.users[email]
	if !ok {
		return schema.User{}, app.ErrNotFound
	}

	return user, nil
}

func (db *usersDB) GetAll() ([]schema.User, error) {
	users := make([]schema.User, 0, len(db.users))
	i := 0
	for _, user := range db.users {
		users = append(users, user)
		i++
	}
	return users, nil
}

func (db *usersDB) Insert(email, fullname string) (schema.User, error) {
	u := schema.User{
		Email:    email,
		Fullname: fullname,
	}
	db.users[email] = u
	return u, nil
}
<commit_msg>Add comments and synchronize access to the map.<commit_after>package services

import (
	"sync"

	"github.com/gtarcea/1DevDayTalk2014/app"
	"github.com/gtarcea/1DevDayTalk2014/schema"
)

// usersDB implements an in memory db store. It synchronizes
// access to the underlying map.
type usersDB struct {
	users map[string]schema.User
	mutex sync.RWMutex
}

// NewUsersDB creates a new instance of the usersDB.
func NewUsersDB() app.UserDBService {
	return &usersDB{
		users: make(map[string]schema.User),
	}
}

// GetByEmail looks up a user by their email address. It returns
// ErrNotFound if the email could not be found.
func (db *usersDB) GetByEmail(email string) (schema.User, error) {
	defer db.mutex.RUnlock()
	db.mutex.RLock()

	user, ok := db.users[email]
	if !ok {
		return schema.User{}, app.ErrNotFound
	}

	return user, nil
}

// GetAll returns all known users. It will return an empty list
// if there are no users.
func (db *usersDB) GetAll() ([]schema.User, error) {
	defer db.mutex.RUnlock()
	db.mutex.RLock()

	users := make([]schema.User, 0, len(db.users))
	i := 0
	for _, user := range db.users {
		users = append(users, user)
		i++
	}
	return users, nil
}

// Insert adds a new user to the system.
func (db *usersDB) Insert(email, fullname string) (schema.User, error) {
	defer db.mutex.Unlock()
	db.mutex.Lock()

	u := schema.User{
		Email:    email,
		Fullname: fullname,
	}
	db.users[email] = u
	return u, nil
}
<|endoftext|>


<commit_before>package cliedit

import (
	"strings"
	"testing"

	"github.com/elves/elvish/cli"
	"github.com/elves/elvish/cli/term"
	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/eval/vars"
	"github.com/elves/elvish/styled"
)

func TestPrompt_ValueOutput(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(
		`edit:prompt = { put 'val'; styled '> ' red }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("val").WriteStyled(styled.MakeText("> ", "red")).
			SetDotToCursor().Buffer())
}

func TestPrompt_ByteOutput(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(`edit:prompt = { put 'bytes> ' }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("bytes> ").SetDotToCursor().Buffer())
}

func TestPrompt_NotifiesInvalidValueOutput(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(`edit:prompt = { put good [bad] good2 }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("goodgood2").SetDotToCursor().Buffer())
	ttyCtrl.TestNotesBuffer(t, bb().
		WritePlain("invalid output type from prompt: list").Buffer())
}

func TestPrompt_NotifiesException(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(`edit:prompt = { fail ERROR }`)
	defer cleanup()

	ttyCtrl.TestNotesBuffer(t, bb().
		WritePlain("prompt function error: ERROR").Buffer())
}

func TestRPrompt(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(`edit:rprompt = { put 'RRR' }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("~> ").SetDotToCursor().
			WritePlain(strings.Repeat(" ", testTTYWidth-6)+"RRR").Buffer())
}

func TestPromptEagerness(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(
		`i = 0`,
		`edit:prompt = { i = (+ $i 1); put $i'> ' }`,
		`edit:-prompt-eagerness = 10`)
	defer cleanup()

	wantBuf1 := bb().WritePlain("1> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf1)
	// With eagerness = 10, any key press will cause the prompt to be
	// recomputed.
	ttyCtrl.Inject(term.K(ui.Backspace))
	wantBuf2 := bb().WritePlain("2> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf2)
}

func TestPromptStaleThreshold(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(
		`edit:prompt = { esleep 0.1; put '> ' }`,
		`edit:prompt-stale-threshold = 0.05`)
	defer cleanup()

	wantBufStale := bb().
		WriteStyled(styled.MakeText("???> ", "inverse")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufStale)

	wantBufFresh := bb().WritePlain("> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufFresh)
}

func TestPromptStaleTransform(t *testing.T) {
	ttyCtrl, cleanup := setupWithRC(
		`edit:prompt = { esleep 0.1; put '> ' }`,
		`edit:prompt-stale-threshold = 0.05`,
		`edit:prompt-stale-transform = [a]{ put S; put $a; put S }`)
	defer cleanup()

	wantBufStale := bb().
		WriteStyled(styled.Plain("S???> S")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufStale)
}

func TestDefaultPromptForNonRoot(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultPrompt(false))
	evalf(ev, `edit:prompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func TestDefaultPromptForRoot(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultPrompt(true))
	evalf(ev, `edit:prompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~").
		WriteStyled(styled.MakeText("# ", "red")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func TestDefaultRPrompt(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultRPrompt("elf", "host"))
	evalf(ev, `edit:rprompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~> ").SetDotToCursor().
		WritePlain(strings.Repeat(" ", 49)).
		WriteStyled(styled.MakeText("elf@host", "inverse")).Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func setupWithRC(codes ...string) (cli.TTYCtrl, func()) {
	ed, ttyCtrl, ev, cleanup := setup()
	for _, code := range codes {
		evalf(ev, `%s`, code)
	}
	_, _, stop := start(ed)
	return ttyCtrl, func() {
		stop()
		cleanup()
	}
}
<commit_msg>cliedit: Make prompt_test more robust.<commit_after>package cliedit

import (
	"strings"
	"testing"

	"github.com/elves/elvish/cli"
	"github.com/elves/elvish/cli/term"
	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/eval/vars"
	"github.com/elves/elvish/styled"
)

func TestPrompt_ValueOutput(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(
		`edit:prompt = { put 'val'; styled '> ' red }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("val").WriteStyled(styled.MakeText("> ", "red")).
			SetDotToCursor().Buffer())
}

func TestPrompt_ByteOutput(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(`edit:prompt = { put 'bytes> ' }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("bytes> ").SetDotToCursor().Buffer())
}

func TestPrompt_NotifiesInvalidValueOutput(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(`edit:prompt = { put good [bad] good2 }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("goodgood2").SetDotToCursor().Buffer())
	ttyCtrl.TestNotesBuffer(t, bb().
		WritePlain("invalid output type from prompt: list").Buffer())
}

func TestPrompt_NotifiesException(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(`edit:prompt = { fail ERROR }`)
	defer cleanup()

	ttyCtrl.TestNotesBuffer(t, bb().
		WritePlain("prompt function error: ERROR").Buffer())
}

func TestRPrompt(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(`edit:rprompt = { put 'RRR' }`)
	defer cleanup()

	ttyCtrl.TestBuffer(t,
		bb().WritePlain("~> ").SetDotToCursor().
			WritePlain(strings.Repeat(" ", testTTYWidth-6)+"RRR").Buffer())
}

func TestPromptEagerness(t *testing.T) {
	ttyCtrl, _, cleanup := setupWithRC(
		`i = 0`,
		`edit:prompt = { i = (+ $i 1); put $i'> ' }`,
		`edit:-prompt-eagerness = 10`)
	defer cleanup()

	wantBuf1 := bb().WritePlain("1> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf1)
	// With eagerness = 10, any key press will cause the prompt to be
	// recomputed.
	ttyCtrl.Inject(term.K(ui.Backspace))
	wantBuf2 := bb().WritePlain("2> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf2)
}

func TestPromptStaleThreshold(t *testing.T) {
	ttyCtrl, ev, cleanup := setupWithRC(
		`pipe = (pipe)`,
		`edit:prompt = { nop (slurp < $pipe); put '> ' }`,
		`edit:prompt-stale-threshold = 0.05`)
	defer cleanup()

	wantBufStale := bb().
		WriteStyled(styled.MakeText("???> ", "inverse")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufStale)

	evalf(ev, `pwclose $pipe`)
	wantBufFresh := bb().WritePlain("> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufFresh)
	evalf(ev, `prclose $pipe`)
}

func TestPromptStaleTransform(t *testing.T) {
	ttyCtrl, ev, cleanup := setupWithRC(
		`pipe = (pipe)`,
		`edit:prompt = { nop (slurp < $pipe); put '> ' }`,
		`edit:prompt-stale-threshold = 0.05`,
		`edit:prompt-stale-transform = [a]{ put S; put $a; put S }`)
	defer cleanup()

	wantBufStale := bb().
		WriteStyled(styled.Plain("S???> S")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBufStale)
	evalf(ev, `pwclose $pipe`)
	evalf(ev, `prclose $pipe`)
}

func TestDefaultPromptForNonRoot(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultPrompt(false))
	evalf(ev, `edit:prompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~> ").SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func TestDefaultPromptForRoot(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultPrompt(true))
	evalf(ev, `edit:prompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~").
		WriteStyled(styled.MakeText("# ", "red")).SetDotToCursor().Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func TestDefaultRPrompt(t *testing.T) {
	ed, ttyCtrl, ev, cleanup := setup()
	defer cleanup()
	ev.Global["f"] = vars.NewReadOnly(getDefaultRPrompt("elf", "host"))
	evalf(ev, `edit:rprompt = $f`)

	_, _, stop := start(ed)
	defer stop()

	wantBuf := bb().WritePlain("~> ").SetDotToCursor().
		WritePlain(strings.Repeat(" ", 49)).
		WriteStyled(styled.MakeText("elf@host", "inverse")).Buffer()
	ttyCtrl.TestBuffer(t, wantBuf)
}

func setupWithRC(codes ...string) (cli.TTYCtrl, *eval.Evaler, func()) {
	ed, ttyCtrl, ev, cleanup := setup()
	for _, code := range codes {
		evalf(ev, `%s`, code)
	}
	_, _, stop := start(ed)
	return ttyCtrl, ev, func() {
		stop()
		cleanup()
	}
}
<|endoftext|>


<commit_before>// +build linux darwin freebsd

package main

import (
	"errors"
	"fmt"

	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

	"github.com/jbenet/go-ipfs/daemon"
	rofs "github.com/jbenet/go-ipfs/fuse/readonly"
	u "github.com/jbenet/go-ipfs/util"
)

var cmdIpfsMount = &commander.Command{
	UsageLine: "mount",
	Short:     "Mount an ipfs read-only mountpoint.",
	Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.

    Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
    will be accessible under that directory. Note that the root will
    not be listable, as it is virtual. Accessing known paths directly.

`,
	Run:  mountCmd,
	Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
}

func mountCmd(c *commander.Command, inp []string) error {
	if len(inp) < 1 || len(inp[0]) == 0 {
		u.POut(c.Long)
		return nil
	}

	conf, err := getConfigDir(c.Parent)
	if err != nil {
		fmt.Println("Couldnt get config dir")
		return err
	}
	n, err := localNode(conf, true)
	if err != nil {
		fmt.Println("Local node creation failed.")
		return err
	}

	// launch the API RPC endpoint.
	if n.Config.Addresses.API == "" {
		return errors.New("no config.RPCAddress endpoint supplied")
	}

	maddr, err := ma.NewMultiaddr(n.Config.Addresses.API)
	if err != nil {
		return err
	}

	dl, err := daemon.NewDaemonListener(n, maddr, conf)
	if err != nil {
		fmt.Println("Failed to create daemon listener.")
		return err
	}
	go dl.Listen()
	defer dl.Close()

	mp := inp[0]
	fmt.Printf("Mounting at %s\n", mp)
	return rofs.Mount(n, mp)
}
<commit_msg>allow ipns to be mounted by mount command<commit_after>// +build linux darwin freebsd

package main

import (
	"errors"
	"fmt"

	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

	"github.com/jbenet/go-ipfs/daemon"
	ipns "github.com/jbenet/go-ipfs/fuse/ipns"
	rofs "github.com/jbenet/go-ipfs/fuse/readonly"
	u "github.com/jbenet/go-ipfs/util"
)

var cmdIpfsMount = &commander.Command{
	UsageLine: "mount",
	Short:     "Mount an ipfs read-only mountpoint.",
	Long: `ipfs mount <os-path> - Mount an ipfs read-only mountpoint.

    Mount ipfs at a read-only mountpoint on the OS. All ipfs objects
    will be accessible under that directory. Note that the root will
    not be listable, as it is virtual. Accessing known paths directly.

`,
	Run:  mountCmd,
	Flag: *flag.NewFlagSet("ipfs-mount", flag.ExitOnError),
}

func init() {
	cmdIpfsMount.Flag.String("n", "", "specify a mountpoint for ipns")
}

func mountCmd(c *commander.Command, inp []string) error {
	if len(inp) < 1 || len(inp[0]) == 0 {
		u.POut(c.Long)
		return nil
	}

	conf, err := getConfigDir(c.Parent)
	if err != nil {
		fmt.Println("Couldnt get config dir")
		return err
	}
	n, err := localNode(conf, true)
	if err != nil {
		fmt.Println("Local node creation failed.")
		return err
	}

	// launch the API RPC endpoint.
	if n.Config.Addresses.API == "" {
		return errors.New("no config.RPCAddress endpoint supplied")
	}

	maddr, err := ma.NewMultiaddr(n.Config.Addresses.API)
	if err != nil {
		return err
	}

	dl, err := daemon.NewDaemonListener(n, maddr, conf)
	if err != nil {
		fmt.Println("Failed to create daemon listener.")
		return err
	}
	go dl.Listen()
	defer dl.Close()

	mp := inp[0]
	fmt.Printf("Mounting at %s\n", mp)

	ns, ok := c.Flag.Lookup("n").Value.Get().(string)
	if ok {
		go func() {
			err = ipns.Mount(n, ns, mp)
			if err != nil {
				fmt.Printf("Error mounting ipns: %s\n", err)
			}
		}()
	}

	return rofs.Mount(n, mp)
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"testing"
)

func TestStringSlice(t *testing.T) {
	var ss stringslice
	ss.Set("a")
	ss.Set("a")
	ss.Set("b")
	if want, have := "a a b", strings.Join(ss, " "); want != have {
		t.Errorf("want %q, have %q", want, have)
	}
}

func TestParseAddr(t *testing.T) {
	for _, testcase := range []struct {
		addr        string
		defaultPort int
		network     string
		address     string
		host        string
		port        int
	}{
		{"foo", 123, "tcp", "foo:123", "foo", 123},
		{"foo:80", 123, "tcp", "foo:80", "foo", 80},
		{"udp://foo", 123, "udp", "foo:123", "foo", 123},
		{"udp://foo:8080", 123, "udp", "foo:8080", "foo", 8080},
		{"tcp+dnssrv://testing:7650", 7650, "tcp+dnssrv", "testing:7650", "testing", 7650},
	} {
		network, address, host, port, err := parseAddr(testcase.addr, testcase.defaultPort)
		if err != nil {
			t.Errorf("(%q, %d): %v", testcase.addr, testcase.defaultPort, err)
			continue
		}
		var (
			matchNetwork = network == testcase.network
			matchAddress = address == testcase.address
			matchHost    = host == testcase.host
			matchPort    = port == testcase.port
		)
		if !matchNetwork || !matchAddress || !matchHost || !matchPort {
			t.Errorf("(%q, %d): want [%s %s %s %d], have [%s %s %s %d]",
				testcase.addr, testcase.defaultPort,
				testcase.network, testcase.address, testcase.host, testcase.port,
				network, address, host, port,
			)
			continue
		}
	}
}

func TestHasNonlocal(t *testing.T) {
	makeslice := func(a ...string) stringslice {
		ss := stringslice{}
		for _, s := range a {
			ss.Set(s)
		}
		return ss
	}
	for _, testcase := range []struct {
		name  string
		input stringslice
		want  bool
	}{
		{
			"empty",
			makeslice(),
			false,
		},
		{
			"127",
			makeslice("127.0.0.9"),
			false,
		},
		{
			"127 with port",
			makeslice("127.0.0.1:1234"),
			false,
		},
		{
			"nonlocal IP",
			makeslice("1.2.3.4"),
			true,
		},
		{
			"nonlocal IP with port",
			makeslice("1.2.3.4:5678"),
			true,
		},
		{
			"nonlocal host",
			makeslice("foo.corp"),
			true,
		},
		{
			"nonlocal host with port",
			makeslice("foo.corp:7659"),
			true,
		},
		{
			"localhost",
			makeslice("localhost"),
			false,
		},
		{
			"localhost with port",
			makeslice("localhost:1234"),
			false,
		},
		{
			"multiple IP",
			makeslice("127.0.0.1", "1.2.3.4"),
			true,
		},
		{
			"multiple hostname",
			makeslice("localhost", "otherhost"),
			true,
		},
		{
			"multiple local",
			makeslice("localhost", "127.0.0.1", "127.128.129.130:4321", "localhost:10001", "localhost:10002"),
			false,
		},
		{
			"multiple mixed",
			makeslice("localhost", "127.0.0.1", "129.128.129.130:4321", "localhost:10001", "localhost:10002"),
			true,
		},
	} {
		t.Run(testcase.name, func(t *testing.T) {
			if want, have := testcase.want, hasNonlocal(testcase.input); want != have {
				t.Errorf("want %v, have %v", want, have)
			}
		})
	}
}

func TestIsUnroutable(t *testing.T) {
	for _, testcase := range []struct {
		input string
		want  bool
	}{
		{"0.0.0.0", true},
		{"127.0.0.1", true},
		{"127.128.129.130", true},
		{"localhost", true},
		{"foo", false},
	} {
		t.Run(testcase.input, func(t *testing.T) {
			if want, have := testcase.want, isUnroutable(testcase.input); want != have {
				t.Errorf("want %v, have %v", want, have)
			}
		})
	}
}
<commit_msg>cmd/oklog: ensure :: isUnroutable<commit_after>package main

import (
	"strings"
	"testing"
)

func TestStringSlice(t *testing.T) {
	var ss stringslice
	ss.Set("a")
	ss.Set("a")
	ss.Set("b")
	if want, have := "a a b", strings.Join(ss, " "); want != have {
		t.Errorf("want %q, have %q", want, have)
	}
}

func TestParseAddr(t *testing.T) {
	for _, testcase := range []struct {
		addr        string
		defaultPort int
		network     string
		address     string
		host        string
		port        int
	}{
		{"foo", 123, "tcp", "foo:123", "foo", 123},
		{"foo:80", 123, "tcp", "foo:80", "foo", 80},
		{"udp://foo", 123, "udp", "foo:123", "foo", 123},
		{"udp://foo:8080", 123, "udp", "foo:8080", "foo", 8080},
		{"tcp+dnssrv://testing:7650", 7650, "tcp+dnssrv", "testing:7650", "testing", 7650},
	} {
		network, address, host, port, err := parseAddr(testcase.addr, testcase.defaultPort)
		if err != nil {
			t.Errorf("(%q, %d): %v", testcase.addr, testcase.defaultPort, err)
			continue
		}
		var (
			matchNetwork = network == testcase.network
			matchAddress = address == testcase.address
			matchHost    = host == testcase.host
			matchPort    = port == testcase.port
		)
		if !matchNetwork || !matchAddress || !matchHost || !matchPort {
			t.Errorf("(%q, %d): want [%s %s %s %d], have [%s %s %s %d]",
				testcase.addr, testcase.defaultPort,
				testcase.network, testcase.address, testcase.host, testcase.port,
				network, address, host, port,
			)
			continue
		}
	}
}

func TestHasNonlocal(t *testing.T) {
	makeslice := func(a ...string) stringslice {
		ss := stringslice{}
		for _, s := range a {
			ss.Set(s)
		}
		return ss
	}
	for _, testcase := range []struct {
		name  string
		input stringslice
		want  bool
	}{
		{
			"empty",
			makeslice(),
			false,
		},
		{
			"127",
			makeslice("127.0.0.9"),
			false,
		},
		{
			"127 with port",
			makeslice("127.0.0.1:1234"),
			false,
		},
		{
			"nonlocal IP",
			makeslice("1.2.3.4"),
			true,
		},
		{
			"nonlocal IP with port",
			makeslice("1.2.3.4:5678"),
			true,
		},
		{
			"nonlocal host",
			makeslice("foo.corp"),
			true,
		},
		{
			"nonlocal host with port",
			makeslice("foo.corp:7659"),
			true,
		},
		{
			"localhost",
			makeslice("localhost"),
			false,
		},
		{
			"localhost with port",
			makeslice("localhost:1234"),
			false,
		},
		{
			"multiple IP",
			makeslice("127.0.0.1", "1.2.3.4"),
			true,
		},
		{
			"multiple hostname",
			makeslice("localhost", "otherhost"),
			true,
		},
		{
			"multiple local",
			makeslice("localhost", "127.0.0.1", "127.128.129.130:4321", "localhost:10001", "localhost:10002"),
			false,
		},
		{
			"multiple mixed",
			makeslice("localhost", "127.0.0.1", "129.128.129.130:4321", "localhost:10001", "localhost:10002"),
			true,
		},
	} {
		t.Run(testcase.name, func(t *testing.T) {
			if want, have := testcase.want, hasNonlocal(testcase.input); want != have {
				t.Errorf("want %v, have %v", want, have)
			}
		})
	}
}

func TestIsUnroutable(t *testing.T) {
	for _, testcase := range []struct {
		input string
		want  bool
	}{
		{"0.0.0.0", true},
		{"127.0.0.1", true},
		{"127.128.129.130", true},
		{"localhost", true},
		{"foo", false},
		{"::", true},
	} {
		t.Run(testcase.input, func(t *testing.T) {
			if want, have := testcase.want, isUnroutable(testcase.input); want != have {
				t.Errorf("want %v, have %v", want, have)
			}
		})
	}
}
<|endoftext|>


<commit_before>/**
 * Copyright 2015 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   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 util

import (
	"time"
)

type DefaultRetrier struct {
}

// RetryEndpoint same as HitEndpoint but with local trivial implementation exponential backoff.
func (d *DefaultRetrier) RetryEndpoint(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string) (string, int, error) {
	return d.Retry(ctx, url, payload, verb, headers, auth, HitEndpoint)
}

// Retry implements retry logic with injected request function.
func (*DefaultRetrier) Retry(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string, f func(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string) (string, int, error)) (string, int, error) {
	attempt := 1
	backoffMs := GetConfig(ctx).InitialBackoff * time.Millisecond
	initialDelayMs := GetConfig(ctx).InitialDelay * time.Millisecond
	padMs := GetConfig(ctx).Pad * time.Millisecond
start:
	ctx.AddLogValue("attempt", attempt)
	resp, status, err := f(ctx, url, payload, verb, headers, auth)
	if err != nil || status < 200 || status > 299 {
		if attempt < GetConfig(ctx).MaxAttempts {
			if attempt == 1 {
				time.Sleep(initialDelayMs)
			} else {
				time.Sleep(backoffMs + padMs)
				backoffMs *= 2
			}
			attempt++
			goto start
		}
	}
	return resp, status, err
}
<commit_msg>Update retry to not retry for 300 and 400<commit_after>/**
 * Copyright 2015 Comcast Cable Communications Management, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   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 util

import (
	"time"
)

type DefaultRetrier struct {
}

// RetryEndpoint same as HitEndpoint but with local trivial implementation exponential backoff.
func (d *DefaultRetrier) RetryEndpoint(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string) (string, int, error) {
	return d.Retry(ctx, url, payload, verb, headers, auth, HitEndpoint)
}

// Retry implements retry logic with injected request function.
func (*DefaultRetrier) Retry(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string, f func(ctx Context, url string, payload string, verb string, headers map[string]string, auth map[string]string) (string, int, error)) (string, int, error) {
	attempt := 1
	backoffMs := GetConfig(ctx).InitialBackoff * time.Millisecond
	initialDelayMs := GetConfig(ctx).InitialDelay * time.Millisecond
	padMs := GetConfig(ctx).Pad * time.Millisecond
start:
	ctx.AddLogValue("attempt", attempt)
	resp, status, err := f(ctx, url, payload, verb, headers, auth)
	if err != nil || status < 200 || status > 499 {
		if attempt < GetConfig(ctx).MaxAttempts {
			if attempt == 1 {
				time.Sleep(initialDelayMs)
			} else {
				time.Sleep(backoffMs + padMs)
				backoffMs *= 2
			}
			attempt++
			goto start
		}
	}
	return resp, status, err
}
<|endoftext|>


<commit_before>// Copyright 2020 conntrack-prometheus 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 kubelet

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/pkg/errors"
	"github.com/tsuru/prometheus-conntrack/workload"
)

type podList struct {
	Items []pod `json:"items"`
}
type pod struct {
	Metadata podMetadata `json:"metadata"`
	Spec     podSpec     `json:"spec"`
	Status   podStatus   `json:"status"`
}

type podMetadata struct {
	Name      string            `json:"name"`
	Namespace string            `json:"namespace"`
	Labels    map[string]string `json:"labels"`
}

type podSpec struct {
	HostNetwork bool `json:"hostNetwork"`
}

type podStatus struct {
	PodIP string `json:"podIP"`
}

type kubeletEngine struct {
	Opts

	client       *http.Client
	tokenContent string
}

func (d *kubeletEngine) Name() string {
	return "kubernetes"
}

func (d *kubeletEngine) Kind() string {
	return "pod"
}

func (k *kubeletEngine) Workloads() ([]*workload.Workload, error) {
	workloads := []*workload.Workload{}

	req, _ := http.NewRequest(http.MethodGet, k.Endpoint, nil)
	if k.tokenContent != "" {
		req.Header.Set("Authorization", "Bearer "+k.tokenContent)
	}
	response, err := k.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Invalid response code: %d", response.StatusCode)
	}

	list := &podList{}
	err = json.NewDecoder(response.Body).Decode(&list)
	if err != nil {
		return nil, err
	}

	for _, pod := range list.Items {
		// we skip all pods with hostNetwork because its use the same ip of host
		// and may generate a mess in the metrics
		if pod.Spec.HostNetwork {
			continue
		}
		pod.Metadata.Labels["pod_namespace"] = pod.Metadata.Namespace
		workloads = append(workloads, &workload.Workload{
			Name:   pod.Metadata.Name,
			IP:     pod.Status.PodIP,
			Labels: pod.Metadata.Labels,
		})
	}

	return workloads, nil
}

type Opts struct {
	Endpoint string
	Key      string
	Cert     string
	CA       string
	Token    string

	InsecureSkipVerify bool
}

func NewEngine(opts Opts) (workload.Engine, error) {
	// Setup HTTPS client
	tlsConfig := &tls.Config{
		InsecureSkipVerify: opts.InsecureSkipVerify,
	}

	var tokenContent string
	if opts.Token != "" {
		tokenBytes, err := ioutil.ReadFile(opts.Token)
		if err != nil {
			return nil, errors.Wrap(err, "could not read Token file")
		}
		tokenContent = string(tokenBytes)
	}
	if opts.CA != "" {
		caCert, err := ioutil.ReadFile(opts.CA)
		if err != nil {
			return nil, errors.Wrap(err, "could not read CA file")
		}

		caCertPool := x509.NewCertPool()
		caCertPool.AppendCertsFromPEM(caCert)
		tlsConfig.RootCAs = caCertPool
	}

	if opts.Key != "" && opts.Cert != "" {
		cert, err := tls.LoadX509KeyPair(opts.Cert, opts.Key)
		if err != nil {
			return nil, errors.Wrap(err, "could not read cert and key file")
		}

		tlsConfig.Certificates = []tls.Certificate{cert}
	}

	tlsConfig.BuildNameToCertificate()

	transport := &http.Transport{TLSClientConfig: tlsConfig}
	client := &http.Client{Transport: transport}

	return &kubeletEngine{Opts: opts, client: client, tokenContent: tokenContent}, nil
}
<commit_msg>Fix crash of prometheus-conntrack<commit_after>// Copyright 2020 conntrack-prometheus 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 kubelet

import (
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/pkg/errors"
	"github.com/tsuru/prometheus-conntrack/workload"
)

type podList struct {
	Items []pod `json:"items"`
}
type pod struct {
	Metadata podMetadata `json:"metadata"`
	Spec     podSpec     `json:"spec"`
	Status   podStatus   `json:"status"`
}

type podMetadata struct {
	Name      string            `json:"name"`
	Namespace string            `json:"namespace"`
	Labels    map[string]string `json:"labels"`
}

type podSpec struct {
	HostNetwork bool `json:"hostNetwork"`
}

type podStatus struct {
	PodIP string `json:"podIP"`
}

type kubeletEngine struct {
	Opts

	client       *http.Client
	tokenContent string
}

func (d *kubeletEngine) Name() string {
	return "kubernetes"
}

func (d *kubeletEngine) Kind() string {
	return "pod"
}

func (k *kubeletEngine) Workloads() ([]*workload.Workload, error) {
	workloads := []*workload.Workload{}

	req, _ := http.NewRequest(http.MethodGet, k.Endpoint, nil)
	if k.tokenContent != "" {
		req.Header.Set("Authorization", "Bearer "+k.tokenContent)
	}
	response, err := k.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Invalid response code: %d", response.StatusCode)
	}

	list := &podList{}
	err = json.NewDecoder(response.Body).Decode(&list)
	if err != nil {
		return nil, err
	}

	for _, pod := range list.Items {
		// we skip all pods with hostNetwork because its use the same ip of host
		// and may generate a mess in the metrics
		if pod.Spec.HostNetwork {
			continue
		}
		if pod.Metadata.Labels == nil {
			pod.Metadata.Labels = map[string]string{}
		}
		pod.Metadata.Labels["pod_namespace"] = pod.Metadata.Namespace
		workloads = append(workloads, &workload.Workload{
			Name:   pod.Metadata.Name,
			IP:     pod.Status.PodIP,
			Labels: pod.Metadata.Labels,
		})
	}

	return workloads, nil
}

type Opts struct {
	Endpoint string
	Key      string
	Cert     string
	CA       string
	Token    string

	InsecureSkipVerify bool
}

func NewEngine(opts Opts) (workload.Engine, error) {
	// Setup HTTPS client
	tlsConfig := &tls.Config{
		InsecureSkipVerify: opts.InsecureSkipVerify,
	}

	var tokenContent string
	if opts.Token != "" {
		tokenBytes, err := ioutil.ReadFile(opts.Token)
		if err != nil {
			return nil, errors.Wrap(err, "could not read Token file")
		}
		tokenContent = string(tokenBytes)
	}
	if opts.CA != "" {
		caCert, err := ioutil.ReadFile(opts.CA)
		if err != nil {
			return nil, errors.Wrap(err, "could not read CA file")
		}

		caCertPool := x509.NewCertPool()
		caCertPool.AppendCertsFromPEM(caCert)
		tlsConfig.RootCAs = caCertPool
	}

	if opts.Key != "" && opts.Cert != "" {
		cert, err := tls.LoadX509KeyPair(opts.Cert, opts.Key)
		if err != nil {
			return nil, errors.Wrap(err, "could not read cert and key file")
		}

		tlsConfig.Certificates = []tls.Certificate{cert}
	}

	tlsConfig.BuildNameToCertificate()

	transport := &http.Transport{TLSClientConfig: tlsConfig}
	client := &http.Client{Transport: transport}

	return &kubeletEngine{Opts: opts, client: client, tokenContent: tokenContent}, nil
}
<|endoftext|>


<commit_before>package ircbot

import (
	"bufio"
	"crypto/rand"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/textproto"
	"strings"
	"time"
)

type IrcBot struct {
	// identity
	User     string
	Nick     string
	Password string

	// server info
	Server  string
	Port    string
	Channel []string

	// tcp communication
	conn   net.Conn
	reader *textproto.Reader
	writer *textproto.Writer

	// web interface
	WebEnable bool
	WebPort   string

	// crypto
	Encrypted bool
	config    tls.Config

	// data flow
	In    chan *IrcMsg
	Out   chan *IrcMsg
	Error chan error

	// exit flag
	Exit chan bool

	//action handlers
	Handlers map[string][]ActionFunc

	//are we Joined in channel?
	Joined bool
}

func NewIrcBot() *IrcBot {
	bot := IrcBot{
		Handlers: make(map[string][]ActionFunc),
		In:       make(chan *IrcMsg),
		Out:      make(chan *IrcMsg),
		Error:    make(chan error),
		Exit:     make(chan bool),
		Joined:   false,
	}

	//defautl actions, needed to run proprely
	bot.AddAction("PING", Pong)
	bot.AddAction("MODE", ValidConnect)

	return &bot
}

func (b *IrcBot) url() string {
	return fmt.Sprintf("%s:%s", b.Server, b.Port)
}

func (b *IrcBot) Connect() {
	//launch a go routine that handle errors
	// b.handleError()

	log.Println("Info> connection to", b.url())

	var tcpCon net.Conn
	var err error
	if b.Encrypted {
		cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
		b.errChk(err)

		config := tls.Config{Certificates: []tls.Certificate{cert}}
		config.Rand = rand.Reader
		tcpCon, err = tls.Dial("tcp", b.url(), &config)
		b.errChk(err)

	} else {
		tcpCon, err = net.Dial("tcp", b.url())
		b.errChk(err)
	}

	b.conn = tcpCon
	r := bufio.NewReader(b.conn)
	w := bufio.NewWriter(b.conn)
	b.reader = textproto.NewReader(r)
	b.writer = textproto.NewWriter(w)

	//connect to server
	b.writer.PrintfLine("USER %s 8 * :%s", b.Nick, b.Nick)
	b.writer.PrintfLine("NICK %s", b.Nick)

	//launch go routines that handle requests
	b.listen()
	b.handleActionIn()
	b.handleActionOut()
	b.HandleError()
	if b.WebEnable {
		b.HandleWeb()
	}

	//join all channels
	b.join()

	b.identify()
}

func (b *IrcBot) join() {

	//prevent to send JOIN command before we are conected
	for {
		if !b.Joined {
			time.Sleep(1 * time.Second)
			continue
		}
		break
	}

	for _, v := range b.Channel {
		s := fmt.Sprintf("JOIN %s", v)
		fmt.Println("irc >> ", s)
		b.writer.PrintfLine(s)
	}
	b.Joined = true
}

func (b *IrcBot) identify() {
	//idenify with nickserv
	if b.Password != "" {
		s := fmt.Sprintf("PRIVMSG NickServ :identify %s %s", b.Nick, b.Password)
		fmt.Println("irc >> ", s)
		b.writer.PrintfLine(s)
	}
}

func (b *IrcBot) listen() {

	go func() {

		for {
			//block read line from socket
			line, err := b.reader.ReadLine()
			if err != nil {
				b.Error <- err
			}
			//convert line into IrcMsg
			msg := Parseline(line)
			b.In <- msg
		}

	}()
}

func (b *IrcBot) Say(s string) {
	msg := NewIrcMsg()
	msg.Command = "PRIVMSG"
	msg.Args = append(msg.Args, s)

	b.Out <- msg
}

func (b *IrcBot) AddAction(command string, action ActionFunc) {
	b.Handlers[command] = append(b.Handlers[command], action)
}

func (b *IrcBot) handleActionIn() {
	go func() {
		for {
			//receive new message
			msg := <-b.In
			fmt.Println("irc << ", msg.Raw)
			//handle action
			actions := b.Handlers[msg.Command]
			if len(actions) > 0 {
				for _, action := range actions {
					action(b, msg)
				}
			}
		}
	}()
}

func (b *IrcBot) handleActionOut() {
	go func() {
		for {
			msg := <-b.Out

			//we send nothing before we sure we join channel
			if b.Joined == false {
				continue
			}

			s := fmt.Sprintf("%s %s %s", msg.Command, msg.Channel, strings.Join(msg.Args, " "))
			fmt.Println("irc >> ", s)
			b.writer.PrintfLine(s)
		}
	}()
}

func (b *IrcBot) HandleError() {
	go func() {
		for {
			err := <-b.Error
			fmt.Printf("error >> %s", err)
			if err != nil {
				b.Disconnect()
				log.Fatalln("Error ocurs :", err)
			}
		}
	}()
}

//HandleWeb handles requests receive on http server
func (b *IrcBot) HandleWeb() {
	go func() {
		http.HandleFunc("/qg", Gui)
		http.HandleFunc("/send", func(w http.ResponseWriter, r *http.Request) {
			Send(b, w, r)
		})
		http.HandleFunc("/ircbot", func(w http.ResponseWriter, r *http.Request) {
			Handler(b, w, r)
		})
		http.ListenAndServe(":"+b.WebPort, nil)
	}()
}

func (b *IrcBot) errChk(err error) {
	if err != nil {
		log.Println("Error> ", err)
		b.Error <- err
	}
}

func (b *IrcBot) Disconnect() {
	b.writer.PrintfLine("QUIT")
	b.conn.Close()
}

func (b *IrcBot) String() string {
	s := fmt.Sprintf("server: %s\n", b.Server)
	s += fmt.Sprintf("port: %s\n", b.Port)
	s += fmt.Sprintf("ssl: %t\n", b.Encrypted)

	if len(b.Channel) > 0 {
		s += "channels: "
		for _, v := range b.Channel {
			s += fmt.Sprintf("%s ", v)
		}
	}

	return s
}
<commit_msg>specify in wich channel to talk<commit_after>package ircbot

import (
	"bufio"
	"crypto/rand"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/textproto"
	"strings"
	"time"
)

type IrcBot struct {
	// identity
	User     string
	Nick     string
	Password string

	// server info
	Server  string
	Port    string
	Channel []string

	// tcp communication
	conn   net.Conn
	reader *textproto.Reader
	writer *textproto.Writer

	// web interface
	WebEnable bool
	WebPort   string

	// crypto
	Encrypted bool
	config    tls.Config

	// data flow
	In    chan *IrcMsg
	Out   chan *IrcMsg
	Error chan error

	// exit flag
	Exit chan bool

	//action handlers
	Handlers map[string][]ActionFunc

	//are we Joined in channel?
	Joined bool
}

func NewIrcBot() *IrcBot {
	bot := IrcBot{
		Handlers: make(map[string][]ActionFunc),
		In:       make(chan *IrcMsg),
		Out:      make(chan *IrcMsg),
		Error:    make(chan error),
		Exit:     make(chan bool),
		Joined:   false,
	}

	//defautl actions, needed to run proprely
	bot.AddAction("PING", Pong)
	bot.AddAction("MODE", ValidConnect)

	return &bot
}

func (b *IrcBot) url() string {
	return fmt.Sprintf("%s:%s", b.Server, b.Port)
}

func (b *IrcBot) Connect() {
	//launch a go routine that handle errors
	// b.handleError()

	log.Println("Info> connection to", b.url())

	var tcpCon net.Conn
	var err error
	if b.Encrypted {
		cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
		b.errChk(err)

		config := tls.Config{Certificates: []tls.Certificate{cert}}
		config.Rand = rand.Reader
		tcpCon, err = tls.Dial("tcp", b.url(), &config)
		b.errChk(err)

	} else {
		tcpCon, err = net.Dial("tcp", b.url())
		b.errChk(err)
	}

	b.conn = tcpCon
	r := bufio.NewReader(b.conn)
	w := bufio.NewWriter(b.conn)
	b.reader = textproto.NewReader(r)
	b.writer = textproto.NewWriter(w)

	//connect to server
	b.writer.PrintfLine("USER %s 8 * :%s", b.Nick, b.Nick)
	b.writer.PrintfLine("NICK %s", b.Nick)

	//launch go routines that handle requests
	b.listen()
	b.handleActionIn()
	b.handleActionOut()
	b.HandleError()
	if b.WebEnable {
		b.HandleWeb()
	}

	//join all channels
	b.join()

	b.identify()
}

func (b *IrcBot) join() {

	//prevent to send JOIN command before we are conected
	for {
		if !b.Joined {
			time.Sleep(1 * time.Second)
			continue
		}
		break
	}

	for _, v := range b.Channel {
		s := fmt.Sprintf("JOIN %s", v)
		fmt.Println("irc >> ", s)
		b.writer.PrintfLine(s)
	}
	b.Joined = true
}

func (b *IrcBot) identify() {
	//idenify with nickserv
	if b.Password != "" {
		s := fmt.Sprintf("PRIVMSG NickServ :identify %s %s", b.Nick, b.Password)
		fmt.Println("irc >> ", s)
		b.writer.PrintfLine(s)
	}
}

func (b *IrcBot) listen() {

	go func() {

		for {
			//block read line from socket
			line, err := b.reader.ReadLine()
			if err != nil {
				b.Error <- err
			}
			//convert line into IrcMsg
			msg := Parseline(line)
			b.In <- msg
		}

	}()
}

func (b *IrcBot) Say(channel string, text string) {
	msg := NewIrcMsg()
	msg.Command = "PRIVMSG"
	msg.Channel = channel
	msg.Args = append(msg.Args, text)

	b.Out <- msg
}

func (b *IrcBot) AddAction(command string, action ActionFunc) {
	b.Handlers[command] = append(b.Handlers[command], action)
}

func (b *IrcBot) handleActionIn() {
	go func() {
		for {
			//receive new message
			msg := <-b.In
			fmt.Println("irc << ", msg.Raw)
			//handle action
			actions := b.Handlers[msg.Command]
			if len(actions) > 0 {
				for _, action := range actions {
					action(b, msg)
				}
			}
		}
	}()
}

func (b *IrcBot) handleActionOut() {
	go func() {
		for {
			msg := <-b.Out

			//we send nothing before we sure we join channel
			if b.Joined == false {
				continue
			}

			s := fmt.Sprintf("%s %s %s", msg.Command, msg.Channel, strings.Join(msg.Args, " "))
			fmt.Println("irc >> ", s)
			b.writer.PrintfLine(s)
		}
	}()
}

func (b *IrcBot) HandleError() {
	go func() {
		for {
			err := <-b.Error
			fmt.Printf("error >> %s", err)
			if err != nil {
				b.Disconnect()
				log.Fatalln("Error ocurs :", err)
			}
		}
	}()
}

//HandleWeb handles requests receive on http server
func (b *IrcBot) HandleWeb() {
	go func() {
		http.HandleFunc("/qg", Gui)
		http.HandleFunc("/send", func(w http.ResponseWriter, r *http.Request) {
			Send(b, w, r)
		})
		http.HandleFunc("/ircbot", func(w http.ResponseWriter, r *http.Request) {
			Handler(b, w, r)
		})
		http.ListenAndServe(":"+b.WebPort, nil)
	}()
}

func (b *IrcBot) errChk(err error) {
	if err != nil {
		log.Println("Error> ", err)
		b.Error <- err
	}
}

func (b *IrcBot) Disconnect() {
	b.writer.PrintfLine("QUIT")
	b.conn.Close()
}

func (b *IrcBot) String() string {
	s := fmt.Sprintf("server: %s\n", b.Server)
	s += fmt.Sprintf("port: %s\n", b.Port)
	s += fmt.Sprintf("ssl: %t\n", b.Encrypted)

	if len(b.Channel) > 0 {
		s += "channels: "
		for _, v := range b.Channel {
			s += fmt.Sprintf("%s ", v)
		}
	}

	return s
}
<|endoftext|>


<commit_before>package stepman

import (
	"archive/zip"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/go-pathutil/pathutil"
	"github.com/bitrise-io/stepman/models"
	"gopkg.in/yaml.v2"
)

// DebugMode ...
var DebugMode bool

func parseStepYml(pth, id, version string) (models.StepModel, error) {
	bytes, err := ioutil.ReadFile(pth)
	if err != nil {
		return models.StepModel{}, err
	}

	var stepJSON models.StepModel
	if err := yaml.Unmarshal(bytes, &stepJSON); err != nil {
		return models.StepModel{}, err
	}

	stepJSON.ID = id
	stepJSON.VersionTag = version
	stepJSON.StepLibSource = CollectionURI

	return stepJSON, nil
}

// ParseStepCollection ...
func ParseStepCollection(pth string) (models.StepCollectionModel, error) {
	bytes, err := ioutil.ReadFile(pth)
	if err != nil {
		return models.StepCollectionModel{}, err
	}

	var stepCollection models.StepCollectionModel
	if err := yaml.Unmarshal(bytes, &stepCollection); err != nil {
		return models.StepCollectionModel{}, err
	}
	return stepCollection, nil
}

// DownloadStep ...
func DownloadStep(collection models.StepCollectionModel, step models.StepModel) error {
	downloadLocations := collection.GetDownloadLocations(step)

	success := false
	for _, downloadLocationMap := range downloadLocations {
		for key, value := range downloadLocationMap {
			switch key {
			case "zip":
				if err := DownloadAndUnZIP(value, GetStepPath(step)); err != nil {
					log.Error("Failed to download step.zip:", err)
					break
				}
				success = true
			case "git":
				if err := DoGitUpdate(value, GetStepPath(step)); err != nil {
					log.Error("Failed to clone step:", err)
					break
				}
				success = true
			default:
				log.Error("[STEPMAN] - Invalid download location")
			}
		}
	}

	if !success {
		return errors.New("Failed to download step")
	}
	return nil
}

// GetStepPath ...
// cach is cool
func GetStepPath(step models.StepModel) string {
	return GetCurrentStepCacheDir() + step.ID + "/" + step.VersionTag + "/"
}

// semantic version (X.Y.Z)
// true if version 2 is greater then version 1
func isVersionGrater(version1, version2 string) bool {
	version1Slice := strings.Split(version1, ".")
	version2Slice := strings.Split(version2, ".")

	for i, num := range version1Slice {
		num1, err1 := strconv.ParseInt(num, 0, 64)
		if err1 != nil {
			log.Error("[STEPMAN] - Failed to parse int:", err1)
			return false
		}

		num2, err2 := strconv.ParseInt(version2Slice[i], 0, 64)
		if err2 != nil {
			log.Error("[STEPMAN] - Failed to parse int:", err2)
			return false
		}

		if num2 > num1 {
			return true
		}
	}
	return false
}

func addStepToStepGroup(step models.StepModel, stepGroup models.StepGroupModel) models.StepGroupModel {
	var newStepGroup models.StepGroupModel
	if len(stepGroup.Versions) > 0 {
		// Step Group already created -> new version of step
		newStepGroup = stepGroup

		if isVersionGrater(newStepGroup.Latest.VersionTag, step.VersionTag) {
			newStepGroup.Latest = step
		}
	} else {
		// Create Step Group
		newStepGroup = models.StepGroupModel{}
		newStepGroup.Latest = step
	}

	versions := make([]models.StepModel, len(newStepGroup.Versions))
	for idx, step := range newStepGroup.Versions {
		versions[idx] = step
	}
	versions = append(versions, step)

	newStepGroup.Versions = versions
	newStepGroup.ID = step.ID
	return newStepGroup
}

func generateFormattedJSONForStepsSpec(templateCollection models.StepCollectionModel) ([]byte, error) {
	collection := models.StepCollectionModel{
		FormatVersion:        templateCollection.FormatVersion,
		GeneratedAtTimeStamp: time.Now().Unix(),
		SteplibSource:        CollectionURI,
		DownloadLocations:    templateCollection.DownloadLocations,
	}

	stepHash := models.StepHash{}

	stepsSpecDir := GetCurrentStepCollectionPath()
	err := filepath.Walk(stepsSpecDir, func(path string, f os.FileInfo, err error) error {
		truncatedPath := strings.Replace(path, stepsSpecDir, "", -1)
		match, matchErr := regexp.MatchString("([a-z]+).yml", truncatedPath)
		if matchErr != nil {
			return matchErr
		}

		if match {
			components := strings.Split(truncatedPath, "/")
			if len(components) == 4 {
				name := components[1]
				version := components[2]

				step, parseErr := parseStepYml(path, name, version)
				if parseErr != nil {
					return parseErr
				}
				stepGroup := addStepToStepGroup(step, stepHash[name])

				stepHash[name] = stepGroup
			} else {
				log.Debug("[STEPMAN] - Path:", truncatedPath)
				log.Debug("[STEPMAN] - Legth:", len(components))
			}
		}

		return err
	})
	if err != nil {
		log.Error("[STEPMAN] - Failed to walk through path:", err)
	}

	collection.Steps = stepHash

	var bytes []byte
	// if DebugMode == true {
	bytes, err = json.MarshalIndent(collection, "", "\t")
	// } else {
	// 	bytes, err = json.Marshal(collection)
	// }
	if err != nil {
		log.Error("[STEPMAN] - Failed to parse json:", err)
		return []byte{}, err
	}

	return bytes, nil
}

// WriteStepSpecToFile ...
func WriteStepSpecToFile(templateCollection models.StepCollectionModel) error {
	pth := GetCurrentStepSpecPath()

	if exist, err := pathutil.IsPathExists(pth); err != nil {
		log.Error("[STEPMAN] - Failed to check path:", err)
		return err
	} else if exist == false {
		dir, _ := path.Split(pth)
		err := os.MkdirAll(dir, 0777)
		if err != nil {
			return err
		}
	} else {
		err := os.Remove(pth)
		if err != nil {
			return err
		}
	}

	file, err := os.OpenFile(pth, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	defer func() {
		err := file.Close()
		if err != nil {
			log.Error("[STEPMAN] - Failed to close file:", err)
		}
	}()

	jsonContBytes, err := generateFormattedJSONForStepsSpec(templateCollection)
	if err != nil {
		return err
	}

	_, err = file.Write(jsonContBytes)
	if err != nil {
		return err
	}

	return nil
}

// ReadStepSpec ...
func ReadStepSpec() (models.StepCollectionModel, error) {
	pth := GetCurrentStepSpecPath()
	file, err := os.Open(pth)
	if err != nil {
		return models.StepCollectionModel{}, err
	}

	var stepCollection models.StepCollectionModel
	parser := json.NewDecoder(file)
	if err = parser.Decode(&stepCollection); err != nil {
		return models.StepCollectionModel{}, err
	}
	return stepCollection, err
}

// DownloadAndUnZIP ...
func DownloadAndUnZIP(url, pth string) error {
	filePath := os.TempDir() + "step.zip"
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer func() {
		if err := file.Close(); err != nil {
			log.Fatal("Failed to close file:", err)
		}
		if err := os.Remove(filePath); err != nil {
			log.Fatal("Failed to remove file:", err)
		}
	}()

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer func() {
		if err := response.Body.Close(); err != nil {
			log.Fatal("Failed to close response body:", err)
		}
	}()

	if response.StatusCode != http.StatusOK {
		errorMsg := "Failed to download step.zip from: " + url
		return errors.New(errorMsg)
	}

	log.Info("Successfully downloaded step.zip")
	if _, err := io.Copy(file, response.Body); err != nil {
		return err
	}

	return unzip(filePath, pth)
}

func unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer func() {
		if err := r.Close(); err != nil {
			log.Fatal(err)
		}
	}()

	if err := os.MkdirAll(dest, 0755); err != nil {
		return err
	}

	// Closure to address file descriptors issue with all the deferred .Close() methods
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer func() {
			if err := rc.Close(); err != nil {
				log.Fatal(err)
			}
		}()

		path := filepath.Join(dest, f.Name)

		if f.FileInfo().IsDir() {
			if err := os.MkdirAll(path, f.Mode()); err != nil {
				return err
			}
		} else {
			f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return err
			}
			defer func() {
				if err := f.Close(); err != nil {
					log.Fatal(err)
				}
			}()

			if _, err = io.Copy(f, rc); err != nil {
				return err
			}
		}
		return nil
	}

	for _, f := range r.File {
		if err := extractAndWriteFile(f); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>minor error debug log<commit_after>package stepman

import (
	"archive/zip"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/go-pathutil/pathutil"
	"github.com/bitrise-io/stepman/models"
	"gopkg.in/yaml.v2"
)

// DebugMode ...
var DebugMode bool

func parseStepYml(pth, id, version string) (models.StepModel, error) {
	bytes, err := ioutil.ReadFile(pth)
	if err != nil {
		return models.StepModel{}, err
	}

	var stepJSON models.StepModel
	if err := yaml.Unmarshal(bytes, &stepJSON); err != nil {
		return models.StepModel{}, err
	}

	stepJSON.ID = id
	stepJSON.VersionTag = version
	stepJSON.StepLibSource = CollectionURI

	return stepJSON, nil
}

// ParseStepCollection ...
func ParseStepCollection(pth string) (models.StepCollectionModel, error) {
	bytes, err := ioutil.ReadFile(pth)
	if err != nil {
		return models.StepCollectionModel{}, err
	}

	var stepCollection models.StepCollectionModel
	if err := yaml.Unmarshal(bytes, &stepCollection); err != nil {
		return models.StepCollectionModel{}, err
	}
	return stepCollection, nil
}

// DownloadStep ...
func DownloadStep(collection models.StepCollectionModel, step models.StepModel) error {
	downloadLocations := collection.GetDownloadLocations(step)

	success := false
	for _, downloadLocationMap := range downloadLocations {
		for key, value := range downloadLocationMap {
			switch key {
			case "zip":
				if err := DownloadAndUnZIP(value, GetStepPath(step)); err != nil {
					log.Error("Failed to download step.zip:", err)
					break
				}
				success = true
			case "git":
				if err := DoGitUpdate(value, GetStepPath(step)); err != nil {
					log.Error("Failed to clone step ("+value+"):", err)
					break
				}
				success = true
			default:
				log.Error("[STEPMAN] - Invalid download location")
			}
		}
	}

	if !success {
		return errors.New("Failed to download step")
	}
	return nil
}

// GetStepPath ...
// cach is cool
func GetStepPath(step models.StepModel) string {
	return GetCurrentStepCacheDir() + step.ID + "/" + step.VersionTag + "/"
}

// semantic version (X.Y.Z)
// true if version 2 is greater then version 1
func isVersionGrater(version1, version2 string) bool {
	version1Slice := strings.Split(version1, ".")
	version2Slice := strings.Split(version2, ".")

	for i, num := range version1Slice {
		num1, err1 := strconv.ParseInt(num, 0, 64)
		if err1 != nil {
			log.Error("[STEPMAN] - Failed to parse int:", err1)
			return false
		}

		num2, err2 := strconv.ParseInt(version2Slice[i], 0, 64)
		if err2 != nil {
			log.Error("[STEPMAN] - Failed to parse int:", err2)
			return false
		}

		if num2 > num1 {
			return true
		}
	}
	return false
}

func addStepToStepGroup(step models.StepModel, stepGroup models.StepGroupModel) models.StepGroupModel {
	var newStepGroup models.StepGroupModel
	if len(stepGroup.Versions) > 0 {
		// Step Group already created -> new version of step
		newStepGroup = stepGroup

		if isVersionGrater(newStepGroup.Latest.VersionTag, step.VersionTag) {
			newStepGroup.Latest = step
		}
	} else {
		// Create Step Group
		newStepGroup = models.StepGroupModel{}
		newStepGroup.Latest = step
	}

	versions := make([]models.StepModel, len(newStepGroup.Versions))
	for idx, step := range newStepGroup.Versions {
		versions[idx] = step
	}
	versions = append(versions, step)

	newStepGroup.Versions = versions
	newStepGroup.ID = step.ID
	return newStepGroup
}

func generateFormattedJSONForStepsSpec(templateCollection models.StepCollectionModel) ([]byte, error) {
	collection := models.StepCollectionModel{
		FormatVersion:        templateCollection.FormatVersion,
		GeneratedAtTimeStamp: time.Now().Unix(),
		SteplibSource:        CollectionURI,
		DownloadLocations:    templateCollection.DownloadLocations,
	}

	stepHash := models.StepHash{}

	stepsSpecDir := GetCurrentStepCollectionPath()
	err := filepath.Walk(stepsSpecDir, func(path string, f os.FileInfo, err error) error {
		truncatedPath := strings.Replace(path, stepsSpecDir, "", -1)
		match, matchErr := regexp.MatchString("([a-z]+).yml", truncatedPath)
		if matchErr != nil {
			return matchErr
		}

		if match {
			components := strings.Split(truncatedPath, "/")
			if len(components) == 4 {
				name := components[1]
				version := components[2]

				step, parseErr := parseStepYml(path, name, version)
				if parseErr != nil {
					return parseErr
				}
				stepGroup := addStepToStepGroup(step, stepHash[name])

				stepHash[name] = stepGroup
			} else {
				log.Debug("[STEPMAN] - Path:", truncatedPath)
				log.Debug("[STEPMAN] - Legth:", len(components))
			}
		}

		return err
	})
	if err != nil {
		log.Error("[STEPMAN] - Failed to walk through path:", err)
	}

	collection.Steps = stepHash

	var bytes []byte
	// if DebugMode == true {
	bytes, err = json.MarshalIndent(collection, "", "\t")
	// } else {
	// 	bytes, err = json.Marshal(collection)
	// }
	if err != nil {
		log.Error("[STEPMAN] - Failed to parse json:", err)
		return []byte{}, err
	}

	return bytes, nil
}

// WriteStepSpecToFile ...
func WriteStepSpecToFile(templateCollection models.StepCollectionModel) error {
	pth := GetCurrentStepSpecPath()

	if exist, err := pathutil.IsPathExists(pth); err != nil {
		log.Error("[STEPMAN] - Failed to check path:", err)
		return err
	} else if exist == false {
		dir, _ := path.Split(pth)
		err := os.MkdirAll(dir, 0777)
		if err != nil {
			return err
		}
	} else {
		err := os.Remove(pth)
		if err != nil {
			return err
		}
	}

	file, err := os.OpenFile(pth, os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		return err
	}
	defer func() {
		err := file.Close()
		if err != nil {
			log.Error("[STEPMAN] - Failed to close file:", err)
		}
	}()

	jsonContBytes, err := generateFormattedJSONForStepsSpec(templateCollection)
	if err != nil {
		return err
	}

	_, err = file.Write(jsonContBytes)
	if err != nil {
		return err
	}

	return nil
}

// ReadStepSpec ...
func ReadStepSpec() (models.StepCollectionModel, error) {
	pth := GetCurrentStepSpecPath()
	file, err := os.Open(pth)
	if err != nil {
		return models.StepCollectionModel{}, err
	}

	var stepCollection models.StepCollectionModel
	parser := json.NewDecoder(file)
	if err = parser.Decode(&stepCollection); err != nil {
		return models.StepCollectionModel{}, err
	}
	return stepCollection, err
}

// DownloadAndUnZIP ...
func DownloadAndUnZIP(url, pth string) error {
	filePath := os.TempDir() + "step.zip"
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer func() {
		if err := file.Close(); err != nil {
			log.Fatal("Failed to close file:", err)
		}
		if err := os.Remove(filePath); err != nil {
			log.Fatal("Failed to remove file:", err)
		}
	}()

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer func() {
		if err := response.Body.Close(); err != nil {
			log.Fatal("Failed to close response body:", err)
		}
	}()

	if response.StatusCode != http.StatusOK {
		errorMsg := "Failed to download step.zip from: " + url
		return errors.New(errorMsg)
	}

	log.Info("Successfully downloaded step.zip")
	if _, err := io.Copy(file, response.Body); err != nil {
		return err
	}

	return unzip(filePath, pth)
}

func unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer func() {
		if err := r.Close(); err != nil {
			log.Fatal(err)
		}
	}()

	if err := os.MkdirAll(dest, 0755); err != nil {
		return err
	}

	// Closure to address file descriptors issue with all the deferred .Close() methods
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer func() {
			if err := rc.Close(); err != nil {
				log.Fatal(err)
			}
		}()

		path := filepath.Join(dest, f.Name)

		if f.FileInfo().IsDir() {
			if err := os.MkdirAll(path, f.Mode()); err != nil {
				return err
			}
		} else {
			f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return err
			}
			defer func() {
				if err := f.Close(); err != nil {
					log.Fatal(err)
				}
			}()

			if _, err = io.Copy(f, rc); err != nil {
				return err
			}
		}
		return nil
	}

	for _, f := range r.File {
		if err := extractAndWriteFile(f); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package cec

import(
	"log"
	"time"
	"strings"
)

type Device struct {
	OSDName string
	Vendor string
	LogicalAddress int
	ActiveSource bool
	PowerStatus string
	PhysicalAddress string
}

var logicalNames = []string{ "TV", "Recording", "Recording2", "Tuner",
	"Playback","Audio", "Tuner2", "Tuner3",
	"Playback2", "Recording3", "Tuner4", "Playback3",
	"Reserved", "Reserved2", "Free", "Broadcast" }

var vendorList = map[uint64]string{ 0x000039:"Toshiba", 0x0000F0:"Samsung",
	0x0005CD:"Denon", 0x000678:"Marantz", 0x000982:"Loewe", 0x0009B0:"Onkyo",
	0x000CB8:"Medion", 0x000CE7:"Toshiba", 0x001582:"Pulse Eight",
	0x0020C7:"Akai", 0x002467:"Aoc", 0x008045:"Panasonic", 0x00903E:"Philips",
	0x009053:"Daewoo", 0x00A0DE:"Yamaha", 0x00D0D5:"Grundig",
	0x00E036:"Pioneer", 0x00E091:"LG", 0x08001F:"Sharp", 0x080046:"Sony",
	0x18C086:"Broadcom", 0x6B746D:"Vizio", 0x8065E9:"Benq",
	0x9C645E:"Harman Kardon" }

func Open(name string, deviceName string) {
	var config CECConfiguration
	config.DeviceName = deviceName

	if er := cecInit(config); er != nil {
		log.Println(er)
		return
	}

	adapter, er := getAdapter(name)
	if er != nil {
		log.Println(er)
		return
	}

	er = openAdapter(adapter)
	if er != nil {
		log.Println(er)
		return
	}
}

func Key(address int, key int) {
	er := KeyPress(address, key)
	if er != nil {
		log.Println(er)
		return
	}
	time.Sleep(10 * time.Millisecond)
	er = KeyRelease(address)
	if er != nil {
		log.Println(er)
		return
	}
}

func List() map[string]Device {
	devices := make(map[string]Device)

	active_devices := GetActiveDevices()

	for address, active := range active_devices {
		if (active) {
			var dev Device

			dev.LogicalAddress = address
			dev.PhysicalAddress = GetDevicePhysicalAddress(address)
			dev.OSDName = GetDeviceOSDName(address)
			dev.PowerStatus = GetDevicePowerStatus(address)
			dev.ActiveSource = IsActiveSource(address)
			dev.Vendor = GetVendorById(GetDeviceVendorId(address))

			devices[logicalNames[address]] = dev
		}
	}
	return devices
}

func removeSeparators(in string) string {
        // remove separators (":", "-", " ", "_")
        out := strings.Map(func(r rune) rune {
                if strings.IndexRune(":-_ ", r) < 0 {
                        return r
                }
                return -1
        }, in)

	return(out)
}

func GetLogicalAddressByName(name string) int {
	name = removeSeparators(name)
	l := len(name)

	if name[l-1] == '1' {
		name = name[:l-1]
	}

	for i:=0; i<16; i++ {
		if logicalNames[i] == name {
			return i
		}
	}

	if name == "Unregistered" {
		return 15
	}

	return -1
}

func GetLogicalNameByAddress(addr int) string {
	return logicalNames[addr]
}

func GetVendorById(id uint64) string {
	return vendorList[id]
}
<commit_msg>make GetLogicalAddressByName case insensitive<commit_after>package cec

import(
	"log"
	"time"
	"strings"
)

type Device struct {
	OSDName string
	Vendor string
	LogicalAddress int
	ActiveSource bool
	PowerStatus string
	PhysicalAddress string
}

var logicalNames = []string{ "TV", "Recording", "Recording2", "Tuner",
	"Playback","Audio", "Tuner2", "Tuner3",
	"Playback2", "Recording3", "Tuner4", "Playback3",
	"Reserved", "Reserved2", "Free", "Broadcast" }

var vendorList = map[uint64]string{ 0x000039:"Toshiba", 0x0000F0:"Samsung",
	0x0005CD:"Denon", 0x000678:"Marantz", 0x000982:"Loewe", 0x0009B0:"Onkyo",
	0x000CB8:"Medion", 0x000CE7:"Toshiba", 0x001582:"Pulse Eight",
	0x0020C7:"Akai", 0x002467:"Aoc", 0x008045:"Panasonic", 0x00903E:"Philips",
	0x009053:"Daewoo", 0x00A0DE:"Yamaha", 0x00D0D5:"Grundig",
	0x00E036:"Pioneer", 0x00E091:"LG", 0x08001F:"Sharp", 0x080046:"Sony",
	0x18C086:"Broadcom", 0x6B746D:"Vizio", 0x8065E9:"Benq",
	0x9C645E:"Harman Kardon" }

func Open(name string, deviceName string) {
	var config CECConfiguration
	config.DeviceName = deviceName

	if er := cecInit(config); er != nil {
		log.Println(er)
		return
	}

	adapter, er := getAdapter(name)
	if er != nil {
		log.Println(er)
		return
	}

	er = openAdapter(adapter)
	if er != nil {
		log.Println(er)
		return
	}
}

func Key(address int, key int) {
	er := KeyPress(address, key)
	if er != nil {
		log.Println(er)
		return
	}
	time.Sleep(10 * time.Millisecond)
	er = KeyRelease(address)
	if er != nil {
		log.Println(er)
		return
	}
}

func List() map[string]Device {
	devices := make(map[string]Device)

	active_devices := GetActiveDevices()

	for address, active := range active_devices {
		if (active) {
			var dev Device

			dev.LogicalAddress = address
			dev.PhysicalAddress = GetDevicePhysicalAddress(address)
			dev.OSDName = GetDeviceOSDName(address)
			dev.PowerStatus = GetDevicePowerStatus(address)
			dev.ActiveSource = IsActiveSource(address)
			dev.Vendor = GetVendorById(GetDeviceVendorId(address))

			devices[logicalNames[address]] = dev
		}
	}
	return devices
}

func removeSeparators(in string) string {
        // remove separators (":", "-", " ", "_")
        out := strings.Map(func(r rune) rune {
                if strings.IndexRune(":-_ ", r) < 0 {
                        return r
                }
                return -1
        }, in)

	return(out)
}

func GetLogicalAddressByName(name string) int {
	name = removeSeparators(name)
	l := len(name)

	if name[l-1] == '1' {
		name = name[:l-1]
	}

	name = strings.ToLower(name)

	for i:=0; i<16; i++ {
		if strings.ToLower(logicalNames[i]) == name {
			return i
		}
	}

	if name == "unregistered" {
		return 15
	}

	return -1
}

func GetLogicalNameByAddress(addr int) string {
	return logicalNames[addr]
}

func GetVendorById(id uint64) string {
	return vendorList[id]
}
<|endoftext|>


<commit_before>// packcage strip provides the same functionality as http.StripPrefix
// and can be used in martini instance level and request context level.
package strip

import (
	"github.com/codegangsta/martini"
	"net/http"
	"strings"
)

func Prefix(prefix string) martini.Handler {
	return func(w http.ResponseWriter, r *http.Request) {
		if prefix == "" {
			return
		}
		if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
			r.URL.Path = p
		} else {
			http.NotFound(w, r)
		}
	}
}
<commit_msg>add doc string for stip.Prefix<commit_after>// packcage strip provides the same functionality as http.StripPrefix
// and can be used in martini instance level and request context level.
package strip

import (
	"github.com/codegangsta/martini"
	"net/http"
	"strings"
)

// strip Prefix for every incoming http request
func Prefix(prefix string) martini.Handler {
	return func(w http.ResponseWriter, r *http.Request) {
		if prefix == "" {
			return
		}
		if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
			r.URL.Path = p
		} else {
			http.NotFound(w, r)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"sync"
)

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

func main() {
	app := cli.NewApp()
	app.Name = "cig"
	app.Usage = "cig (Can I go?) checks all your git repos to see if they're in the state you want them to be"
	app.Version = "0.1.0"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "filter, f",
			Value: "",
			Usage: "Filter repos being searched",
		},
		cli.StringFlag{
			Name:  "type, t",
			Value: "",
			Usage: "Filter by type",
		},
	}

	app.Action = func(c *cli.Context) {
		project_type := c.String("type")

		var channel = make(chan string)
		go output(channel)

		paths := make(map[interface{}]interface{})
		home_dir, err := homedir.Dir()
		path := fmt.Sprintf("%s%s.cig.yaml", home_dir, string(os.PathSeparator))

		data, err := ioutil.ReadFile(path)

		if err != nil {
			channel <- color.RedString(fmt.Sprintf("Can't find config '%s'", path))
			os.Exit(-1)
		}

		err = yaml.Unmarshal([]byte(data), &paths)
		if err != nil {
			panic(err)
			channel <- color.RedString(fmt.Sprintf("Problem parsing '%s', please check documentation", path))
			os.Exit(-1)
		}
		check(err)

		var wg sync.WaitGroup

		for k, v := range paths {
			if project_type == "" || project_type == k {
				fmt.Printf("\nChecking '%s' (%s) repos...\n", k, v)

				visit := func(path string, info os.FileInfo, err error) error {
					filter := c.String("filter")

					matched, _ := regexp.MatchString(filter, path)
					if info.IsDir() && (filter == "" || matched) {
						wg.Add(1)
						go checkRepo(v.(string), path, channel, &wg)
					}
					return nil
				}

				err := filepath.Walk(v.(string), visit)
				if err != nil {
					log.Fatal(err)
				}
			}

			wg.Wait()
		}

		wg.Wait()
	}
	app.Run(os.Args)
}

func output(channel chan string) {
	for {
		entry := <-channel
		fmt.Printf(entry)
	}
}

func checkRepo(root string, path string, channel chan string, wg *sync.WaitGroup) {
	exists, err := exists(fmt.Sprintf("%s%s.git", path, string(os.PathSeparator)))

	if exists {
		modified_files := exec.Command("git", "status", "-s")
		modified_files.Dir = path

		count_out, _ := modified_files.Output()
		modified_lines := strings.Split(string(count_out), "\n")
		modified := len(modified_lines) - 1

		if err != nil {
			println(err.Error())
			return
		}

		changes := []string{}

		if modified > 0 && modified_lines[0] != "" {
			changes = append(changes, print_output(fmt.Sprintf(" M(%d)", modified), "red"))
		}

		branch := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
		branch.Dir = path
		bstdout, _ := branch.Output()
		branch_name := strings.TrimSpace(string(bstdout[:]))

		local := exec.Command("git", "rev-parse", branch_name)
		local.Dir = path
		lstdout, _ := local.Output()
		local_ref := strings.TrimSpace(string(lstdout[:]))

		remote := exec.Command("git", "rev-parse", fmt.Sprintf("origin/%s", branch_name))
		remote.Dir = path
		rstdout, err := remote.Output()
		remote_ref := strings.TrimSpace(string(rstdout[:]))

		if err == nil && remote_ref != local_ref {
			changes = append(changes, print_output(" P", "blue"))
		}

		if len(changes) > 0 {
			var buffer bytes.Buffer

			repo_name := strings.Replace(path, fmt.Sprintf("%s%s", root, string(os.PathSeparator)), "", -1)

			buffer.WriteString(fmt.Sprintf("- %s (%s)", repo_name, branch_name))
			for _, change := range changes {
				buffer.WriteString(change)
			}
			channel <- buffer.String() + "\n"
		}

	}
	wg.Done()
}

func print_output(message string, output_type string) string {
	if runtime.GOOS != "windows" {
		switch output_type {
		case "red":
			return color.RedString(message)
		case "blue":
			return color.BlueString(message)
		}

	}
	return message
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<commit_msg>Removes unwanted panic<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fatih/color"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"sync"
)

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

func main() {
	app := cli.NewApp()
	app.Name = "cig"
	app.Usage = "cig (Can I go?) checks all your git repos to see if they're in the state you want them to be"
	app.Version = "0.1.0"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "filter, f",
			Value: "",
			Usage: "Filter repos being searched",
		},
		cli.StringFlag{
			Name:  "type, t",
			Value: "",
			Usage: "Filter by type",
		},
	}

	app.Action = func(c *cli.Context) {
		project_type := c.String("type")

		var channel = make(chan string)
		go output(channel)

		paths := make(map[interface{}]interface{})
		home_dir, err := homedir.Dir()
		path := fmt.Sprintf("%s%s.cig.yaml", home_dir, string(os.PathSeparator))

		data, err := ioutil.ReadFile(path)

		if err != nil {
			channel <- color.RedString(fmt.Sprintf("Can't find config '%s'", path))
			os.Exit(-1)
		}

		err = yaml.Unmarshal([]byte(data), &paths)
		if err != nil {
			channel <- color.RedString(fmt.Sprintf("Problem parsing '%s', please check documentation", path))
			os.Exit(-1)
		}
		check(err)

		var wg sync.WaitGroup

		for k, v := range paths {
			if project_type == "" || project_type == k {
				fmt.Printf("\nChecking '%s' (%s) repos...\n", k, v)

				visit := func(path string, info os.FileInfo, err error) error {
					filter := c.String("filter")

					matched, _ := regexp.MatchString(filter, path)
					if info.IsDir() && (filter == "" || matched) {
						wg.Add(1)
						go checkRepo(v.(string), path, channel, &wg)
					}
					return nil
				}

				err := filepath.Walk(v.(string), visit)
				if err != nil {
					log.Fatal(err)
				}
			}

			wg.Wait()
		}

		wg.Wait()
	}
	app.Run(os.Args)
}

func output(channel chan string) {
	for {
		entry := <-channel
		fmt.Printf(entry)
	}
}

func checkRepo(root string, path string, channel chan string, wg *sync.WaitGroup) {
	exists, err := exists(fmt.Sprintf("%s%s.git", path, string(os.PathSeparator)))

	if exists {
		modified_files := exec.Command("git", "status", "-s")
		modified_files.Dir = path

		count_out, _ := modified_files.Output()
		modified_lines := strings.Split(string(count_out), "\n")
		modified := len(modified_lines) - 1

		if err != nil {
			println(err.Error())
			return
		}

		changes := []string{}

		if modified > 0 && modified_lines[0] != "" {
			changes = append(changes, print_output(fmt.Sprintf(" M(%d)", modified), "red"))
		}

		branch := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
		branch.Dir = path
		bstdout, _ := branch.Output()
		branch_name := strings.TrimSpace(string(bstdout[:]))

		local := exec.Command("git", "rev-parse", branch_name)
		local.Dir = path
		lstdout, _ := local.Output()
		local_ref := strings.TrimSpace(string(lstdout[:]))

		remote := exec.Command("git", "rev-parse", fmt.Sprintf("origin/%s", branch_name))
		remote.Dir = path
		rstdout, err := remote.Output()
		remote_ref := strings.TrimSpace(string(rstdout[:]))

		if err == nil && remote_ref != local_ref {
			changes = append(changes, print_output(" P", "blue"))
		}

		if len(changes) > 0 {
			var buffer bytes.Buffer

			repo_name := strings.Replace(path, fmt.Sprintf("%s%s", root, string(os.PathSeparator)), "", -1)

			buffer.WriteString(fmt.Sprintf("- %s (%s)", repo_name, branch_name))
			for _, change := range changes {
				buffer.WriteString(change)
			}
			channel <- buffer.String() + "\n"
		}

	}
	wg.Done()
}

func print_output(message string, output_type string) string {
	if runtime.GOOS != "windows" {
		switch output_type {
		case "red":
			return color.RedString(message)
		case "blue":
			return color.BlueString(message)
		}

	}
	return message
}

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}
<|endoftext|>


<commit_before>package strrand

import (
	"fmt"
	"reflect"
	"testing"
)

func TestMakeRange(t *testing.T) {
	s := makeRange('A', 'C')

	if !reflect.DeepEqual(s, []string{"A", "B", "C"}) {
		t.Errorf("something wrong")
	}

	reg := `..\.adf.!\d\w`
	ss, _ := New().Generate(reg)
	fmt.Printf("`%s`: %s\n", reg, ss)

	reg = `.[1-9koc\]]hoge`
	ss, _ = New().Generate(reg)
	fmt.Printf("`%s`: %s\n", reg, ss)

	reg = `[1-9koc\]]{16}`
	ss, _ = New().Generate(reg)
	fmt.Printf("`%s`: %s\n", reg, ss)

	reg = `a{1,4}`
	ss, _ = New().Generate(reg)
	fmt.Printf("`%s`: %s\n", reg, ss)
}

func TestPicker(t *testing.T) {
	p := chrPicker([]string{"X"})

	if !reflect.DeepEqual(p, chrPicker([]string{"X"})) {
		t.Errorf("something wrong")
	}

	if p.pick() != "X" {
		t.Errorf("something wrong")
	}
}

func TestVariantPicker(t *testing.T) {
	vp := variantPicker{
		min:    1,
		max:    3,
		picker: chrPicker([]string{"a", "b", "c", "d"}),
	}

	r := vp.pick()
	fmt.Println(r)

	if len(r) < 1 || len(r) > 3 {
		t.Errorf("something wrong")
	}
}
<commit_msg>add TestCreateGenerator<commit_after>package strrand

import (
	"fmt"
	"reflect"
	"testing"
)

func TestMakeRange(t *testing.T) {
	s := makeRange('A', 'C')

	if !reflect.DeepEqual(s, []string{"A", "B", "C"}) {
		t.Errorf("something wrong")
	}
}

func TestCreateGenerator(t *testing.T) {
	reg := `.\.a{1,4}[a-c][A-B]?\d*\s+\![-OMG!\?]`
	g, _ := New().CreateGenerator(reg)

	if !reflect.DeepEqual(g, pickers([]picker{
		any,
		chrPicker([]string{"."}),
		variantPicker{
			min:    1,
			max:    4,
			picker: chrPicker([]string{"a"}),
		},
		chrPicker([]string{"a", "b", "c"}),
		variantPicker{
			min:    0,
			max:    1,
			picker: chrPicker([]string{"A", "B"}),
		},
		variantPicker{
			min:    0,
			max:    10,
			picker: digit,
		},
		variantPicker{
			min:    1,
			max:    10,
			picker: chrPicker([]string{" ", "\t"}),
		},
		chrPicker([]string{"!"}),
		chrPicker([]string{"-", "O", "M", "G", "!", "?"}),
	})) {
		t.Errorf("error")
	}

	fmt.Printf("`%s`: %s\n", reg, g.Generate())
}

func TestPicker(t *testing.T) {
	p := chrPicker([]string{"X"})

	if !reflect.DeepEqual(p, chrPicker([]string{"X"})) {
		t.Errorf("something wrong")
	}

	if p.pick() != "X" {
		t.Errorf("something wrong")
	}
}

func TestVariantPicker(t *testing.T) {
	vp := variantPicker{
		min:    1,
		max:    3,
		picker: chrPicker([]string{"a", "b", "c", "d"}),
	}

	r := vp.pick()
	fmt.Println(r)

	if len(r) < 1 || len(r) > 3 {
		t.Errorf("something wrong")
	}
}
<|endoftext|>


<commit_before>package summary

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestSummary(t *testing.T) {
	Convey("Given Summary", t, func() {
		Convey("Intersection works", func() {
			var testCases = []struct {
				s1       []string
				s2       []string
				expected int
			}{
				{
					[]string{},
					[]string{},
					0,
				},
				{
					[]string{"one", "two", "three"},
					[]string{"two", "four", "six"},
					1,
				},
			}
			for _, tc := range testCases {
				So(sentencesIntersection(tc.s1, tc.s2), ShouldEqual, tc.expected)
			}

		})
		Convey("Sum works", func() {
			var testCases = []struct {
				arr      []int
				expected int
			}{
				{
					[]int{},
					0,
				},
				{
					[]int{1, 2, 3},
					6,
				},
			}
			for _, tc := range testCases {
				So(sum(tc.arr), ShouldEqual, tc.expected)
			}
		})
		Convey("Generating summary works", func() {
			var testCases = []struct {
				given    string
				expected string
			}{
				{
					``,
					``,
				},
				{
					`Действието започва една вечер в двора на чорбаджи Марко, който вечеря с многолюдното си семейство. След вечерята той изпраща жена си при болния си син Асен, който е трескав, защото видял трупа на едно обезглавено от страшния бандит Емексиз Пехливан дете. В този момент се чува тропот при дувара, а слугинята се разкрещява. Марко отива да види какво е станало и там се натъква на Иван Краличът, който му се представя. Като най-близък приятел на баща му той решава да го скрие у дома си, но виковете на слугинята вече са предизвикали хората да повикат онбашия и турците вече тропат на вратата. В това време беглецът прескача зида и се измъква от заптиетата, но при сборичкването си с един от тях връхната му дреха остава в ръцете му.

След дивия си бяг, подпомогнат от тъмнината и настъпващата буря, той се измъква от турците и се скрива в една воденица на Манастирската река. Той смята, че тя е пуста, но скоро се прибира стопанинът дядо Стоян с дъщеря си Марийка и беглецът се укрива. Скоро дохождат двама турци на връщане от лов. Това са страшният Емексиз Пехливан и другарят му. Те принуждават стопанина да ги прислони във воденицата, а след като виждат младата му дъщеря, решават да го завържат и да се гаврят с момичето. В този момент Иван излиза от скривалището си, напада ги и ги убива — Емексиз Пехливан с една брадва, а на другаря му забива нож в гърлото. С това той печели вечната признателност и преданост на бащата и дъщерята. С общи усилия Иван и стопанинът заличават следите и погребват турците зад воденицата, а убитото куче пускат във водата. Решават да се приютят в манастира за през нощта и тръгват натам, но никой не подозира, че освен тях има още един свидетел на случката — идиотът Мунчо.

В манастира беглецът е добре приет от дякон Викентий, който се отнася гостоприемно с бунтовниците. На другия ден се връща и игуменът Натанаил, който носи лоши новини от града. Доктор Соколов през нощта е бил арестуван и откаран. Когато Иван го питал предния ден за Марковата къща, докторът му подарил дрехата си, защото беглецът бил дрипав. Иван сложил в джоба си бунтовнически книжа, а дрехата останала у турците. След тия известия той решава да отиде да се предаде, за да избави този добър човек.`,
					`Действието започва една вечер в двора на чорбаджи Марко, който вечеря с многолюдното си семейство.
След дивия си бяг, подпомогнат от тъмнината и настъпващата буря, той се измъква от турците и се скрива в една воденица на Манастирската река.
В манастира беглецът е добре приет от дякон Викентий, който се отнася гостоприемно с бунтовниците.
`,
				},
			}
			for _, tc := range testCases {
				So(Summarize(tc.given, NewDefaultTokenizer()), ShouldEqual, tc.expected)
			}
		})
	})
}
<commit_msg>Added getRank benchmark<commit_after>package summary

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestSummary(t *testing.T) {
	Convey("Given Summary", t, func() {
		Convey("Intersection works", func() {
			var testCases = []struct {
				s1       []string
				s2       []string
				expected int
			}{
				{
					[]string{},
					[]string{},
					0,
				},
				{
					[]string{"one", "two", "three"},
					[]string{"two", "four", "six"},
					1,
				},
			}
			for _, tc := range testCases {
				So(sentencesIntersection(tc.s1, tc.s2), ShouldEqual, tc.expected)
			}

		})
		Convey("Sum works", func() {
			var testCases = []struct {
				arr      []int
				expected int
			}{
				{
					[]int{},
					0,
				},
				{
					[]int{1, 2, 3},
					6,
				},
			}
			for _, tc := range testCases {
				So(sum(tc.arr), ShouldEqual, tc.expected)
			}
		})
		Convey("Generating summary works", func() {
			var testCases = []struct {
				given    string
				expected string
			}{
				{
					``,
					``,
				},
				{
					`Действието започва една вечер в двора на чорбаджи Марко, който вечеря с многолюдното си семейство. След вечерята той изпраща жена си при болния си син Асен, който е трескав, защото видял трупа на едно обезглавено от страшния бандит Емексиз Пехливан дете. В този момент се чува тропот при дувара, а слугинята се разкрещява. Марко отива да види какво е станало и там се натъква на Иван Краличът, който му се представя. Като най-близък приятел на баща му той решава да го скрие у дома си, но виковете на слугинята вече са предизвикали хората да повикат онбашия и турците вече тропат на вратата. В това време беглецът прескача зида и се измъква от заптиетата, но при сборичкването си с един от тях връхната му дреха остава в ръцете му.

След дивия си бяг, подпомогнат от тъмнината и настъпващата буря, той се измъква от турците и се скрива в една воденица на Манастирската река. Той смята, че тя е пуста, но скоро се прибира стопанинът дядо Стоян с дъщеря си Марийка и беглецът се укрива. Скоро дохождат двама турци на връщане от лов. Това са страшният Емексиз Пехливан и другарят му. Те принуждават стопанина да ги прислони във воденицата, а след като виждат младата му дъщеря, решават да го завържат и да се гаврят с момичето. В този момент Иван излиза от скривалището си, напада ги и ги убива — Емексиз Пехливан с една брадва, а на другаря му забива нож в гърлото. С това той печели вечната признателност и преданост на бащата и дъщерята. С общи усилия Иван и стопанинът заличават следите и погребват турците зад воденицата, а убитото куче пускат във водата. Решават да се приютят в манастира за през нощта и тръгват натам, но никой не подозира, че освен тях има още един свидетел на случката — идиотът Мунчо.

В манастира беглецът е добре приет от дякон Викентий, който се отнася гостоприемно с бунтовниците. На другия ден се връща и игуменът Натанаил, който носи лоши новини от града. Доктор Соколов през нощта е бил арестуван и откаран. Когато Иван го питал предния ден за Марковата къща, докторът му подарил дрехата си, защото беглецът бил дрипав. Иван сложил в джоба си бунтовнически книжа, а дрехата останала у турците. След тия известия той решава да отиде да се предаде, за да избави този добър човек.`,
					`Действието започва една вечер в двора на чорбаджи Марко, който вечеря с многолюдното си семейство.
След дивия си бяг, подпомогнат от тъмнината и настъпващата буря, той се измъква от турците и се скрива в една воденица на Манастирската река.
В манастира беглецът е добре приет от дякон Викентий, който се отнася гостоприемно с бунтовниците.
`,
				},
			}
			for _, tc := range testCases {
				So(Summarize(tc.given, NewDefaultTokenizer()), ShouldEqual, tc.expected)
			}
		})
	})
}

func BenchmarkGetRanks(b *testing.B) {
	text := `Three Beauties of the Present Day is a nishiki-e colour woodblock print of c. 1792–93 by Japanese ukiyo-e artist Kitagawa Utamaro (c. 1753–1806). The triangular composition depicts the busts of three celebrity beauties of the time: geisha Tomimoto Toyohina (middle), and teahouse waitresses Takashima Hisa (left) and Naniwa Kita (right), each adorned with an identifying family crest. Subtle differences can be detected in the faces of the subjects—a level of individualized realism at the time unusual in ukiyo-e, and a contrast with the stereotyped beauties in earlier masters such as Harunobu and Kiyonaga. The triangular positioning became a vogue in the 1790s. Utamaro produced several other pictures with this arrangement of the same three beauties, and each appeared in numerous other portraits by Utamaro and other artists. Utamaro was the leading ukiyo-e artist in the 1790s in the bijin-ga genre of pictures of female beauties, and was known in particular for his ōkubi-e, which focus on the heads. The luxurious print was published by Tsutaya Jūzaburō and made with multiple woodblocks—one for each colour—and the background was dusted with muscovite to produce a glimmering effect. `
	t := NewDefaultTokenizer()
	for i := 0; i < b.N; i++ {
		getRanks(text, t)
	}
}
<|endoftext|>