<commit_before>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package main

import (
	"fmt"
	"io"
	"os"

	"github.com/ying32/govcl/vcl"
)

//::private::
type TForm1Fields struct {
	paths map[uintptr]string
}

func (f *TForm1) OnFormCreate(object vcl.IObject) {

	f.TreeView1.Items().Clear()
	f.TreeView1.Items().BeginUpdate()
	node := f.TreeView1.Items().Add(nil, "Root")
	f.paths = make(map[uintptr]string, 0)
	f.walkFile(node, ".")
	node.Expand(true)
	f.TreeView1.Items().EndUpdate()

}

func (f *TForm1) OnTreeView1Click(object vcl.IObject) {
	node := f.TreeView1.Selected()
	if node != nil {
		if path, ok := f.paths[node.Instance()]; ok {
			_, err := os.Stat(path)
			if err == nil {
				if !os.IsNotExist(err) {
					f.ListBox1.Clear()
					f.ListBox1.Items().BeginUpdate()
					f.walkFile2(path)
					f.ListBox1.Items().EndUpdate()
				}
			}
			fmt.Println(path)
		} else {
			fmt.Println("没有", node.Instance())
		}
	}
}

// 只列出当前目录的
func (f *TForm1) walkFile2(path string) {

	fd, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		return
	}
	defer fd.Close()
	for {
		files, err := fd.Readdir(100)
		for _, file := range files {
			if !file.IsDir() {
				f.ListBox1.Items().Add(file.Name())
			}
		}
		if err == io.EOF {
			break
		}
		if len(files) == 0 {
			break
		}
	}
}

func (f *TForm1) walkFile(node *vcl.TTreeNode, path string) {

	fd, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		return
	}
	defer fd.Close()
	for {
		files, err := fd.Readdir(100)
		for _, file := range files {
			if file.IsDir() {

				curPath := path + string(os.PathSeparator) + file.Name()
				subNode := f.TreeView1.Items().AddChild(node, file.Name())

				//subNode.SetData(unsafe.Pointer(uintptr(index)))

				f.paths[subNode.Instance()] = curPath
				f.walkFile(subNode, curPath)
			}
		}
		if err == io.EOF {
			break
		}
		if len(files) == 0 {
			break
		}
	}
}
<commit_msg>Update filedirtree example<commit_after>//----------------------------------------
//
// Copyright © ying32. All Rights Reserved.
//
// Licensed under Apache License 2.0
//
//----------------------------------------

package main

import (
	"fmt"
	"io"
	"os"

	"github.com/ying32/govcl/vcl"
)

//::private::
type TForm1Fields struct {
	paths map[uintptr]string
}

func (f *TForm1) OnFormCreate(object vcl.IObject) {

	f.TreeView1.Items().Clear()
	f.TreeView1.Items().BeginUpdate()
	node := f.TreeView1.Items().Add(nil, "Root")
	f.paths = make(map[uintptr]string, 0)
	f.paths[node.Instance()] = "."
	f.walkFile(node, ".", false)
	node.Expand(true)
	f.TreeView1.Items().EndUpdate()

}

func (f *TForm1) OnTreeView1Click(object vcl.IObject) {
	node := f.TreeView1.Selected()
	if node != nil {
		if path, ok := f.paths[node.Instance()]; ok {
			_, err := os.Stat(path)
			if err == nil {
				if !os.IsNotExist(err) {
					f.ListBox1.Clear()
					f.ListBox1.Items().BeginUpdate()
					f.walkFile(nil, path, true)
					f.ListBox1.Items().EndUpdate()
				}
			}
			fmt.Println(path)
		} else {
			fmt.Println("没有", node.Instance())
		}
	}
}

func (f *TForm1) walkFile(node *vcl.TTreeNode, path string, isFile bool) {
	fd, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		return
	}
	defer fd.Close()
	for {
		files, err := fd.Readdir(100)
		for _, file := range files {
			if !isFile {
				if file.IsDir() {
					curPath := path + string(os.PathSeparator) + file.Name()
					subNode := f.TreeView1.Items().AddChild(node, file.Name())
					//subNode.SetData(unsafe.Pointer(uintptr(index)))
					f.paths[subNode.Instance()] = curPath
					f.walkFile(subNode, curPath, isFile)
				}
			} else {
				f.ListBox1.Items().Add(file.Name())
			}
		}
		if err == io.EOF {
			break
		}
		if len(files) == 0 {
			break
		}
	}
}
<|endoftext|>


<commit_before>package jspointer

import (
	"encoding/json"
	"errors"
	"reflect"
	"strconv"
	"strings"
	"sync"

	"github.com/lestrrat/go-structinfo"
)

var ctxPool = sync.Pool{
	New: moreCtx,
}

func moreCtx() interface{} {
	return &matchCtx{}
}

func getCtx() *matchCtx {
	return ctxPool.Get().(*matchCtx)
}

func releaseCtx(ctx *matchCtx) {
	ctx.err = nil
	ctx.set = false
	ctx.tokens = nil
	ctx.result = nil
	ctxPool.Put(ctx)
}

// New creates a new JSON pointer for given path spec. If the path fails
// to be parsed, an error is returned
func New(path string) (*JSPointer, error) {
	var p JSPointer
	dtokens, err := parse(path)
	if err != nil {
		return nil, err
	}
	p.raw = path
	p.tokens = dtokens
	return &p, nil
}

func parse(s string) ([]string, error) {
	if s == "" {
		return nil, nil
	}

	if s[0] != Separator {
		return nil, ErrInvalidPointer
	}

	prev := 0
	tokens := []string{}
	for i := 1; i < len(s); i++ {
		switch s[i] {
		case Separator:
			tokens = append(tokens, s[prev+1:i])
			prev = i
		}
	}

	if prev != len(s) {
		tokens = append(tokens, s[prev+1:])
	}

	dtokens := make([]string, 0, len(tokens))
	for _, t := range tokens {
		t = strings.Replace(strings.Replace(t, EncodedSlash, "/", -1), EncodedTilde, "~", -1)
		dtokens = append(dtokens, t)
	}

	return dtokens, nil
}

// String returns the stringified version of this JSON pointer
func (p JSPointer) String() string {
	return p.raw
}

// Get applies the JSON pointer to the given item, and returns
// the result.
func (p JSPointer) Get(item interface{}) (interface{}, error) {
	ctx := getCtx()
	defer releaseCtx(ctx)

	ctx.raw = p.raw
	ctx.tokens = p.tokens
	ctx.apply(item)
	return ctx.result, ctx.err
}

// Set applies the JSON pointer to the given item, and sets the
// value accordingly.
func (p JSPointer) Set(item interface{}, value interface{}) error {
	ctx := getCtx()
	defer releaseCtx(ctx)

	ctx.set = true
	ctx.raw = p.raw
	ctx.tokens = p.tokens
	ctx.setvalue = value
	ctx.apply(item)
	return ctx.err
}

type matchCtx struct {
	err      error
	raw      string
	result   interface{}
	set      bool
	setvalue interface{}
	tokens   []string
}

func (e ErrNotFound) Error() string {
	return "match to JSON pointer not found: " + e.Ptr
}

var strType = reflect.TypeOf("")

func (c *matchCtx) apply(item interface{}) {
	if len(c.tokens) == 0 {
		c.result = item
		return
	}

	lastidx := len(c.tokens) - 1
	node := item
	for tidx, token := range c.tokens {
		v := reflect.ValueOf(node)
		if v.Kind() == reflect.Ptr {
			v = v.Elem()
		}

		switch v.Kind() {
		case reflect.Struct:
			i := structinfo.StructFieldFromJSONName(v, token)
			if i < 0 {
				c.err = ErrNotFound{Ptr: c.raw}
				return
			}
			f := v.Field(i)
			if tidx == lastidx {
				if c.set {
					if !f.CanSet() {
						c.err = ErrCanNotSet
						return
					}
					f.Set(reflect.ValueOf(c.setvalue))
					return
				}
				c.result = f.Interface()
				return
			}
			node = f.Interface()
		case reflect.Map:
			var vt reflect.Value
			// We shall try to inflate the token to its Go native
			// type if it's not a string. In other words, try not to
			// outdo yourselves.
			if t := v.Type().Key(); t != strType {
				vt = reflect.New(t).Elem()
				if err := json.Unmarshal([]byte(token), vt.Addr().Interface()); err != nil {
					name := t.PkgPath() + "." + t.Name()
					if name == "" {
						name = "(anonymous type)"
					}
					c.err = errors.New("unsupported conversion of string to " + name)
					return
				}
			} else {
				vt = reflect.ValueOf(token)
			}
			n := v.MapIndex(vt)
			if (reflect.Value{}) == n {
				c.err = ErrNotFound{Ptr: c.raw}
				return
			}

			if tidx == lastidx {
				if c.set {
					v.SetMapIndex(vt, reflect.ValueOf(c.setvalue))
				} else {
					c.result = n.Interface()
				}
				return
			}

			node = n.Interface()
		case reflect.Slice:
			m := node.([]interface{})
			wantidx, err := strconv.Atoi(token)
			if err != nil {
				c.err = err
				return
			}

			if wantidx < 0 || len(m) <= wantidx {
				c.err = ErrSliceIndexOutOfBounds
				return
			}

			if tidx == lastidx {
				if c.set {
					m[wantidx] = c.setvalue
				} else {
					c.result = m[wantidx]
				}
				return
			}
			node = m[wantidx]
		default:
			c.err = ErrNotFound{Ptr: c.raw}
			return
		}
	}

	// If you fell through here, there was a big problem
	c.err = ErrNotFound{Ptr: c.raw}
}
<commit_msg>Use the latest structinfo<commit_after>package jspointer

import (
	"encoding/json"
	"errors"
	"reflect"
	"strconv"
	"strings"
	"sync"

	"github.com/lestrrat/go-structinfo"
)

var ctxPool = sync.Pool{
	New: moreCtx,
}

func moreCtx() interface{} {
	return &matchCtx{}
}

func getCtx() *matchCtx {
	return ctxPool.Get().(*matchCtx)
}

func releaseCtx(ctx *matchCtx) {
	ctx.err = nil
	ctx.set = false
	ctx.tokens = nil
	ctx.result = nil
	ctxPool.Put(ctx)
}

// New creates a new JSON pointer for given path spec. If the path fails
// to be parsed, an error is returned
func New(path string) (*JSPointer, error) {
	var p JSPointer
	dtokens, err := parse(path)
	if err != nil {
		return nil, err
	}
	p.raw = path
	p.tokens = dtokens
	return &p, nil
}

func parse(s string) ([]string, error) {
	if s == "" {
		return nil, nil
	}

	if s[0] != Separator {
		return nil, ErrInvalidPointer
	}

	prev := 0
	tokens := []string{}
	for i := 1; i < len(s); i++ {
		switch s[i] {
		case Separator:
			tokens = append(tokens, s[prev+1:i])
			prev = i
		}
	}

	if prev != len(s) {
		tokens = append(tokens, s[prev+1:])
	}

	dtokens := make([]string, 0, len(tokens))
	for _, t := range tokens {
		t = strings.Replace(strings.Replace(t, EncodedSlash, "/", -1), EncodedTilde, "~", -1)
		dtokens = append(dtokens, t)
	}

	return dtokens, nil
}

// String returns the stringified version of this JSON pointer
func (p JSPointer) String() string {
	return p.raw
}

// Get applies the JSON pointer to the given item, and returns
// the result.
func (p JSPointer) Get(item interface{}) (interface{}, error) {
	ctx := getCtx()
	defer releaseCtx(ctx)

	ctx.raw = p.raw
	ctx.tokens = p.tokens
	ctx.apply(item)
	return ctx.result, ctx.err
}

// Set applies the JSON pointer to the given item, and sets the
// value accordingly.
func (p JSPointer) Set(item interface{}, value interface{}) error {
	ctx := getCtx()
	defer releaseCtx(ctx)

	ctx.set = true
	ctx.raw = p.raw
	ctx.tokens = p.tokens
	ctx.setvalue = value
	ctx.apply(item)
	return ctx.err
}

type matchCtx struct {
	err      error
	raw      string
	result   interface{}
	set      bool
	setvalue interface{}
	tokens   []string
}

func (e ErrNotFound) Error() string {
	return "match to JSON pointer not found: " + e.Ptr
}

var strType = reflect.TypeOf("")

