<commit_before>package bloom

import (
	"math/rand"
	"testing"
)

func TestNewBloom(t *testing.T) {
	s := NewBloom(64, 1)
	if s.k != 1 {
		t.Errorf("NewBloom returned wrong hashes for filter")
	}
	if s.m != 64 {
		t.Errorf("NewBloom returned wrong filter size")
	}
	if cap(s.collection) != 1 {
		t.Errorf("NewBloom built wrong sized collection of uint64s")
	}
}

func TestJustTest(t *testing.T) {
	b := NewBloom(128, 1)
	if b.Test([]byte("test")) {
		t.Errorf("Insert or Test broken")
	}
}

func TestInsertAndTest(t *testing.T) {
	b := NewBloom(128, 1)
	b.hasher = func(b *Bloom, value []byte) []uint64 {
		return make([]uint64, 1)
	}
	b.Insert([]byte("test"))
	if !b.Test([]byte("test")) {
		t.Errorf("Insert or Test broken")
	}
}

func randByteSlice(len int) []byte {
	rbs := make([]byte, len)

	for i := 0; i < len; i++ {
		rbs[i] = byte(rand.Int())
	}
	return rbs
}

func TestAvalanche(t *testing.T) {
	wordLen := 32
	pairs := 1000000

	// let's build pairs comprised of a random hash key and its copy with a single bit twiddled!

	inputs := make([][]byte, pairs)
	tweaked := make([][]byte, pairs)
	inputsc := make([][]uint64, pairs)
	tweakedc := make([][]uint64, pairs)
	avalanche := make([][]uint64, pairs)

	for i := 0; i < pairs; i++ {
		inputs[i] = make([]byte, wordLen)
		tweaked[i] = make([]byte, wordLen)
		inputsc[i] = make([]uint64, 2)
		tweakedc[i] = make([]uint64, 2)
		avalanche[i] = make([]uint64, 2)
		for j := 0; j < wordLen; j++ {
			inputs[i][j] = byte(rand.Int())
			tweaked[i][j] = inputs[i][j]
		}
		tweaked[i][rand.Intn(wordLen)] ^= (1 << uint(rand.Intn(8)))
		inputsc[i][0], inputsc[i][1] = murmur3_128(inputs[i])
		tweakedc[i][0], tweakedc[i][1] = murmur3_128(tweaked[i])

		avalanche[i][0] = inputsc[i][0] ^ tweakedc[i][0]
		avalanche[i][1] = inputsc[i][1] ^ tweakedc[i][1]
	}

	B := make([]uint64, pairs)

	for i := 0; i < pairs; i++ {
		for j := 0; j < 2; j++ {
			c := avalanche[i][j]
			for m := 0; m < 64; m++ {
				B[i] += (c & 1)
				c >>= 1
			}
		}
	}

	// For each experiment/trial, we've counted the number of avalanche bits.
	// Each is equivalent to 128 coin flips, so we can use Fisher's Method
	// and some simple probability to find upper and lower bounds on the
	// number of 1-bit per experiment. Because they're a series of coin
	// flips, we know they ought to be distributed approximately normally,
	// and that the probability of exceeding our chosen threshold is a
	// two-tailed p-value is:
	//   2 * 1/2^128 * sum (128 choose (128-j)), j=0 to 32 ~= 1.28418*10^-8
	// I picked 32 because it has the nice property of being 1/4 of 128,
	// which means any 1-bit or 0-bit count that exceeds half of the total
	// bits implies that we reject the hypothesis.

	var minOnes uint64 = 32
	var maxOnes uint64 = 96

	for i := 0; i < pairs; i++ {
		if B[i] > maxOnes || B[i] < minOnes {
			t.Errorf("Hash failed Avalanche test with %v bits\n", B[i])
		}
	}
}

func TestEstimateFalsePositives(t *testing.T) {
	// If we overload the hash any input should appear to be a set member
	if EstimateFalsePositives(2, 8, 256) != 1.0 {
		t.Errorf("Bad false positive probability estimate")
	}

	// If we've put nothing in the hash, there can't be false positives
	if EstimateFalsePositives(2, 8, 0) != 0.0 {
		t.Errorf("Bad false positive probability estimate")
	}

	// If we put four items into an 8 bit filter, it's possible that with
	// one hash round all four items are assigned distinct bits, however,
	// it isn't expected.
	if EstimateFalsePositives(1, 8, 4) > 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}

	// Likewise, if we put eight items in, it's possible that all of
	// them get assigned to the same bit, but it isn't expected.
	if EstimateFalsePositives(1, 8, 8) < 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}

	// This is a bit contrived, but by way of hand calculations,
	// these estimations should straddle 0.5
	lower := EstimateFalsePositives(1, 64, 44)
	upper := EstimateFalsePositives(1, 64, 45)
	if lower >= 0.5 || upper <= 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}
}

func TestBloomEstimateFalsePositives(t *testing.T) {
	// This is a very simple test of convergence. We ought to be able to
	// build a bloom filter and estimate its false positive probability,
	// then show that many applications of Test using random input
	// forms a hit-rate that approaches the estimate.

	var m uint64 = 65536

	trials := 100000
	hits := 0
	members := m / 3

	b := NewBloom(m, 1)
	for i := 0; uint64(i) < members; i++ {
		b.Insert(randByteSlice(50))
	}

	estimate := b.EstimateFalsePositives(members)

	for i := 0; i < trials; i++ {
		val := randByteSlice(100)
		if b.Test(val) {
			hits++
		}
		// If we've iterated enough and the hit rate is within a percent of the estimate, stop.
		if i > 100 && (((float64(hits)/float64(i))-estimate)/estimate) < 0.01 {
			return
		}
	}
	t.Errorf("Failed to approach the estimate")
}

func TestOptimalHashNumber(t *testing.T) {
	// If our calculation has actually found a k that minimizes the
	// false probability rate, then we ought to be able to try it
	// against other values of k and see that it's better.
	var m uint64 = 1024
	var n uint64 = 64
	k := uint(OptimalHashNumber(m, n))
	estimate := EstimateFalsePositives(k, m, n)
	for i := 1; uint64(i) < 20; i++ {
		est := EstimateFalsePositives(uint(i), m, n)
		if est < estimate {
			t.Errorf("optimal hash calculation returned wrong k")
		}
	}
}

func TestOptimalFilterSize(t *testing.T) {
	// If our calculation has actually minimized the filter size while
	// maintaining a false probability rate as given, then every smaller
	// filter must have a false probability that exceeds p.
	var n uint64 = 64
	var p float64 = 0.01

	best := OptimalFilterSize(n, p)

	for i := 1; uint64(i) < best; i++ {
		if EstimateFalsePositives(1, uint64(i), n) < p {
			t.Errorf("optimal filter size calculation is wrong")
		}
	}
}
<commit_msg>added an easy example<commit_after>package bloom

import (
	"math/rand"
	"testing"
)

func ExampleEasy() {
	b := NewBloom(64, 1)

	b.Insert([]byte("test"))

	if b.Test([]byte("test")) {
		// True!
	}

	if b.Test([]byte("not test")) {
		// Probably False!
	}
}

func TestNewBloom(t *testing.T) {
	s := NewBloom(64, 1)
	if s.k != 1 {
		t.Errorf("NewBloom returned wrong hashes for filter")
	}
	if s.m != 64 {
		t.Errorf("NewBloom returned wrong filter size")
	}
	if cap(s.collection) != 1 {
		t.Errorf("NewBloom built wrong sized collection of uint64s")
	}
}

func TestJustTest(t *testing.T) {
	b := NewBloom(128, 1)
	if b.Test([]byte("test")) {
		t.Errorf("Insert or Test broken")
	}
}

func TestInsertAndTest(t *testing.T) {
	b := NewBloom(128, 1)
	b.hasher = func(b *Bloom, value []byte) []uint64 {
		return make([]uint64, 1)
	}
	b.Insert([]byte("test"))
	if !b.Test([]byte("test")) {
		t.Errorf("Insert or Test broken")
	}
}

func randByteSlice(len int) []byte {
	rbs := make([]byte, len)

	for i := 0; i < len; i++ {
		rbs[i] = byte(rand.Int())
	}
	return rbs
}

func TestAvalanche(t *testing.T) {
	wordLen := 32
	pairs := 1000000

	// let's build pairs comprised of a random hash key and its copy with a single bit twiddled!

	inputs := make([][]byte, pairs)
	tweaked := make([][]byte, pairs)
	inputsc := make([][]uint64, pairs)
	tweakedc := make([][]uint64, pairs)
	avalanche := make([][]uint64, pairs)

	for i := 0; i < pairs; i++ {
		inputs[i] = make([]byte, wordLen)
		tweaked[i] = make([]byte, wordLen)
		inputsc[i] = make([]uint64, 2)
		tweakedc[i] = make([]uint64, 2)
		avalanche[i] = make([]uint64, 2)
		for j := 0; j < wordLen; j++ {
			inputs[i][j] = byte(rand.Int())
			tweaked[i][j] = inputs[i][j]
		}
		tweaked[i][rand.Intn(wordLen)] ^= (1 << uint(rand.Intn(8)))
		inputsc[i][0], inputsc[i][1] = murmur3_128(inputs[i])
		tweakedc[i][0], tweakedc[i][1] = murmur3_128(tweaked[i])

		avalanche[i][0] = inputsc[i][0] ^ tweakedc[i][0]
		avalanche[i][1] = inputsc[i][1] ^ tweakedc[i][1]
	}

	B := make([]uint64, pairs)

	for i := 0; i < pairs; i++ {
		for j := 0; j < 2; j++ {
			c := avalanche[i][j]
			for m := 0; m < 64; m++ {
				B[i] += (c & 1)
				c >>= 1
			}
		}
	}

	// For each experiment/trial, we've counted the number of avalanche bits.
	// Each is equivalent to 128 coin flips, so we can use Fisher's Method
	// and some simple probability to find upper and lower bounds on the
	// number of 1-bit per experiment. Because they're a series of coin
	// flips, we know they ought to be distributed approximately normally,
	// and that the probability of exceeding our chosen threshold is a
	// two-tailed p-value is:
	//   2 * 1/2^128 * sum (128 choose (128-j)), j=0 to 32 ~= 1.28418*10^-8
	// I picked 32 because it has the nice property of being 1/4 of 128,
	// which means any 1-bit or 0-bit count that exceeds half of the total
	// bits implies that we reject the hypothesis.

	var minOnes uint64 = 32
	var maxOnes uint64 = 96

	for i := 0; i < pairs; i++ {
		if B[i] > maxOnes || B[i] < minOnes {
			t.Errorf("Hash failed Avalanche test with %v bits\n", B[i])
		}
	}
}

func TestEstimateFalsePositives(t *testing.T) {
	// If we overload the hash any input should appear to be a set member
	if EstimateFalsePositives(2, 8, 256) != 1.0 {
		t.Errorf("Bad false positive probability estimate")
	}

	// If we've put nothing in the hash, there can't be false positives
	if EstimateFalsePositives(2, 8, 0) != 0.0 {
		t.Errorf("Bad false positive probability estimate")
	}

	// If we put four items into an 8 bit filter, it's possible that with
	// one hash round all four items are assigned distinct bits, however,
	// it isn't expected.
	if EstimateFalsePositives(1, 8, 4) > 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}

	// Likewise, if we put eight items in, it's possible that all of
	// them get assigned to the same bit, but it isn't expected.
	if EstimateFalsePositives(1, 8, 8) < 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}

	// This is a bit contrived, but by way of hand calculations,
	// these estimations should straddle 0.5
	lower := EstimateFalsePositives(1, 64, 44)
	upper := EstimateFalsePositives(1, 64, 45)
	if lower >= 0.5 || upper <= 0.5 {
		t.Errorf("Bad false positive probability estimate")
	}
}

func TestBloomEstimateFalsePositives(t *testing.T) {
	// This is a very simple test of convergence. We ought to be able to
	// build a bloom filter and estimate its false positive probability,
	// then show that many applications of Test using random input
	// forms a hit-rate that approaches the estimate.

	var m uint64 = 65536

	trials := 100000
	hits := 0
	members := m / 3

	b := NewBloom(m, 1)
	for i := 0; uint64(i) < members; i++ {
		b.Insert(randByteSlice(50))
	}

	estimate := b.EstimateFalsePositives(members)

	for i := 0; i < trials; i++ {
		val := randByteSlice(100)
		if b.Test(val) {
			hits++
		}
		// If we've iterated enough and the hit rate is within a percent of the estimate, stop.
		if i > 100 && (((float64(hits)/float64(i))-estimate)/estimate) < 0.01 {
			return
		}
	}
	t.Errorf("Failed to approach the estimate")
}

func TestOptimalHashNumber(t *testing.T) {
	// If our calculation has actually found a k that minimizes the
	// false probability rate, then we ought to be able to try it
	// against other values of k and see that it's better.
	var m uint64 = 1024
	var n uint64 = 64
	k := uint(OptimalHashNumber(m, n))
	estimate := EstimateFalsePositives(k, m, n)
	for i := 1; uint64(i) < 20; i++ {
		est := EstimateFalsePositives(uint(i), m, n)
		if est < estimate {
			t.Errorf("optimal hash calculation returned wrong k")
		}
	}
}

func TestOptimalFilterSize(t *testing.T) {
	// If our calculation has actually minimized the filter size while
	// maintaining a false probability rate as given, then every smaller
	// filter must have a false probability that exceeds p.
	var n uint64 = 64
	var p float64 = 0.01

	best := OptimalFilterSize(n, p)

	for i := 1; uint64(i) < best; i++ {
		if EstimateFalsePositives(1, uint64(i), n) < p {
			t.Errorf("optimal filter size calculation is wrong")
		}
	}
}
<|endoftext|>


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

package logger

import (
	"fmt"
	"os"
	"strings"

	"github.com/fatih/color"
	prettyjson "github.com/hokaccha/go-prettyjson"
	"go.uber.org/zap"
	"go.uber.org/zap/buffer"
	"go.uber.org/zap/zapcore"
)

func init() {
	if err := zap.RegisterEncoder("debug", func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
		return NewConsoleEncoder(encoderConfig), nil
	}); err != nil {
		panic(err)
	}
}

type consoleEncoder struct {
	zapcore.Encoder
	consoleEncoder zapcore.Encoder
}

func NewConsoleEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
	color.NoColor = false // Force enabled

	cfg.StacktraceKey = ""
	cfg2 := cfg
	cfg2.NameKey = ""
	cfg2.MessageKey = ""
	cfg2.LevelKey = ""
	cfg2.CallerKey = ""
	cfg2.StacktraceKey = ""
	cfg2.TimeKey = ""
	return consoleEncoder{
		consoleEncoder: zapcore.NewConsoleEncoder(cfg),
		Encoder:        zapcore.NewJSONEncoder(cfg2),
	}
}

func (c consoleEncoder) Clone() zapcore.Encoder {
	return consoleEncoder{
		consoleEncoder: c.consoleEncoder.Clone(),
		Encoder:        c.Encoder.Clone(),
	}
}

func (c consoleEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
	line, err := c.consoleEncoder.EncodeEntry(ent, nil)
	if err != nil {
		return nil, err
	}

	line2, err := c.Encoder.EncodeEntry(ent, fields)
	if err != nil {
		return nil, err
	}

	s, err := prettyjson.Format(line2.Bytes())
	if err != nil {
		line.AppendString("errrr")
	}

	line2.Reset()
	line2.AppendString(string(s))

	if ent.Stack != "" {
		line2.AppendByte('\n')
		line2.AppendString("Caller StackTrace\n")
		line2.AppendString(ent.Stack)
	}

	for _, field := range fields {
		switch field.Key {
		case "stacktrace":
			line2.AppendByte('\n')
			line2.AppendString("Error StackTrace\n")
			line2.AppendString(fmt.Sprintf("%v\n", field.String))
		}
	}

	parts := strings.Split(line2.String(), "\n")
	for i := range parts {
		line.AppendString("| ")
		line.AppendString(parts[i])
		line.AppendByte('\n')
	}

	return line, nil
}

func NewZapLogger(opts ...zap.Option) *zap.Logger {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""
	var cfg zap.Config
	if !debug {
		cfg = zap.NewProductionConfig()
	} else {
		cfg = zap.NewDevelopmentConfig()
		cfg.Encoding = "debug" // already registered init function
		cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
		opts = append(opts, zap.AddCaller())
	}
	cfg.EncoderConfig.EncodeTime = nil

	if level := os.Getenv("NVIM_GO_LOG_LEVEL"); level != "" {
		var lv zapcore.Level
		if err := lv.UnmarshalText([]byte(level)); err != nil {
			panic(fmt.Sprintf("unknown zap log level: %v", level))
		}
		cfg.Level.SetLevel(lv)
	}

	zapLogger, err := cfg.Build(opts...)
	if err != nil {
		panic(err)
	}

	return zapLogger
}

func NewRedirectZapLogger(opts ...zap.Option) (*zap.Logger, func()) {
	log := NewZapLogger()
	undo := zap.RedirectStdLog(log)

	return log, undo
}
<commit_msg>logger: change function order<commit_after>// Copyright 2017 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package logger

import (
	"fmt"
	"os"
	"strings"

	"github.com/fatih/color"
	prettyjson "github.com/hokaccha/go-prettyjson"
	"go.uber.org/zap"
	"go.uber.org/zap/buffer"
	"go.uber.org/zap/zapcore"
)

func init() {
	if err := zap.RegisterEncoder("debug", func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
		return NewConsoleEncoder(encoderConfig), nil
	}); err != nil {
		panic(err)
	}
}

func NewZapLogger(opts ...zap.Option) *zap.Logger {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""
	var cfg zap.Config
	if !debug {
		cfg = zap.NewProductionConfig()
	} else {
		cfg = zap.NewDevelopmentConfig()
		cfg.Encoding = "debug" // already registered init function
		cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
		opts = append(opts, zap.AddCaller())
	}
	cfg.EncoderConfig.EncodeTime = nil

	if level := os.Getenv("NVIM_GO_LOG_LEVEL"); level != "" {
		var lv zapcore.Level
		if err := lv.UnmarshalText([]byte(level)); err != nil {
			panic(fmt.Sprintf("unknown zap log level: %v", level))
		}
		cfg.Level.SetLevel(lv)
	}

	zapLogger, err := cfg.Build(opts...)
	if err != nil {
		panic(err)
	}

	return zapLogger
}

func NewRedirectZapLogger(opts ...zap.Option) (*zap.Logger, func()) {
	log := NewZapLogger()
	undo := zap.RedirectStdLog(log)

	return log, undo
}

type consoleEncoder struct {
	zapcore.Encoder
	consoleEncoder zapcore.Encoder
}

func NewConsoleEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder {
	color.NoColor = false // Force enabled

	cfg.StacktraceKey = ""
	cfg2 := cfg
	cfg2.NameKey = ""
	cfg2.MessageKey = ""
	cfg2.LevelKey = ""
	cfg2.CallerKey = ""
	cfg2.StacktraceKey = ""
	cfg2.TimeKey = ""
	return consoleEncoder{
		consoleEncoder: zapcore.NewConsoleEncoder(cfg),
		Encoder:        zapcore.NewJSONEncoder(cfg2),
	}
}

func (c consoleEncoder) Clone() zapcore.Encoder {
	return consoleEncoder{
		consoleEncoder: c.consoleEncoder.Clone(),
		Encoder:        c.Encoder.Clone(),
	}
}

func (c consoleEncoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
	line, err := c.consoleEncoder.EncodeEntry(ent, nil)
	if err != nil {
		return nil, err
	}

	line2, err := c.Encoder.EncodeEntry(ent, fields)
	if err != nil {
		return nil, err
	}

	s, err := prettyjson.Format(line2.Bytes())
	if err != nil {
		line.AppendString("errrr")
	}

	line2.Reset()
	line2.AppendString(string(s))

	if ent.Stack != "" {
		line2.AppendByte('\n')
		line2.AppendString("Caller StackTrace\n")
		line2.AppendString(ent.Stack)
	}

	for _, field := range fields {
		switch field.Key {
		case "stacktrace":
			line2.AppendByte('\n')
			line2.AppendString("Error StackTrace\n")
			line2.AppendString(fmt.Sprintf("%v\n", field.String))
		}
	}

	parts := strings.Split(line2.String(), "\n")
	for i := range parts {
		line.AppendString("| ")
		line.AppendString(parts[i])
		line.AppendByte('\n')
	}

	return line, nil
}
<|endoftext|>


<commit_before>package main

import (
	"exercism"
	"fmt"
	"github.com/codegangsta/cli"
	"os"
	"os/user"
)

func main() {
	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Commands = []cli.Command{
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     "Fetch first assignment for each language from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["demo"], config.ApiKey)
				if err != nil {
					panic(err)
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						panic(err)
					}
				}
			},
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     "Fetch current assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["current"], config.ApiKey)
				if err != nil {
					panic(err)
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						panic(err)
					}
				}
			},
		},
		{
			Name:      "login",
			ShortName: "l",
			Usage:     "Save exercism.io api credentials",
			Action: func(c *cli.Context) {
				usr, err := user.Current()
				if err != nil {
					panic(nil)
				}
				exercism.ConfigToFile(*usr, homeDir(), askForConfigInfo())
			},
		},
		{
			Name:      "logout",
			ShortName: "o",
			Usage:     "Clear exercism.io api credentials",
			Action: func(c *cli.Context) {
				exercism.Logout(homeDir())
			},
		},
		{
			Name:      "peek",
			ShortName: "p",
			Usage:     "Fetch upcoming assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["next"], config.ApiKey)
				if err != nil {
					panic(err)
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						panic(err)
					}
				}
			},
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     "Submit code to exercism.io on your current assignment",
			Action: func(c *cli.Context) {
				println("Not yet implemented")
			},
		},
		{
			Name:      "whoami",
			ShortName: "w",
			Usage:     "Get the github username that you are logged in as",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				fmt.Println(config.GithubUsername)
			},
		},
	}
	app.Run(os.Args)
}

func homeDir() string {
	user, err := user.Current()
	if err != nil {
		panic(err)
	}

	return user.HomeDir
}

func askForConfigInfo() (c exercism.Config) {
	var un, key, dir string

	currentDir, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	fmt.Print("Your GitHub username: ")
	_, err = fmt.Scanln(&un)
	if err != nil {
		panic(err)
	}

	fmt.Print("Your exercism.io API key: ")
	_, err = fmt.Scanln(&key)
	if err != nil {
		panic(err)
	}

	fmt.Println("What is your exercism exercises project path?")
	fmt.Printf("Press Enter to select the default (%s):\n", currentDir)
	fmt.Print("> ")
	_, err = fmt.Scanln(&dir)
	if err != nil && err.Error() != "unexpected newline" {
		panic(err)
	}

	if dir == "" {
		dir = currentDir
	}

	return exercism.Config{un, key, dir}
}
<commit_msg>No need to panic, just tell user about it.<commit_after>package main

import (
	"exercism"
	"fmt"
	"github.com/codegangsta/cli"
	"os"
	"os/user"
)

func main() {
	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Commands = []cli.Command{
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     "Fetch first assignment for each language from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["demo"], config.ApiKey)
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     "Fetch current assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["current"], config.ApiKey)
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "login",
			ShortName: "l",
			Usage:     "Save exercism.io api credentials",
			Action: func(c *cli.Context) {
				usr, err := user.Current()
				if err != nil {
					panic(nil)
				}
				exercism.ConfigToFile(*usr, homeDir(), askForConfigInfo())
			},
		},
		{
			Name:      "logout",
			ShortName: "o",
			Usage:     "Clear exercism.io api credentials",
			Action: func(c *cli.Context) {
				exercism.Logout(homeDir())
			},
		},
		{
			Name:      "peek",
			ShortName: "p",
			Usage:     "Fetch upcoming assignment from exercism.io",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}
				assignments, err := exercism.FetchAssignments("http://exercism.io",
					exercism.FetchEndpoints["next"], config.ApiKey)
				if err != nil {
					fmt.Println(err)
					return
				}

				for _, a := range assignments {
					err := exercism.SaveAssignment(config.ExercismDirectory, a)
					if err != nil {
						fmt.Println(err)
					}
				}
			},
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     "Submit code to exercism.io on your current assignment",
			Action: func(c *cli.Context) {
				println("Not yet implemented")
			},
		},
		{
			Name:      "whoami",
			ShortName: "w",
			Usage:     "Get the github username that you are logged in as",
			Action: func(c *cli.Context) {
				config, err := exercism.ConfigFromFile(homeDir())
				if err != nil {
					fmt.Println("Are you sure you are logged in? Please login again.")
					return
				}

				fmt.Println(config.GithubUsername)
			},
		},
	}
	app.Run(os.Args)
}

func homeDir() string {
	user, err := user.Current()
	if err != nil {
		panic(err)
	}

	return user.HomeDir
}

func askForConfigInfo() (c exercism.Config) {
	var un, key, dir string

	currentDir, err := os.Getwd()
	if err != nil {
		panic(err)
	}

	fmt.Print("Your GitHub username: ")
	_, err = fmt.Scanln(&un)
	if err != nil {
		panic(err)
	}

	fmt.Print("Your exercism.io API key: ")
	_, err = fmt.Scanln(&key)
	if err != nil {
		panic(err)
	}

	fmt.Println("What is your exercism exercises project path?")
	fmt.Printf("Press Enter to select the default (%s):\n", currentDir)
	fmt.Print("> ")
	_, err = fmt.Scanln(&dir)
	if err != nil && err.Error() != "unexpected newline" {
		panic(err)
	}

	if dir == "" {
		dir = currentDir
	}

	return exercism.Config{un, key, dir}
}
<|endoftext|>