func (c *matchCtx) apply(item interface{}) {
	if len(c.tokens) == 0 {
		c.result = item
		return
	}

	lastidx := len(c.tokens) - 1
	node := item
	for tidx, token := range c.tokens {
		v := reflect.ValueOf(node)
		if v.Kind() == reflect.Ptr {
			v = v.Elem()
		}

		switch v.Kind() {
		case reflect.Struct:
			fn := structinfo.StructFieldFromJSONName(v, token)
			if fn == "" {
				c.err = ErrNotFound{Ptr: c.raw}
				return
			}
			f := v.FieldByName(fn)
			if tidx == lastidx {
				if c.set {
					if !f.CanSet() {
						c.err = ErrCanNotSet
						return
					}
					f.Set(reflect.ValueOf(c.setvalue))
					return
				}
				c.result = f.Interface()
				return
			}
			node = f.Interface()
		case reflect.Map:
			var vt reflect.Value
			// We shall try to inflate the token to its Go native
			// type if it's not a string. In other words, try not to
			// outdo yourselves.
			if t := v.Type().Key(); t != strType {
				vt = reflect.New(t).Elem()
				if err := json.Unmarshal([]byte(token), vt.Addr().Interface()); err != nil {
					name := t.PkgPath() + "." + t.Name()
					if name == "" {
						name = "(anonymous type)"
					}
					c.err = errors.New("unsupported conversion of string to " + name)
					return
				}
			} else {
				vt = reflect.ValueOf(token)
			}
			n := v.MapIndex(vt)
			if (reflect.Value{}) == n {
				c.err = ErrNotFound{Ptr: c.raw}
				return
			}

			if tidx == lastidx {
				if c.set {
					v.SetMapIndex(vt, reflect.ValueOf(c.setvalue))
				} else {
					c.result = n.Interface()
				}
				return
			}

			node = n.Interface()
		case reflect.Slice:
			m := node.([]interface{})
			wantidx, err := strconv.Atoi(token)
			if err != nil {
				c.err = err
				return
			}

			if wantidx < 0 || len(m) <= wantidx {
				c.err = ErrSliceIndexOutOfBounds
				return
			}

			if tidx == lastidx {
				if c.set {
					m[wantidx] = c.setvalue
				} else {
					c.result = m[wantidx]
				}
				return
			}
			node = m[wantidx]
		default:
			c.err = ErrNotFound{Ptr: c.raw}
			return
		}
	}

	// If you fell through here, there was a big problem
	c.err = ErrNotFound{Ptr: c.raw}
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// 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.

// sample-bar demonstrates a sample i3bar built using barista.
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os/exec"
	"os/user"
	"path/filepath"
	"time"

	"barista.run"
	"barista.run/bar"
	"barista.run/base/watchers/netlink"
	"barista.run/colors"
	"barista.run/group/collapsing"
	"barista.run/modules/battery"
	"barista.run/modules/clock"
	"barista.run/modules/cputemp"
	"barista.run/modules/media"
	"barista.run/modules/meminfo"
	"barista.run/modules/netspeed"
	"barista.run/modules/sysinfo"
	"barista.run/modules/volume"
	"barista.run/modules/weather"
	"barista.run/modules/weather/openweathermap"
	"barista.run/outputs"
	"barista.run/pango"
	"barista.run/pango/icons/fontawesome"
	"barista.run/pango/icons/ionicons"
	"barista.run/pango/icons/material"
	"barista.run/pango/icons/mdi"
	"barista.run/pango/icons/typicons"

	colorful "github.com/lucasb-eyer/go-colorful"
	"github.com/martinlindhe/unit"
)

var spacer = pango.Text(" ").XXSmall()

func truncate(in string, l int) string {
	if len([]rune(in)) <= l {
		return in
	}
	return string([]rune(in)[:l-1]) + "⋯"
}

func hms(d time.Duration) (h int, m int, s int) {
	h = int(d.Hours())
	m = int(d.Minutes()) % 60
	s = int(d.Seconds()) % 60
	return
}

func formatMediaTime(d time.Duration) string {
	h, m, s := hms(d)
	if h > 0 {
		return fmt.Sprintf("%d:%02d:%02d", h, m, s)
	}
	return fmt.Sprintf("%d:%02d", m, s)
}

func mediaFormatFunc(m media.Info) bar.Output {
	if m.PlaybackStatus == media.Stopped || m.PlaybackStatus == media.Disconnected {
		return nil
	}
	artist := truncate(m.Artist, 20)
	title := truncate(m.Title, 40-len(artist))
	if len(title) < 20 {
		artist = truncate(m.Artist, 40-len(title))
	}
	iconAndPosition := pango.Icon("fa-music").Color(colors.Hex("#f70"))
	if m.PlaybackStatus == media.Playing {
		iconAndPosition.Append(
			spacer, pango.Textf("%s/%s",
				formatMediaTime(m.Position()),
				formatMediaTime(m.Length)),
		)
	}
	return outputs.Pango(iconAndPosition, spacer, title, " - ", artist)
}

func startTaskManager(e bar.Event) {
	if e.Button == bar.ButtonLeft {
		exec.Command("xfce4-taskmanager").Run()
	}
}

func home(path string) string {
	usr, err := user.Current()
	if err != nil {
		panic(err)
	}
	return filepath.Join(usr.HomeDir, path)
}

type freegeoipResponse struct {
	Lat float64 `json:"latitude"`
	Lng float64 `json:"longitude"`
}

func whereami() (lat float64, lng float64, err error) {
	resp, err := http.Get("https://freegeoip.app/json/")
	if err != nil {
		return 0, 0, err
	}
	var res freegeoipResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return 0, 0, err
	}
	return res.Lat, res.Lng, nil
}

type autoWeatherProvider struct{}

func (a autoWeatherProvider) GetWeather() (weather.Weather, error) {
	lat, lng, err := whereami()
	if err != nil {
		return weather.Weather{}, err
	}
	return openweathermap.Coords(lat, lng).Build().GetWeather()
}

func main() {
	material.Load(home("Github/material-design-icons"))
	mdi.Load(home("Github/MaterialDesign-Webfont"))
	typicons.Load(home("Github/typicons.font"))
	ionicons.LoadMd(home("Github/ionicons"))
	fontawesome.Load(home("Github/Font-Awesome"))

	colors.LoadBarConfig()
	bg := colors.Scheme("background")
	fg := colors.Scheme("statusline")
	if fg != nil && bg != nil {
		iconColor := fg.Colorful().BlendHcl(bg.Colorful(), 0.5).Clamped()
		colors.Set("dim-icon", iconColor)
		_, fgC, fgL := fg.Colorful().Hcl()
		if fgC < 0.8 {
			fgC = 0.8
		}
		if fgL < 0.7 {
			fgL = 0.7
		}
		colors.Set("bad", colorful.Hcl(40, fgC, fgL).Clamped())
		colors.Set("degraded", colorful.Hcl(90, fgC, fgL).Clamped())
		colors.Set("good", colorful.Hcl(120, fgC, fgL).Clamped())
	}

	localtime := clock.Local().
		Output(time.Second, func(now time.Time) bar.Output {
			return outputs.Pango(
				pango.Icon("material-today").Color(colors.Scheme("dim-icon")),
				now.Format("Mon Jan 2 "),
				pango.Icon("material-access-time").Color(colors.Scheme("dim-icon")),
				now.Format("15:04:05"),
			).OnClick(func(e bar.Event) {
				if e.Button == bar.ButtonLeft {
					exec.Command("gsimplecal").Run()
				}
			})
		})

	// Weather information comes from OpenWeatherMap.
	// https://openweathermap.org/api.
	wthr := weather.New(autoWeatherProvider{}).Output(func(w weather.Weather) bar.Output {
		iconName := ""
		switch w.Condition {
		case weather.Thunderstorm,
			weather.TropicalStorm,
			weather.Hurricane:
			iconName = "stormy"
		case weather.Drizzle,
			weather.Hail:
			iconName = "shower"
		case weather.Rain:
			iconName = "downpour"
		case weather.Snow,
			weather.Sleet:
			iconName = "snow"
		case weather.Mist,
			weather.Smoke,
			weather.Whirls,
			weather.Haze,
			weather.Fog:
			iconName = "windy-cloudy"
		case weather.Clear:
			if !w.Sunset.IsZero() && time.Now().After(w.Sunset) {
				iconName = "night"
			} else {
				iconName = "sunny"
			}
		case weather.PartlyCloudy:
			iconName = "partly-sunny"
		case weather.Cloudy, weather.Overcast:
			iconName = "cloudy"
		case weather.Tornado,
			weather.Windy:
			iconName = "windy"
		}
		if iconName == "" {
			iconName = "warning-outline"
		} else {
			iconName = "weather-" + iconName
		}
		return outputs.Pango(
			pango.Icon("typecn-"+iconName), spacer,
			pango.Textf("%.1f℃", w.Temperature.Celsius()),
			pango.Textf(" (provided by %s)", w.Attribution).XSmall(),
		)
	})

	getBattIcon := func(i battery.Info) *pango.Node {
		if i.Status == battery.Disconnected || i.Status == battery.Unknown {
			return nil
		}
		iconName := "battery"
		if i.Status == battery.Charging {
			iconName += "-charging"
		}
		tenth := i.RemainingPct() / 10
		switch {
		case tenth == 0:
			iconName += "-outline"
		case tenth < 10:
			iconName += fmt.Sprintf("-%d0", tenth)
		}
		return pango.Icon("mdi-" + iconName)
	}
	var showBattPct, showBattTime func(battery.Info) bar.Output

	batt := battery.All()
	showBattPct = func(i battery.Info) bar.Output {
		n := getBattIcon(i)
		if n == nil {
			return nil
		}
		return outputs.Pango(n, pango.Textf("%d%%", i.RemainingPct())).
			OnClick(func(e bar.Event) {
				if e.Button == bar.ButtonLeft {
					batt.Output(showBattTime)
				}
			})
	}
	showBattTime = func(i battery.Info) bar.Output {
		n := getBattIcon(i)
		if n == nil {
			return nil
		}
		rem := i.RemainingTime()
		return outputs.Pango(n, pango.Textf("%d:%02d", int(rem.Hours()), int(rem.Minutes())%60)).
			OnClick(func(e bar.Event) {
				if e.Button == bar.ButtonLeft {
					batt.Output(showBattPct)
				}
			})
	}
	batt.Output(showBattPct)

	vol := volume.DefaultMixer().Output(func(v volume.Volume) bar.Output {
		if v.Mute {
			return outputs.
				Pango(pango.Icon("ion-volume-off"), "MUT").
				Color(colors.Scheme("degraded"))
		}
		iconName := "mute"
		pct := v.Pct()
		if pct > 66 {
			iconName = "high"
		} else if pct > 33 {
			iconName = "low"
		}
		return outputs.Pango(
			pango.Icon("ion-volume-"+iconName),
			spacer,
			pango.Textf("%2d%%", pct),
		)
	})

	loadAvg := sysinfo.New().Output(func(s sysinfo.Info) bar.Output {
		out := outputs.Textf("%0.2f %0.2f", s.Loads[0], s.Loads[2])
		// Load averages are unusually high for a few minutes after boot.
		if s.Uptime < 10*time.Minute {
			// so don't add colours until 10 minutes after system start.
			return out
		}
		switch {
		case s.Loads[0] > 128, s.Loads[2] > 64:
			out.Urgent(true)
		case s.Loads[0] > 64, s.Loads[2] > 32:
			out.Color(colors.Scheme("bad"))
		case s.Loads[0] > 32, s.Loads[2] > 16:
			out.Color(colors.Scheme("degraded"))
		}
		out.OnClick(startTaskManager)
		return out
	})

	freeMem := meminfo.New().Output(func(m meminfo.Info) bar.Output {
		out := outputs.Pango(pango.Icon("material-memory"), outputs.IBytesize(m.Available()))
		freeGigs := m.Available().Gigabytes()
		switch {
		case freeGigs < 0.5:
			out.Urgent(true)
		case freeGigs < 1:
			out.Color(colors.Scheme("bad"))
		case freeGigs < 2:
			out.Color(colors.Scheme("degraded"))
		case freeGigs > 12:
			out.Color(colors.Scheme("good"))
		}
		out.OnClick(startTaskManager)
		return out
	})

	temp := cputemp.New().
		RefreshInterval(2 * time.Second).
		Output(func(temp unit.Temperature) bar.Output {
			out := outputs.Pango(
				pango.Icon("mdi-fan"), spacer,
				pango.Textf("%2d℃", int(temp.Celsius())),
			)
			switch {
			case temp.Celsius() > 90:
				out.Urgent(true)
			case temp.Celsius() > 70:
				out.Color(colors.Scheme("bad"))
			case temp.Celsius() > 60:
				out.Color(colors.Scheme("degraded"))
			}
			return out
		})

	sub := netlink.Any()
	iface := (<-sub).Name
	sub.Unsubscribe()
	net := netspeed.New(iface).
		RefreshInterval(2 * time.Second).
		Output(func(s netspeed.Speeds) bar.Output {
			return outputs.Pango(
				pango.Icon("fa-upload"), spacer, pango.Textf("%7s", outputs.Byterate(s.Tx)),
				pango.Text(" ").Small(),
				pango.Icon("fa-download"), spacer, pango.Textf("%7s", outputs.Byterate(s.Rx)),
			)
		})

	rhythmbox := media.New("rhythmbox").Output(mediaFormatFunc)

	grp, _ := collapsing.Group(net, temp, freeMem, loadAvg)

	panic(barista.Run(
		rhythmbox,
		grp,
		vol,
		batt,
		wthr,
		localtime,
	))
}
<commit_msg>Colourise battery output at low percentages<commit_after>// Copyright 2017 Google Inc.
//
// 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.