<commit_before>// Copyright 2017 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

// +build sql

package apd

import (
	"database/sql"
	"flag"
	"testing"

	_ "github.com/lib/pq"
)

var (
	flagPostgres = flag.String("postgres", "postgres://postgres@localhost/apd?sslmode=disable", "Postgres connection string to an empty database")
)

// TestSQL tests the Scan and Value methods of Decimal.
func TestSQL(t *testing.T) {
	db, err := sql.Open("postgres", *flagPostgres)
	if err != nil {
		t.Fatal(err)
	}
	a, _, err := NewFromString("1234.567e5")
	if err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("drop table if exists d"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("create table d (v decimal)"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("insert into d values ($1)", a); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("update d set v = v + 1e5"); err != nil {
		t.Fatal(err)
	}
	var b, c, d Decimal
	var nd NullDecimal
	if err := db.QueryRow("select v, v::text, v::int, v::float, v from d").Scan(a, &b, &c, &d, &nd); err != nil {
		t.Fatal(err)
	}
	want, _, err := NewFromString("123556700")
	if err != nil {
		t.Fatal(err)
	}
	for i, v := range []*Decimal{a, &b, &c, &d, &nd.Decimal} {
		if v.Cmp(want) != 0 {
			t.Fatalf("%d: unexpected: %s, want: %s", i, v.String(), want.String())
		}
	}

	if _, err := db.Exec("update d set v = NULL"); err != nil {
		t.Fatal(err)
	}
	if err := db.QueryRow("select v from d").Scan(&nd); err != nil {
		t.Fatal(err)
	}
	if nd.Valid {
		t.Fatal("expected null")
	}
}
<commit_msg>apd: fix TestSQL<commit_after>// Copyright 2017 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.

//go:build sql
// +build sql

package apd

import (
	"database/sql"
	"flag"
	"testing"

	_ "github.com/lib/pq"
)

var (
	flagPostgres = flag.String("postgres", "postgres://postgres@localhost/apd?sslmode=disable", "Postgres connection string to an empty database")
)

// TestSQL tests the Scan and Value methods of Decimal.
func TestSQL(t *testing.T) {
	db, err := sql.Open("postgres", *flagPostgres)
	if err != nil {
		t.Fatal(err)
	}
	var a Decimal
	if _, _, err = a.SetString("1234.567e5"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("drop table if exists d"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("create table d (v decimal)"); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("insert into d values ($1)", a); err != nil {
		t.Fatal(err)
	}
	if _, err := db.Exec("update d set v = v + 1e5"); err != nil {
		t.Fatal(err)
	}
	var b, c, d Decimal
	var nd NullDecimal
	if err := db.QueryRow("select v, v::text, v::int, v::float, v from d").Scan(&a, &b, &c, &d, &nd); err != nil {
		t.Fatal(err)
	}
	want, _, err := NewFromString("123556700")
	if err != nil {
		t.Fatal(err)
	}
	for i, v := range []*Decimal{&a, &b, &c, &d, &nd.Decimal} {
		if v.Cmp(want) != 0 {
			t.Fatalf("%d: unexpected: %s, want: %s", i, v.String(), want.String())
		}
	}

	if _, err := db.Exec("update d set v = NULL"); err != nil {
		t.Fatal(err)
	}
	if err := db.QueryRow("select v from d").Scan(&nd); err != nil {
		t.Fatal(err)
	}
	if nd.Valid {
		t.Fatal("expected null")
	}
}
<|endoftext|>


<commit_before>// +build windows

package main

import (
	"log"
	"syscall"
	"unsafe"
)

type realRegistry struct{}

// do not reorder
var hKeyTable = []syscall.Handle{
	syscall.HKEY_CLASSES_ROOT,
	syscall.HKEY_CURRENT_USER,
	syscall.HKEY_LOCAL_MACHINE,
	syscall.HKEY_USERS,
	syscall.HKEY_PERFORMANCE_DATA,
	syscall.HKEY_CURRENT_CONFIG,
	syscall.HKEY_DYN_DATA,
}

// Writes a REG_QWORD (uint64) to the Windows registry.
func (realRegistry) SetQword(path regPath, valueName string, value uint64) error {
	handle := openKey(path, syscall.KEY_SET_VALUE)
	defer syscall.RegCloseKey(handle)

	return regSetValueEx(
		handle,
		syscall.StringToUTF16Ptr(valueName),
		0,
		syscall.REG_QWORD,
		(*byte)(unsafe.Pointer(&value)),
		8)
}

// Reads a REG_QWORD (uint64) from the Windows registry.
func (realRegistry) GetQword(path regPath, valueName string) (uint64, error) {
	handle := openKey(path, syscall.KEY_READ)
	defer syscall.RegCloseKey(handle)

	var value uint64
	n := uint32(8)
	var vtype uint32

	err := syscall.RegQueryValueEx(
		handle,
		syscall.StringToUTF16Ptr(valueName),
		nil,
		&vtype,
		(*byte)(unsafe.Pointer(&value)),
		&n)

	if err != nil {
		return 0, err
	}

	if vtype != syscall.REG_QWORD {
		log.Fatalln("Expected key of type REG_QWORD, but was", valueTypeName[vtype])
	}
	return value, nil
}

// Deletes a key value from the Windows registry.
func (realRegistry) DeleteValue(path regPath, valueName string) error {
	handle := openKey(path, syscall.KEY_WRITE)
	defer syscall.RegCloseKey(handle)

	return regDeleteValue(handle, syscall.StringToUTF16Ptr(valueName))
}

// Creates a key in the Windows registry.
func (realRegistry) CreateKey(path regPath) error {

	// handle is required by function call, but not used
	var handle syscall.Handle

	// 1 - newly created
	// 2 - already existing
	var d uint32

	return regCreateKeyEx(
		hKeyTable[path.hKeyIdx],
		syscall.StringToUTF16Ptr(path.lpSubKey),
		0,
		nil,
		0,
		syscall.KEY_CREATE_SUB_KEY,
		nil,
		&handle,
		&d)
}

// Deletes a key from the Windows registry.  All sub-keys must be
// deleted before deleting the key, or you will get `access denied`.
func (realRegistry) DeleteKey(path regPath) error {
	parent, child := splitPathSubkey(path)

	handle := openKey(parent, syscall.KEY_WRITE)
	defer syscall.RegCloseKey(handle)

	return regDeleteKey(handle, syscall.StringToUTF16Ptr(child))
}

// Enumerates the values for the specified registry key index. The function
// returns an array of valueNames.
func (realRegistry) EnumValues(path regPath) []string {
	var values []string
	name, err := getNextEnumValue(path, uint32(0))
	for i := 1; err == nil; i++ {
		values = append(values, name)
		name, err = getNextEnumValue(path, uint32(i))
	}
	return values
}

// Enumerates the values for the specified registry key. The function
// returns one indexed value name for the key each time it is called.
func getNextEnumValue(path regPath, index uint32) (string, error) {
	handle := openKey(path, syscall.KEY_READ)
	defer syscall.RegCloseKey(handle)

	var nameLen uint32 = 16383
	name := make([]uint16, nameLen)

	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
	err := regEnumValue(
		handle,
		index,
		&name[0],
		&nameLen,
		nil,
		nil,
		nil,
		nil)

	return syscall.UTF16ToString(name), err
}

// Opens a Windows registry key and returns a handle. You must close
// the handle with `defer syscall.RegCloseKey(handle)` in the calling code.
func openKey(path regPath, desiredAccess uint32) syscall.Handle {
	var handle syscall.Handle

	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724897(v=vs.85).aspx
	err := syscall.RegOpenKeyEx(
		hKeyTable[path.hKeyIdx],
		syscall.StringToUTF16Ptr(path.lpSubKey),
		0,
		desiredAccess,
		&handle)

	if err != nil {
		log.Fatalln("Cannot open registry path:", path)
	}
	return handle
}
<commit_msg>fix access rights<commit_after>// +build windows

package main

import (
	"log"
	"syscall"
	"unsafe"
)

type realRegistry struct{}

// do not reorder
var hKeyTable = []syscall.Handle{
	syscall.HKEY_CLASSES_ROOT,
	syscall.HKEY_CURRENT_USER,
	syscall.HKEY_LOCAL_MACHINE,
	syscall.HKEY_USERS,
	syscall.HKEY_PERFORMANCE_DATA,
	syscall.HKEY_CURRENT_CONFIG,
	syscall.HKEY_DYN_DATA,
}

// Writes a REG_QWORD (uint64) to the Windows registry.
func (realRegistry) SetQword(path regPath, valueName string, value uint64) error {
	handle := openKey(path, syscall.KEY_SET_VALUE)
	defer syscall.RegCloseKey(handle)

	return regSetValueEx(
		handle,
		syscall.StringToUTF16Ptr(valueName),
		0,
		syscall.REG_QWORD,
		(*byte)(unsafe.Pointer(&value)),
		8)
}

// Reads a REG_QWORD (uint64) from the Windows registry.
func (realRegistry) GetQword(path regPath, valueName string) (uint64, error) {
	handle := openKey(path, syscall.KEY_QUERY_VALUE)
	defer syscall.RegCloseKey(handle)

	var value uint64
	n := uint32(8)
	var vtype uint32

	err := syscall.RegQueryValueEx(
		handle,
		syscall.StringToUTF16Ptr(valueName),
		nil,
		&vtype,
		(*byte)(unsafe.Pointer(&value)),
		&n)

	if err != nil {
		return 0, err
	}

	if vtype != syscall.REG_QWORD {
		log.Fatalln("Expected key of type REG_QWORD, but was", valueTypeName[vtype])
	}
	return value, nil
}

// Deletes a key value from the Windows registry.
func (realRegistry) DeleteValue(path regPath, valueName string) error {
	handle := openKey(path, syscall.KEY_SET_VALUE)
	defer syscall.RegCloseKey(handle)

	return regDeleteValue(handle, syscall.StringToUTF16Ptr(valueName))
}

// Creates a key in the Windows registry.
func (realRegistry) CreateKey(path regPath) error {

	// handle is required by function call, but not used
	var handle syscall.Handle

	// 1 - newly created
	// 2 - already existing
	var d uint32

	return regCreateKeyEx(
		hKeyTable[path.hKeyIdx],
		syscall.StringToUTF16Ptr(path.lpSubKey),
		0,
		nil,
		0,
		syscall.KEY_CREATE_SUB_KEY,
		nil,
		&handle,
		&d)
}

// Deletes a key from the Windows registry.  All sub-keys must be
// deleted before deleting the key, or you will get `access denied`.
func (realRegistry) DeleteKey(path regPath) error {
	parent, child := splitPathSubkey(path)

	handle := openKey(parent, syscall.KEY_WRITE)
	defer syscall.RegCloseKey(handle)

	return regDeleteKey(handle, syscall.StringToUTF16Ptr(child))
}

// Enumerates the values for the specified registry key index. The function
// returns an array of valueNames.
func (realRegistry) EnumValues(path regPath) []string {
	var values []string
	name, err := getNextEnumValue(path, uint32(0))
	for i := 1; err == nil; i++ {
		values = append(values, name)
		name, err = getNextEnumValue(path, uint32(i))
	}
	return values
}

// Enumerates the values for the specified registry key. The function
// returns one indexed value name for the key each time it is called.
func getNextEnumValue(path regPath, index uint32) (string, error) {
	handle := openKey(path, syscall.KEY_QUERY_VALUE)
	defer syscall.RegCloseKey(handle)

	var nameLen uint32 = 16383
	name := make([]uint16, nameLen)

	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx
	err := regEnumValue(
		handle,
		index,
		&name[0],
		&nameLen,
		nil,
		nil,
		nil,
		nil)

	return syscall.UTF16ToString(name), err
}

// Opens a Windows registry key and returns a handle. You must close
// the handle with `defer syscall.RegCloseKey(handle)` in the calling code.
func openKey(path regPath, desiredAccess uint32) syscall.Handle {
	var handle syscall.Handle

	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724897(v=vs.85).aspx
	err := syscall.RegOpenKeyEx(
		hKeyTable[path.hKeyIdx],
		syscall.StringToUTF16Ptr(path.lpSubKey),
		0,
		desiredAccess,
		&handle)

	if err != nil {
		log.Fatalln("Cannot open registry path:", path)
	}
	return handle
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/bmizerany/mc"
	"github.com/elazarl/goproxy"
	"github.com/jackc/pgx"
	"github.com/pquerna/ffjson/ffjson"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

func checkError(err error) {
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
}

func UrlHasPrefix(prefix string) goproxy.ReqConditionFunc {
	return func(req *http.Request, ctx *goproxy.ProxyCtx) bool {
		return req.Method == http.MethodGet && strings.HasPrefix(req.URL.Path, prefix)
	}
}

func PathIs(path string) goproxy.ReqConditionFunc {
	return func(req *http.Request, ctx *goproxy.ProxyCtx) bool {
		return req.Method == http.MethodGet && req.URL.Path == path
	}
}

var pool *pgx.ConnPool

func afterConnect(conn *pgx.Conn) (err error) {
	_, err = conn.Prepare("getPackage", `
		SELECT name, url FROM packages WHERE name = $1
  `)
	if err != nil {
		return
	}

	return
}

func main() {
	var err error

	memcached_url := os.Getenv("MEMCACHEDCLOUD_SERVERS")
	memcached_username := os.Getenv("MEMCACHEDCLOUD_USERNAME")
	memcached_password := os.Getenv("MEMCACHEDCLOUD_PASSWORD")

	if memcached_url == "" {
		memcached_url = "localhost:11211"
	}

	cn, err := mc.Dial("tcp", memcached_url)
	if err != nil {
		log.Fatalf("Memcached connection error: %s", err)
	}

	if memcached_url != "" && memcached_password != "" {
		err = cn.Auth(memcached_username, memcached_password)
		if err != nil {
			log.Fatalf("Memcached auth error: %s", err)
		}
	}

	pgxcfg, err := pgx.ParseURI(os.Getenv("DATABASE_URL"))
	if err != nil {
		log.Fatalf("Parse URI error: %s", err)
	}
	pool, err = pgx.NewConnPool(pgx.ConnPoolConfig{
		ConnConfig:     pgxcfg,
		MaxConnections: 10,
		AfterConnect:   afterConnect,
	})
	if err != nil {
		log.Fatalf("Connection error: %s", err)
	}
	defer pool.Close()

	port := os.Getenv("PORT")

	if port == "" {
		port = "3000"
	}

	binary, err := exec.LookPath("node")
	checkError(err)
	cmd := exec.Command(binary, "--expose_gc", "index.js")
	env := os.Environ()
	env = append([]string{"PORT=3001"}, env...)
	cmd.Env = env
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	checkError(err)
	defer func() {
		err = cmd.Wait()
		checkError(err)
	}()

	proxy := goproxy.NewProxyHttpServer()
	proxy.Verbose = true

	proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		req.Host = "bower.herokuapp.com"
		req.URL.Scheme = "http"
		req.URL.Host = "localhost:3001"
		proxy.ServeHTTP(w, req)
	})

	proxy.OnRequest(PathIs("/packages")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			var val string

			val, _, _, err = cn.Get("packages")

			switch err {
			case nil:
				fmt.Println("MEMCACHED FROM GO SERVER")
				return r, goproxy.NewResponse(r, "application/json", http.StatusOK, val)
			default:
				return r, nil
			}

			return r, nil
		})

	proxy.OnRequest(UrlHasPrefix("/packages/")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			var name string
			var url string
			elements := strings.Split(r.URL.Path, "/")
			packageName := elements[len(elements)-1]
			err := pool.QueryRow("getPackage", packageName).Scan(&name, &url)
			switch err {
			case nil:
				result := map[string]string{"name": name, "url": url}
				resultByteArray, _ := ffjson.Marshal(result)
				return r, goproxy.NewResponse(r, "application/json", http.StatusOK, string(resultByteArray))
			case pgx.ErrNoRows:
				return r, goproxy.NewResponse(r, "text/html", http.StatusNotFound, "Package not found")
			default:
				return r, goproxy.NewResponse(r, "text/html", http.StatusInternalServerError, "Internal server error")
			}
		})

	fmt.Println("Starting web server at port", port)

	log.Fatal(http.ListenAndServe(":"+port, proxy))
}
<commit_msg>Less verbosity<commit_after>package main

import (
	"fmt"
	"github.com/bmizerany/mc"
	"github.com/elazarl/goproxy"
	"github.com/jackc/pgx"
	"github.com/pquerna/ffjson/ffjson"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

func checkError(err error) {
	if err != nil {
		log.Fatalf("Error: %s", err)
	}
}

func UrlHasPrefix(prefix string) goproxy.ReqConditionFunc {
	return func(req *http.Request, ctx *goproxy.ProxyCtx) bool {
		return req.Method == http.MethodGet && strings.HasPrefix(req.URL.Path, prefix)
	}
}

func PathIs(path string) goproxy.ReqConditionFunc {
	return func(req *http.Request, ctx *goproxy.ProxyCtx) bool {
		return req.Method == http.MethodGet && req.URL.Path == path
	}
}

var pool *pgx.ConnPool

func afterConnect(conn *pgx.Conn) (err error) {
	_, err = conn.Prepare("getPackage", `
		SELECT name, url FROM packages WHERE name = $1
  `)
	if err != nil {
		return
	}

	return
}

func main() {
	var err error

	memcached_url := os.Getenv("MEMCACHEDCLOUD_SERVERS")
	memcached_username := os.Getenv("MEMCACHEDCLOUD_USERNAME")
	memcached_password := os.Getenv("MEMCACHEDCLOUD_PASSWORD")

	if memcached_url == "" {
		memcached_url = "localhost:11211"
	}

	cn, err := mc.Dial("tcp", memcached_url)
	if err != nil {
		log.Fatalf("Memcached connection error: %s", err)
	}

	if memcached_url != "" && memcached_password != "" {
		err = cn.Auth(memcached_username, memcached_password)
		if err != nil {
			log.Fatalf("Memcached auth error: %s", err)
		}
	}

	pgxcfg, err := pgx.ParseURI(os.Getenv("DATABASE_URL"))
	if err != nil {
		log.Fatalf("Parse URI error: %s", err)
	}
	pool, err = pgx.NewConnPool(pgx.ConnPoolConfig{
		ConnConfig:     pgxcfg,
		MaxConnections: 10,
		AfterConnect:   afterConnect,
	})
	if err != nil {
		log.Fatalf("Connection error: %s", err)
	}
	defer pool.Close()

	port := os.Getenv("PORT")

	if port == "" {
		port = "3000"
	}

	binary, err := exec.LookPath("node")
	checkError(err)
	cmd := exec.Command(binary, "--expose_gc", "index.js")
	env := os.Environ()
	env = append([]string{"PORT=3001"}, env...)
	cmd.Env = env
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err = cmd.Start()
	checkError(err)
	defer func() {
		err = cmd.Wait()
		checkError(err)
	}()

	proxy := goproxy.NewProxyHttpServer()

	proxy.Verbose = false

	proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		req.Host = "bower.herokuapp.com"
		req.URL.Scheme = "http"
		req.URL.Host = "localhost:3001"
		proxy.ServeHTTP(w, req)
	})

	proxy.OnRequest(PathIs("/packages")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			var val string

			val, _, _, err = cn.Get("packages")

			switch err {
			case nil:
				fmt.Println("MEMCACHED FROM GO SERVER")
				return r, goproxy.NewResponse(r, "application/json", http.StatusOK, val)
			default:
				return r, nil
			}

			return r, nil
		})

	proxy.OnRequest(UrlHasPrefix("/packages/")).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			var name string
			var url string
			elements := strings.Split(r.URL.Path, "/")
			packageName := elements[len(elements)-1]
			err := pool.QueryRow("getPackage", packageName).Scan(&name, &url)
			switch err {
			case nil:
				result := map[string]string{"name": name, "url": url}
				resultByteArray, _ := ffjson.Marshal(result)
				return r, goproxy.NewResponse(r, "application/json", http.StatusOK, string(resultByteArray))
			case pgx.ErrNoRows:
				return r, goproxy.NewResponse(r, "text/html", http.StatusNotFound, "Package not found")
			default:
				return r, goproxy.NewResponse(r, "text/html", http.StatusInternalServerError, "Internal server error")
			}
		})

	fmt.Println("Starting web server at port", port)

	log.Fatal(http.ListenAndServe(":"+port, proxy))
}
<|endoftext|>