// sample-bar demonstrates a sample i3bar built using barista.
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os/exec"
	"os/user"
	"path/filepath"
	"time"

	"barista.run"
	"barista.run/bar"
	"barista.run/base/watchers/netlink"
	"barista.run/colors"
	"barista.run/group/collapsing"
	"barista.run/modules/battery"
	"barista.run/modules/clock"
	"barista.run/modules/cputemp"
	"barista.run/modules/media"
	"barista.run/modules/meminfo"
	"barista.run/modules/netspeed"
	"barista.run/modules/sysinfo"
	"barista.run/modules/volume"
	"barista.run/modules/weather"
	"barista.run/modules/weather/openweathermap"
	"barista.run/outputs"
	"barista.run/pango"
	"barista.run/pango/icons/fontawesome"
	"barista.run/pango/icons/ionicons"
	"barista.run/pango/icons/material"
	"barista.run/pango/icons/mdi"
	"barista.run/pango/icons/typicons"

	colorful "github.com/lucasb-eyer/go-colorful"
	"github.com/martinlindhe/unit"
)

var spacer = pango.Text(" ").XXSmall()

func truncate(in string, l int) string {
	if len([]rune(in)) <= l {
		return in
	}
	return string([]rune(in)[:l-1]) + "⋯"
}

func hms(d time.Duration) (h int, m int, s int) {
	h = int(d.Hours())
	m = int(d.Minutes()) % 60
	s = int(d.Seconds()) % 60
	return
}

func formatMediaTime(d time.Duration) string {
	h, m, s := hms(d)
	if h > 0 {
		return fmt.Sprintf("%d:%02d:%02d", h, m, s)
	}
	return fmt.Sprintf("%d:%02d", m, s)
}

func mediaFormatFunc(m media.Info) bar.Output {
	if m.PlaybackStatus == media.Stopped || m.PlaybackStatus == media.Disconnected {
		return nil
	}
	artist := truncate(m.Artist, 20)
	title := truncate(m.Title, 40-len(artist))
	if len(title) < 20 {
		artist = truncate(m.Artist, 40-len(title))
	}
	iconAndPosition := pango.Icon("fa-music").Color(colors.Hex("#f70"))
	if m.PlaybackStatus == media.Playing {
		iconAndPosition.Append(
			spacer, pango.Textf("%s/%s",
				formatMediaTime(m.Position()),
				formatMediaTime(m.Length)),
		)
	}
	return outputs.Pango(iconAndPosition, spacer, title, " - ", artist)
}

func startTaskManager(e bar.Event) {
	if e.Button == bar.ButtonLeft {
		exec.Command("xfce4-taskmanager").Run()
	}
}

func home(path string) string {
	usr, err := user.Current()
	if err != nil {
		panic(err)
	}
	return filepath.Join(usr.HomeDir, path)
}

type freegeoipResponse struct {
	Lat float64 `json:"latitude"`
	Lng float64 `json:"longitude"`
}

func whereami() (lat float64, lng float64, err error) {
	resp, err := http.Get("https://freegeoip.app/json/")
	if err != nil {
		return 0, 0, err
	}
	var res freegeoipResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return 0, 0, err
	}
	return res.Lat, res.Lng, nil
}

type autoWeatherProvider struct{}

func (a autoWeatherProvider) GetWeather() (weather.Weather, error) {
	lat, lng, err := whereami()
	if err != nil {
		return weather.Weather{}, err
	}
	return openweathermap.Coords(lat, lng).Build().GetWeather()
}

func main() {
	material.Load(home("Github/material-design-icons"))
	mdi.Load(home("Github/MaterialDesign-Webfont"))
	typicons.Load(home("Github/typicons.font"))
	ionicons.LoadMd(home("Github/ionicons"))
	fontawesome.Load(home("Github/Font-Awesome"))

	colors.LoadBarConfig()
	bg := colors.Scheme("background")
	fg := colors.Scheme("statusline")
	if fg != nil && bg != nil {
		iconColor := fg.Colorful().BlendHcl(bg.Colorful(), 0.5).Clamped()
		colors.Set("dim-icon", iconColor)
		_, fgC, fgL := fg.Colorful().Hcl()
		if fgC < 0.8 {
			fgC = 0.8
		}
		if fgL < 0.7 {
			fgL = 0.7
		}
		colors.Set("bad", colorful.Hcl(40, fgC, fgL).Clamped())
		colors.Set("degraded", colorful.Hcl(90, fgC, fgL).Clamped())
		colors.Set("good", colorful.Hcl(120, fgC, fgL).Clamped())
	}

	localtime := clock.Local().
		Output(time.Second, func(now time.Time) bar.Output {
			return outputs.Pango(
				pango.Icon("material-today").Color(colors.Scheme("dim-icon")),
				now.Format("Mon Jan 2 "),
				pango.Icon("material-access-time").Color(colors.Scheme("dim-icon")),
				now.Format("15:04:05"),
			).OnClick(func(e bar.Event) {
				if e.Button == bar.ButtonLeft {
					exec.Command("gsimplecal").Run()
				}
			})
		})

	// Weather information comes from OpenWeatherMap.
	// https://openweathermap.org/api.
	wthr := weather.New(autoWeatherProvider{}).Output(func(w weather.Weather) bar.Output {
		iconName := ""
		switch w.Condition {
		case weather.Thunderstorm,
			weather.TropicalStorm,
			weather.Hurricane:
			iconName = "stormy"
		case weather.Drizzle,
			weather.Hail:
			iconName = "shower"
		case weather.Rain:
			iconName = "downpour"
		case weather.Snow,
			weather.Sleet:
			iconName = "snow"
		case weather.Mist,
			weather.Smoke,
			weather.Whirls,
			weather.Haze,
			weather.Fog:
			iconName = "windy-cloudy"
		case weather.Clear:
			if !w.Sunset.IsZero() && time.Now().After(w.Sunset) {
				iconName = "night"
			} else {
				iconName = "sunny"
			}
		case weather.PartlyCloudy:
			iconName = "partly-sunny"
		case weather.Cloudy, weather.Overcast:
			iconName = "cloudy"
		case weather.Tornado,
			weather.Windy:
			iconName = "windy"
		}
		if iconName == "" {
			iconName = "warning-outline"
		} else {
			iconName = "weather-" + iconName
		}
		return outputs.Pango(
			pango.Icon("typecn-"+iconName), spacer,
			pango.Textf("%.1f℃", w.Temperature.Celsius()),
			pango.Textf(" (provided by %s)", w.Attribution).XSmall(),
		)
	})

	buildBattOutput := func(i battery.Info, disp *pango.Node) *bar.Segment {
		if i.Status == battery.Disconnected || i.Status == battery.Unknown {
			return nil
		}
		iconName := "battery"
		if i.Status == battery.Charging {
			iconName += "-charging"
		}
		tenth := i.RemainingPct() / 10
		switch {
		case tenth == 0:
			iconName += "-outline"
		case tenth < 10:
			iconName += fmt.Sprintf("-%d0", tenth)
		}
		out := outputs.Pango(pango.Icon("mdi-"+iconName), disp)
		switch {
		case i.RemainingPct() <= 5:
			out.Urgent(true)
		case i.RemainingPct() <= 15:
			out.Color(colors.Scheme("bad"))
		case i.RemainingPct() <= 25:
			out.Color(colors.Scheme("degraded"))
		}
		return out
	}
	var showBattPct, showBattTime func(battery.Info) bar.Output

	batt := battery.All()
	showBattPct = func(i battery.Info) bar.Output {
		out := buildBattOutput(i, pango.Textf("%d%%", i.RemainingPct()))
		if out == nil {
			return nil
		}
		return out.OnClick(func(e bar.Event) {
			if e.Button == bar.ButtonLeft {
				batt.Output(showBattTime)
			}
		})
	}
	showBattTime = func(i battery.Info) bar.Output {
		rem := i.RemainingTime()
		out := buildBattOutput(i, pango.Textf(
			"%d:%02d", int(rem.Hours()), int(rem.Minutes())%60))
		if out == nil {
			return nil
		}
		return out.OnClick(func(e bar.Event) {
			if e.Button == bar.ButtonLeft {
				batt.Output(showBattPct)
			}
		})
	}
	batt.Output(showBattPct)

	vol := volume.DefaultMixer().Output(func(v volume.Volume) bar.Output {
		if v.Mute {
			return outputs.
				Pango(pango.Icon("ion-volume-off"), "MUT").
				Color(colors.Scheme("degraded"))
		}
		iconName := "mute"
		pct := v.Pct()
		if pct > 66 {
			iconName = "high"
		} else if pct > 33 {
			iconName = "low"
		}
		return outputs.Pango(
			pango.Icon("ion-volume-"+iconName),
			spacer,
			pango.Textf("%2d%%", pct),
		)
	})

	loadAvg := sysinfo.New().Output(func(s sysinfo.Info) bar.Output {
		out := outputs.Textf("%0.2f %0.2f", s.Loads[0], s.Loads[2])
		// Load averages are unusually high for a few minutes after boot.
		if s.Uptime < 10*time.Minute {
			// so don't add colours until 10 minutes after system start.
			return out
		}
		switch {
		case s.Loads[0] > 128, s.Loads[2] > 64:
			out.Urgent(true)
		case s.Loads[0] > 64, s.Loads[2] > 32:
			out.Color(colors.Scheme("bad"))
		case s.Loads[0] > 32, s.Loads[2] > 16:
			out.Color(colors.Scheme("degraded"))
		}
		out.OnClick(startTaskManager)
		return out
	})

	freeMem := meminfo.New().Output(func(m meminfo.Info) bar.Output {
		out := outputs.Pango(pango.Icon("material-memory"), outputs.IBytesize(m.Available()))
		freeGigs := m.Available().Gigabytes()
		switch {
		case freeGigs < 0.5:
			out.Urgent(true)
		case freeGigs < 1:
			out.Color(colors.Scheme("bad"))
		case freeGigs < 2:
			out.Color(colors.Scheme("degraded"))
		case freeGigs > 12:
			out.Color(colors.Scheme("good"))
		}
		out.OnClick(startTaskManager)
		return out
	})

	temp := cputemp.New().
		RefreshInterval(2 * time.Second).
		Output(func(temp unit.Temperature) bar.Output {
			out := outputs.Pango(
				pango.Icon("mdi-fan"), spacer,
				pango.Textf("%2d℃", int(temp.Celsius())),
			)
			switch {
			case temp.Celsius() > 90:
				out.Urgent(true)
			case temp.Celsius() > 70:
				out.Color(colors.Scheme("bad"))
			case temp.Celsius() > 60:
				out.Color(colors.Scheme("degraded"))
			}
			return out
		})

	sub := netlink.Any()
	iface := (<-sub).Name
	sub.Unsubscribe()
	net := netspeed.New(iface).
		RefreshInterval(2 * time.Second).
		Output(func(s netspeed.Speeds) bar.Output {
			return outputs.Pango(
				pango.Icon("fa-upload"), spacer, pango.Textf("%7s", outputs.Byterate(s.Tx)),
				pango.Text(" ").Small(),
				pango.Icon("fa-download"), spacer, pango.Textf("%7s", outputs.Byterate(s.Rx)),
			)
		})

	rhythmbox := media.New("rhythmbox").Output(mediaFormatFunc)

	grp, _ := collapsing.Group(net, temp, freeMem, loadAvg)

	panic(barista.Run(
		rhythmbox,
		grp,
		vol,
		batt,
		wthr,
		localtime,
	))
}
<|endoftext|>


<commit_before>// Copyright 2014 Tjerk Santegoeds
//
// 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 oanda

import (
	"encoding/json"
	"fmt"
	"strings"
	"sync"
	"time"
)

// PriceTick holds the Bid price, Ask price and status for an instrument at a given point
// in time
type PriceTick struct {
	Time   time.Time `json:"time"`
	Bid    float64   `json:"bid"`
	Ask    float64   `json:"ask"`
	Status string    `json:"status"`
}

// Spread returns the difference between Ask and Bid prices.
func (p *PriceTick) Spread() float64 {
	return p.Ask - p.Bid
}

// PollPrices returns the latest PriceTick for instruments.
func (c *Client) PollPrices(instrument string, instruments ...string) (
	map[string]PriceTick, error) {

	return c.PollPricesSince(time.Time{}, instrument, instruments...)
}

// PollPricesSince returns the PriceTicks for instruments.  If since is not the zero time
// instruments whose prices were not updated since the requested time.Time are excluded from the
// result.
func (c *Client) PollPricesSince(since time.Time, instrument string, instruments ...string) (
	map[string]PriceTick, error) {

	ctx, err := c.NewPollPricesContext(since, instrument, instruments...)
	if err != nil {
		return nil, err
	}
	return ctx.Poll()
}

type PollPricesContext struct {
	ctx *Context
}

func (ppc *PollPricesContext) Poll() (map[string]PriceTick, error) {
	v := struct {
		ApiError
		Prices []struct {
			Instrument string `json:"instrument"`
			PriceTick
		} `json:"prices"`
	}{}
	if _, err := ppc.ctx.Decode(&v); err != nil {
		return nil, err
	}

	prices := make(map[string]PriceTick)
	for _, p := range v.Prices {
		prices[p.Instrument] = p.PriceTick
	}
	return prices, nil
}

// NewPollPricesContext creates a context to repeatedly poll for PriceTicks using the same
// args.
func (c *Client) NewPollPricesContext(since time.Time, instrument string, instruments ...string) (
	*PollPricesContext, error) {

	instruments = append(instruments, instrument)

	u := c.getUrl("/v1/prices", "api")
	q := u.Query()
	q.Set("instruments", strings.ToUpper(strings.Join(instruments, ",")))
	if !since.IsZero() {
		q.Set("since", since.UTC().Format(time.RFC3339))
	}
	u.RawQuery = q.Encode()

	ctx, err := c.newContext("GET", u, nil)
	if err != nil {
		return nil, err
	}
	return &PollPricesContext{ctx}, nil
}

type instrumentTick struct {
	Instrument string `json:"instrument"`
	PriceTick
}

const (
	DefaultChannelSize = 5
)

var tickPool = sync.Pool{
	New: func() interface{} { return &instrumentTick{} },
}

type TickHandleFunc func(instrument string, pp PriceTick)

type pricesServer struct {
	ChannelSize int

	*streamServer
	instruments []string
	tickChs     map[string]chan *instrumentTick
}

// NewPricesServer creates a pricesServer to receive and handle PriceTicks from the Oanda server.
func (c *Client) NewPricesServer(instrument string, instruments ...string) (*pricesServer, error) {
	instruments = append(instruments, instrument)
	for i := range instruments {
		instruments[i] = strings.ToUpper(instruments[i])
	}

	u := c.getUrl("/v1/prices", "stream")
	q := u.Query()
	q.Set("instruments", strings.Join(instruments, ","))
	u.RawQuery = q.Encode()

	ss, err := c.newStreamServer(u)
	if err != nil {
		return nil, err
	}

	ps := pricesServer{
		ChannelSize:  DefaultChannelSize,
		streamServer: ss,
		instruments:  instruments,
		tickChs:      make(map[string]chan *instrumentTick, len(instruments)),
	}

	return &ps, nil
}

// Run connects to the oanda server and dispatches PriceTicks to handleFn. A separate handleFun
// go-routine is started for each of the instruments.
func (ps *pricesServer) Run(handleFn TickHandleFunc) error {
	err := ps.init(handleFn)
	if err != nil {
		return err
	}
	defer ps.cleanup()

	err = ps.streamServer.Run(func(msgType string, msgData json.RawMessage) error {
		if msgType != "tick" {
			return fmt.Errorf("%s is an unexpected message type", msgType)
		}
		tick := tickPool.Get().(*instrumentTick)
		if err = json.Unmarshal(msgData, tick); err != nil {
			return err
		}

		tickCh := ps.tickChs[tick.Instrument]
		select {
		case tickCh <- tick:
			// Nop
		default:
			// Channel is full. Remove a tick from the channel to make space.
			select {
			case <-tickCh:
			default:
			}
			tickCh <- tick
		}

		return nil
	})

	return err
}

func (ps *pricesServer) init(handleFn TickHandleFunc) error {
	for _, in := range ps.instruments {
		ch := make(chan *instrumentTick)
		ps.tickChs[in] = ch

		ps.wg.Add(1)
		go func(tickCh <-chan *instrumentTick) {
			for tick := range tickCh {
				handleFn(tick.Instrument, tick.PriceTick)
				tickPool.Put(tick)
			}
			ps.wg.Done()
		}(ch)
	}

	return nil
}

func (ps *pricesServer) cleanup() {
	for _, tickCh := range ps.tickChs {
		close(tickCh)
	}
	ps.wg.Wait()
}
<commit_msg>Fix bug where multiple go-routines for the same instrument is started if there are duplicate entries in the arguments to NewPricesServer<commit_after>// Copyright 2014 Tjerk Santegoeds
//
// 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 oanda

import (
	"encoding/json"
	"fmt"
	"strings"
	"sync"
	"time"
)

// PriceTick holds the Bid price, Ask price and status for an instrument at a given point
// in time
type PriceTick struct {
	Time   time.Time `json:"time"`
	Bid    float64   `json:"bid"`
	Ask    float64   `json:"ask"`
	Status string    `json:"status"`
}

// Spread returns the difference between Ask and Bid prices.
func (p *PriceTick) Spread() float64 {
	return p.Ask - p.Bid
}

// PollPrices returns the latest PriceTick for instruments.
func (c *Client) PollPrices(instrument string, instruments ...string) (
	map[string]PriceTick, error) {

	return c.PollPricesSince(time.Time{}, instrument, instruments...)
}

// PollPricesSince returns the PriceTicks for instruments.  If since is not the zero time
// instruments whose prices were not updated since the requested time.Time are excluded from the
// result.
func (c *Client) PollPricesSince(since time.Time, instrument string, instruments ...string) (
	map[string]PriceTick, error) {

	ctx, err := c.NewPollPricesContext(since, instrument, instruments...)
	if err != nil {
		return nil, err
	}
	return ctx.Poll()
}

type PollPricesContext struct {
	ctx *Context
}

func (ppc *PollPricesContext) Poll() (map[string]PriceTick, error) {
	v := struct {
		ApiError
		Prices []struct {
			Instrument string `json:"instrument"`
			PriceTick
		} `json:"prices"`
	}{}
	if _, err := ppc.ctx.Decode(&v); err != nil {
		return nil, err
	}

	prices := make(map[string]PriceTick)
	for _, p := range v.Prices {
		prices[p.Instrument] = p.PriceTick
	}
	return prices, nil
}

// NewPollPricesContext creates a context to repeatedly poll for PriceTicks using the same
// args.
func (c *Client) NewPollPricesContext(since time.Time, instrument string, instruments ...string) (
	*PollPricesContext, error) {

	instruments = append(instruments, instrument)

	u := c.getUrl("/v1/prices", "api")
	q := u.Query()
	q.Set("instruments", strings.ToUpper(strings.Join(instruments, ",")))
	if !since.IsZero() {
		q.Set("since", since.UTC().Format(time.RFC3339))
	}
	u.RawQuery = q.Encode()

	ctx, err := c.newContext("GET", u, nil)
	if err != nil {
		return nil, err
	}
	return &PollPricesContext{ctx}, nil
}

type instrumentTick struct {
	Instrument string `json:"instrument"`
	PriceTick
}

const (
	DefaultChannelSize = 5
)

var tickPool = sync.Pool{
	New: func() interface{} { return &instrumentTick{} },
}

type TickHandleFunc func(instrument string, pp PriceTick)

type pricesServer struct {
	ChannelSize int

	*streamServer
	instruments []string
	tickChs     map[string]chan *instrumentTick
}

// NewPricesServer creates a pricesServer to receive and handle PriceTicks from the Oanda server.
func (c *Client) NewPricesServer(instrument string, instruments ...string) (*pricesServer, error) {
	instruments = append(instruments, instrument)
	for i := range instruments {
		instruments[i] = strings.ToUpper(instruments[i])
	}

	u := c.getUrl("/v1/prices", "stream")
	q := u.Query()
	q.Set("instruments", strings.Join(instruments, ","))
	u.RawQuery = q.Encode()

	ss, err := c.newStreamServer(u)
	if err != nil {
		return nil, err
	}

	ps := pricesServer{
		ChannelSize:  DefaultChannelSize,
		streamServer: ss,
		instruments:  instruments,
		tickChs:      make(map[string]chan *instrumentTick, len(instruments)),
	}

	return &ps, nil
}

// Run connects to the oanda server and dispatches PriceTicks to handleFn. A separate handleFun
// go-routine is started for each of the instruments.
func (ps *pricesServer) Run(handleFn TickHandleFunc) error {
	err := ps.init(handleFn)
	if err != nil {
		return err
	}
	defer ps.cleanup()

	err = ps.streamServer.Run(func(msgType string, msgData json.RawMessage) error {
		if msgType != "tick" {
			return fmt.Errorf("%s is an unexpected message type", msgType)
		}
		tick := tickPool.Get().(*instrumentTick)
		if err = json.Unmarshal(msgData, tick); err != nil {
			return err
		}

		tickCh := ps.tickChs[tick.Instrument]
		select {
		case tickCh <- tick:
			// Nop
		default:
			// Channel is full. Remove a tick from the channel to make space.
			select {
			case <-tickCh:
			default:
			}
			tickCh <- tick
		}

		return nil
	})

	return err
}

func (ps *pricesServer) init(handleFn TickHandleFunc) error {
	for _, in := range ps.instruments {
		ps.tickChs[in] = make(chan *instrumentTick)
	}
	for _, ch := range ps.tickChs {
		ps.wg.Add(1)
		go func(tickCh <-chan *instrumentTick) {
			for tick := range tickCh {
				handleFn(tick.Instrument, tick.PriceTick)
				tickPool.Put(tick)
			}
			ps.wg.Done()
		}(ch)
	}

	return nil
}

func (ps *pricesServer) cleanup() {
	for _, tickCh := range ps.tickChs {
		close(tickCh)
	}
	ps.wg.Wait()
}
<|endoftext|>


<commit_before>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 save_test

import (
	"io/ioutil"
	"os"
	"path"
	"sort"
	"testing"

	"golang.org/x/net/context"

	"github.com/jacobsa/comeback/graph"
	"github.com/jacobsa/comeback/save"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFileSystemVisitor(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type PathAndFileInfoSlice []save.PathAndFileInfo

func (p PathAndFileInfoSlice) Len() int {
	return len(p)
}

func (p PathAndFileInfoSlice) Less(i, j int) bool {
	return p[i].Path < p[j].Path
}

func (p PathAndFileInfoSlice) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FileSystemVisitorTest struct {
	ctx context.Context

	// A temporary directory that is cleaned up at the end of the test. This is
	// the base path with which the visitor is configured.
	dir string

	// The channel into which the visitor writes. Configured with a large buffer.
	output chan save.PathAndFileInfo

	visitor graph.Visitor
}

var _ SetUpInterface = &FileSystemVisitorTest{}
var _ TearDownInterface = &FileSystemVisitorTest{}

func init() { RegisterTestSuite(&FileSystemVisitorTest{}) }

func (t *FileSystemVisitorTest) SetUp(ti *TestInfo) {
	t.ctx = ti.Ctx
	t.output = make(chan save.PathAndFileInfo, 10e3)

	// Create the base directory.
	var err error
	t.dir, err = ioutil.TempDir("", "file_system_visistor_test")
	AssertEq(nil, err)

	// And the visitor.
	t.visitor = save.NewFileSystemVisitor(t.dir, t.output)
}

func (t *FileSystemVisitorTest) TearDown() {
	var err error

	// Clean up the junk we left in the file system.
	err = os.RemoveAll(t.dir)
	AssertEq(nil, err)
}

// Consume the output, returning a slice sorted by path.
func (t *FileSystemVisitorTest) sortOutput() (output PathAndFileInfoSlice) {
	close(t.output)
	for o := range t.output {
		output = append(output, o)
	}

	sort.Sort(output)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FileSystemVisitorTest) NonExistentPath() {
	const node = "foo/bar"

	_, err := t.visitor.Visit(t.ctx, node)
	ExpectThat(err, Error(HasSubstr(node)))
	ExpectThat(err, Error(HasSubstr("no such file")))
}

func (t *FileSystemVisitorTest) VisitRootNode() {
	var err error

	// Create two children.
	err = ioutil.WriteFile(path.Join(t.dir, "foo"), []byte{}, 0500)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(t.dir, "bar"), []byte{}, 0500)
	AssertEq(nil, err)

	// Visit the root.
	_, err = t.visitor.Visit(t.ctx, "")
	AssertEq(nil, err)

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))
	ExpectEq("bar", output[0].Path)
	ExpectEq("foo", output[1].Path)
}