<commit_before>// Copyright 2019 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.

// Package attrrange simplifies tracking of attributes that apply to a range of
// items.
// Refer to the examples if the test file for details on usage.
package attrrange

import (
	"fmt"
	"sort"
)

// AttrRange is a range of items that share the same attributes.
type AttrRange struct {
	// Low is the first position where these attributes apply.
	Low int

	// High is the end of the range. The attributes apply to all items in range
	// Low <= b < high.
	High int

	// AttrIdx is the index of the attributes that apply to this range.
	AttrIdx int
}

// newAttrRange returns a new AttrRange instance.
func newAttrRange(low, high, attrIdx int) *AttrRange {
	return &AttrRange{
		Low:     low,
		High:    high,
		AttrIdx: attrIdx,
	}
}

// Tracker tracks attributes that apply to a range of items.
// This object is not thread safe.
type Tracker struct {
	// ranges maps low indices of ranges to the attribute ranges.
	ranges map[int]*AttrRange
}

// NewTracker returns a new tracker of ranges that share the same attributes.
func NewTracker() *Tracker {
	return &Tracker{
		ranges: map[int]*AttrRange{},
	}
}

// Add adds a new range of items that share attributes with the specified
// index.
// The low position of the range must not overlap with low position of any
// existing range.
func (t *Tracker) Add(low, high, attrIdx int) error {
	ar := newAttrRange(low, high, attrIdx)
	if ar, ok := t.ranges[low]; ok {
		return fmt.Errorf("already have range starting on low:%d, existing:%+v", low, ar)
	}
	t.ranges[low] = ar
	return nil
}

// ForPosition returns attribute index that apply to the specified position.
// Returns ErrNotFound when the requested position wasn't found in any of the
// known ranges.
func (t *Tracker) ForPosition(pos int) (*AttrRange, error) {
	if ar, ok := t.ranges[pos]; ok {
		return ar, nil
	}

	var keys []int
	for k := range t.ranges {
		keys = append(keys, k)
	}
	sort.Ints(keys)

	var res *AttrRange
	for _, k := range keys {
		ar := t.ranges[k]
		if ar.Low > pos {
			break
		}
		if ar.High > pos {
			res = ar
		}
	}

	if res == nil {
		return nil, fmt.Errorf("did not find attribute range for position %d", pos)
	}
	return res, nil
}
<commit_msg>Typo in a comment<commit_after>// Copyright 2019 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.

// Package attrrange simplifies tracking of attributes that apply to a range of
// items.
// Refer to the examples in the test file for details on usage.
package attrrange

import (
	"fmt"
	"sort"
)

// AttrRange is a range of items that share the same attributes.
type AttrRange struct {
	// Low is the first position where these attributes apply.
	Low int

	// High is the end of the range. The attributes apply to all items in range
	// Low <= b < high.
	High int

	// AttrIdx is the index of the attributes that apply to this range.
	AttrIdx int
}

// newAttrRange returns a new AttrRange instance.
func newAttrRange(low, high, attrIdx int) *AttrRange {
	return &AttrRange{
		Low:     low,
		High:    high,
		AttrIdx: attrIdx,
	}
}

// Tracker tracks attributes that apply to a range of items.
// This object is not thread safe.
type Tracker struct {
	// ranges maps low indices of ranges to the attribute ranges.
	ranges map[int]*AttrRange
}

// NewTracker returns a new tracker of ranges that share the same attributes.
func NewTracker() *Tracker {
	return &Tracker{
		ranges: map[int]*AttrRange{},
	}
}

// Add adds a new range of items that share attributes with the specified
// index.
// The low position of the range must not overlap with low position of any
// existing range.
func (t *Tracker) Add(low, high, attrIdx int) error {
	ar := newAttrRange(low, high, attrIdx)
	if ar, ok := t.ranges[low]; ok {
		return fmt.Errorf("already have range starting on low:%d, existing:%+v", low, ar)
	}
	t.ranges[low] = ar
	return nil
}

// ForPosition returns attribute index that apply to the specified position.
// Returns ErrNotFound when the requested position wasn't found in any of the
// known ranges.
func (t *Tracker) ForPosition(pos int) (*AttrRange, error) {
	if ar, ok := t.ranges[pos]; ok {
		return ar, nil
	}

	var keys []int
	for k := range t.ranges {
		keys = append(keys, k)
	}
	sort.Ints(keys)

	var res *AttrRange
	for _, k := range keys {
		ar := t.ranges[k]
		if ar.Low > pos {
			break
		}
		if ar.High > pos {
			res = ar
		}
	}

	if res == nil {
		return nil, fmt.Errorf("did not find attribute range for position %d", pos)
	}
	return res, nil
}
<|endoftext|>


<commit_before>package audit

import (
	"encoding/json"
	"errors"
	"reflect"
	"time"

	"github.com/hashicorp/vault/sdk/helper/salt"
	"github.com/hashicorp/vault/sdk/helper/strutil"
	"github.com/hashicorp/vault/sdk/helper/wrapping"
	"github.com/hashicorp/vault/sdk/logical"
	"github.com/mitchellh/copystructure"
	"github.com/mitchellh/reflectwalk"
)

// HashString hashes the given opaque string and returns it
func HashString(salter *salt.Salt, data string) string {
	return salter.GetIdentifiedHMAC(data)
}

// HashAuth returns a hashed copy of the logical.Auth input.
func HashAuth(salter *salt.Salt, in *logical.Auth, HMACAccessor bool) (*logical.Auth, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	auth := *in

	if auth.ClientToken != "" {
		auth.ClientToken = fn(auth.ClientToken)
	}
	if HMACAccessor && auth.Accessor != "" {
		auth.Accessor = fn(auth.Accessor)
	}
	return &auth, nil
}

// HashRequest returns a hashed copy of the logical.Request input.
func HashRequest(salter *salt.Salt, in *logical.Request, HMACAccessor bool, nonHMACDataKeys []string) (*logical.Request, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	req := *in

	if req.Auth != nil {
		cp, err := copystructure.Copy(req.Auth)
		if err != nil {
			return nil, err
		}

		req.Auth, err = HashAuth(salter, cp.(*logical.Auth), HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	if req.ClientToken != "" {
		req.ClientToken = fn(req.ClientToken)
	}
	if HMACAccessor && req.ClientTokenAccessor != "" {
		req.ClientTokenAccessor = fn(req.ClientTokenAccessor)
	}

	data, err := hashMap(fn, req.Data, nonHMACDataKeys)
	if err != nil {
		return nil, err
	}

	req.Data = data
	return &req, nil
}

func hashMap(fn func(string) string, data map[string]interface{}, nonHMACDataKeys []string) (map[string]interface{}, error) {
	if data == nil {
		return nil, nil
	}

	copy, err := copystructure.Copy(data)
	if err != nil {
		return nil, err
	}
	newData := copy.(map[string]interface{})
	for k, v := range newData {
		if o, ok := v.(logical.OptMarshaler); ok {
			marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
				ValueHasher: fn,
			})
			if err != nil {
				return nil, err
			}
			newData[k] = json.RawMessage(marshaled)
		}
	}

	if err := HashStructure(newData, fn, nonHMACDataKeys); err != nil {
		return nil, err
	}

	return newData, nil
}