func (t *FileSystemVisitorTest) VisitNonRootNode() {
	var err error

	// Make a few levels of sub-directories.
	d := path.Join(t.dir, "sub/dirs")

	err = os.MkdirAll(d, 0700)
	AssertEq(nil, err)

	// Create two children.
	err = ioutil.WriteFile(path.Join(d, "foo"), []byte{}, 0500)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(d, "bar"), []byte{}, 0500)
	AssertEq(nil, err)

	// Visit the root.
	_, err = t.visitor.Visit(t.ctx, "sub/dirs")
	AssertEq(nil, err)

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))
	ExpectEq("sub/dirs/bar", output[0].Path)
	ExpectEq("sub/dirs/foo", output[1].Path)
}

func (t *FileSystemVisitorTest) Files() {
	var err error
	var pfi save.PathAndFileInfo

	// Make a sub-directory.
	d := path.Join(t.dir, "dir")

	err = os.MkdirAll(d, 0700)
	AssertEq(nil, err)

	// Create two children.
	err = ioutil.WriteFile(path.Join(d, "foo"), []byte("taco"), 0400)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(d, "bar"), []byte("burrito"), 0400)
	AssertEq(nil, err)

	// Visit.
	adjacent, err := t.visitor.Visit(t.ctx, "dir")

	AssertEq(nil, err)
	ExpectThat(adjacent, ElementsAre())

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))

	pfi = output[0]
	ExpectEq("dir/bar", pfi.Path)
	ExpectEq("bar", pfi.Info.Name())
	ExpectEq(len("burrito"), pfi.Info.Size())

	pfi = output[1]
	ExpectEq("dir/foo", pfi.Path)
	ExpectEq("foo", pfi.Info.Name())
	ExpectEq(len("taco"), pfi.Info.Size())
}

func (t *FileSystemVisitorTest) Directories() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Symlinks() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Devices() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) CharDevices() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) NamedPipes() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Sockets() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Exclusions() {
	AssertFalse(true, "TODO")
}
<commit_msg>FileSystemVisitorTest.Directories<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 save_test

import (
	"io/ioutil"
	"os"
	"path"
	"sort"
	"testing"

	"golang.org/x/net/context"

	"github.com/jacobsa/comeback/graph"
	"github.com/jacobsa/comeback/save"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
)

func TestFileSystemVisitor(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type PathAndFileInfoSlice []save.PathAndFileInfo

func (p PathAndFileInfoSlice) Len() int {
	return len(p)
}

func (p PathAndFileInfoSlice) Less(i, j int) bool {
	return p[i].Path < p[j].Path
}

func (p PathAndFileInfoSlice) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type FileSystemVisitorTest struct {
	ctx context.Context

	// A temporary directory that is cleaned up at the end of the test. This is
	// the base path with which the visitor is configured.
	dir string

	// The channel into which the visitor writes. Configured with a large buffer.
	output chan save.PathAndFileInfo

	visitor graph.Visitor
}

var _ SetUpInterface = &FileSystemVisitorTest{}
var _ TearDownInterface = &FileSystemVisitorTest{}

func init() { RegisterTestSuite(&FileSystemVisitorTest{}) }

func (t *FileSystemVisitorTest) SetUp(ti *TestInfo) {
	t.ctx = ti.Ctx
	t.output = make(chan save.PathAndFileInfo, 10e3)

	// Create the base directory.
	var err error
	t.dir, err = ioutil.TempDir("", "file_system_visistor_test")
	AssertEq(nil, err)

	// And the visitor.
	t.visitor = save.NewFileSystemVisitor(t.dir, t.output)
}

func (t *FileSystemVisitorTest) TearDown() {
	var err error

	// Clean up the junk we left in the file system.
	err = os.RemoveAll(t.dir)
	AssertEq(nil, err)
}

// Consume the output, returning a slice sorted by path.
func (t *FileSystemVisitorTest) sortOutput() (output PathAndFileInfoSlice) {
	close(t.output)
	for o := range t.output {
		output = append(output, o)
	}

	sort.Sort(output)
	return
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *FileSystemVisitorTest) NonExistentPath() {
	const node = "foo/bar"

	_, err := t.visitor.Visit(t.ctx, node)
	ExpectThat(err, Error(HasSubstr(node)))
	ExpectThat(err, Error(HasSubstr("no such file")))
}

func (t *FileSystemVisitorTest) VisitRootNode() {
	var err error

	// Create two children.
	err = ioutil.WriteFile(path.Join(t.dir, "foo"), []byte{}, 0500)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(t.dir, "bar"), []byte{}, 0500)
	AssertEq(nil, err)

	// Visit the root.
	_, err = t.visitor.Visit(t.ctx, "")
	AssertEq(nil, err)

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))
	ExpectEq("bar", output[0].Path)
	ExpectEq("foo", output[1].Path)
}

func (t *FileSystemVisitorTest) VisitNonRootNode() {
	var err error

	// Make a few levels of sub-directories.
	d := path.Join(t.dir, "sub/dirs")

	err = os.MkdirAll(d, 0700)
	AssertEq(nil, err)

	// Create two children.
	err = ioutil.WriteFile(path.Join(d, "foo"), []byte{}, 0500)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(d, "bar"), []byte{}, 0500)
	AssertEq(nil, err)

	// Visit the root.
	_, err = t.visitor.Visit(t.ctx, "sub/dirs")
	AssertEq(nil, err)

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))
	ExpectEq("sub/dirs/bar", output[0].Path)
	ExpectEq("sub/dirs/foo", output[1].Path)
}

func (t *FileSystemVisitorTest) Files() {
	var err error
	var pfi save.PathAndFileInfo

	// Make a sub-directory.
	d := path.Join(t.dir, "dir")

	err = os.MkdirAll(d, 0700)
	AssertEq(nil, err)

	// Create two children.
	err = ioutil.WriteFile(path.Join(d, "foo"), []byte("taco"), 0400)
	AssertEq(nil, err)

	err = ioutil.WriteFile(path.Join(d, "bar"), []byte("burrito"), 0400)
	AssertEq(nil, err)

	// Visit.
	adjacent, err := t.visitor.Visit(t.ctx, "dir")

	AssertEq(nil, err)
	ExpectThat(adjacent, ElementsAre())

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))

	pfi = output[0]
	ExpectEq("dir/bar", pfi.Path)
	ExpectEq("bar", pfi.Info.Name())
	ExpectEq(len("burrito"), pfi.Info.Size())

	pfi = output[1]
	ExpectEq("dir/foo", pfi.Path)
	ExpectEq("foo", pfi.Info.Name())
	ExpectEq(len("taco"), pfi.Info.Size())
}

func (t *FileSystemVisitorTest) Directories() {
	var err error
	var pfi save.PathAndFileInfo

	// Make a sub-directory.
	d := path.Join(t.dir, "dir")

	err = os.MkdirAll(d, 0700)
	AssertEq(nil, err)

	// Create children.
	err = os.Mkdir(path.Join(d, "foo"), 0400)
	AssertEq(nil, err)

	err = os.Mkdir(path.Join(d, "bar"), 0400)
	AssertEq(nil, err)

	// Visit.
	adjacent, err := t.visitor.Visit(t.ctx, "dir")
	sort.Strings(adjacent)

	AssertEq(nil, err)
	ExpectThat(adjacent, ElementsAre("dir/bar", "dir/foo"))

	// Check the output.
	output := t.sortOutput()
	AssertEq(2, len(output))

	pfi = output[0]
	ExpectEq("dir/bar", pfi.Path)
	ExpectEq("bar", pfi.Info.Name())
	ExpectTrue(pfi.Info.IsDir())

	pfi = output[1]
	ExpectEq("dir/foo", pfi.Path)
	ExpectEq("foo", pfi.Info.Name())
	ExpectTrue(pfi.Info.IsDir())
}

func (t *FileSystemVisitorTest) Symlinks() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Devices() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) CharDevices() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) NamedPipes() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Sockets() {
	AssertFalse(true, "TODO")
}

func (t *FileSystemVisitorTest) Exclusions() {
	AssertFalse(true, "TODO")
}
<|endoftext|>


<commit_before>package gorush