// HashResponse returns a hashed copy of the logical.Request input.
func HashResponse(salter *salt.Salt, in *logical.Response, HMACAccessor bool, nonHMACDataKeys []string) (*logical.Response, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	resp := *in

	if resp.Auth != nil {
		cp, err := copystructure.Copy(resp.Auth)
		if err != nil {
			return nil, err
		}

		resp.Auth, err = HashAuth(salter, cp.(*logical.Auth), HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	data, err := hashMap(fn, resp.Data, nonHMACDataKeys)
	if err != nil {
		return nil, err
	}
	resp.Data = data

	if resp.WrapInfo != nil {
		var err error
		resp.WrapInfo, err = HashWrapInfo(salter, resp.WrapInfo, HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	return &resp, nil
}

// HashWrapInfo returns a hashed copy of the wrapping.ResponseWrapInfo input.
func HashWrapInfo(salter *salt.Salt, in *wrapping.ResponseWrapInfo, HMACAccessor bool) (*wrapping.ResponseWrapInfo, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	wrapinfo := *in

	wrapinfo.Token = fn(wrapinfo.Token)

	if HMACAccessor {
		wrapinfo.Accessor = fn(wrapinfo.Accessor)

		if wrapinfo.WrappedAccessor != "" {
			wrapinfo.WrappedAccessor = fn(wrapinfo.WrappedAccessor)
		}
	}

	return &wrapinfo, nil
}

// HashStructure takes an interface and hashes all the values within
// the structure. Only _values_ are hashed: keys of objects are not.
//
// For the HashCallback, see the built-in HashCallbacks below.
func HashStructure(s interface{}, cb HashCallback, ignoredKeys []string) error {
	walker := &hashWalker{Callback: cb, IgnoredKeys: ignoredKeys}
	return reflectwalk.Walk(s, walker)
}

// HashCallback is the callback called for HashStructure to hash
// a value.
type HashCallback func(string) string

// hashWalker implements interfaces for the reflectwalk package
// (github.com/mitchellh/reflectwalk) that can be used to automatically
// replace primitives with a hashed value.
type hashWalker struct {
	// Callback is the function to call with the primitive that is
	// to be hashed. If there is an error, walking will be halted
	// immediately and the error returned.
	Callback HashCallback
	// IgnoreKeys are the keys that wont have the HashCallback applied
	IgnoredKeys []string
	// MapElem appends the key itself (not the reflect.Value) to key.
	// The last element in key is the most recently entered map key.
	// Since Exit pops the last element of key, only nesting to another
	// structure increases the size of this slice.
	key       []string
	lastValue reflect.Value
	// Enter appends to loc and exit pops loc. The last element of loc is thus
	// the current location.
	loc []reflectwalk.Location
	// Map and Slice append to cs, Exit pops the last element off cs.
	// The last element in cs is the most recently entered map or slice.
	cs []reflect.Value
	// MapElem and SliceElem append to csKey. The last element in csKey is the
	// most recently entered map key or slice index. Since Exit pops the last
	// element of csKey, only nesting to another structure increases the size of
	// this slice.
	csKey []reflect.Value
}

// hashTimeType stores a pre-computed reflect.Type for a time.Time so
// we can quickly compare in hashWalker.Struct. We create an empty/invalid
// time.Time{} so we don't need to incur any additional startup cost vs.
// Now() or Unix().
var hashTimeType = reflect.TypeOf(time.Time{})

func (w *hashWalker) Enter(loc reflectwalk.Location) error {
	w.loc = append(w.loc, loc)
	return nil
}

func (w *hashWalker) Exit(loc reflectwalk.Location) error {
	w.loc = w.loc[:len(w.loc)-1]

	switch loc {
	case reflectwalk.Map:
		w.cs = w.cs[:len(w.cs)-1]
	case reflectwalk.MapValue:
		w.key = w.key[:len(w.key)-1]
		w.csKey = w.csKey[:len(w.csKey)-1]
	case reflectwalk.Slice:
		w.cs = w.cs[:len(w.cs)-1]
	case reflectwalk.SliceElem:
		w.csKey = w.csKey[:len(w.csKey)-1]
	}

	return nil
}

func (w *hashWalker) Map(m reflect.Value) error {
	w.cs = append(w.cs, m)
	return nil
}

func (w *hashWalker) MapElem(m, k, v reflect.Value) error {
	w.csKey = append(w.csKey, k)
	w.key = append(w.key, k.String())
	w.lastValue = v
	return nil
}

func (w *hashWalker) Slice(s reflect.Value) error {
	w.cs = append(w.cs, s)
	return nil
}

func (w *hashWalker) SliceElem(i int, elem reflect.Value) error {
	w.csKey = append(w.csKey, reflect.ValueOf(i))
	return nil
}

func (w *hashWalker) Struct(v reflect.Value) error {
	// We are looking for time values. If it isn't one, ignore it.
	if v.Type() != hashTimeType {
		return nil
	}

	if len(w.loc) < 3 {
		// The last element of w.loc is reflectwalk.Struct, by definition.
		// If len(w.loc) < 3 that means hashWalker.Walk was given a struct
		// value and this is the very first step in the walk, and we don't
		// currently support structs as inputs,
		return errors.New("structs as direct inputs not supported")
	}

	// Second to last element of w.loc is location that contains this struct.
	switch w.loc[len(w.loc)-2] {
	case reflectwalk.MapValue:
		// Create a string value of the time. IMPORTANT: this must never change
		// across Vault versions or the hash value of equivalent time.Time will
		// change.
		strVal := v.Interface().(time.Time).Format(time.RFC3339Nano)

		// Set the map value to the string instead of the time.Time object
		m := w.cs[len(w.cs)-1]
		mk := w.csKey[len(w.cs)-1]
		m.SetMapIndex(mk, reflect.ValueOf(strVal))
	case reflectwalk.SliceElem:
		// Create a string value of the time. IMPORTANT: this must never change
		// across Vault versions or the hash value of equivalent time.Time will
		// change.
		strVal := v.Interface().(time.Time).Format(time.RFC3339Nano)

		// Set the map value to the string instead of the time.Time object
		s := w.cs[len(w.cs)-1]
		si := int(w.csKey[len(w.cs)-1].Int())
		s.Slice(si, si+1).Index(0).Set(reflect.ValueOf(strVal))
	}

	// Skip this entry so that we don't walk the struct.
	return reflectwalk.SkipEntry
}

func (w *hashWalker) StructField(reflect.StructField, reflect.Value) error {
	return nil
}

// Primitive calls Callback to transform strings in-place, except for map keys.
// Strings hiding within interfaces are also transformed.
func (w *hashWalker) Primitive(v reflect.Value) error {
	if w.Callback == nil {
		return nil
	}

	// We don't touch map keys
	if w.loc[len(w.loc)-1] == reflectwalk.MapKey {
		return nil
	}

	setV := v

	// We only care about strings
	if v.Kind() == reflect.Interface {
		v = v.Elem()
	}
	if v.Kind() != reflect.String {
		return nil
	}

	// See if the current key is part of the ignored keys
	currentKey := w.key[len(w.key)-1]
	if strutil.StrListContains(w.IgnoredKeys, currentKey) {
		return nil
	}

	replaceVal := w.Callback(v.String())

	resultVal := reflect.ValueOf(replaceVal)
	switch w.loc[len(w.loc)-1] {
	case reflectwalk.MapValue:
		// If we're in a map, then the only way to set a map value is
		// to set it directly.
		m := w.cs[len(w.cs)-1]
		mk := w.csKey[len(w.cs)-1]
		m.SetMapIndex(mk, resultVal)
	case reflectwalk.SliceElem:
		s := w.cs[len(w.cs)-1]
		si := int(w.csKey[len(w.cs)-1].Int())
		s.Slice(si, si+1).Index(0).Set(resultVal)
	default:
		// Otherwise, we should be addressable
		setV.Set(resultVal)
	}

	return nil
}
<commit_msg>Ensure that http_raw_body is always passed to the audit redaction system as a string <commit_after>package audit

import (
	"encoding/json"
	"errors"
	"reflect"
	"time"

	"github.com/hashicorp/vault/sdk/helper/salt"
	"github.com/hashicorp/vault/sdk/helper/strutil"
	"github.com/hashicorp/vault/sdk/helper/wrapping"
	"github.com/hashicorp/vault/sdk/logical"
	"github.com/mitchellh/copystructure"
	"github.com/mitchellh/reflectwalk"
)

// HashString hashes the given opaque string and returns it
func HashString(salter *salt.Salt, data string) string {
	return salter.GetIdentifiedHMAC(data)
}

// HashAuth returns a hashed copy of the logical.Auth input.
func HashAuth(salter *salt.Salt, in *logical.Auth, HMACAccessor bool) (*logical.Auth, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	auth := *in

	if auth.ClientToken != "" {
		auth.ClientToken = fn(auth.ClientToken)
	}
	if HMACAccessor && auth.Accessor != "" {
		auth.Accessor = fn(auth.Accessor)
	}
	return &auth, nil
}

// HashRequest returns a hashed copy of the logical.Request input.
func HashRequest(salter *salt.Salt, in *logical.Request, HMACAccessor bool, nonHMACDataKeys []string) (*logical.Request, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	req := *in

	if req.Auth != nil {
		cp, err := copystructure.Copy(req.Auth)
		if err != nil {
			return nil, err
		}

		req.Auth, err = HashAuth(salter, cp.(*logical.Auth), HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	if req.ClientToken != "" {
		req.ClientToken = fn(req.ClientToken)
	}
	if HMACAccessor && req.ClientTokenAccessor != "" {
		req.ClientTokenAccessor = fn(req.ClientTokenAccessor)
	}

	if req.Data != nil {
		copy, err := copystructure.Copy(req.Data)
		if err != nil {
			return nil, err
		}

		err = hashMap(fn, copy.(map[string]interface{}), nonHMACDataKeys)
		if err != nil {
			return nil, err
		}
		req.Data = copy.(map[string]interface{})
	}

	return &req, nil
}

func hashMap(fn func(string) string, data map[string]interface{}, nonHMACDataKeys []string) error {
	for k, v := range data {
		if o, ok := v.(logical.OptMarshaler); ok {
			marshaled, err := o.MarshalJSONWithOptions(&logical.MarshalOptions{
				ValueHasher: fn,
			})
			if err != nil {
				return err
			}
			data[k] = json.RawMessage(marshaled)
		}
	}

	return HashStructure(data, fn, nonHMACDataKeys)
}

// HashResponse returns a hashed copy of the logical.Request input.
func HashResponse(salter *salt.Salt, in *logical.Response, HMACAccessor bool, nonHMACDataKeys []string) (*logical.Response, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	resp := *in

	if resp.Auth != nil {
		cp, err := copystructure.Copy(resp.Auth)
		if err != nil {
			return nil, err
		}

		resp.Auth, err = HashAuth(salter, cp.(*logical.Auth), HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	if resp.Data != nil {
		copy, err := copystructure.Copy(resp.Data)
		if err != nil {
			return nil, err
		}

		mapCopy := copy.(map[string]interface{})
		if b, ok := mapCopy[logical.HTTPRawBody].([]byte); ok {
			mapCopy[logical.HTTPRawBody] = string(b)
		}

		err = hashMap(fn, mapCopy, nonHMACDataKeys)
		if err != nil {
			return nil, err
		}
		resp.Data = mapCopy
	}
	if resp.WrapInfo != nil {
		var err error
		resp.WrapInfo, err = HashWrapInfo(salter, resp.WrapInfo, HMACAccessor)
		if err != nil {
			return nil, err
		}
	}

	return &resp, nil
}

// HashWrapInfo returns a hashed copy of the wrapping.ResponseWrapInfo input.
func HashWrapInfo(salter *salt.Salt, in *wrapping.ResponseWrapInfo, HMACAccessor bool) (*wrapping.ResponseWrapInfo, error) {
	if in == nil {
		return nil, nil
	}

	fn := salter.GetIdentifiedHMAC
	wrapinfo := *in

	wrapinfo.Token = fn(wrapinfo.Token)

	if HMACAccessor {
		wrapinfo.Accessor = fn(wrapinfo.Accessor)

		if wrapinfo.WrappedAccessor != "" {
			wrapinfo.WrappedAccessor = fn(wrapinfo.WrappedAccessor)
		}
	}

	return &wrapinfo, nil
}

// HashStructure takes an interface and hashes all the values within
// the structure. Only _values_ are hashed: keys of objects are not.
//
// For the HashCallback, see the built-in HashCallbacks below.
func HashStructure(s interface{}, cb HashCallback, ignoredKeys []string) error {
	walker := &hashWalker{Callback: cb, IgnoredKeys: ignoredKeys}
	return reflectwalk.Walk(s, walker)
}

// HashCallback is the callback called for HashStructure to hash
// a value.
type HashCallback func(string) string

// hashWalker implements interfaces for the reflectwalk package
// (github.com/mitchellh/reflectwalk) that can be used to automatically
// replace primitives with a hashed value.
type hashWalker struct {
	// Callback is the function to call with the primitive that is
	// to be hashed. If there is an error, walking will be halted
	// immediately and the error returned.
	Callback HashCallback
	// IgnoreKeys are the keys that wont have the HashCallback applied
	IgnoredKeys []string
	// MapElem appends the key itself (not the reflect.Value) to key.
	// The last element in key is the most recently entered map key.
	// Since Exit pops the last element of key, only nesting to another
	// structure increases the size of this slice.
	key       []string
	lastValue reflect.Value
	// Enter appends to loc and exit pops loc. The last element of loc is thus
	// the current location.
	loc []reflectwalk.Location
	// Map and Slice append to cs, Exit pops the last element off cs.
	// The last element in cs is the most recently entered map or slice.
	cs []reflect.Value
	// MapElem and SliceElem append to csKey. The last element in csKey is the
	// most recently entered map key or slice index. Since Exit pops the last
	// element of csKey, only nesting to another structure increases the size of
	// this slice.
	csKey []reflect.Value
}

// hashTimeType stores a pre-computed reflect.Type for a time.Time so
// we can quickly compare in hashWalker.Struct. We create an empty/invalid
// time.Time{} so we don't need to incur any additional startup cost vs.
// Now() or Unix().
var hashTimeType = reflect.TypeOf(time.Time{})

func (w *hashWalker) Enter(loc reflectwalk.Location) error {
	w.loc = append(w.loc, loc)
	return nil
}

func (w *hashWalker) Exit(loc reflectwalk.Location) error {
	w.loc = w.loc[:len(w.loc)-1]

	switch loc {
	case reflectwalk.Map:
		w.cs = w.cs[:len(w.cs)-1]
	case reflectwalk.MapValue:
		w.key = w.key[:len(w.key)-1]
		w.csKey = w.csKey[:len(w.csKey)-1]
	case reflectwalk.Slice:
		w.cs = w.cs[:len(w.cs)-1]
	case reflectwalk.SliceElem:
		w.csKey = w.csKey[:len(w.csKey)-1]
	}

	return nil
}

func (w *hashWalker) Map(m reflect.Value) error {
	w.cs = append(w.cs, m)
	return nil
}

func (w *hashWalker) MapElem(m, k, v reflect.Value) error {
	w.csKey = append(w.csKey, k)
	w.key = append(w.key, k.String())
	w.lastValue = v
	return nil
}

func (w *hashWalker) Slice(s reflect.Value) error {
	w.cs = append(w.cs, s)
	return nil
}

func (w *hashWalker) SliceElem(i int, elem reflect.Value) error {
	w.csKey = append(w.csKey, reflect.ValueOf(i))
	return nil
}

func (w *hashWalker) Struct(v reflect.Value) error {
	// We are looking for time values. If it isn't one, ignore it.
	if v.Type() != hashTimeType {
		return nil
	}

	if len(w.loc) < 3 {
		// The last element of w.loc is reflectwalk.Struct, by definition.
		// If len(w.loc) < 3 that means hashWalker.Walk was given a struct
		// value and this is the very first step in the walk, and we don't
		// currently support structs as inputs,
		return errors.New("structs as direct inputs not supported")
	}

	// Second to last element of w.loc is location that contains this struct.
	switch w.loc[len(w.loc)-2] {
	case reflectwalk.MapValue:
		// Create a string value of the time. IMPORTANT: this must never change
		// across Vault versions or the hash value of equivalent time.Time will
		// change.
		strVal := v.Interface().(time.Time).Format(time.RFC3339Nano)

		// Set the map value to the string instead of the time.Time object
		m := w.cs[len(w.cs)-1]
		mk := w.csKey[len(w.cs)-1]
		m.SetMapIndex(mk, reflect.ValueOf(strVal))
	case reflectwalk.SliceElem:
		// Create a string value of the time. IMPORTANT: this must never change
		// across Vault versions or the hash value of equivalent time.Time will
		// change.
		strVal := v.Interface().(time.Time).Format(time.RFC3339Nano)

		// Set the map value to the string instead of the time.Time object
		s := w.cs[len(w.cs)-1]
		si := int(w.csKey[len(w.cs)-1].Int())
		s.Slice(si, si+1).Index(0).Set(reflect.ValueOf(strVal))
	}

	// Skip this entry so that we don't walk the struct.
	return reflectwalk.SkipEntry
}

func (w *hashWalker) StructField(reflect.StructField, reflect.Value) error {
	return nil
}

// Primitive calls Callback to transform strings in-place, except for map keys.
// Strings hiding within interfaces are also transformed.
func (w *hashWalker) Primitive(v reflect.Value) error {
	if w.Callback == nil {
		return nil
	}

	// We don't touch map keys
	if w.loc[len(w.loc)-1] == reflectwalk.MapKey {
		return nil
	}

	setV := v

	// We only care about strings
	if v.Kind() == reflect.Interface {
		v = v.Elem()
	}
	if v.Kind() != reflect.String {
		return nil
	}

	// See if the current key is part of the ignored keys
	currentKey := w.key[len(w.key)-1]
	if strutil.StrListContains(w.IgnoredKeys, currentKey) {
		return nil
	}

	replaceVal := w.Callback(v.String())

	resultVal := reflect.ValueOf(replaceVal)
	switch w.loc[len(w.loc)-1] {
	case reflectwalk.MapValue:
		// If we're in a map, then the only way to set a map value is
		// to set it directly.
		m := w.cs[len(w.cs)-1]
		mk := w.csKey[len(w.cs)-1]
		m.SetMapIndex(mk, resultVal)
	case reflectwalk.SliceElem:
		s := w.cs[len(w.cs)-1]
		si := int(w.csKey[len(w.cs)-1].Int())
		s.Slice(si, si+1).Index(0).Set(resultVal)
	default:
		// Otherwise, we should be addressable
		setV.Set(resultVal)
	}

	return nil
}
<|endoftext|>


<commit_before>// Package kvite is a simple embedded K/V store backed by SQLite
package kvite

import (
	"database/sql"
	"errors"
	"fmt"

	_ "github.com/mattn/go-sqlite3" //import sqlite3 for driver
)

type (
	// DB is a wrapper around the underlying SQLite database.
	DB struct {
		db           *sql.DB
		table        string
		putQuery     string
		deleteQuery  string
		getQuery     string
		foreachQuery string
		bucketsQuery string
	}

	// Tx wraps most interactions with the datastore.
	Tx struct {
		db      *DB
		tx      *sql.Tx
		managed bool
	}

	//Bucket represents a collection of key/value pairs inside the database.
	Bucket struct {
		name string
		tx   *Tx
	}
)

// Open opens a KVite datastore. The returned DB is safe for concurrent use by multiple goroutines.
// It is rarely necessary to close a DB.
func Open(filename, table string) (*DB, error) {
	db, err := sql.Open("sqlite3", filename)
	if err != nil {
		return nil, err
	}

	if table == "" {
		table = "kvite"
	}

	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}

	defer func() {
		_ = tx.Rollback()
	}()

	query := fmt.Sprintf("create TABLE IF NOT EXISTS '%s' (key text not null, bucket text not null, value blob not null)", table)
	if _, err := tx.Exec(query); err != nil {
		return nil, err
	}
	query = fmt.Sprintf("create UNIQUE INDEX IF NOT EXISTS '%s_kvite_key_index' ON '%s' (key, bucket)", table, table)
	if _, err := tx.Exec(query); err != nil {
		return nil, err
	}

	if err := tx.Commit(); err != nil {
		return nil, err
	}

	return &DB{
		db:           db,
		table:        table,
		getQuery:     fmt.Sprintf("SELECT value FROM '%s' WHERE key = ? and bucket = ?", table),
		deleteQuery:  fmt.Sprintf("DELETE FROM '%s' WHERE key = ? AND bucket = ?", table),
		putQuery:     fmt.Sprintf("INSERT OR REPLACE INTO '%s' (key, value, bucket) VALUES (?, ?, ?)", table),
		foreachQuery: fmt.Sprintf("SELECT key, value FROM '%s' WHERE bucket = ?", table),
		bucketsQuery: fmt.Sprintf("SELECT DISTINCT bucket from '%s'", table),
	}, nil
}

// Close closes the database, releasing any open resources.
// It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
func (db *DB) Close() error {
	return db.db.Close()
}

// Begin starts a transaction.
func (db *DB) Begin() (*Tx, error) {
	tx, err := db.db.Begin()
	if err != nil {
		return nil, err
	}
	t := &Tx{
		db: db,
		tx: tx,
	}
	return t, nil

}

// Buckets returns all the buckets
func (db *DB) Buckets() ([]string, error) {
	rows, err := db.db.Query(db.bucketsQuery)
	if err != nil {
		return nil, err
	}

	buckets := make([]string, 0, 32)
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			return nil, err
		}
		buckets = append(buckets, name)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return buckets, nil
}

// Transaction executes a function within the context of a  managed transaction.
// If no error is returned from the function then the transaction is committed.
// If an error is returned then the entire transaction is rolled back.
// Rollback and Commit cannot be used inside of the function
func (db *DB) Transaction(fn func(*Tx) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	// Make sure the transaction rolls back in the event of a panic.
	defer func() {
		if tx.db != nil {
			_ = tx.Rollback()
		}
	}()

	tx.managed = true
	err = fn(tx)
	tx.managed = false
	if err != nil {
		_ = tx.Rollback()
		return err
	}

	return tx.Commit()
}

// Commit commits the transaction.
func (tx *Tx) Commit() error {
	if tx.managed {
		return errors.New("managed tx commit not allowed")
	}
	if tx.db == nil {
		// should we return an error here?
		return nil
	}

	err := tx.tx.Commit()
	tx.db = nil
	return err
}

// Rollback aborts the transaction.
func (tx *Tx) Rollback() error {
	if tx.managed {
		return errors.New("managed tx commit not allowed")
	}
	return tx.tx.Rollback()
}

func (tx *Tx) newBucket(name string) *Bucket {
	return &Bucket{
		tx:   tx,
		name: name,
	}
}

// Bucket gets a bucket by name.  Buckets can be created on the fly and do not "exist" until they have keys.
func (tx *Tx) Bucket(name string) (*Bucket, error) {
	return tx.newBucket(name), nil
}

// CreateBucket is provided for compatibility. It just calls Bucket.
func (tx *Tx) CreateBucket(name string) (*Bucket, error) {
	return tx.Bucket(name)

}

// CreateBucketIfNotExists is provided for compatibility. It just calls Bucket.
func (tx *Tx) CreateBucketIfNotExists(name string) (*Bucket, error) {
	return tx.Bucket(name)
}

// Put sets the value for a key in the bucket. If the key exists, then its previous value will be overwritten.
func (b *Bucket) Put(key string, value []byte) error {
	_, err := b.tx.tx.Exec(b.tx.db.putQuery, key, value, b.name)
	return err
}

// Delete removes a key from the bucket. If the key does not exist then nothing is done and a nil error is returned.
func (b *Bucket) Delete(key string) error {
	_, err := b.tx.tx.Exec(b.tx.db.deleteQuery, key, b.name)
	return err
}

// Get retrieves the value for a key in the bucket. Returns a nil value if the key does not exist
func (b *Bucket) Get(key string) ([]byte, error) {
	var value []byte

	if err := b.tx.tx.QueryRow(b.tx.db.getQuery, key, b.name).Scan(&value); err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return value, nil
}

//ForEach executes a function for each key/value pair in a bucket. If the provided function returns an error then the iteration is stopped and the error is returned to the caller.
func (b *Bucket) ForEach(fn func(k string, v []byte) error) error {
	rows, err := b.tx.tx.Query(b.tx.db.foreachQuery, b.name)
	if err != nil {
		return err
	}
	for rows.Next() {
		var key string
		var value []byte
		if err := rows.Scan(&key, &value); err != nil {
			return err
		}
		if err := fn(key, value); err != nil {
			return err
		}
	}
	return rows.Err()
}
<commit_msg>Don't nil the transaction database on commit<commit_after>// Package kvite is a simple embedded K/V store backed by SQLite
package kvite

import (
	"database/sql"
	"errors"
	"fmt"

	_ "github.com/mattn/go-sqlite3" //import sqlite3 for driver
)

type (
	// DB is a wrapper around the underlying SQLite database.
	DB struct {
		db           *sql.DB
		table        string
		putQuery     string
		deleteQuery  string
		getQuery     string
		foreachQuery string
		bucketsQuery string
	}

	// Tx wraps most interactions with the datastore.
	Tx struct {
		db      *DB
		tx      *sql.Tx
		managed bool
	}

	//Bucket represents a collection of key/value pairs inside the database.
	Bucket struct {
		name string
		tx   *Tx
	}
)

// Open opens a KVite datastore. The returned DB is safe for concurrent use by multiple goroutines.
// It is rarely necessary to close a DB.
func Open(filename, table string) (*DB, error) {
	db, err := sql.Open("sqlite3", filename)
	if err != nil {
		return nil, err
	}

	if table == "" {
		table = "kvite"
	}

	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}

	defer func() {
		_ = tx.Rollback()
	}()

	query := fmt.Sprintf("create TABLE IF NOT EXISTS '%s' (key text not null, bucket text not null, value blob not null)", table)
	if _, err := tx.Exec(query); err != nil {
		return nil, err
	}
	query = fmt.Sprintf("create UNIQUE INDEX IF NOT EXISTS '%s_kvite_key_index' ON '%s' (key, bucket)", table, table)
	if _, err := tx.Exec(query); err != nil {
		return nil, err
	}

	if err := tx.Commit(); err != nil {
		return nil, err
	}

	return &DB{
		db:           db,
		table:        table,
		getQuery:     fmt.Sprintf("SELECT value FROM '%s' WHERE key = ? and bucket = ?", table),
		deleteQuery:  fmt.Sprintf("DELETE FROM '%s' WHERE key = ? AND bucket = ?", table),
		putQuery:     fmt.Sprintf("INSERT OR REPLACE INTO '%s' (key, value, bucket) VALUES (?, ?, ?)", table),
		foreachQuery: fmt.Sprintf("SELECT key, value FROM '%s' WHERE bucket = ?", table),
		bucketsQuery: fmt.Sprintf("SELECT DISTINCT bucket from '%s'", table),
	}, nil
}

// Close closes the database, releasing any open resources.
// It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
func (db *DB) Close() error {
	return db.db.Close()
}

// Begin starts a transaction.
func (db *DB) Begin() (*Tx, error) {
	tx, err := db.db.Begin()
	if err != nil {
		return nil, err
	}
	t := &Tx{
		db: db,
		tx: tx,
	}
	return t, nil

}

// Buckets returns all the buckets
func (db *DB) Buckets() ([]string, error) {
	rows, err := db.db.Query(db.bucketsQuery)
	if err != nil {
		return nil, err
	}

	buckets := make([]string, 0, 32)
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			return nil, err
		}
		buckets = append(buckets, name)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}

	return buckets, nil
}

// Transaction executes a function within the context of a  managed transaction.
// If no error is returned from the function then the transaction is committed.
// If an error is returned then the entire transaction is rolled back.
// Rollback and Commit cannot be used inside of the function
func (db *DB) Transaction(fn func(*Tx) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	// Make sure the transaction rolls back in the event of a panic.
	defer func() {
		if tx.db != nil {
			_ = tx.Rollback()
		}
	}()

	tx.managed = true
	err = fn(tx)
	tx.managed = false
	if err != nil {
		_ = tx.Rollback()
		return err
	}

	return tx.Commit()
}

// Commit commits the transaction.
func (tx *Tx) Commit() error {
	if tx.managed {
		return errors.New("managed tx commit not allowed")
	}

	err := tx.tx.Commit()
	return err
}

// Rollback aborts the transaction.
func (tx *Tx) Rollback() error {
	if tx.managed {
		return errors.New("managed tx commit not allowed")
	}
	return tx.tx.Rollback()
}

func (tx *Tx) newBucket(name string) *Bucket {
	return &Bucket{
		tx:   tx,
		name: name,
	}
}

// Bucket gets a bucket by name.  Buckets can be created on the fly and do not "exist" until they have keys.
func (tx *Tx) Bucket(name string) (*Bucket, error) {
	return tx.newBucket(name), nil
}

// CreateBucket is provided for compatibility. It just calls Bucket.
func (tx *Tx) CreateBucket(name string) (*Bucket, error) {
	return tx.Bucket(name)

}

// CreateBucketIfNotExists is provided for compatibility. It just calls Bucket.
func (tx *Tx) CreateBucketIfNotExists(name string) (*Bucket, error) {
	return tx.Bucket(name)
}

// Put sets the value for a key in the bucket. If the key exists, then its previous value will be overwritten.
func (b *Bucket) Put(key string, value []byte) error {
	_, err := b.tx.tx.Exec(b.tx.db.putQuery, key, value, b.name)
	return err
}

// Delete removes a key from the bucket. If the key does not exist then nothing is done and a nil error is returned.
func (b *Bucket) Delete(key string) error {
	_, err := b.tx.tx.Exec(b.tx.db.deleteQuery, key, b.name)
	return err
}

// Get retrieves the value for a key in the bucket. Returns a nil value if the key does not exist
func (b *Bucket) Get(key string) ([]byte, error) {
	var value []byte

	if err := b.tx.tx.QueryRow(b.tx.db.getQuery, key, b.name).Scan(&value); err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		return nil, err
	}

	return value, nil
}

//ForEach executes a function for each key/value pair in a bucket. If the provided function returns an error then the iteration is stopped and the error is returned to the caller.
func (b *Bucket) ForEach(fn func(k string, v []byte) error) error {
	rows, err := b.tx.tx.Query(b.tx.db.foreachQuery, b.name)
	if err != nil {
		return err
	}
	for rows.Next() {
		var key string
		var value []byte
		if err := rows.Scan(&key, &value); err != nil {
			return err
		}
		if err := fn(key, value); err != nil {
			return err
		}
	}
	return rows.Err()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
	"time"

	"github.com/aktau/github-release/github"
	"github.com/dustin/go-humanize"
)

const (
	RELEASE_LIST_URI    = "/repos/%s/%s/releases"
	RELEASE_LATEST_URI  = "/repos/%s/%s/releases/latest"
	RELEASE_DATE_FORMAT = "02/01/2006 at 15:04"
)

type Release struct {
	Url         string     `json:"url"`
	PageUrl     string     `json:"html_url"`
	UploadUrl   string     `json:"upload_url"`
	Id          int        `json:"id"`
	Name        string     `json:"name"`
	Description string     `json:"body"`
	TagName     string     `json:"tag_name"`
	Draft       bool       `json:"draft"`
	Prerelease  bool       `json:"prerelease"`
	Created     *time.Time `json:"created_at"`
	Published   *time.Time `json:"published_at"`
	Assets      []Asset    `json:"assets"`
}

func (r *Release) CleanUploadUrl() string {
	bracket := strings.Index(r.UploadUrl, "{")

	if bracket == -1 {
		return r.UploadUrl
	}

	return r.UploadUrl[0:bracket]
}

func (r *Release) String() string {
	str := make([]string, len(r.Assets)+1)
	str[0] = fmt.Sprintf(
		"%s, name: '%s', description: '%s', id: %d, tagged: %s, published: %s, draft: %v, prerelease: %v",
		r.TagName, r.Name, r.Description, r.Id,
		timeFmtOr(r.Created, RELEASE_DATE_FORMAT, ""),
		timeFmtOr(r.Published, RELEASE_DATE_FORMAT, ""),
		Mark(r.Draft), Mark(r.Prerelease))

	for idx, asset := range r.Assets {
		str[idx+1] = fmt.Sprintf("  - artifact: %s, downloads: %d, state: %s, type: %s, size: %s, id: %d",
			asset.Name, asset.Downloads, asset.State, asset.ContentType,
			humanize.Bytes(asset.Size), asset.Id)
	}

	return strings.Join(str, "\n")
}

type ReleaseCreate struct {
	TagName         string `json:"tag_name"`
	TargetCommitish string `json:"target_commitish,omitempty"`
	Name            string `json:"name"`
	Body            string `json:"body"`
	Draft           bool   `json:"draft"`
	Prerelease      bool   `json:"prerelease"`
}

func Releases(user, repo, token string) ([]Release, error) {
	var releases []Release
	err := github.Client{Token: token, BaseURL: EnvApiEndpoint}.Get(fmt.Sprintf(RELEASE_LIST_URI, user, repo), &releases)
	if err != nil {
		return nil, err
	}

	return releases, nil
}

func latestReleaseApi(user, repo, token string) (*Release, error) {
	var release Release
	return &release, github.Client{Token: token, BaseURL: EnvApiEndpoint}.Get(fmt.Sprintf(RELEASE_LATEST_URI, user, repo), &release)
}

func LatestRelease(user, repo, token string) (*Release, error) {
	// If latestReleaseApi DOESN'T give an error, return the release.
	if latestRelease, err := latestReleaseApi(user, repo, token); err == nil {
		return latestRelease, nil
	}

	// The enterprise api doesnt support the latest release endpoint. Get
	// all releases and compare the published date to get the latest.
	releases, err := Releases(user, repo, token)
	if err != nil {
		return nil, err
	}

	var latestRelIndex = -1
	maxDate := time.Time{}
	for i, release := range releases {
		if relDate := *release.Published; relDate.After(maxDate) {
			maxDate = relDate
			latestRelIndex = i
		}
	}
	if latestRelIndex == -1 {
		return nil, fmt.Errorf("could not find the latest release")
	}

	vprintln("Scanning ", len(releases), "releases, latest release is", releases[latestRelIndex])
	return &releases[latestRelIndex], nil
}

func ReleaseOfTag(user, repo, tag, token string) (*Release, error) {
	releases, err := Releases(user, repo, token)
	if err != nil {
		return nil, err
	}

	for _, release := range releases {
		if release.TagName == tag {
			return &release, nil
		}
	}

	return nil, fmt.Errorf("could not find the release corresponding to tag %s", tag)
}

/* find the release-id of the specified tag */
func IdOfTag(user, repo, tag, token string) (int, error) {
	release, err := ReleaseOfTag(user, repo, tag, token)
	if err != nil {
		return 0, err
	}

	return release.Id, nil
}
<commit_msg>releases: use specific release-of-tag endpoint<commit_after>package main

import (
	"fmt"
	"strings"
	"time"

	"github.com/aktau/github-release/github"
	"github.com/dustin/go-humanize"
)

const (
	RELEASE_LIST_URI    = "/repos/%s/%s/releases"
	RELEASE_BY_TAG_URI  = "/repos/%s/%s/releases/tags/%s" // /repos/:owner/:repo/releases/tags/:tag
	RELEASE_LATEST_URI  = "/repos/%s/%s/releases/latest"
	RELEASE_DATE_FORMAT = "02/01/2006 at 15:04"
)

type Release struct {
	Url         string     `json:"url"`
	PageUrl     string     `json:"html_url"`
	UploadUrl   string     `json:"upload_url"`
	Id          int        `json:"id"`
	Name        string     `json:"name"`
	Description string     `json:"body"`
	TagName     string     `json:"tag_name"`
	Draft       bool       `json:"draft"`
	Prerelease  bool       `json:"prerelease"`
	Created     *time.Time `json:"created_at"`
	Published   *time.Time `json:"published_at"`
	Assets      []Asset    `json:"assets"`
}

func (r *Release) CleanUploadUrl() string {
	bracket := strings.Index(r.UploadUrl, "{")

	if bracket == -1 {
		return r.UploadUrl
	}

	return r.UploadUrl[0:bracket]
}

func (r *Release) String() string {
	str := make([]string, len(r.Assets)+1)
	str[0] = fmt.Sprintf(
		"%s, name: '%s', description: '%s', id: %d, tagged: %s, published: %s, draft: %v, prerelease: %v",
		r.TagName, r.Name, r.Description, r.Id,
		timeFmtOr(r.Created, RELEASE_DATE_FORMAT, ""),
		timeFmtOr(r.Published, RELEASE_DATE_FORMAT, ""),
		Mark(r.Draft), Mark(r.Prerelease))

	for idx, asset := range r.Assets {
		str[idx+1] = fmt.Sprintf("  - artifact: %s, downloads: %d, state: %s, type: %s, size: %s, id: %d",
			asset.Name, asset.Downloads, asset.State, asset.ContentType,
			humanize.Bytes(asset.Size), asset.Id)
	}

	return strings.Join(str, "\n")
}

type ReleaseCreate struct {
	TagName         string `json:"tag_name"`
	TargetCommitish string `json:"target_commitish,omitempty"`
	Name            string `json:"name"`
	Body            string `json:"body"`
	Draft           bool   `json:"draft"`
	Prerelease      bool   `json:"prerelease"`
}

func Releases(user, repo, token string) ([]Release, error) {
	var releases []Release
	err := github.Client{Token: token, BaseURL: EnvApiEndpoint}.Get(fmt.Sprintf(RELEASE_LIST_URI, user, repo), &releases)
	if err != nil {
		return nil, err
	}

	return releases, nil
}

func latestReleaseApi(user, repo, token string) (*Release, error) {
	var release Release
	return &release, github.Client{Token: token, BaseURL: EnvApiEndpoint}.Get(fmt.Sprintf(RELEASE_LATEST_URI, user, repo), &release)
}

func LatestRelease(user, repo, token string) (*Release, error) {
	// If latestReleaseApi DOESN'T give an error, return the release.
	if latestRelease, err := latestReleaseApi(user, repo, token); err == nil {
		return latestRelease, nil
	}

	// The enterprise api doesnt support the latest release endpoint. Get
	// all releases and compare the published date to get the latest.
	releases, err := Releases(user, repo, token)
	if err != nil {
		return nil, err
	}

	var latestRelIndex = -1
	maxDate := time.Time{}
	for i, release := range releases {
		if relDate := *release.Published; relDate.After(maxDate) {
			maxDate = relDate
			latestRelIndex = i
		}
	}
	if latestRelIndex == -1 {
		return nil, fmt.Errorf("could not find the latest release")
	}

	vprintln("Scanning ", len(releases), "releases, latest release is", releases[latestRelIndex])
	return &releases[latestRelIndex], nil
}

// ReleaseOfTag returns the Github release corresponding to a git tag, if it
// exists.
func ReleaseOfTag(user, repo, tag, token string) (*Release, error) {
	var release Release
	return &release, github.Client{Token: token, BaseURL: EnvApiEndpoint}.Get(fmt.Sprintf(RELEASE_BY_TAG_URI, user, repo, tag), &release)
}

/* find the release-id of the specified tag */
func IdOfTag(user, repo, tag, token string) (int, error) {
	release, err := ReleaseOfTag(user, repo, tag, token)
	if err != nil {
		return 0, err
	}

	return release.Id, nil
}
<|endoftext|>


<commit_before>package auth0

import (
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
)

func handler() http.Handler {
	hmux := http.NewServeMux()
	hmux.HandleFunc("/callback", CallbackHandler)
	return hmux
}

func mockAuth0() http.Handler {
	hmux := http.NewServeMux()
	hmux.HandleFunc("/oauth/token", tokenHandler)
	hmux.HandleFunc("/userinfo", loggingHandler)
	hmux.HandleFunc("/authorize", loggingHandler)
	hmux.HandleFunc("/*", loggingHandler)
	return hmux
}

func tokenHandler(w http.ResponseWriter, r *http.Request) {
	log.Printf("*r = %+v\n", *r)
}

func loggingHandler(w http.ResponseWriter, r *http.Request) {
	log.Printf("*r = %+v\n", *r)
}

func TestCallbackHandler(t *testing.T) {
	server := httptest.NewServer(handler())
	defer server.Close()

	auth0Server := httptest.NewServer(mockAuth0())
	defer auth0Server.Close()

	Init(nil)
	os.Setenv("AUTH0_CLIENT_ID", "client_id")
	os.Setenv("AUTH0_CLIENT_SECRET", "secret")
	os.Setenv("AUTH0_CALLBACK_URL", server.URL+"/callback")
	os.Setenv("AUTH0_DOMAIN", "localhost")
	resp, err := http.Get(server.URL + "/callback?code=12345")
	if err != nil {
		t.Fatalf("error in getting callback: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusSeeOther {
		//body, _ := ioutil.ReadAll(resp.Body)
		//t.Fatalf("did not get redirected; status was %v response was %v, body was %v", resp.Status, resp, string(body))
	}
	expectLocation := "some"
	actualLocation := resp.Header.Get("location")
	if actualLocation != expectLocation {
		//t.Fatalf("expected redirect to %v, got %v", expectLocation, actualLocation)
	}
}
<commit_msg>removed test<commit_after><|endoftext|>


<commit_before>package cli

import (
	"io"
	"os"
)
import "fmt"

import "strings"
import "github.com/jwaldrip/odin/cli/values"

// ShowUsage is a function to show usage
var ShowUsage = func(cmd Command) { cmd.Usage() }

// CLI represents a set of defined flags.  The zero value of a FlagSet
// has no name and has ContinueOnError error handling.
type CLI struct {
	ErrorHandling ErrorHandling

	aliases          map[rune]*Flag
	description      string
	errOutput        io.Writer
	flags            flagMap
	flagsTerminated  bool
	flagValues       map[*Flag]values.Value
	fn               func(Command)
	inheritedFlags   flagMap
	name             string
	params           paramsList
	paramValues      map[*Param]values.Value
	paramsParsed     bool
	parent           Command
	propogatingFlags flagMap
	stdOutput        io.Writer
	subCommands      map[string]*SubCommand
	unparsedArgs     values.List
	usage            func()
	version          string
}

func (cmd *CLI) init(name, desc string, fn func(Command), paramNames ...string) {
	cmd.name = name
	cmd.fn = fn
	cmd.description = desc
	cmd.DefineParams(paramNames...)
}

// New returns a new cli with the specified name and
// error handling property.
func New(version, desc string, fn func(Command), paramNames ...string) *CLI {
	nameParts := strings.Split(os.Args[0], "/")
	cli := new(CLI)
	cli.init(nameParts[len(nameParts)-1], desc, fn, paramNames...)
	cli.version = version
	cli.description = desc
	cli.ErrorHandling = ExitOnError
	return cli
}

// Alias for New
var NewCLI = New

// Start starts the command with args, arg[0] is ignored
func (cmd *CLI) Start(args ...string) {
	if args == nil {
		args = os.Args
	}

	if len(args) > 1 {
		args = args[1:]
	} else {
		args = []string{}
	}

	// parse flags and args
	args = cmd.parseFlags(args)

	// Show a version
	if len(cmd.Version()) > 0 && cmd.Flag("version").Get() == true {
		fmt.Fprintln(cmd.StdOutput(), cmd.Name(), cmd.Version())
		return
	}

	// Show Help
	if cmd.Flag("help").Get() == true {
		cmd.Usage()
		return
	}

	// Parse Params
	args = cmd.parseParams(args)

	var subCommandsParsed bool
	if args, subCommandsParsed = cmd.parseSubCommands(args); subCommandsParsed {
		return
	}

	cmd.assignUnparsedArgs(args)

	// Run the function
	cmd.fn(cmd)
}
<commit_msg>move where ExitOnError is defined<commit_after>package cli

import (
	"io"
	"os"
)
import "fmt"

import "strings"
import "github.com/jwaldrip/odin/cli/values"

// ShowUsage is a function to show usage
var ShowUsage = func(cmd Command) { cmd.Usage() }

// CLI represents a set of defined flags.  The zero value of a FlagSet
// has no name and has ContinueOnError error handling.
type CLI struct {
	ErrorHandling ErrorHandling

	aliases          map[rune]*Flag
	description      string
	errOutput        io.Writer
	flags            flagMap
	flagsTerminated  bool
	flagValues       map[*Flag]values.Value
	fn               func(Command)
	inheritedFlags   flagMap
	name             string
	params           paramsList
	paramValues      map[*Param]values.Value
	paramsParsed     bool
	parent           Command
	propogatingFlags flagMap
	stdOutput        io.Writer
	subCommands      map[string]*SubCommand
	unparsedArgs     values.List
	usage            func()
	version          string
}

func (cmd *CLI) init(name, desc string, fn func(Command), paramNames ...string) {
	cmd.name = name
	cmd.fn = fn
	cmd.description = desc
	cmd.DefineParams(paramNames...)
	cmd.ErrorHandling = ExitOnError
}

// New returns a new cli with the specified name and
// error handling property.
func New(version, desc string, fn func(Command), paramNames ...string) *CLI {
	nameParts := strings.Split(os.Args[0], "/")
	cli := new(CLI)
	cli.init(nameParts[len(nameParts)-1], desc, fn, paramNames...)
	cli.version = version
	cli.description = desc
	return cli
}

// Alias for New
var NewCLI = New

// Start starts the command with args, arg[0] is ignored
func (cmd *CLI) Start(args ...string) {
	if args == nil {
		args = os.Args
	}

	if len(args) > 1 {
		args = args[1:]
	} else {
		args = []string{}
	}

	// parse flags and args
	args = cmd.parseFlags(args)

	// Show a version
	if len(cmd.Version()) > 0 && cmd.Flag("version").Get() == true {
		fmt.Fprintln(cmd.StdOutput(), cmd.Name(), cmd.Version())
		return
	}

	// Show Help
	if cmd.Flag("help").Get() == true {
		cmd.Usage()
		return
	}

	// Parse Params
	args = cmd.parseParams(args)

	var subCommandsParsed bool
	if args, subCommandsParsed = cmd.parseSubCommands(args); subCommandsParsed {
		return
	}

	cmd.assignUnparsedArgs(args)

	// Run the function
	cmd.fn(cmd)
}
<|endoftext|>


<commit_before>package cli

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

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

var ()

func before(c *cli.Context) error {
	// Log level
	if logLevel, err := log.ParseLevel(c.String(LogLevelKey)); err != nil {
		log.Fatal("Failed to parse log level:", err)
	} else {
		log.SetLevel(logLevel)
		log.Debugf("Loglevel: %s", logLevel)
	}

	return nil
}

func printVersion(c *cli.Context) {
	fmt.Fprintf(c.App.Writer, "%v\n", c.App.Version)
}

// Run the Envman CLI.
func Run() {
	cli.VersionPrinter = printVersion

	app := cli.NewApp()
	app.Name = filepath.Base(os.Args[0])
	app.Usage = "codesigndoc"
	app.Version = "0.9.9"

	app.Author = ""
	app.Email = ""

	app.Before = before

	app.Flags = appFlags
	app.Commands = commands

	if err := app.Run(os.Args); err != nil {
		log.Fatal("Finished with error:", err)
	}
}
<commit_msg>v0.9.10<commit_after>package cli

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

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

var ()

func before(c *cli.Context) error {
	// Log level
	if logLevel, err := log.ParseLevel(c.String(LogLevelKey)); err != nil {
		log.Fatal("Failed to parse log level:", err)
	} else {
		log.SetLevel(logLevel)
		log.Debugf("Loglevel: %s", logLevel)
	}

	return nil
}

func printVersion(c *cli.Context) {
	fmt.Fprintf(c.App.Writer, "%v\n", c.App.Version)
}

// Run the Envman CLI.
func Run() {
	cli.VersionPrinter = printVersion

	app := cli.NewApp()
	app.Name = filepath.Base(os.Args[0])
	app.Usage = "codesigndoc"
	app.Version = "0.9.10"

	app.Author = ""
	app.Email = ""

	app.Before = before

	app.Flags = appFlags
	app.Commands = commands

	if err := app.Run(os.Args); err != nil {
		log.Fatal("Finished with error:", err)
	}
}
<|endoftext|>