import (
	"fmt"
	"runtime"

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

var version string

// SetVersion for setup version string.
func SetVersion(ver string) {
	version = ver
}

// GetVersion for get current version.
func GetVersion() string {
	return version
}

// PrintGoRushVersion provide print server engine
func PrintGoRushVersion() {
	fmt.Printf(`GoRush %s, Compiler: %s %s, Copyright (C) 2016 Bo-Yi Wu, Inc.`,
		version,
		runtime.Compiler,
		runtime.Version())
	fmt.Println()
}

// VersionMiddleware : add version on header.
func VersionMiddleware() gin.HandlerFunc {
	// Set out header value for each response
	return func(c *gin.Context) {
		c.Writer.Header().Set("Server-Version", "GoRush/"+version)
		c.Next()
	}
}
<commit_msg>refactor: update version name in header. (#188)<commit_after>package gorush

import (
	"fmt"
	"runtime"

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

var version string

// SetVersion for setup version string.
func SetVersion(ver string) {
	version = ver
}

// GetVersion for get current version.
func GetVersion() string {
	return version
}

// PrintGoRushVersion provide print server engine
func PrintGoRushVersion() {
	fmt.Printf(`GoRush %s, Compiler: %s %s, Copyright (C) 2016 Bo-Yi Wu, Inc.`,
		version,
		runtime.Compiler,
		runtime.Version())
	fmt.Println()
}

// VersionMiddleware : add version on header.
func VersionMiddleware() gin.HandlerFunc {
	// Set out header value for each response
	return func(c *gin.Context) {
		c.Header("X-DRONE-VERSION", version)
		c.Next()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

func getPrimes7(n int) []int {
	if n < 2 {
		return []int{}
	}
	if n == 2 {
		return []int{2}
	}

	s := make([]int, 0, n/2)
	for i := 3; i <= n; i += 2 {
		s = append(s, i)
	}

	var j int
	m := 3
	mroot := int(math.Sqrt(float64(n)))
	half := len(s)
	for i := 0; m <= mroot; {
		if s[i] != 0 {
			j = (m*m - 3) / 2
			s[j] = 0
			for j < half {
				s[j] = 0
				j += m
			}
		}
		i++
		m = 2*i + 3
	}

	res := make([]int, 0, n/int(math.Log(float64(n))))
	res = append(res, 2)
	for _, v := range s {
		if v != 0 {
			res = append(res, v)
		}
	}

	return res
}

func main() {
	var res []int
	for i := 0; i < 10; i++ {
		res = getPrimes7(10000000)
		fmt.Printf("Found %d prime numbers.\n", len(res))
	}
}
<commit_msg>no compiler hints<commit_after>package main

import (
	"fmt"
	"math"
)

func getPrimes7(n int) []int {
	if n < 2 {
		return []int{}
	}
	if n == 2 {
		return []int{2}
	}

	s := []int{}
	for i := 3; i <= n; i += 2 {
		s = append(s, i)
	}

	var j int
	m := 3
	mroot := int(math.Sqrt(float64(n)))
	half := len(s)
	for i := 0; m <= mroot; {
		if s[i] != 0 {
			j = (m*m - 3) / 2
			s[j] = 0
			for j < half {
				s[j] = 0
				j += m
			}
		}
		i++
		m = 2*i + 3
	}

	res := []int{}
	res = append(res, 2)
	for _, v := range s {
		if v != 0 {
			res = append(res, v)
		}
	}

	return res
}

func main() {
	var res []int
	for i := 0; i < 10; i++ {
		res = getPrimes7(10000000)
		fmt.Printf("Found %d prime numbers.\n", len(res))
	}
}
<|endoftext|>


<commit_before>/**
 * (C) Copyright 2013, Deft Labs
 *
 * 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 dlshared

import (
	"math"
	"testing"
	"net/http"
	"encoding/json"
)

type RecordingResponseWriter struct {
	header http.Header
	HeaderCode int
	Data []byte
}

func (self *RecordingResponseWriter) reset() {
	self.header = make(map[string][]string)
	self.HeaderCode = 0
	self.Data = nil
}

func (self *RecordingResponseWriter) Header() http.Header {
	return self.header
}

func (self *RecordingResponseWriter) Write(data []byte) (int, error) {
	self.Data = append(self.Data, data...)
	return len(data), nil
}

func NewRecordingResponseWriter() *RecordingResponseWriter {
	return &RecordingResponseWriter{ header : make(map[string][]string) }
}

func (self *RecordingResponseWriter) WriteHeader(code int) {
	self.HeaderCode = code
}

type testJsonStruct struct {
	String string
	Boolean bool
	Number float64
}

func TestJsonEncodeAndWriteResponse(t *testing.T) {

	response := NewRecordingResponseWriter()

	test := &testJsonStruct{ String: "test", Boolean: true, Number: math.MaxFloat64 }

	// Write the data
	if err := JsonEncodeAndWriteResponse(response, test); err != nil {
		t.Errorf("JsonEncodeAndWriteResponse is broken - %v", err)
	}

	// Ensure the response
	decoded := &testJsonStruct{}
	if err := json.Unmarshal(response.Data, decoded); err != nil {
		t.Errorf("JsonEncodeAndWriteResponse unmarshal data is broken - %v", err)
	}

	if test.String != decoded.String {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected string: %s - received: %s", test.String, decoded.String)
	}

	if test.Boolean != decoded.Boolean {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected bool : %s - received: %s", test.Boolean, decoded.Boolean)
	}

	if test.Number != decoded.Number {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected number : %s - received: %s", test.Number, decoded.Number)
	}

}

func TestWriteOkResponseString(t *testing.T) {

	response := NewRecordingResponseWriter()

	if err := WriteOkResponseString(response, "test"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	if string(response.Data) != "test" {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if response.Header().Get("Content-Type") != "text/plain; charset=utf-8" {
		t.Errorf("IsHttpMethodPost Content-Type is broken")
	}

	response.reset()

	if response.Header().Get("Content-Type") != "" {
		t.Errorf("IsHttpMethodPost reset is broken")
	}

	err := WriteOkResponseString(response, "")
	if err == nil {
		t.Errorf("WriteOkResponseString is broken - no error on empty message")
	}

	//writeOkResponseStringEmptyMsgPanic(response, t)

	if err := WriteOkResponseString(response, "t"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	if string(response.Data) != "t" {
		t.Errorf("IsHttpMethodPost is broken")
	}

	response.reset()
	if err := WriteOkResponseString(response, "tttttttttttttttttttttttttttttttttttttttttttttttt"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	// This will panic
	err = WriteOkResponseString(nil, "")
	if err == nil {
		t.Errorf("WriteOkResponseString is broken  - no error on nil response param")
	}
}

func TestIsHttpMethodPost(t *testing.T) {

	if IsHttpMethodPost(&http.Request{ Method : "" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if IsHttpMethodPost(&http.Request{ Method : "wrong" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "post" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "Post" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "POST" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "PosT" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	// Verify the panic
	defer func() {
		if r := recover(); r == nil {
			t.Errorf("IsHttpMethodPost is broken - it did not panic on nil request")
		}
	}()

	// This method will panic.
	IsHttpMethodPost(nil)
}

<commit_msg>added a clone test<commit_after>/**
 * (C) Copyright 2013, Deft Labs
 *
 * 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 dlshared

import (
	"math"
	"testing"
	"net/http"
	"encoding/json"
)

type RecordingResponseWriter struct {
	header http.Header
	HeaderCode int
	Data []byte
}

func (self *RecordingResponseWriter) reset() {
	self.header = make(map[string][]string)
	self.HeaderCode = 0
	self.Data = nil
}

func (self *RecordingResponseWriter) Header() http.Header {
	return self.header
}

func (self *RecordingResponseWriter) Write(data []byte) (int, error) {
	self.Data = append(self.Data, data...)
	return len(data), nil
}

func NewRecordingResponseWriter() *RecordingResponseWriter {
	return &RecordingResponseWriter{ header : make(map[string][]string) }
}

func (self *RecordingResponseWriter) WriteHeader(code int) {
	self.HeaderCode = code
}

type testJsonStruct struct {
	String string
	Boolean bool
	Number float64
}

func TestHttpRequestClientClone(t *testing.T) {
	client := NewDefaultHttpRequestClient()

	clone := client.Clone()
	clone.DisableKeepAlives = false
	clone.MaxIdleConnsPerHost = 10000

	if client.DisableKeepAlives == clone.DisableKeepAlives {
		t.Errorf("TestHttpRequestClientClone is broken - values are equal")
	}

	if client.MaxIdleConnsPerHost == clone.MaxIdleConnsPerHost {
		t.Errorf("TestHttpRequestClientClone is broken - values are equal")
	}
}

func TestJsonEncodeAndWriteResponse(t *testing.T) {

	response := NewRecordingResponseWriter()

	test := &testJsonStruct{ String: "test", Boolean: true, Number: math.MaxFloat64 }

	// Write the data
	if err := JsonEncodeAndWriteResponse(response, test); err != nil {
		t.Errorf("JsonEncodeAndWriteResponse is broken - %v", err)
	}

	// Ensure the response
	decoded := &testJsonStruct{}
	if err := json.Unmarshal(response.Data, decoded); err != nil {
		t.Errorf("JsonEncodeAndWriteResponse unmarshal data is broken - %v", err)
	}

	if test.String != decoded.String {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected string: %s - received: %s", test.String, decoded.String)
	}

	if test.Boolean != decoded.Boolean {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected bool : %s - received: %s", test.Boolean, decoded.Boolean)
	}

	if test.Number != decoded.Number {
		t.Errorf("JsonEncodeAndWriteResponse is broken - expected number : %s - received: %s", test.Number, decoded.Number)
	}

}

func TestWriteOkResponseString(t *testing.T) {

	response := NewRecordingResponseWriter()

	if err := WriteOkResponseString(response, "test"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	if string(response.Data) != "test" {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if response.Header().Get("Content-Type") != "text/plain; charset=utf-8" {
		t.Errorf("IsHttpMethodPost Content-Type is broken")
	}

	response.reset()

	if response.Header().Get("Content-Type") != "" {
		t.Errorf("IsHttpMethodPost reset is broken")
	}

	err := WriteOkResponseString(response, "")
	if err == nil {
		t.Errorf("WriteOkResponseString is broken - no error on empty message")
	}

	//writeOkResponseStringEmptyMsgPanic(response, t)

	if err := WriteOkResponseString(response, "t"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	if string(response.Data) != "t" {
		t.Errorf("IsHttpMethodPost is broken")
	}

	response.reset()
	if err := WriteOkResponseString(response, "tttttttttttttttttttttttttttttttttttttttttttttttt"); err != nil {
		t.Errorf("IsHttpMethodPost is broken - %v", err)
	}

	// This will panic
	err = WriteOkResponseString(nil, "")
	if err == nil {
		t.Errorf("WriteOkResponseString is broken  - no error on nil response param")
	}
}

func TestIsHttpMethodPost(t *testing.T) {

	if IsHttpMethodPost(&http.Request{ Method : "" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if IsHttpMethodPost(&http.Request{ Method : "wrong" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "post" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "Post" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "POST" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	if !IsHttpMethodPost(&http.Request{ Method : "PosT" }) {
		t.Errorf("IsHttpMethodPost is broken")
	}

	// Verify the panic
	defer func() {
		if r := recover(); r == nil {
			t.Errorf("IsHttpMethodPost is broken - it did not panic on nil request")
		}
	}()

	// This method will panic.
	IsHttpMethodPost(nil)
}

<|endoftext|>


<commit_before>package httpbackend

import (
	"log"
	"net/http"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func mod(next sessionAndChannelHandlerFunc) sessionAndChannelHandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, session *models.HTTPSession, channelID *string, channelName *string) {
		channelInfo, error := repos.GetChannelInfo(channelID)
		log.Println(channelInfo)
		if error != nil {
			log.Println(error)
			writeJSONError(w, "That channel is not defined", http.StatusForbidden)
			return
		}

		if channelInfo.GetIfUserIsMod(&session.UserID) == true {
			next(w, r, session, channelID, channelName)
		} else {
			writeJSONError(w, "You're not moderator", http.StatusForbidden)
			return
		}
	}
}

func withMod(next sessionAndChannelHandlerFunc) http.HandlerFunc {
	return withSessionAndChannel(mod(next))
}
<commit_msg>Fix: debugg<commit_after>package httpbackend

import (
	"log"
	"net/http"

	"github.com/khades/servbot/models"
	"github.com/khades/servbot/repos"
)

func mod(next sessionAndChannelHandlerFunc) sessionAndChannelHandlerFunc {
	return func(w http.ResponseWriter, r *http.Request, session *models.HTTPSession, channelID *string, channelName *string) {
		channelInfo, error := repos.GetChannelInfo(channelID)
		log.Println(channelInfo)
		if error != nil {
			log.Println(error)
			writeJSONError(w, "That channel is not defined", http.StatusForbidden)
			return
		}
		log.Println("FIXING GETTING SESSION")
		log.Println(*session)
		if channelInfo.GetIfUserIsMod(&session.UserID) == true {
			next(w, r, session, channelID, channelName)
		} else {
			writeJSONError(w, "You're not moderator", http.StatusForbidden)
			return
		}
	}
}

func withMod(next sessionAndChannelHandlerFunc) http.HandlerFunc {
	return withSessionAndChannel(mod(next))
}
<|endoftext|>


<commit_before>package httpseverywhere

import (
	"net"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/net/publicsuffix"

	"github.com/getlantern/golog"
)

var (
	log = golog.LoggerFor("httpseverywhere")
)

// Rewrite exports the rewrite method for users of this library.
var Rewrite = newAsync()

// rewrite changes an HTTP URL to rewrite.
type rewrite func(url *url.URL) (string, bool)

type https struct {
	// This is a map of root host names to Targets -- map[string]*Targets
	hostsToTargets atomic.Value
	runs           int64
	totalTime      int64
	max            int64
	maxHost        string
	statM          sync.RWMutex
}

// A rule maps the regular expression to match and the string to change it to.
// It also stores the compiled regular expression for efficiency.
type rule struct {
	from *regexp.Regexp
	From string
	To   string
}

// An exclusion just contains the compiled regular expression exclusion pattern.
type exclusion struct {
	Pattern string
	pattern *regexp.Regexp
}

// Rules is a struct containing rules and exclusions for a given rule set. This
// is public so that we can encode and decode it from GOB format.
type Rules struct {
	Rules      []*rule
	Exclusions []*exclusion
}

// Targets contains the target hosts for the given base domain.
type Targets struct {
	Plain map[string]bool

	wildcardPrefix []*regexp.Regexp
	wildcardSuffix []*regexp.Regexp

	// We use maps here to filter duplicates. Note these are only used in
	// preprocessing and in deserialization.
	WildcardPrefix map[string]bool
	WildcardSuffix map[string]bool

	Rules *Rules
}

// new creates a new rewrite instance from embedded GOB data with asynchronous
// loading of the rule sets to allow the caller to about around a 2 second
// delay.
func newAsync() rewrite {
	h := &https{}

	h.hostsToTargets.Store(make(map[string]*Targets))
	go func() {
		d := newDeserializer()
		temp := d.newHostsToTargets()
		h.hostsToTargets.Store(temp)
	}()

	return h.rewrite
}

// newSync creates a new rewrite instance from embedded GOB data.
func newSync() rewrite {
	h := &https{}
	d := newDeserializer()
	h.hostsToTargets.Store(d.newHostsToTargets())
	return h.rewrite
}

func (h *https) rewrite(url *url.URL) (string, bool) {
	if url.Scheme != "http" {
		return "", false
	}
	start := time.Now()
	host, root := extractHostAndRoot(url)

	if len(root) == 0 {
		log.Error("Root is the empty string!")
		return "", false
	}
	if targets, ok := h.hostsToTargets.Load().(map[string]*Targets)[root]; ok {
		https, done := targets.rewrite(url, host)
		h.addTiming(time.Now().Sub(start), url.String())

		return https, done
	}
	return "", false
}

func (h *https) addTiming(dur time.Duration, host string) {
	nan := dur.Nanoseconds() / 1000
	h.statM.Lock()
	h.runs++
	h.totalTime += nan
	if nan > h.max {
		h.max = nan
		h.maxHost = host
	}
	h.statM.Unlock()

	h.statM.RLock()

	log.Debugf("Average running time: %vms", h.totalTime/h.runs)
	log.Debugf("Max running time: %vms for host: %v", h.max, h.maxHost)
	h.statM.RUnlock()
}

func extractHostAndRoot(url *url.URL) (string, string) {
	host := withoutPort(url.Host)

	// We ignore the second return value which is just a bool indicating whether
	// it's an official ICANN TLD.
	tld, _ := publicsuffix.PublicSuffix(host)

	// Because some TLDs such as "co.uk" include "."s, we strip the TLD prior
	// to stripping subdomains.
	noTLD := strings.TrimSuffix(host, "."+tld)
	root := stripSubdomains(noTLD)
	return host, root
}

func withoutPort(hostport string) string {
	host, _, err := net.SplitHostPort(hostport)
	if err != nil {
		return hostport
	}
	return host
}

func stripSubdomains(host string) string {
	host = strings.TrimSpace(host)
	parts := strings.Split(host, ".")
	return parts[len(parts)-1]
}

func (t *Targets) rewrite(originalURL *url.URL, host string) (string, bool) {
	// We basically want to apply the associated set of rules if any of the
	// targets match the url.
	url := originalURL.String()
	log.Debugf("Attempting to rewrite url %v", url)
	for k := range t.Plain {
		if host == k {
			if r, done := t.Rules.rewrite(url); done {
				return r, done
			}
		}
	}
	if r, done := t.matchTargets(url, t.wildcardPrefix); done {
		return r, done
	}
	return t.matchTargets(url, t.wildcardSuffix)
}

func (t *Targets) matchTargets(url string, targets []*regexp.Regexp) (string, bool) {
	for _, pre := range targets {
		if pre.MatchString(url) {
			if r, done := t.Rules.rewrite(url); done {
				return r, done
			}
		}
	}
	return "", false
}

// rewrite converts the given URL to HTTPS if there is an associated rule for
// it.
func (r *Rules) rewrite(url string) (string, bool) {
	for _, exclude := range r.Exclusions {
		if exclude.pattern.MatchString(url) {
			return "", false
		}
	}
	for _, rule := range r.Rules {
		if rule.from.MatchString(url) {
			return rule.from.ReplaceAllString(url, rule.To), true
		}
	}
	return "", false
}
<commit_msg>fixed conversion<commit_after>package httpseverywhere

import (
	"net"
	"net/url"
	"regexp"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/net/publicsuffix"

	"github.com/getlantern/golog"
)

var (
	log = golog.LoggerFor("httpseverywhere")
)

// Rewrite exports the rewrite method for users of this library.
var Rewrite = newAsync()

// rewrite changes an HTTP URL to rewrite.
type rewrite func(url *url.URL) (string, bool)

type https struct {
	// This is a map of root host names to Targets -- map[string]*Targets
	hostsToTargets atomic.Value
	runs           int64
	totalTime      int64
	max            int64
	maxHost        string
	statM          sync.RWMutex
}

// A rule maps the regular expression to match and the string to change it to.
// It also stores the compiled regular expression for efficiency.
type rule struct {
	from *regexp.Regexp
	From string
	To   string
}

// An exclusion just contains the compiled regular expression exclusion pattern.
type exclusion struct {
	Pattern string
	pattern *regexp.Regexp
}

// Rules is a struct containing rules and exclusions for a given rule set. This
// is public so that we can encode and decode it from GOB format.
type Rules struct {
	Rules      []*rule
	Exclusions []*exclusion
}

// Targets contains the target hosts for the given base domain.
type Targets struct {
	Plain map[string]bool

	wildcardPrefix []*regexp.Regexp
	wildcardSuffix []*regexp.Regexp

	// We use maps here to filter duplicates. Note these are only used in
	// preprocessing and in deserialization.
	WildcardPrefix map[string]bool
	WildcardSuffix map[string]bool

	Rules *Rules
}

// new creates a new rewrite instance from embedded GOB data with asynchronous
// loading of the rule sets to allow the caller to about around a 2 second
// delay.
func newAsync() rewrite {
	h := &https{}

	h.hostsToTargets.Store(make(map[string]*Targets))
	go func() {
		d := newDeserializer()
		temp := d.newHostsToTargets()
		h.hostsToTargets.Store(temp)
	}()

	return h.rewrite
}

// newSync creates a new rewrite instance from embedded GOB data.
func newSync() rewrite {
	h := &https{}
	d := newDeserializer()
	h.hostsToTargets.Store(d.newHostsToTargets())
	return h.rewrite
}

func (h *https) rewrite(url *url.URL) (string, bool) {
	if url.Scheme != "http" {
		return "", false
	}
	start := time.Now()
	host, root := extractHostAndRoot(url)

	if len(root) == 0 {
		log.Error("Root is the empty string!")
		return "", false
	}
	if targets, ok := h.hostsToTargets.Load().(map[string]*Targets)[root]; ok {
		https, done := targets.rewrite(url, host)
		h.addTiming(time.Now().Sub(start), url.String())

		return https, done
	}
	return "", false
}

func (h *https) addTiming(dur time.Duration, host string) {
	nan := dur.Nanoseconds() / 1000000
	h.statM.Lock()
	h.runs++
	h.totalTime += nan
	if nan > h.max {
		h.max = nan
		h.maxHost = host
	}
	h.statM.Unlock()

	h.statM.RLock()

	log.Debugf("Average running time: %vms", h.totalTime/h.runs)
	log.Debugf("Max running time: %vms for host: %v", h.max, h.maxHost)
	h.statM.RUnlock()
}

func extractHostAndRoot(url *url.URL) (string, string) {
	host := withoutPort(url.Host)

	// We ignore the second return value which is just a bool indicating whether
	// it's an official ICANN TLD.
	tld, _ := publicsuffix.PublicSuffix(host)

	// Because some TLDs such as "co.uk" include "."s, we strip the TLD prior
	// to stripping subdomains.
	noTLD := strings.TrimSuffix(host, "."+tld)
	root := stripSubdomains(noTLD)
	return host, root
}

func withoutPort(hostport string) string {
	host, _, err := net.SplitHostPort(hostport)
	if err != nil {
		return hostport
	}
	return host
}

func stripSubdomains(host string) string {
	host = strings.TrimSpace(host)
	parts := strings.Split(host, ".")
	return parts[len(parts)-1]
}

func (t *Targets) rewrite(originalURL *url.URL, host string) (string, bool) {
	// We basically want to apply the associated set of rules if any of the
	// targets match the url.
	url := originalURL.String()
	log.Debugf("Attempting to rewrite url %v", url)
	for k := range t.Plain {
		if host == k {
			if r, done := t.Rules.rewrite(url); done {
				return r, done
			}
		}
	}
	if r, done := t.matchTargets(url, t.wildcardPrefix); done {
		return r, done
	}
	return t.matchTargets(url, t.wildcardSuffix)
}

func (t *Targets) matchTargets(url string, targets []*regexp.Regexp) (string, bool) {
	for _, pre := range targets {
		if pre.MatchString(url) {
			if r, done := t.Rules.rewrite(url); done {
				return r, done
			}
		}
	}
	return "", false
}

// rewrite converts the given URL to HTTPS if there is an associated rule for
// it.
func (r *Rules) rewrite(url string) (string, bool) {
	for _, exclude := range r.Exclusions {
		if exclude.pattern.MatchString(url) {
			return "", false
		}
	}
	for _, rule := range r.Rules {
		if rule.from.MatchString(url) {
			return rule.from.ReplaceAllString(url, rule.To), true
		}
	}
	return "", false
}
<|endoftext|>


<commit_before>package main

import "github.com/dmulholland/janus-go/janus"

import (
    "fmt"
    "os"
    "path/filepath"
)

const version = "1.4.1.dev"

var helptext = fmt.Sprintf(`
Usage: %s [FLAGS] [COMMAND]

  Ironclad is a command line password manager.

Flags:
  -h, --help        Print the application's help text and exit.
  -v, --version     Print the application's version number and exit.

Basic Commands:
  add               Add a new entry to a password database.
  delete            Delete one or more entries from a database.
  edit              Edit an existing database entry.
  gen               Generate a new random password.
  init              Initialize a new password database.
  list              List database entries.
  new               Alias for 'add'.
  pass              Copy a password to the clipboard.
  show              Alias for 'list --verbose'.
  url               Copy a url to the clipboard.
  user              Copy a username to the clipboard.

Additional Commands:
  config            Set or print a configuration option.
  decrypt           Decrypt a file.
  dump              Dump a database's internal JSON data store.
  encrypt           Encrypt a file.
  export            Export entries from a database.
  import            Import entries into a database.
  purge             Purge inactive (i.e. deleted) entries from a database.
  restore           Restore one or more previously deleted entries.
  setpass           Change a database's master password.
  tags              List database tags.

Command Help:
  help <command>    Print the specified command's help text and exit.
`, filepath.Base(os.Args[0]))

func main() {

    // Instantiate an argument parser.
    parser := janus.NewParser()
    parser.Helptext = helptext
    parser.Version = version

    // Register commands.
    registerAddCmd(parser)
    registerCacheCmd(parser)
    registerConfigCmd(parser)
    registerDecryptCmd(parser)
    registerDeleteCmd(parser)
    registerDumpCmd(parser)
    registerEditCmd(parser)
    registerEncryptCmd(parser)
    registerExportCmd(parser)
    registerGenCmd(parser)
    registerImportCmd(parser)
    registerInitCmd(parser)
    registerListCmd(parser)
    registerPassCmd(parser)
    registerPurgeCmd(parser)
    registerRestoreCmd(parser)
    registerSetpassCmd(parser)
    registerTagsCmd(parser)
    registerUrlCmd(parser)
    registerUserCmd(parser)

    // Parse the command line arguments.
    parser.Parse()
    if !parser.HasCmd() {
        parser.ExitHelp()
    }
}
<commit_msg>Bump version<commit_after>package main

import "github.com/dmulholland/janus-go/janus"

import (
    "fmt"
    "os"
    "path/filepath"
)

const version = "1.4.1"

var helptext = fmt.Sprintf(`
Usage: %s [FLAGS] [COMMAND]

  Ironclad is a command line password manager.

Flags:
  -h, --help        Print the application's help text and exit.
  -v, --version     Print the application's version number and exit.

Basic Commands:
  add               Add a new entry to a password database.
  delete            Delete one or more entries from a database.
  edit              Edit an existing database entry.
  gen               Generate a new random password.
  init              Initialize a new password database.
  list              List database entries.
  new               Alias for 'add'.
  pass              Copy a password to the clipboard.
  show              Alias for 'list --verbose'.
  url               Copy a url to the clipboard.
  user              Copy a username to the clipboard.

Additional Commands:
  config            Set or print a configuration option.
  decrypt           Decrypt a file.
  dump              Dump a database's internal JSON data store.
  encrypt           Encrypt a file.
  export            Export entries from a database.
  import            Import entries into a database.
  purge             Purge inactive (i.e. deleted) entries from a database.
  restore           Restore one or more previously deleted entries.
  setpass           Change a database's master password.
  tags              List database tags.

Command Help:
  help <command>    Print the specified command's help text and exit.
`, filepath.Base(os.Args[0]))

func main() {

    // Instantiate an argument parser.
    parser := janus.NewParser()
    parser.Helptext = helptext
    parser.Version = version

    // Register commands.
    registerAddCmd(parser)
    registerCacheCmd(parser)
    registerConfigCmd(parser)
    registerDecryptCmd(parser)
    registerDeleteCmd(parser)
    registerDumpCmd(parser)
    registerEditCmd(parser)
    registerEncryptCmd(parser)
    registerExportCmd(parser)
    registerGenCmd(parser)
    registerImportCmd(parser)
    registerInitCmd(parser)
    registerListCmd(parser)
    registerPassCmd(parser)
    registerPurgeCmd(parser)
    registerRestoreCmd(parser)
    registerSetpassCmd(parser)
    registerTagsCmd(parser)
    registerUrlCmd(parser)
    registerUserCmd(parser)

    // Parse the command line arguments.
    parser.Parse()
    if !parser.HasCmd() {
        parser.ExitHelp()
    }
}
<|endoftext|>


<commit_before>// +build !windows
// +build !appengine

package isatty

// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
	return false
}
<commit_msg>restore accidentally removed build constrain<commit_after>// +build !windows
// +build !appengine
// +build !js

package isatty

// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
	return false
}
<|endoftext|>


<commit_before>// Copyright 2014, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// vtprimecache is a standalone version of primecache
package main

import (
	"flag"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/vt/dbconfigs"
	"github.com/youtube/vitess/go/vt/primecache"
)

var (
	mysqlSocketFile = flag.String("mysql_socket_file", "", "location of the mysql socket file")
	relayLogsPath   = flag.String("relay_logs_path", "", "location of the relay logs for the mysql instance")
	sleepDuration   = flag.Duration("sleep_duration", 1*time.Second, "how long to sleep in between each run")
	workerCount     = flag.Int("worker_count", 4, "number of connections to use to talk to mysql")
)

func main() {
	dbconfigs.RegisterFlags()
	flag.Parse()

	dbcfgs, err := dbconfigs.Init(*mysqlSocketFile)
	if err != nil {
		log.Warning(err)
	}

	pc := primecache.NewPrimeCache(dbcfgs, *relayLogsPath)
	pc.WorkerCount = *workerCount
	pc.SleepDuration = *sleepDuration

	pc.Loop()
}
<commit_msg>Making a fatal condition actually Fatalf.<commit_after>// Copyright 2014, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// vtprimecache is a standalone version of primecache
package main

import (
	"flag"
	"time"

	log "github.com/golang/glog"
	"github.com/youtube/vitess/go/vt/dbconfigs"
	"github.com/youtube/vitess/go/vt/primecache"
)

var (
	mysqlSocketFile = flag.String("mysql_socket_file", "", "location of the mysql socket file")
	relayLogsPath   = flag.String("relay_logs_path", "", "location of the relay logs for the mysql instance")
	sleepDuration   = flag.Duration("sleep_duration", 1*time.Second, "how long to sleep in between each run")
	workerCount     = flag.Int("worker_count", 4, "number of connections to use to talk to mysql")
)

func main() {
	dbconfigs.RegisterFlags()
	flag.Parse()

	dbcfgs, err := dbconfigs.Init(*mysqlSocketFile)
	if err != nil {
		log.Fatalf("Failed to init dbconfigs: %v", err)
	}

	pc := primecache.NewPrimeCache(dbcfgs, *relayLogsPath)
	pc.WorkerCount = *workerCount
	pc.SleepDuration = *sleepDuration

	pc.Loop()
}
<|endoftext|>


<commit_before>package filters

import (
	"net/http"
	"net/http/httputil"

	"github.com/gorilla/context"

	"github.com/getlantern/measured"

	"../utils"
)

const (
	uIDHeader = "X-Lantern-UID"
)

type UIDFilter struct {
	log  utils.Logger
	next http.Handler
}

func NewUIDFilter(next http.Handler, log utils.Logger) *UIDFilter {
	return &UIDFilter{
		log:  log,
		next: next,
	}
}

func (f *UIDFilter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if f.log.IsLevel(utils.DEBUG) {
		reqStr, _ := httputil.DumpRequest(req, true)
		f.log.Debugf("UIDFilter Middleware received request:\n%s", reqStr)
	}

	lanternUID := req.Header.Get(uIDHeader)

	// An UID must be provided always by the client.  Respond 404 otherwise.
	if lanternUID == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Get the client and attach it as request context
	key := []byte(lanternUID)
	c := context.Get(req, "conn")
	c.(*measured.Conn).ID = string(key)

	req.Header.Del(uIDHeader)

	f.next.ServeHTTP(w, req)
}
<commit_msg>add comment<commit_after>package filters

import (
	"net/http"
	"net/http/httputil"

	"github.com/gorilla/context"

	"github.com/getlantern/measured"

	"../utils"
)

const (
	uIDHeader = "X-Lantern-UID"
)

type UIDFilter struct {
	log  utils.Logger
	next http.Handler
}

func NewUIDFilter(next http.Handler, log utils.Logger) *UIDFilter {
	return &UIDFilter{
		log:  log,
		next: next,
	}
}

func (f *UIDFilter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if f.log.IsLevel(utils.DEBUG) {
		reqStr, _ := httputil.DumpRequest(req, true)
		f.log.Debugf("UIDFilter Middleware received request:\n%s", reqStr)
	}

	lanternUID := req.Header.Get(uIDHeader)

	// An UID must be provided always by the client.  Respond 404 otherwise.
	if lanternUID == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	// Attached the uid to connection to report stats to redis correctly
	// "conn" in context is previously attached in server.go
	key := []byte(lanternUID)
	c := context.Get(req, "conn")
	c.(*measured.Conn).ID = string(key)

	req.Header.Del(uIDHeader)

	f.next.ServeHTTP(w, req)
}
<|endoftext|>


<commit_before>package common

import (
	"reflect"
)

type Syscall struct {
	Name     string
	Kernel   *KernelBase
	Instance reflect.Value
	Method   reflect.Method
	In       []reflect.Type
	Out      []reflect.Type
	ObufArr  bool
	UintArr  bool
}

// Call a syscall from the dispatch table. Will panic() if anything goes terribly wrong.
func (sys Syscall) Call(args []uint64) uint64 {
	extraArgs := 1
	if sys.ObufArr || sys.UintArr {
		extraArgs += 1
	}
	in := make([]reflect.Value, len(sys.In)+extraArgs)
	in[0] = sys.Instance
	// special case "all args" buf list
	if sys.ObufArr && len(sys.In) > 1 {
		arr := make([]Obuf, len(sys.In)-1)
		for i := range arr {
			arr[i] = Obuf{NewBuf(sys.Kernel, args[i])}
		}
		in[1] = reflect.ValueOf(arr)
	} else if sys.UintArr {
		in[1] = reflect.ValueOf(args)
	}
	// convert syscall arguments
	converted, err := sys.Kernel.Argjoy.Convert(sys.In, false, args)
	if err != nil {
		panic(err)
	}
	copy(in[extraArgs:], converted)
	// call handler function
	out := sys.Method.Func.Call(in)
	// return output if first return of function is representable as an int type
	Uint64Type := reflect.TypeOf(uint64(0))
	if len(out) > 0 && out[0].Type().ConvertibleTo(Uint64Type) {
		return out[0].Convert(Uint64Type).Uint()
	}
	return 0
}
<commit_msg>improve panic msg for unimplemented arg unpack<commit_after>package common

import (
	"fmt"
	"reflect"
)

type Syscall struct {
	Name     string
	Kernel   *KernelBase
	Instance reflect.Value
	Method   reflect.Method
	In       []reflect.Type
	Out      []reflect.Type
	ObufArr  bool
	UintArr  bool
}

// Call a syscall from the dispatch table. Will panic() if anything goes terribly wrong.
func (sys Syscall) Call(args []uint64) uint64 {
	extraArgs := 1
	if sys.ObufArr || sys.UintArr {
		extraArgs += 1
	}
	in := make([]reflect.Value, len(sys.In)+extraArgs)
	in[0] = sys.Instance
	// special case "all args" buf list
	if sys.ObufArr && len(sys.In) > 1 {
		arr := make([]Obuf, len(sys.In)-1)
		for i := range arr {
			arr[i] = Obuf{NewBuf(sys.Kernel, args[i])}
		}
		in[1] = reflect.ValueOf(arr)
	} else if sys.UintArr {
		in[1] = reflect.ValueOf(args)
	}
	// convert syscall arguments
	converted, err := sys.Kernel.Argjoy.Convert(sys.In, false, args)
	if err != nil {
		msg := fmt.Sprintf("calling %T.%s(): %s", sys.Instance.Interface(), sys.Method.Name, err)
		panic(msg)
	}
	copy(in[extraArgs:], converted)
	// call handler function
	out := sys.Method.Func.Call(in)
	// return output if first return of function is representable as an int type
	Uint64Type := reflect.TypeOf(uint64(0))
	if len(out) > 0 && out[0].Type().ConvertibleTo(Uint64Type) {
		return out[0].Convert(Uint64Type).Uint()
	}
	return 0
}
<|endoftext|>


<commit_before>// Package moreflag contains definitions for some useful flag types, such as maps.
package moreflag

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"sort"
	"strings"
)

// Parse parses flags which are set in environment variables using the FLAG_ prefix. That is
// for a flag named x, x=$FLAG_x if $FLAG_x is set. If the flag is set in the command line, the
// command line value of the flag takes precedence over the environment variable value.
// It also calls flag.Parse() to parse flags sent directly as arguments, unless flag.Parse
// has been previously called.
func Parse() {
	if !flag.Parsed() {
		ParseFromEnv()
		flag.Parse()
	}
}

// ParseFromEnv parses flags which are set in environment variables using the FLAG_ prefix. That is
// for a flag named x, x=$FLAG_x if $FLAG_x is set. If the flag is set in the command line, the
// command line value of the flag takes precedence over the environment variable value.
func ParseFromEnv() {
	flag.VisitAll(func(f *flag.Flag) {
		v := os.Getenv("FLAG_" + f.Name)
		if v != "" {
			flag.Set(f.Name, v)
		}
	})
}

// StringMapValue is a command line flag that interprets a string in the format key1=value1,key2=value2
// as a map.
type StringMapValue map[string]string

// String retrieves the flag's map in the format key1=value1,key2=value, sorted by keys.
func (m *StringMapValue) String() string {
	// Construct the output in key sorted order
	keys := make([]string, 0, len(*m))
	for key := range *m {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	var b bytes.Buffer
	for i, key := range keys {
		if i > 0 {
			b.WriteRune(',')
		}
		b.WriteString(key)
		b.WriteRune('=')
		b.WriteString((*m)[key])
	}
	return b.String()
}

// Set updates the map with key and value pair(s) in the format key1=value1,key2=value2.
func (m *StringMapValue) Set(s string) error {
	*m = make(map[string]string)
	pairs := strings.Split(s, ",")
	for _, p := range pairs {
		if p == "" {
			continue
		}
		pair := strings.Split(p, "=")
		if len(pair) != 2 {
			return fmt.Errorf("wrong format for key-value pair: %v", p)
		}
		if pair[0] == "" {
			return fmt.Errorf("key not provided")
		}
		if _, ok := (*m)[pair[0]]; ok {
			return fmt.Errorf("key %v already defined in list of key-value pairs %v", pair[0], s)
		}
		(*m)[pair[0]] = pair[1]
	}
	return nil
}

// Get returns the flag value as a map of strings.
func (m *StringMapValue) Get() interface{} {
	return map[string]string(*m)
}

// StringListValue is a command line flag that interprets a string as a list of comma-separated values.
type StringListValue []string

// String returns the list value.
func (m *StringListValue) String() string {
	return strings.Join(*m, ",")
}

// Set for StringListValue accepts one list of comma-separated values.
func (m *StringListValue) Set(s string) error {
	splitFn := func(c rune) bool {
		return c == ','
	}
	*m = StringListValue(strings.FieldsFunc(s, splitFn))
	return nil
}

// Get returns the flag value as a list of strings.
func (m *StringListValue) Get() interface{} {
	return []string(*m)
}
<commit_msg>Fixing moreflag to work with both internal and external package. (#125)<commit_after>// Package moreflag contains definitions for some useful flag types, such as maps.
package moreflag

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"sort"
	"strings"
)

// Parse parses flags which are set in environment variables using the FLAG_ prefix. That is
// for a flag named x, x=$FLAG_x if $FLAG_x is set. If the flag is set in the command line, the
// command line value of the flag takes precedence over the environment variable value.
// It also calls flag.CommandLine.Parse() to parse flags sent directly as arguments, unless flag.Parse
// has been previously called.
func Parse() {
	if !flag.Parsed() {
		ParseFromEnv()
		flag.CommandLine.Parse(os.Args[1:])
	}
}

// ParseFromEnv parses flags which are set in environment variables using the FLAG_ prefix. That is
// for a flag named x, x=$FLAG_x if $FLAG_x is set. If the flag is set in the command line, the
// command line value of the flag takes precedence over the environment variable value.
func ParseFromEnv() {
	flag.VisitAll(func(f *flag.Flag) {
		v, ok := os.LookupEnv("FLAG_" + f.Name)
		if ok {
			flag.Set(f.Name, v)
		}
	})
}

// StringMapValue is a command line flag that interprets a string in the format key1=value1,key2=value2
// as a map.
type StringMapValue map[string]string

// String retrieves the flag's map in the format key1=value1,key2=value, sorted by keys.
func (m *StringMapValue) String() string {
	// Construct the output in key sorted order
	keys := make([]string, 0, len(*m))
	for key := range *m {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	var b bytes.Buffer
	for i, key := range keys {
		if i > 0 {
			b.WriteRune(',')
		}
		b.WriteString(key)
		b.WriteRune('=')
		b.WriteString((*m)[key])
	}
	return b.String()
}

// Set updates the map with key and value pair(s) in the format key1=value1,key2=value2.
func (m *StringMapValue) Set(s string) error {
	*m = make(map[string]string)
	pairs := strings.Split(s, ",")
	for _, p := range pairs {
		if p == "" {
			continue
		}
		pair := strings.Split(p, "=")
		if len(pair) != 2 {
			return fmt.Errorf("wrong format for key-value pair: %v", p)
		}
		if pair[0] == "" {
			return fmt.Errorf("key not provided")
		}
		if _, ok := (*m)[pair[0]]; ok {
			return fmt.Errorf("key %v already defined in list of key-value pairs %v", pair[0], s)
		}
		(*m)[pair[0]] = pair[1]
	}
	return nil
}

// Get returns the flag value as a map of strings.
func (m *StringMapValue) Get() interface{} {
	return map[string]string(*m)
}

// StringListValue is a command line flag that interprets a string as a list of comma-separated values.
type StringListValue []string

// String returns the list value.
func (m *StringListValue) String() string {
	return strings.Join(*m, ",")
}

// Set for StringListValue accepts one list of comma-separated values.
func (m *StringListValue) Set(s string) error {
	splitFn := func(c rune) bool {
		return c == ','
	}
	*m = StringListValue(strings.FieldsFunc(s, splitFn))
	return nil
}

// Get returns the flag value as a list of strings.
func (m *StringListValue) Get() interface{} {
	return []string(*m)
}
<|endoftext|>