package main

import (
	"flag"
	"golang.org/x/crypto/ssh/terminal"
	"os"
)

func main() {
	if terminal.IsTerminal(int(os.Stdin.Fd())) {
		println("Cellophane v0.1 (C) 2015 Sten Linnarsson <http://linnarssonlab.org/>")
		println()
	}

	// Define command-line flags
	var flHelp = flag.Bool("help", false, "Show this help message and quit")
	flag.Parse()

	if *flHelp {
		println("Usage:")
		flag.PrintDefaults()
		return
	}
}

package main

import (
	"gopkg.in/alecthomas/kingpin.v1"
	"os"
)

func main() {
	// Define the command-line structure using Kingpin
	var app = kingpin.New("cef", "Cellophane v0.1 (C) 2015 Sten Linnarsson <http://linnarssonlab.org/>")
	var app_input = app.Flag("input", "Name of file to use as input (default: use STDIN)").String()
	var app_output = app.Flag("output", "Name of file to use as output (default: use STDOUT)").String()
	var app_cef = app.Flag("cef", "Generate CEF as output (default: generate CEB)").Bool()
	var transpose = app.Command("transpose", "Transpose the file")
	//	var info = app.Command("info", "Show a summary of the file contents")
	//	var join = app.Command("join", "Join two files based on an attribute used as key")
	//	var join_other = join.Flag("other", "The file to which <STDIN> should be joined").Required().String()

	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	// Transpose file
	case transpose.FullCommand():
		println("Transposing the CEF/CEB file...")
		if *app_input == "" {
			println("Reading from STDIN")
		} else {
			println("Reading from " + *app_input)
		}
		if *app_output == "" {
			println("Writing to STDOUT")
		} else {
			println("Writing to " + *app_output)
		}
		if *app_cef {
			println("Generating CEF file instead of CEB")
		}
	}
}

Use kingpin for arg parsing


package main

import (
	"fmt"
	"os"
	"runtime/debug"

	"testing"

	. "github.com/onsi/gomega"
	"github.com/sclevine/agouti"
)

const (
	PORT = 9009
)

var (
	baseUrl = fmt.Sprintf("http://localhost:%v/admin", PORT)
	driver  *agouti.WebDriver
	page    *agouti.Page
)

func TestMain(m *testing.M) {
	var t *testing.T
	var err error

	driver = agouti.Selenium()
	driver.Start()

	go Start(PORT)

	page, err = driver.NewPage(agouti.Browser("chrome"))
	if err != nil {
		t.Error("Failed to open page.")
	}

	RegisterTestingT(t)
	test := m.Run()

	driver.Stop()
	os.Exit(test)
}

func StopDriverOnPanic() {
	var t *testing.T
	if r := recover(); r != nil {
		debug.PrintStack()
		fmt.Println("Recovered in f", r)
		driver.Stop()
		t.Fail()
	}
}

package main

import (
	"fmt"
	"os"
	"runtime/debug"

	"testing"

	. "github.com/onsi/gomega"
	"github.com/sclevine/agouti"
)

const (
	PORT = 4444
)

var (
	baseUrl = fmt.Sprintf("http://localhost:%v/admin", PORT)
	driver  *agouti.WebDriver
	page    *agouti.Page
)

func TestMain(m *testing.M) {
	var t *testing.T
	var err error

	driver = agouti.Selenium()
	driver.Start()

	go Start(PORT)

	page, err = driver.NewPage(agouti.Browser("chrome"))
	if err != nil {
		t.Error("Failed to open page.")
	}

	RegisterTestingT(t)
	test := m.Run()

	driver.Stop()
	os.Exit(test)
}

func StopDriverOnPanic() {
	var t *testing.T
	if r := recover(); r != nil {
		debug.PrintStack()
		fmt.Println("Recovered in f", r)
		driver.Stop()
		t.Fail()
	}
}

Update default test server port to selenium default port to test browser on CI.


// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package heaps

// reverseInts reverse elements of an[i:j] in an.
func reverseInts(an []int, i, j int) {
	for i < j {
		an[i], an[j] = an[j], an[i]
		i++
		j--
	}
}

// SortK sorts k-increasing-decreasing slice an and returns the result.
// The time complexity is O(n*log(k)). Beyond the space needed to write
// the final result, the O(k) additional space is needed.
// The an can be modified during the function execution.
func SortK(an []int) []int {
	i := 0
	o := 1 // Order: 1 - increasing, -1 decreasing.
	var ss [][]int
	for j := 1; j <= len(an); j++ {
		if j == len(an) || o > 0 && an[j-1] > an[j] || o < 0 && an[j-1] < an[j] {
			if o < 0 {
				reverseInts(an, i, j-1)
			}
			ss = append(ss, an[i:j])
			i, o = j, -o
		}
	}
	return MergeSorted(ss)
}

// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package heaps

// reverseInts reverse elements of an[i:j] in an.
func reverseInts(an []int, i, j int) {
	for i < j {
		an[i], an[j] = an[j], an[i]
		i++
		j--
	}
}

// SortK sorts k-increasing-decreasing slice an and returns the result.
// The time complexity is O(n*log(k)). Beyond the space needed to write
// the final result, the O(k) additional space is needed.
// The an can be modified during the function execution.
func SortK(an []int) []int {
	i, o := 0, 1 // o - Order: 1 - increasing, -1 - decreasing.
	var ss [][]int
	for j := 1; j <= len(an); j++ {
		if j == len(an) || o > 0 && an[j-1] > an[j] || o < 0 && an[j-1] < an[j] {
			if o < 0 {
				reverseInts(an, i, j-1)
			}
			ss = append(ss, an[i:j])
			i, o = j, -o
		}
	}
	return MergeSorted(ss)
}

Fix comment and improve readability


package bootstrap

import (
	"fmt"
)

type LogAction struct {
	Output string `json:"output"`
}

func init() {
	Register("log", &LogAction{})
}

func (a *LogAction) Run(s *State) error {
	fmt.Println(interpolate(s, a.Output))
	return nil
}

package bootstrap

type LogAction struct {
	ID     string `json:"id"`
	Output string `json:"output"`
}

type LogMessage struct {
	Msg string `json:"message"`
}

func (l *LogMessage) String() string {
	return l.Msg
}

func init() {
	Register("log", &LogAction{})
}

func (a *LogAction) Run(s *State) error {
	s.StepData[a.ID] = &LogMessage{Msg: interpolate(s, a.Output)}
	return nil
}

Modify log action so JSON output is consistent


package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type NatsStreamingClusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []NatsStreamingCluster `json:"items"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type NatsStreamingCluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              NatsStreamingClusterSpec   `json:"spec"`
	Status            NatsStreamingClusterStatus `json:"status,omitempty"`
}

type NatsStreamingClusterSpec struct {
	// Fill me
}
type NatsStreamingClusterStatus struct {
	// Fill me
}

package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type NatsStreamingClusterList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []NatsStreamingCluster `json:"items"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type NatsStreamingCluster struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              NatsStreamingClusterSpec   `json:"spec"`
	Status            NatsStreamingClusterStatus `json:"status,omitempty"`
}

type NatsStreamingClusterSpec struct {
	// Size is the number of nodes in the NATS Streaming cluster.
	Size int32 `json:"size"`

	// NatsService is the Kubernetes service to which the
	// NATS Streaming nodes will connect.
	NatsService string `json:"natsSvc"`
}

type NatsStreamingClusterStatus struct {
	// TODO
}

Add size to NATS cluster spec


package matrix

import (
	"testing"
)

func TestIdentity(t *testing.T) {
	m := Identity(11)
	rows, cols := m.Dim()
	for i := 0; i < rows; i++ {
		for k := 0; k < cols; k++ {
			a := m.Get(i, k)
			if i == k {
				if a != 1 {
					t.Fatalf("(%d, %d) == %f != 1", i, k, a)
				}
			} else {
				if a != 0 {
					t.Fatalf("(%d, %d) == %f != 0", i, k, a)
				}
			}
		}
	}
}

package matrix

import (
	"testing"
)

func TestIdentity(t *testing.T) {
	m := Identity(11)
	rows, cols := m.Dims()
	for i := 0; i < rows; i++ {
		for k := 0; k < cols; k++ {
			a := m.Get(i, k)
			if i == k {
				if a != 1 {
					t.Fatalf("(%d, %d) == %f != 1", i, k, a)
				}
			} else {
				if a != 0 {
					t.Fatalf("(%d, %d) == %f != 0", i, k, a)
				}
			}
		}
	}
}

Fix compile error in TestIdentity().


package helper

var guessExecutableName = "openvpn"
var guessExecutablePaths = []string{
	"/usr/local/sbin/openvpn",
	"/Applications/Tunnelblick.app/Contents/Resources/openvpn/openvpn-2.4.*-openssl-1.*/openvpn",
	"/Applications/Shimo.app/Contents/MacOS/openvpn",
	"/Applications/Viscosity.app/Contents/MacOS/openvpn",
}
var guessExecutableSuggestions = `
If you use Homebrew, you can install the openvpn formula...

    brew install openvpn

Alternatively, the following applications will also install openvpn...

 * Tunnelblick (https://tunnelblick.net/)
 * Shimo (https://www.shimovpn.com/)
 * Viscosity (https://www.sparklabs.com/viscosity/)
`

package helper

var guessExecutableName = "openvpn"
var guessExecutablePaths = []string{
	"/usr/local/sbin/openvpn",
        "/usr/sbin/openvpn",
	"/Applications/Tunnelblick.app/Contents/Resources/openvpn/openvpn-2.4.*-openssl-1.*/openvpn",
	"/Applications/Shimo.app/Contents/MacOS/openvpn",
	"/Applications/Viscosity.app/Contents/MacOS/openvpn",
}
var guessExecutableSuggestions = `
If you use Homebrew, you can install the openvpn formula...

    brew install openvpn

Alternatively, the following applications will also install openvpn...

 * Tunnelblick (https://tunnelblick.net/)
 * Shimo (https://www.shimovpn.com/)
 * Viscosity (https://www.sparklabs.com/viscosity/)
`

Add /usr/sbin/openvpn to darwin path guesser


package main

import (
	"bufio"
	"os"
	"regexp"
)

type procfileEntry struct {
	Name    string
	Command string
	Port    int
}

func parseProcfile(path string, portBase, portStep int) (entries []procfileEntry) {
	re, _ := regexp.Compile("^(\\w+):\\s+(.+)$")

	f, err := os.Open(path)
	fatalOnErr(err)

	port := portBase
	names := make(map[string]bool)

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if len(scanner.Text()) == 0 {
			continue
		}

		params := re.FindStringSubmatch(scanner.Text())
		if len(params) != 3 {
			continue
		}

		name, cmd := params[1], params[2]

		if names[name] {
			fatal("Process names must be uniq")
		}
		names[name] = true

		entries = append(entries, procfileEntry{name, cmd, port})

		port += portStep
	}

	fatalOnErr(scanner.Err())

	if len(entries) == 0 {
		fatal("No entries was found in Procfile")
	}

	return
}

package main

import (
	"bufio"
	"os"
	"regexp"
)

type procfileEntry struct {
	Name    string
	Command string
	Port    int
}

func parseProcfile(path string, portBase, portStep int) (entries []procfileEntry) {
	re, _ := regexp.Compile(`^([\w-]+):\s+(.+)$`)

	f, err := os.Open(path)
	fatalOnErr(err)

	port := portBase
	names := make(map[string]bool)

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		if len(scanner.Text()) == 0 {
			continue
		}

		params := re.FindStringSubmatch(scanner.Text())
		if len(params) != 3 {
			continue
		}

		name, cmd := params[1], params[2]

		if names[name] {
			fatal("Process names must be uniq")
		}
		names[name] = true

		entries = append(entries, procfileEntry{name, cmd, port})

		port += portStep
	}

	fatalOnErr(scanner.Err())

	if len(entries) == 0 {
		fatal("No entries was found in Procfile")
	}

	return
}

Allow `-` in process names


package command

import (
	"testing"

	"github.com/hashicorp/vault/api"
)

func testClient(t *testing.T, addr string, token string) *api.Client {
	config := api.DefaultConfig()
	config.Address = addr
	client, err := api.NewClient(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	client.SetToken(token)

	return client
}

package command

import (
	"testing"

	"github.com/hashicorp/vault/api"
	"github.com/hashicorp/vault/builtin/logical/pki"
	"github.com/hashicorp/vault/builtin/logical/transit"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/vault"

	vaulthttp "github.com/hashicorp/vault/http"
	logxi "github.com/mgutz/logxi/v1"
)

var testVaultServerDefaultBackends = map[string]logical.Factory{
	"transit": transit.Factory,
	"pki":     pki.Factory,
}

func testVaultServer(t testing.TB) (*api.Client, func()) {
	return testVaultServerBackends(t, testVaultServerDefaultBackends)
}

func testVaultServerBackends(t testing.TB, backends map[string]logical.Factory) (*api.Client, func()) {
	coreConfig := &vault.CoreConfig{
		DisableMlock:    true,
		DisableCache:    true,
		Logger:          logxi.NullLog,
		LogicalBackends: backends,
	}

	cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
		HandlerFunc: vaulthttp.Handler,
	})
	cluster.Start()

	// make it easy to get access to the active
	core := cluster.Cores[0].Core
	vault.TestWaitActive(t, core)

	client := cluster.Cores[0].Client
	client.SetToken(cluster.RootToken)

	// Sanity check
	secret, err := client.Auth().Token().LookupSelf()
	if err != nil {
		t.Fatal(err)
	}
	if secret == nil || secret.Data["id"].(string) != cluster.RootToken {
		t.Fatalf("token mismatch: %#v vs %q", secret, cluster.RootToken)
	}
	return client, func() { defer cluster.Cleanup() }
}

func testClient(t *testing.T, addr string, token string) *api.Client {
	config := api.DefaultConfig()
	config.Address = addr
	client, err := api.NewClient(config)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	client.SetToken(token)

	return client
}

Add testing harness for a vault cluster


package actions

import (
	"fmt"

	"github.com/deis/helm/log"
	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/pop"
	"github.com/kindlyops/mappamundi/havenapi/models"
)

// RegistrationHandler accepts json
func RegistrationHandler(c buffalo.Context) error {
	tx := c.Value("tx").(*pop.Connection)
	request := c.Request()
	request.ParseForm()

	err := tx.RawQuery(
		models.Q["registeruser"],
		request.FormValue("email"),
		request.FormValue("ip_address"),
		request.FormValue("survey_results"),
	).Exec()

	if err != nil {
		return c.Error(500, fmt.Errorf("error inserting registration to database: %s", err.Error()))
	}

	log.Info("processed a registration")
	message := "success"
	return c.Render(200, r.JSON(map[string]string{"message": message}))
}

package actions

import (
	"fmt"
	"strings"

	"github.com/deis/helm/log"
	"github.com/gobuffalo/buffalo"
	"github.com/gobuffalo/pop"
	"github.com/kindlyops/mappamundi/havenapi/models"
)

// RegistrationHandler accepts json
func RegistrationHandler(c buffalo.Context) error {
	tx := c.Value("tx").(*pop.Connection)
	request := c.Request()
	request.ParseForm()

	remoteAddress := strings.Split(request.RemoteAddr, ":")[0]

	err := tx.RawQuery(
		models.Q["registeruser"],
		request.FormValue("email"),
		remoteAddress,
		request.FormValue("survey_results"),
	).Exec()

	if err != nil {
		return c.Error(
			500,
			fmt.Errorf(
				"Error inserting registration to database: %s for remote address %s",
				err.Error(),
				remoteAddress))
	}

	log.Info("processed a registration")
	message := "success"
	return c.Render(200, r.JSON(map[string]string{"message": message}))
}

Refactor to use remote address from request.


package rtcp

// RawPacket represents an unparsed RTCP packet. It's returned by Unmarshal when
// a packet with an unknown type is encountered.
type RawPacket []byte

// Marshal encodes the packet in binary.
func (r RawPacket) Marshal() ([]byte, error) {
	return r, nil
}

// Unmarshal decodes the packet from binary.
func (r *RawPacket) Unmarshal(b []byte) error {
	if len(b) < (headerLength) {
		return errPacketTooShort
	}
	*r = b

	var h Header
	if err := h.Unmarshal(b); err != nil {
		return err
	}

	return nil
}

// Header returns the Header associated with this packet.
func (r RawPacket) Header() Header {
	var h Header
	if err := h.Unmarshal(r); err != nil {
		return Header{}
	}
	return h
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
func (r *RawPacket) DestinationSSRC() []uint32 {
	return []uint32{}
}

package rtcp

// RawPacket represents an unparsed RTCP packet. It's returned by Unmarshal when
// a packet with an unknown type is encountered.
type RawPacket []byte

// Marshal encodes the packet in binary.
func (r RawPacket) Marshal() ([]byte, error) {
	return r, nil
}

// Unmarshal decodes the packet from binary.
func (r *RawPacket) Unmarshal(b []byte) error {
	if len(b) < (headerLength) {
		return errPacketTooShort
	}
	*r = b

	var h Header
	return h.Unmarshal(b)
}

// Header returns the Header associated with this packet.
func (r RawPacket) Header() Header {
	var h Header
	if err := h.Unmarshal(r); err != nil {
		return Header{}
	}
	return h
}

// DestinationSSRC returns an array of SSRC values that this packet refers to.
func (r *RawPacket) DestinationSSRC() []uint32 {
	return []uint32{}
}

Fix golint and misspell errors


package request

import "net/http"

var DefaultClient = ClientImplementation{http.DefaultClient}

type Client interface {
	Get(string, ...Parameter) (*Response, error)
}

type ClientImplementation struct {
	HTTPClient *http.Client
}

func (c *ClientImplementation) performRequest(r *Request) (*Response, error) {
	req := r.Normalize()

	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, err
	}

	return &Response{resp}, nil
}

func (c *ClientImplementation) Perform(method, url string, params ...Parameter) (*Response, error) {
	req := &Request{
		URL:     url,
		Method:  method,
		Headers: http.Header{},
	}

	for _, parametrize := range params {
		parametrize(req)
	}

	return c.performRequest(req)
}

package request

import (
	"fmt"
	"net/http"
	"strings"
)

var DefaultClient = ClientImplementation{http.DefaultClient}

type Client interface {
	Get(string, ...Parameter) (*Response, error)
}

type ClientImplementation struct {
	HTTPClient *http.Client
}

func (c *ClientImplementation) performRequest(r *Request) (*Response, error) {
	req := r.Normalize()

	resp, err := c.HTTPClient.Do(req)
	if err != nil {
		return nil, err
	}

	if !strings.HasPrefix(resp.Status, "20") {
		return nil, fmt.Errorf("request: bad status code %v", resp.StatusCode)
	}

	return &Response{resp}, nil
}

func (c *ClientImplementation) Perform(method, url string, params ...Parameter) (*Response, error) {
	req := &Request{
		URL:     url,
		Method:  method,
		Headers: http.Header{},
	}

	for _, parametrize := range params {
		parametrize(req)
	}

	return c.performRequest(req)
}

Return more meaningful status code messages in request pkg


package main

import (
	"net/http"

	"github.com/bigroom/communicator"
)

func defaultServerHandler(w http.ResponseWriter, r *http.Request) {
	coms := communicator.New(w)

	resp := struct {
		Server string `json:"server"`
	}{
		Server: *defaultIRCServer,
	}

	coms.With(resp).
		OK("Here is your thing!")
}

package main

import (
	"net/http"

	"github.com/bigroom/communicator"
)

func defaultServerHandler(w http.ResponseWriter, r *http.Request) {
	coms := communicator.New(w)

	resp := struct {
		Server string `json:"server"`
	}{
		Server: *defaultIRCServer,
	}

	coms.With(resp).
		OK()
}

Fix communicator to work with new API


package acme

import (
	"fmt"

	"github.com/jetstack-experimental/cert-manager/pkg/apis/certmanager/v1alpha1"
)

func (a *Acme) Setup() (v1alpha1.IssuerStatus, error) {
	updateStatus := a.issuer.Status.DeepCopy()

	err := a.verifyAccount()

	if err == nil {
		updateStatus.Ready = true
		return *updateStatus, nil
	}

	uri, err := a.registerAccount()

	if err != nil {
		updateStatus.Ready = false
		return *updateStatus, fmt.Errorf("error registering acme account: %s", err.Error())
	}

	updateStatus.ACMEStatus().URI = uri

	return *updateStatus, nil
}

package acme

import (
	"fmt"

	"github.com/jetstack-experimental/cert-manager/pkg/apis/certmanager/v1alpha1"
)

const (
	reasonAccountVerified           = "ACME account verified"
	reasonAccountRegistered         = "ACME account registered"
	reasonAccountRegistrationFailed = "ACME account registration failed"

	messageAccountVerified           = "The ACME account was verified with the ACME server"
	messagedAccountRegistered        = "The ACME account was registered with the ACME server"
	messageAccountRegistrationFailed = "Failed to register ACME account with server: %s"
)

func (a *Acme) Setup() (v1alpha1.IssuerStatus, error) {
	err := a.verifyAccount()

	if err == nil {
		update := v1alpha1.UpdateIssuerStatusCondition(a.issuer, v1alpha1.IssuerConditionReady, v1alpha1.ConditionTrue, reasonAccountVerified, reasonAccountRegistered)
		return update.Status, nil
	}

	uri, err := a.registerAccount()

	if err != nil {
		update := v1alpha1.UpdateIssuerStatusCondition(a.issuer, v1alpha1.IssuerConditionReady, v1alpha1.ConditionFalse, reasonAccountRegistrationFailed, fmt.Sprintf(messageAccountRegistrationFailed, err.Error()))
		return update.Status, fmt.Errorf("error registering acme account: %s", err.Error())
	}

	update := v1alpha1.UpdateIssuerStatusCondition(a.issuer, v1alpha1.IssuerConditionReady, v1alpha1.ConditionFalse, reasonAccountRegistered, messageAccountVerified)
	update.Status.ACMEStatus().URI = uri

	return update.Status, nil
}

Switch to using Conditions for Issuer status


package gfx

// ClearMask represents a bitmask to choose which buffers to clear during a
// framebuffer clearing operation. It must be one of the predefined constants.
type ClearMask int

// Clearing masks to select the color, depth, and stencil buffers. They can be
// bitwise OR'd together to select multiple:
//
//  colorAndDepth := ColorBufer|DepthBuffer
//
const (
	ColorBuffer ClearMask = iota
	DepthBuffer
	StencilBuffer
)

// Clearable represents the clearing state and API of a framebuffer object.
type Clearable interface {
	// ClearColor sets the color to clear the color buffer to upon a call to
	// the Clear method.
	ClearColor(r, g, b, a float32)

	// ClearDepth sets the value to clear the depth buffer to upon a depth
	// buffer clearing operation (a call to Clear with the DepthBuffer clear
	// mask)
	ClearDepth(depth float32)

	// ClearStencil sets the value to clear the stencil buffer to upon a
	// stencil buffer clearing operation (a call to Clear with the
	// StencilBuffer clear mask)
	ClearStencil(stencil int)

	// Clear clears the buffers selected by the bitmask to their respective
	// clear values. Multiple bitmasks can be OR'd together to select multiple
	// buffers to clear at once:
	//
	//  // Clear both(!) the color and depth buffers in one call.
	//  Clear(ColorBuffer|DepthBuffer)
	//
	Clear(m ClearMask)
}

package gfx

// ClearMask represents a bitmask to choose which buffers to clear during a
// framebuffer clearing operation. It must be one of the predefined constants.
type ClearMask int

// Clearing masks to select the color, depth, and stencil buffers. They can be
// bitwise OR'd together to select multiple:
//
//  colorAndDepth := ColorBufer|DepthBuffer
//
const (
	ColorBuffer ClearMask = 1 << iota
	DepthBuffer
	StencilBuffer
)

// Clearable represents the clearing state and API of a framebuffer object.
type Clearable interface {
	// ClearColor sets the color to clear the color buffer to upon a call to
	// the Clear method.
	ClearColor(r, g, b, a float32)

	// ClearDepth sets the value to clear the depth buffer to upon a depth
	// buffer clearing operation (a call to Clear with the DepthBuffer clear
	// mask)
	ClearDepth(depth float32)

	// ClearStencil sets the value to clear the stencil buffer to upon a
	// stencil buffer clearing operation (a call to Clear with the
	// StencilBuffer clear mask)
	ClearStencil(stencil int)

	// Clear clears the buffers selected by the bitmask to their respective
	// clear values. Multiple bitmasks can be OR'd together to select multiple
	// buffers to clear at once:
	//
	//  // Clear both(!) the color and depth buffers in one call.
	//  Clear(ColorBuffer|DepthBuffer)
	//
	Clear(m ClearMask)
}

Fix declaration of ClearMask bitmasks.


package probe

import (
	"github.com/weaveworks/scope/report"
)

type topologyTagger struct{}

// NewTopologyTagger tags each node with the topology that it comes from. It's
// kind of a proof-of-concept tagger, useful primarily for debugging.
func NewTopologyTagger() Tagger {
	return &topologyTagger{}
}

func (topologyTagger) Name() string { return "Topology" }

// Tag implements Tagger
func (topologyTagger) Tag(r report.Report) (report.Report, error) {
	for name, t := range map[string]*report.Topology{
		report.Endpoint:       &(r.Endpoint),
		report.Process:        &(r.Process),
		report.Container:      &(r.Container),
		report.ContainerImage: &(r.ContainerImage),
		report.Pod:            &(r.Pod),
		report.Service:        &(r.Service),
		report.Host:           &(r.Host),
		report.Overlay:        &(r.Overlay),
	} {
		for _, node := range t.Nodes {
			t.AddNode(node.WithTopology(name))
		}
	}
	return r, nil
}

package probe

import (
	"github.com/weaveworks/scope/report"
)

type topologyTagger struct{}

// NewTopologyTagger tags each node with the topology that it comes from. It's
// kind of a proof-of-concept tagger, useful primarily for debugging.
func NewTopologyTagger() Tagger {
	return &topologyTagger{}
}

func (topologyTagger) Name() string { return "Topology" }

// Tag implements Tagger
func (topologyTagger) Tag(r report.Report) (report.Report, error) {
	for name, t := range map[string]*report.Topology{
		report.Endpoint:       &(r.Endpoint),
		report.Process:        &(r.Process),
		report.Container:      &(r.Container),
		report.ContainerImage: &(r.ContainerImage),
		report.Pod:            &(r.Pod),
		report.Service:        &(r.Service),
		report.ECSTask:        &(r.ECSTask),
		report.ECSService:     &(r.ECSService),
		report.Host:           &(r.Host),
		report.Overlay:        &(r.Overlay),
	} {
		for _, node := range t.Nodes {
			t.AddNode(node.WithTopology(name))
		}
	}
	return r, nil
}

Add ECS topologies to tagger


package fsutil

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

func copyToFile(destFilename string, perm os.FileMode, reader io.Reader,
	length uint64) error {
	tmpFilename := destFilename + "~"
	destFile, err := os.OpenFile(tmpFilename, os.O_CREATE|os.O_WRONLY, perm)
	if err != nil {
		return err
	}
	defer os.Remove(tmpFilename)
	defer destFile.Close()
	writer := bufio.NewWriter(destFile)
	defer writer.Flush()
	var nCopied int64
	if nCopied, err = io.Copy(writer, reader); err != nil {
		return fmt.Errorf("error copying: %s", err)
	}
	if nCopied != int64(length) {
		return fmt.Errorf("expected length: %d, got: %d for: %s\n",
			length, nCopied, tmpFilename)
	}
	return os.Rename(tmpFilename, destFilename)
}

package fsutil

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

func copyToFile(destFilename string, perm os.FileMode, reader io.Reader,
	length uint64) error {
	tmpFilename := destFilename + "~"
	destFile, err := os.OpenFile(tmpFilename, os.O_CREATE|os.O_WRONLY, perm)
	if err != nil {
		return err
	}
	defer os.Remove(tmpFilename)
	defer destFile.Close()
	var nCopied int64
	if nCopied, err = io.Copy(destFile, reader); err != nil {
		return fmt.Errorf("error copying: %s", err)
	}
	if nCopied != int64(length) {
		return fmt.Errorf("expected length: %d, got: %d for: %s\n",
			length, nCopied, tmpFilename)
	}
	return os.Rename(tmpFilename, destFilename)
}

Fix ignore of error when calling Flush() in lib/fsutil.CopyToFile().


package stats

type SingleStat struct {
	TotalGB float32
	UsedGB float32
	AvailableGB float32
	UsagePercentage float32
}

type MultipleStat struct {
	AverageUsagePercentage float32
	UsagePercentagePerCore []float32
}

package stats

type SingleStat struct {
	TotalGB         float32 `json:"totalGB"`
	UsedGB          float32 `json:"usedGB"`
	AvailableGB     float32 `json:"availableGB"`
	UsagePercentage float32 `json:"usagePercentage"`
}

type MultipleStat struct {
	AverageUsagePercentage float32   `json:"averageUsagePercentage"`
	UsagePercentagePerCore []float32 `json:"usagePercentagePerCore"`
}

type AllStat struct {
	CPU  MultipleStat `json:"cpu"`
	RAM  SingleStat   `json:"ram"`
	Disk SingleStat   `json:"disk"`
}

Define JSON data structure serialization.


package matching

import "github.com/SpectoLabs/hoverfly/core/state"

func StateMatcher(currentState *state.State, requiredState map[string]string) *FieldMatch {

	score := 0
	matched := true

	if requiredState == nil || len(requiredState) == 0 {
		return &FieldMatch{
			Matched: true,
			Score:   0,
		}
	}

	currentState.RWMutex.RLock()
	for key, value := range requiredState {
		if _, ok := currentState.State[key]; !ok {
			matched = false
		}
		if currentState.State[key] != value {
			matched = false
		} else {
			score++
		}
	}
	currentState.RWMutex.RUnlock()

	return &FieldMatch{
		Matched: matched,
		Score:   score,
	}
}

package matching

import "github.com/SpectoLabs/hoverfly/core/state"

func StateMatcher(currentState *state.State, requiredState map[string]string) *FieldMatch {

	score := 0
	matched := true

	if requiredState == nil || len(requiredState) == 0 {
		return &FieldMatch{
			Matched: true,
			Score:   0,
		}
	}

	currentState.RWMutex.RLock()
	copy_state := currentState.State
	currentState.RWMutex.RUnlock()
	for key, value := range requiredState {
		if _, ok := copy_state[key]; !ok {
			matched = false
		}
		if copy_state[key] != value {
			matched = false
		} else {
			score++
		}
	}

	return &FieldMatch{
		Matched: matched,
		Score:   score,
	}
}

Copy state before checking values


/* This example demonstrates reading a string from input, rather than a
 * single character. Note that only the 'n' versions of getstr have been
 * implemented in goncurses to ensure buffer overflows won't exist */

package main

import gc "code.google.com/p/goncurses"

func main() {
	stdscr, _ := gc.Init()
	defer gc.End()

	row, col := stdscr.Maxyx()
	msg := "Enter a string: "
	stdscr.Print(row/2, (col-len(msg)-8)/2, msg)

	str, _ := stdscr.GetString(10)
	stdscr.Print(row-2, 0, "You entered: %s", str)

	stdscr.Refresh()
	stdscr.GetChar()
}

/* This example demonstrates reading a string from input, rather than a
 * single character. Note that only the 'n' versions of getstr have been
 * implemented in goncurses to ensure buffer overflows won't exist */

package main

import gc "code.google.com/p/goncurses"

func main() {
	stdscr, _ := gc.Init()
	defer gc.End()

	row, col := stdscr.Maxyx()
	msg := "Enter a string: "
	stdscr.MovePrint(row/2, (col-len(msg)-8)/2, msg)

	str, _ := stdscr.GetString(10)
	stdscr.MovePrint(row-2, 0, "You entered: %s", str)

	stdscr.Refresh()
	stdscr.GetChar()
}

Update form example for MovePrint


package main

import (
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"os"
)

var (
	// Use mcu pin 22, corresponds to GPIO3 on the pi
	pin = rpio.Pin(22)
)

func main() {
	// Open and map memory to access gpio, check for errors
	if err := rpio.Open(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Unmap gpio memory when done
	defer rpio.Close()

	// Pull up and read value
	pin.PullUp()
	fmt.Printf("PullUp: %d\n", pin.Read())

	// Pull down and read value
	pin.PullDown()
	fmt.Printf("PullDown: %d\n", pin.Read())

}

package main

import (
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"os"
)

var (
	// Use mcu pin 22, corresponds to GPIO3 on the pi
	pin = rpio.Pin(22)
)

func main() {
	// Open and map memory to access gpio, check for errors
	if err := rpio.Open(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Unmap gpio memory when done
	defer rpio.Close()

	// Pull up and read value
	pin.PullUp()
	fmt.Printf("PullUp: %d, %d\n", pin.Read(), pin.ReadPull())

	// Pull down and read value
	pin.PullDown()
	fmt.Printf("PullDown: %d, %d\n", pin.Read(), pin.ReadPull())

}

Expand example to cover new Pi 4 ReadPull() interface


package model

type Site struct {
	ID              string      `json:"id,omitempty" redis:"id"`
	Name            *string     `json:"name,omitempty" redis:"name"`
	Type            *string     `json:"type,omitempty" redis:"type"`
	Latitude        *float64    `json:"latitude,omitempty" redis:"latitude"`
	Longitude       *float64    `json:"longitude,omitempty" redis:"longitude"`
	TimeZoneID      *string     `json:"timeZoneId,omitempty" redis:"timeZoneId"`
	TimeZoneName    *string     `json:"timeZoneName,omitempty" redis:"timeZoneName"`
	TimeZoneOffset  *int        `json:"timeZoneOffset,omitempty" redis:"timeZoneOffset"`
	SitePreferences interface{} `json:"site-preferences,omitempty" redis:"site-preferences,json"`
}

//https://maps.googleapis.com/maps/api/timezone/json?location=-33.86,151.20&timestamp=1414645501

/*{
  id: "whatever",
  name: "Home",
  type: "home",
  latitude: -33.86,
  longitude: 151.20,
  timeZoneID: "Australia/Sydney",
  timeZoneName: "Australian Eastern Daylight Time",
  timeZoneOffset: 36000
}*/

package model

type Site struct {
	ID              string      `json:"id,omitempty" redis:"id"`
	Name            *string     `json:"name,omitempty" redis:"name"`
	Type            *string     `json:"type,omitempty" redis:"type"`
	Latitude        *float64    `json:"latitude,omitempty" redis:"latitude"`
	Longitude       *float64    `json:"longitude,omitempty" redis:"longitude"`
	TimeZoneID      *string     `json:"timeZoneId,omitempty" redis:"timeZoneId"`
	TimeZoneName    *string     `json:"timeZoneName,omitempty" redis:"timeZoneName"`
	TimeZoneOffset  *int        `json:"timeZoneOffset,omitempty" redis:"timeZoneOffset"`
	SitePreferences interface{} `json:"site-preferences,omitempty" redis:"site-preferences,json"`
	DefaultRoomID   *string     `json:"defaultRoomId,omitempty" redis:"defaultRoomId,json"`
}

//https://maps.googleapis.com/maps/api/timezone/json?location=-33.86,151.20&timestamp=1414645501

/*{
  id: "whatever",
  name: "Home",
  type: "home",
  latitude: -33.86,
  longitude: 151.20,
  timeZoneID: "Australia/Sydney",
  timeZoneName: "Australian Eastern Daylight Time",
  timeZoneOffset: 36000
}*/

Extend site model with storage for a defaultRoomID.


package dto

// type MessageIn struct {
// 	Id      string `json:"-"`
// 	Topic   string `json:"topic"`
// 	Payload string `json:"payload"`
// }

// type MessageOut struct {
// 	Id      string      `json:"-"`
// 	Topic   string      `json:"topic"`
// 	Payload interface{} `json:"payload"`
// }

// Packet -
type Packet struct {
	ID      string      `json:"-"`
	Topic   string      `json:"topic"`
	Payload interface{} `json:"payload"`
}

type Locate struct {
	Payload []string `json:"payload"`
}

package dto

// type MessageIn struct {
// 	Id      string `json:"-"`
// 	Topic   string `json:"topic"`
// 	Payload string `json:"payload"`
// }

// type MessageOut struct {
// 	Id      string      `json:"-"`
// 	Topic   string      `json:"topic"`
// 	Payload interface{} `json:"payload"`
// }

// Packet -
type Packet struct {
	ID      string      `json:"-"`
	Topic   string      `json:"topic"`
	Payload interface{} `json:"payload"`
}

type Chosen struct {
	Payload []string `json:"payload"`
}

Set a proper name for the dto


package main

import (
	"fmt"
	"github.com/go-martini/martini"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
)

type Human struct {
	Name string
	Age  string
}

func main() {
	f, err := os.Open("/home/user/GoCode/src/html/SimpleTemplate.html")
	defer f.Close()
	if err != nil {
		fmt.Println(err)
	}
	data, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Println(err)
	}
	//tmpl, err := template.New("test").Parse("Hello {{.Name}} aged {{.Age}}. Nice to meet you!!!")
	tmpl, err := template.New("test").Parse(string(data))
	if err != nil {
		fmt.Println(err)
	}

	m := martini.Classic()
	m.Get("/:name/:age", func(params martini.Params, res http.ResponseWriter, req *http.Request) {
		testSubject := Human{params["name"], params["age"]}
		err = tmpl.Execute(res, testSubject)
		if err != nil {
			fmt.Println(err)
		}
	})
	m.Run()
}

package main

import (
	"fmt"
	"github.com/go-martini/martini"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
)

type Human struct {
	Name string
	Age  string
}

func main() {
	f, err := os.Open("src/html/SimpleTemplate.html")
	defer f.Close()
	if err != nil {
		fmt.Println(err)
	}
	data, err := ioutil.ReadAll(f)
	if err != nil {
		fmt.Println(err)
	}
	//tmpl, err := template.New("test").Parse("Hello {{.Name}} aged {{.Age}}. Nice to meet you!!!")
	tmpl, err := template.New("test").Parse(string(data))
	if err != nil {
		fmt.Println(err)
	}

	m := martini.Classic()
	m.Get("/:name/:age", func(params martini.Params, res http.ResponseWriter, req *http.Request) {
		testSubject := Human{params["name"], params["age"]}
		err = tmpl.Execute(res, testSubject)
		if err != nil {
			fmt.Println(err)
		}
	})
	m.Run()
}

Fix path to be cross-platform


package monk

import (
	"fmt"
)

type Resolution struct {
	Resolved []string
	Seen     []string
}

// Resolve the asset at assetPath and its dependencies.
//
// TODO should return error
func (r *Resolution) Resolve(assetPath string, context *Context) error {
	r.Seen = append(r.Seen, assetPath)

	asset, err := context.lookup(assetPath)
	if err != nil {
		return err
	}

	for _, edge := range asset.Dependencies {
		if !contains(edge, r.Resolved) {
			if contains(edge, r.Seen) {
				return fmt.Errorf("circular dependency detected: %s <-> %s", assetPath, edge)
			}
			if err := r.Resolve(edge, context); err != nil {
				return err
			}
		}
	}

	r.Resolved = append(r.Resolved, assetPath)
	return nil
}

func contains(needle string, haystack []string) bool {
	found := false

	for _, item := range haystack {
		if needle == item {
			found = true
			break
		}
	}

	return found
}

package monk

import (
	"fmt"
)

type Resolution struct {
	Resolved []string
	Seen     []string
}

// Resolve the asset at assetPath and its dependencies.
func (r *Resolution) Resolve(assetPath string, context *Context) error {
	r.Seen = append(r.Seen, assetPath)

	asset, err := context.lookup(assetPath)
	if err != nil {
		return err
	}

	for _, edge := range asset.Dependencies {
		if !contains(edge, r.Resolved) {
			if contains(edge, r.Seen) {
				return fmt.Errorf("circular dependency detected: %s <-> %s", assetPath, edge)
			}
			if err := r.Resolve(edge, context); err != nil {
				return err
			}
		}
	}

	r.Resolved = append(r.Resolved, assetPath)
	return nil
}

func contains(needle string, haystack []string) bool {
	found := false

	for _, item := range haystack {
		if needle == item {
			found = true
			break
		}
	}

	return found
}

Resolve already returns an error.


package geocodio

import (
	"errors"
)

const (
	// GeocodioAPIBaseURLv1 is the Geocod.io Base URL
	GeocodioAPIBaseURLv1 = "https://api.geocod.io/v1.5"
)

// NewGeocodio is a helper to create new Geocodio pointer
func NewGeocodio(apiKey string) (*Geocodio, error) {

	if apiKey == "" {
		return nil, errors.New("apiKey is missing")
	}

	newGeocodio := new(Geocodio)
	newGeocodio.APIKey = apiKey

	return newGeocodio, nil
}

package geocodio

import (
	"os"
	"strings"
)

const (
	// GeocodioAPIBaseURLv1 is the Geocod.io Base URL
	GeocodioAPIBaseURLv1 = "https://api.geocod.io/v1.6"
)

// Geocodio is the base struct
type Geocodio struct {
	APIKey string
}

type Input struct {
	AddressComponents Components `json:"address_components"`
	FormattedAddress  string     `json:"formatted_address"`
}

// New creates a new Geocodio instance based on an API key in either the environment
// or passed in as the first string value
func New(apiKey ...string) (*Geocodio, error) {

	key := os.Getenv(EnvGeocodioAPIKey)
	if strings.TrimSpace(key) == "" {
		key = os.Getenv(EnvOldAPIKey)
	}
	if len(apiKey) == 0 && strings.TrimSpace(key) == "" {
		return nil, ErrMissingApiKey
	}

	if len(apiKey) == 1 {
		key = apiKey[0]
	}

	if strings.TrimSpace(key) == "" {
		return nil, ErrMissingApiKey
	}

	return NewGeocodio(key)
}

// NewGeocodio is a helper to create new Geocodio reference
// since 1.6+ this is kept for backwards compatiblity
// after 2+ this will be deprecated
func NewGeocodio(apiKey string) (*Geocodio, error) {

	if apiKey == "" {
		return nil, ErrMissingApiKey
	}

	g := Geocodio{
		APIKey: apiKey,
	}

	return &g, nil
}

Add simplified New and support env value


package plugin

import (
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

type metaDataStore struct {
	dir           string
	installTarget *installTarget
}

var errDisaleMetaDataStore = errors.New("MetaData disabled. could not detect owner/repo")

func newMetaDataStore(pluginDir string, target *installTarget) (*metaDataStore, error) {
	owner, repo, err := target.getOwnerAndRepo()
	if err != nil {
		return nil, errDisaleMetaDataStore
	}
	dir := filepath.Join(pluginDir, "meta", owner, repo)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, err
	}
	return &metaDataStore{
		dir:           dir,
		installTarget: target,
	}, nil
}

func (m *metaDataStore) load(key string) (string, error) {
	f, err := os.OpenFile(
		filepath.Join(m.dir, key),
		os.O_RDONLY|os.O_CREATE,
		0644,
	)
	if err != nil {
		return "", err
	}
	defer f.Close()
	b, err := ioutil.ReadAll(f)
	return string(b), err
}

func (m *metaDataStore) store(key, value string) error {
	return ioutil.WriteFile(
		filepath.Join(m.dir, key),
		[]byte(value),
		0644,
	)
}

package plugin

import (
	"io/ioutil"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
)

type metaDataStore struct {
	dir           string
	installTarget *installTarget
}

var errDisaleMetaDataStore = errors.New("MetaData disabled. could not detect owner/repo")

func newMetaDataStore(pluginDir string, target *installTarget) (*metaDataStore, error) {
	owner, repo, err := target.getOwnerAndRepo()
	if err != nil {
		return nil, errDisaleMetaDataStore
	}
	dir := filepath.Join(pluginDir, "meta", owner, repo)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, err
	}
	return &metaDataStore{
		dir:           dir,
		installTarget: target,
	}, nil
}

func (m *metaDataStore) load(key string) (string, error) {
	b, err := ioutil.ReadFile(filepath.Join(m.dir, key))
	if os.IsNotExist(err) {
		return "", nil
	} else if err != nil {
		return "", err
	}
	return string(b), nil
}

func (m *metaDataStore) store(key, value string) error {
	return ioutil.WriteFile(
		filepath.Join(m.dir, key),
		[]byte(value),
		0644,
	)
}

Use ioutil.ReadFile instead of os.Openfile with O_CREATE.


// +build go1.7

package providertests

import (
	"testing"

	saml2 "github.com/russellhaering/gosaml2"
	"github.com/stretchr/testify/require"
)

func ExerciseProviderTestScenarios(t *testing.T, scenarios []ProviderTestScenario) {
	println("TESTING")
	for _, scenario := range scenarios {
		t.Run(scenario.ScenarioName, func(t *testing.T) {
			_, err := saml2.DecodeUnverifiedBaseResponse(scenario.Response)
			// DecodeUnverifiedBaseResponse is more permissive than RetrieveAssertionInfo.
			// If an error _is_ returned it should match, but it is OK for no error to be
			// returned even when one is expected during full validation.
			if err != nil {
				scenario.CheckError(t, err)
			}

			assertionInfo, err := scenario.ServiceProvider.RetrieveAssertionInfo(scenario.Response)
			if scenario.CheckError != nil {
				scenario.CheckError(t, err)
			} else {
				require.NoError(t, err)
			}

			if err == nil {
				if scenario.CheckWarningInfo != nil {
					scenario.CheckWarningInfo(t, assertionInfo.WarningInfo)
				} else {
					require.False(t, assertionInfo.WarningInfo.InvalidTime)
					require.False(t, assertionInfo.WarningInfo.NotInAudience)
				}
			}
		})
	}
}

// +build go1.7

package providertests

import (
	"testing"

	saml2 "github.com/russellhaering/gosaml2"
	"github.com/stretchr/testify/require"
)

func ExerciseProviderTestScenarios(t *testing.T, scenarios []ProviderTestScenario) {
	for _, scenario := range scenarios {
		t.Run(scenario.ScenarioName, func(t *testing.T) {
			_, err := saml2.DecodeUnverifiedBaseResponse(scenario.Response)
			// DecodeUnverifiedBaseResponse is more permissive than RetrieveAssertionInfo.
			// If an error _is_ returned it should match, but it is OK for no error to be
			// returned even when one is expected during full validation.
			if err != nil {
				scenario.CheckError(t, err)
			}

			assertionInfo, err := scenario.ServiceProvider.RetrieveAssertionInfo(scenario.Response)
			if scenario.CheckError != nil {
				scenario.CheckError(t, err)
			} else {
				require.NoError(t, err)
			}

			if err == nil {
				if scenario.CheckWarningInfo != nil {
					scenario.CheckWarningInfo(t, assertionInfo.WarningInfo)
				} else {
					require.False(t, assertionInfo.WarningInfo.InvalidTime)
					require.False(t, assertionInfo.WarningInfo.NotInAudience)
				}
			}
		})
	}
}

Remove extraneous println during tests


package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
)

var f = flag.String("f", "", "Output file, else stdout.")
var p = flag.String("p", "main", "Package.")

var fRE = regexp.MustCompile("[a-zA-Z0-9_]+")

func main() {
	flag.Parse()
	w := os.Stdout
	var err error
	if *f != "" {
		if w, err = os.Create(*f); err != nil {
			log.Fatal(err)
		}
		defer w.Close()
	}
	fmt.Fprintf(w, "package %s", *p)
	for _, fname := range flag.Args() {
		b, err := ioutil.ReadFile(fname)
		if err != nil {
			log.Fatal(err)
		}
		v := strings.Join(fRE.FindAllString(fname, -1), "_")
		fmt.Fprintf(w, "\n\nvar %s = []byte(%q)", v, b)
	}
}

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"strings"
)

var f = flag.String("f", "", "Output file, else stdout.")
var p = flag.String("p", "main", "Package.")

var fRE = regexp.MustCompile("[a-zA-Z0-9_]+")

func main() {
	flag.Parse()
	w := os.Stdout
	var err error
	if *f != "" {
		if w, err = os.Create(*f); err != nil {
			log.Fatal(err)
		}
		defer w.Close()
	}
	fmt.Fprintf(w, "package %s\n", *p)
	for _, fname := range flag.Args() {
		b, err := ioutil.ReadFile(fname)
		if err != nil {
			log.Fatal(err)
		}
		v := strings.Join(fRE.FindAllString(fname, -1), "_")
		fmt.Fprintf(w, "\nvar %s = []byte(%q)\n", v, b)
	}
}

Correct newlines for gofmt comapt


package config

import (
	"os"
	"syscall"
)

func createOrOpenLockedFile(name string) (file *os.File, err error) {
	if _, err := os.Stat(name); os.IsNotExist(err) {
		file, err = os.Create(name)
	} else {
		file, err = os.OpenFile(name, os.O_RDWR, 0644)
	}

	if err != nil {
		return
	}

	if flerr := syscall.Flock(int(file.Fd()), syscall.LOCK_EX); flerr != nil {
		return file, flerr
	}

	return
}

func closeLockedFile(file *os.File) error {
	syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
	return file.Close()
}

package config

import (
	"errors"
	"fmt"
	"os"
	"syscall"
)

type closedError struct {
	flockErr error
	fileErr  error
}

func (ce closedError) Error() string {
	return fmt.Sprintf("%s, %s", ce.fileErr.Error(), ce.flockErr.Error())
}

func newClosedError(flockErr, fileErr error) error {
	if fileErr == nil {
		fileErr = errors.New("no file errors")
	}

	if flockErr == nil {
		flockErr = errors.New("no lock errors")
	}

	return closedError{flockErr, fileErr}
}

func createOrOpenLockedFile(name string) (file *os.File, err error) {
	if _, err := os.Stat(name); os.IsNotExist(err) {
		file, err = os.Create(name)
	} else {
		file, err = os.OpenFile(name, os.O_RDWR, 0644)
	}

	if err != nil {
		return
	}

	if flockErr := syscall.Flock(int(file.Fd()), syscall.LOCK_EX); flockErr != nil {
		err = flockErr
	}

	return
}

func closeLockedFile(file *os.File) error {
	flockErr := syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
	fileErr := file.Close()

	if flockErr != nil || fileErr != nil {
		return newClosedError(flockErr, fileErr)
	}

	return nil
}

Handle the flock errors while closing


// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package workload

import (
	"gopkg.in/juju/charm.v5"
)

// Plugin represents the functionality of a workload plugin.
type Plugin interface {
	// Launch runs the plugin's "launch" command, passing the provided
	// workload definition. The output is converted to a Details.
	Launch(definition charm.Workload) (Details, error)
	// Destroy runs the plugin's "destroy" command for the given ID.
	Destroy(id string) error
	// Status runs the plugin's "status" command. The output is
	// converted to a PluginStatus.
	Status(id string) (PluginStatus, error)
}

Add blank lines in an interface.


package helpers

import (
	"runtime"
)

func IsWindows() bool {
	return runtime.GOOS == "windows"
}

package helpers

import (
	"runtime"

	. "github.com/onsi/ginkgo"
)

func IsWindows() bool {
	return runtime.GOOS == "windows"
}

func SkipIfWindows() {

	if IsWindows() {
		Skip("the OS is Windows")
	}

}

Add helper Skip test if OS is Windows


package client

import (
	"sync"

	"github.com/calebamiles/github-client/comments"
	"github.com/calebamiles/github-client/commits"
)

func (c *DefaultClient) processCommits(commitWithoutComments commits.CommitWithoutComments, cs *commitAccumulator, ready chan struct{}, wg *sync.WaitGroup, errs *errorAccumulator) {
	defer wg.Done()
	ready <- struct{}{}
	defer func() { <-ready }()

	var allComments []comments.Comment

	commentsPages, err := c.Fetcher.Fetch(commitWithoutComments.CommentsURL())
	if err != nil {
		errs.Add(err)
		return
	}

	for j := range commentsPages {
		commentsOnPage, commentsLoopErr := comments.New(commentsPages[j])
		if commentsLoopErr != nil {
			errs.Add(commentsLoopErr)
			return
		}

		allComments = append(allComments, commentsOnPage...)
	}

	commitToAdd := &commit{
		CommitWithoutComments: commitWithoutComments,
		comments:              allComments,
	}

	cs.Add(commitToAdd)
	return
}

type commit struct {
	commits.CommitWithoutComments
	comments []comments.Comment
}

func (c *commit) Comments() []comments.Comment { return c.comments }

package client

import (
	"sync"

	"github.com/calebamiles/github-client/comments"
	"github.com/calebamiles/github-client/commits"
)

func (c *DefaultClient) processCommits(commitWithoutComments commits.CommitWithoutComments, cs *commitAccumulator, ready chan struct{}, wg *sync.WaitGroup, errs *errorAccumulator) {
	defer wg.Done()
	ready <- struct{}{}
	defer func(readyChan chan struct{}) { <-readyChan }(ready)

	var allComments []comments.Comment

	commentsPages, err := c.Fetcher.Fetch(commitWithoutComments.CommentsURL())
	if err != nil {
		errs.Add(err)
		return
	}

	for j := range commentsPages {
		commentsOnPage, commentsLoopErr := comments.New(commentsPages[j])
		if commentsLoopErr != nil {
			errs.Add(commentsLoopErr)
			return
		}

		allComments = append(allComments, commentsOnPage...)
	}

	commitToAdd := &commit{
		CommitWithoutComments: commitWithoutComments,
		comments:              allComments,
	}

	cs.Add(commitToAdd)
	return
}

type commit struct {
	commits.CommitWithoutComments
	comments []comments.Comment
}

func (c *commit) Comments() []comments.Comment { return c.comments }

Fix bug in rate limiting when processing commits


package intern

import (
	"bufio"
	"io"
	"sync/atomic"
	"unsafe"
)

type sbwriter interface {
	WriteByte(byte) error
	WriteString(string) (int, error)
}

func (ctx *Context) WriteTo(rawwr io.Writer) error {
	w, ok := rawwr.(sbwriter)
	var bwr *bufio.Writer
	if !ok {
		bwr = bufio.NewWriter(rawwr)
		w = bwr
	}
	c := (*state)(atomic.LoadPointer(&ctx.p))
	for _, s := range c.r {
		_, e := w.WriteString(s)
		if e != nil {
			return e
		}
		e = w.WriteByte('\n')
		if e != nil {
			return e
		}
	}
	if bwr != nil {
		return bwr.Flush()
	}
	return nil
}

func ReadContext(rawrd io.Reader) (Context, error) {
	rd := bufio.NewReader(rawrd)
	st := newst()
	for {
		line, _, err := rd.ReadLine()
		if err != nil {
			if err == io.EOF {
				return Context{unsafe.Pointer(&st)}, nil
			}
			return Context{}, err
		}
		st.addMissing(string(line))
	}
}

package intern

import (
	"bufio"
	"io"
	"sync/atomic"
	"unsafe"
)

type sbwriter interface {
	WriteByte(byte) error
	WriteString(string) (int, error)
}

func (ctx *Context) WriteTo(rawwr io.Writer) error {
	w, ok := rawwr.(sbwriter)
	var bwr *bufio.Writer
	if !ok {
		bwr = bufio.NewWriter(rawwr)
		w = bwr
	}
	c := (*state)(atomic.LoadPointer(&ctx.p))
	for _, s := range c.r {
		_, e := w.WriteString(s)
		if e != nil {
			return e
		}
		e = w.WriteByte('\n')
		if e != nil {
			return e
		}
	}
	if bwr != nil {
		return bwr.Flush()
	}
	return nil
}

func ReadContext(rawrd io.Reader) (Context, error) {
	rd := bufio.NewReader(rawrd)
	st := newst()
	for {
		line, _, err := rd.ReadLine()
		if err != nil {
			if err == io.EOF {
				return Context{unsafe.Pointer(st)}, nil
			}
			return Context{}, err
		}
		st.addMissing(string(line))
	}
}

Fix yet another double-pointer bug


package core

import (
	"fmt"
)

// writer points a shared state. sharedStateSink will point to the same shared state
// even after the state is removed from the context.
type sharedStateSink struct {
	writer Writer
}

// NewSharedStateSink creates a sink that writes to SharedState.
func NewSharedStateSink(ctx *Context, name string) (Sink, error) {
	// Get SharedState by name
	state, err := ctx.SharedStates.Get(name)
	if err != nil {
		return nil, err
	}

	// It fails if the shared state cannot be written
	writer, ok := state.(Writer)
	if !ok {
		return nil, fmt.Errorf("'%v' state cannot be written")
	}

	s := &sharedStateSink{
		writer: writer,
	}
	return s, nil
}

func (s *sharedStateSink) Write(ctx *Context, t *Tuple) error {
	return s.writer.Write(ctx, t)
}

func (s *sharedStateSink) Close(ctx *Context) error {
	return nil
}
}

package core

import (
	"fmt"
)

// writer points a shared state. sharedStateSink will point to the same shared state
// even after the state is removed from the context.
type sharedStateSink struct {
	writer Writer
}

// NewSharedStateSink creates a sink that writes to SharedState.
func NewSharedStateSink(ctx *Context, name string) (Sink, error) {
	// Get SharedState by name
	state, err := ctx.SharedStates.Get(name)
	if err != nil {
		return nil, err
	}

	// It fails if the shared state cannot be written
	writer, ok := state.(Writer)
	if !ok {
		return nil, fmt.Errorf("'%v' state cannot be written", name)
	}

	s := &sharedStateSink{
		writer: writer,
	}
	return s, nil
}

func (s *sharedStateSink) Write(ctx *Context, t *Tuple) error {
	return s.writer.Write(ctx, t)
}

func (s *sharedStateSink) Close(ctx *Context) error {
	return nil
}
}

Fix return error correctly in NewSharedStateSink


package setting

import (
	"os"

	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/rancher/pkg/settings"
)

func New(store types.Store) types.Store {
	return &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			v, ok := data["value"]
			value := os.Getenv(settings.GetENVKey(apiContext.ID))
			switch {
			case value != "":
				data["value"] = value
				data["customized"] = false
				data["source"] = "env"

			case !ok || v == "":
				data["value"] = data["default"]
				data["customized"] = false
				data["source"] = "default"
			default:
				data["customized"] = true
				data["source"] = "db"
			}
			return data, nil
		},
	}
}

package setting

import (
	"os"

	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/norman/types/convert"
	"github.com/rancher/rancher/pkg/settings"
)

func New(store types.Store) types.Store {
	return &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			v, ok := data["value"]
			value := os.Getenv(settings.GetENVKey(convert.ToString(data["id"])))
			switch {
			case value != "":
				data["value"] = value
				data["customized"] = false
				data["source"] = "env"
			case !ok || v == "":
				data["value"] = data["default"]
				data["customized"] = false
				data["source"] = "default"
			default:
				data["customized"] = true
				data["source"] = "db"
			}
			return data, nil
		},
	}
}

Fix setting source attribute is not set when listting settings


package arbreader

import (
	"encoding/json"
	"io"
	"strings"

	"github.com/juju/errgo"
)

type Message struct {
  Key string
  Type string
  Extended map[string]string
  Description string
}

func Read(reader io.Reader) ([]*Message, error) {
	data := map[string]interface{}{}
	if err := json.NewDecoder(reader).Decode(&data); err != nil {
		return nil, errgo.Mask(err)
	}

	messages := []*Message{}
	for key := range data {
		if key[0] == '@' {
			continue
		}

		vv := data["@" + key].(map[string]interface{})

		extended := map[string]string{}
		for ekey, evalue := range vv {
			if !strings.HasPrefix(ekey, "x-") {
				continue
			}

			extended[ekey] = evalue.(string)
		}

		messages = append(messages, &Message{
			Key: key,
			Type: vv["type"].(string),
			Description: vv["description"].(string),
			Extended: extended,
		})
	}

	return messages, nil
}

package arbreader

import (
	"encoding/json"
	"io"
	"strings"

	"github.com/juju/errgo"
)

type Message struct {
  Key string
  Type string
  Extended map[string]string
  Description string
  Value string
}

func Read(reader io.Reader) ([]*Message, error) {
	data := map[string]interface{}{}
	if err := json.NewDecoder(reader).Decode(&data); err != nil {
		return nil, errgo.Mask(err)
	}

	messages := []*Message{}
	for key, value := range data {
		if key[0] == '@' {
			continue
		}

		vv := data["@" + key].(map[string]interface{})

		extended := map[string]string{}
		for ekey, evalue := range vv {
			if !strings.HasPrefix(ekey, "x-") {
				continue
			}

			extended[ekey] = evalue.(string)
		}

		messages = append(messages, &Message{
			Key: key,
			Type: vv["type"].(string),
			Description: vv["description"].(string),
			Extended: extended,
			Value: value,
		})
	}

	return messages, nil
}

Save the value of the message.


package xing

// Constants
const (
	// Type
	Command = "command"
	Event   = "event"
	Result  = "result"

	// Event
	Register = "Register"

	// Exchanges
	RPCExchange   = "xing.rpc"
	EventExchange = "xing.event"

	// Client Types
	ProducerClient      = "producer"
	ServiceClient       = "service"
	EventHandlerClient  = "event_handler"
	StreamHandlerClient = "stream_handler"

	// Defaults
	RPCTTL         = int64(1)
	EVTTTL         = int64(15 * 60 * 1000)     // 15 minutes
	STRMTTL        = int64(60 * 1000)          // 1 minutes
	ResultQueueTTL = int64(3 * 60 * 60 * 1000) // 10 minutes
	QueueTTL       = int64(3 * 60 * 60 * 1000) // 3 hours

	// Threshold
	MinHeatbeat = 3

	// Threading
	PoolSize = 1000
	NWorker  = 5
)

package xing

// Constants
const (
	// Type
	Command = "command"
	Event   = "event"
	Result  = "result"

	// Event
	Register = "Register"

	// Exchanges
	RPCExchange   = "xing.rpc"
	EventExchange = "xing.event"

	// Client Types
	ProducerClient      = "producer"
	ServiceClient       = "service"
	EventHandlerClient  = "event_handler"
	StreamHandlerClient = "stream_handler"

	// Defaults
	RPCTTL         = int64(1)
	EVTTTL         = int64(15 * 60 * 1000)     // 15 minutes
	STRMTTL        = int64(60 * 1000)          // 1 minutes
	ResultQueueTTL = int64(10 * 60 * 1000)     // 10 minutes
	QueueTTL       = int64(3 * 60 * 60 * 1000) // 3 hours

	// Threshold
	MinHeatbeat = 3

	// Threading
	PoolSize = 1000
	NWorker  = 5
)

Revert "increasing result queue TTL"


package main

import (
	"../../../drawer"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"
)

func main() {
	src := image.NewRGBA(image.Rect(0, 0, 100, 100))
	drawer.Fill(src, color.RGBA{0, 255, 255, 255})

	start := image.Pt(100, 100)
	end := image.Pt(0, 0)
	ld := drawer.NewLineDrawer(src, start, end, color.RGBA{255, 0, 0, 255}).Draw()
	draw(ld, src, "negative.png")

	start = image.Pt(0, 100)
	end = image.Pt(100, 0)
	ld.SetStart(end).SetEnd(start).Draw()
	draw(ld, src, "positive.png")
}

func draw(drawer *drawer.LineDrawer, src image.Image, filename string) {
	out, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer out.Close()
	fmt.Println("Writing output to:", filename)

	err = png.Encode(out, src)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

package main

import (
	"../../../drawer"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"os"
)

func main() {
	src := image.NewRGBA(image.Rect(0, 0, 100, 100))
	drawer.Fill(src, color.RGBA{0, 255, 255, 255})

	ld := drawer.NewLineDrawer(src, image.Pt(100, 100), image.Pt(0, 0), color.RGBA{255, 0, 0, 255}).Draw()
	draw(ld, src, "negative.png")

	ld.SetStart(image.Pt(0, 100)).SetEnd(image.Pt(100, 0)).Draw()
	draw(ld, src, "positive.png")

	ld.SetStart(image.Pt(0, 50)).SetEnd(image.Pt(100, 50)).SetThickness(5).Draw()
	draw(ld, src, "thick.png")
}

func draw(drawer *drawer.LineDrawer, src image.Image, filename string) {
	out, err := os.Create(filename)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	defer out.Close()
	fmt.Println("Writing output to:", filename)

	err = png.Encode(out, src)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

Add another example of a line that is thicker


// Package proto contains protocol buffers that are exchanged between the client
// and server.
//
// Generating Protocol Buffer Code
//
// Anytime the Protocol Buffer definitions change, the generated Go code must be
// regenerated. This can be done with "go generate". Just run:
//   go generate ./...
//
// Upstream documentation:
// https://developers.google.com/protocol-buffers/docs/reference/go-generated
//
// Code Generation Dependencies
//
// To generate the Go code, your system must have "protoc" installed. See:
// https://github.com/protocolbuffers/protobuf#protocol-compiler-installation
//
// The "protoc-gen-go" tool must also be installed. To install it, run:
//   go install google.golang.org/protobuf/cmd/protoc-gen-go
package proto

//go:generate protoc --go_out=. --go_opt=module=github.com/google/go-tpm-tools/proto tpm.proto attest.proto

// Package proto contains protocol buffers that are exchanged between the client
// and server.
//
// Generating Protocol Buffer Code
//
// Anytime the Protocol Buffer definitions change, the generated Go code must be
// regenerated. This can be done with "go generate". Just run:
//   go generate ./...
//
// Upstream documentation:
// https://developers.google.com/protocol-buffers/docs/reference/go-generated
//
// Code Generation Dependencies
//
// To generate the Go code, your system must have "protoc" installed. See:
// https://github.com/protocolbuffers/protobuf#protocol-compiler-installation
//
// The "protoc-gen-go" tool must also be installed. To install it, run:
//   go install google.golang.org/protobuf/cmd/protoc-gen-go
//
// If you see a 'protoc-gen-go: program not found or is not executable' error
// for the 'go generate' command, run the following:
//   echo 'export PATH=$PATH:$GOPATH/bin' >> $HOME/.bashrc
//   source $HOME/.bashrc
package proto

//go:generate protoc --go_out=. --go_opt=module=github.com/google/go-tpm-tools/proto tpm.proto attest.proto

Add instructions for resolving proto-gen-go error


// © 2012 Jay Weisskopf

package pty

// #include <stdlib.h>
// #include <fcntl.h>
import "C"

import "os"

func Open() (ptm *os.File, ptsName string, err error) {

	ptmFd, err := C.posix_openpt(C.O_RDWR | C.O_NOCTTY)
	if err != nil {
		return nil, "", err
	}
	ptm = os.NewFile(uintptr(ptmFd), "")
	defer func() {
		if err != nil && ptm != nil {
			ptm.Close()
		}
	}()

	_, err = C.grantpt(ptmFd)
	if err != nil {
		return nil, "", err
	}

	_, err = C.unlockpt(ptmFd)
	if err != nil {
		return nil, "", err
	}

	ptsNameCstr, err := C.ptsname(ptmFd)
	if err != nil {
		return nil, "", err
	}
	ptsName = C.GoString(ptsNameCstr)

	return ptm, ptsName, nil
}

// © 2012 Jay Weisskopf

package pty

// #include <stdlib.h>
// #include <fcntl.h>
import "C"

import "os"

func Open() (ptm *os.File, ptsName string, err error) {

	ptmFd, err := C.posix_openpt(C.O_RDWR | C.O_NOCTTY)
	if err != nil {
		return nil, "", err
	}
	ptm = os.NewFile(uintptr(ptmFd), "")
	defer func() {
		if err != nil && ptm != nil {
			ptm.Close()
			ptm = nil
		}
	}()

	_, err = C.grantpt(ptmFd)
	if err != nil {
		return nil, "", err
	}

	_, err = C.unlockpt(ptmFd)
	if err != nil {
		return nil, "", err
	}

	ptsNameCstr, err := C.ptsname(ptmFd)
	if err != nil {
		return nil, "", err
	}
	ptsName = C.GoString(ptsNameCstr)

	return ptm, ptsName, nil
}

Set ptm return pointer to nil if it is closed.


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

package bridge

import (
	"reflect"

	"github.com/sacloud/libsacloud/v2/helper/service/bridge"
	"github.com/sacloud/usacloud/pkg/cmd/core"
)

var Resource = &core.Resource{
	Name:        "bridge",
	ServiceType: reflect.TypeOf(&bridge.Service{}),
	Category:    core.ResourceCategoryStorage,
	CommandCategories: []core.Category{
		{
			Key:         "basic",
			DisplayName: "Basic Commands",
			Order:       10,
		},
		{
			Key:         "operation",
			DisplayName: "Operation Commands",
			Order:       20,
		},
		{
			Key:         "other",
			DisplayName: "Other Commands",
			Order:       1000,
		},
	},
}

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

package bridge

import (
	"reflect"

	"github.com/sacloud/libsacloud/v2/helper/service/bridge"
	"github.com/sacloud/usacloud/pkg/cmd/core"
)

var Resource = &core.Resource{
	Name:        "bridge",
	ServiceType: reflect.TypeOf(&bridge.Service{}),
	Category:    core.ResourceCategoryNetworking,
	CommandCategories: []core.Category{
		{
			Key:         "basic",
			DisplayName: "Basic Commands",
			Order:       10,
		},
		{
			Key:         "operation",
			DisplayName: "Operation Commands",
			Order:       20,
		},
		{
			Key:         "other",
			DisplayName: "Other Commands",
			Order:       1000,
		},
	},
}

Update command category from Storage to Networking


package main

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

func TestRootAccess(t *testing.T) {
	response := httptest.NewRecorder()

	n := setUpServer()

	req, err := http.NewRequest("GET", "http://localhost:8080/", nil)
	if err != nil {
		t.Error(err)
	}
	n.ServeHTTP(response, req)
	if response.Code != http.StatusOK {
		t.Errorf("Got error for GET ruquest to /")
	}
	body := string(response.Body.Bytes())
	expectedBody := "{\"status\":\"ok\"}"
	if body != expectedBody {
		t.Errorf("Got empty body for GET request to /\n Got: %s, Expected: %s", body, expectedBody)
	}
}

package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/wantedly/risu/schema"
)

func TestGitClone(t *testing.T) {
	opts := schema.BuildCreateOpts{
		SourceRepo: "wantedly/private-nginx-image-server",
		Name:       "quay.io/wantedly/private-nginx-image-server:test",
	}
	build := schema.NewBuild(opts)
	err := gitClone(build)
	if err != nil {
		t.Error(err)
	}
}

func TestRootAccess(t *testing.T) {
	response := httptest.NewRecorder()

	n := setUpServer()

	req, err := http.NewRequest("GET", "http://localhost:8080/", nil)
	if err != nil {
		t.Error(err)
	}
	n.ServeHTTP(response, req)
	if response.Code != http.StatusOK {
		t.Errorf("Got error for GET ruquest to /")
	}
	body := string(response.Body.Bytes())
	expectedBody := "{\"status\":\"ok\"}"
	if body != expectedBody {
		t.Errorf("Got empty body for GET request to /\n Got: %s, Expected: %s", body, expectedBody)
	}
}

Add test for git clone


package stats

import (
	"testing"
)

func TestCorrelation(t *testing.T) {
	s1 := []float64{1, 2, 3, 4, 5}
	s2 := []float64{10, -51.2, 8}
	s3 := []float64{1, 2, 3, 5, 6}
	s4 := []float64{}

	_, err := Correlation(s1, s2)
	if err == nil {
		t.Errorf("Mismatched slice lengths should have returned an error")
	}

	a, err := Correlation(s1, s3)
	if err != nil {
		t.Errorf("Should not have returned an error")
	}

	if a != 0.9912407071619302 {
		t.Errorf("Correlation %v != %v", a, 0.9912407071619302)
	}

	_, err = Correlation(s1, s4)
	if err == nil {
		t.Errorf("Empty slice should have returned an error")
	}

}

package stats

import (
	"testing"
)

func TestCorrelation(t *testing.T) {
	s1 := []float64{1, 2, 3, 4, 5}
	s2 := []float64{10, -51.2, 8}
	s3 := []float64{1, 2, 3, 5, 6}
	s4 := []float64{}
	s5 := []float64{0, 0, 0}

	a, err := Correlation(s5, s5)
	if err != nil {
		t.Errorf("Should not have returned an error")
	}
	if a != 0 {
		t.Errorf("Should have returned 0")
	}

	_, err = Correlation(s1, s2)
	if err == nil {
		t.Errorf("Mismatched slice lengths should have returned an error")
	}

	a, err = Correlation(s1, s3)
	if err != nil {
		t.Errorf("Should not have returned an error")
	}

	if a != 0.9912407071619302 {
		t.Errorf("Correlation %v != %v", a, 0.9912407071619302)
	}

	_, err = Correlation(s1, s4)
	if err == nil {
		t.Errorf("Empty slice should have returned an error")
	}

	a, err = Pearson(s1, s3)
	if err != nil {
		t.Errorf("Should not have returned an error")
	}

	if a != 0.9912407071619302 {
		t.Errorf("Correlation %v != %v", a, 0.9912407071619302)
	}

}

Add unit test for edge case that wasn't covered


package lib

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestRandomIds(t *testing.T) {
	Convey("Given a random identifier", t, func() {
		s := RandomIdentifier()
		Convey("Then it is a string", func() {
			So(s, ShouldHaveSameTypeAs, "asd")
		})
		Convey("When I generate another identifier", func() {
			t := RandomIdentifier()
			Convey("Then it is different from the original", func() {
				So(s, ShouldNotResemble, t)
			})
		})
	})
}

func TestRandomIdsWithLength(t *testing.T) {
	Convey("Given a random identifier of length 64", t, func() {
		s := RandomIdentifierOfLength(64)
		Convey("Then it has length 64", func() {
			So(s, ShouldHaveLength, 64)
		})
	})
}

package lib

import (
	"fmt"
)

func ExampleRandomIdentifier_AreDifferent() {
	a := RandomIdentifier()
	b := RandomIdentifier()
	fmt.Println(a == b)
	// Output: false
}

func ExampleRandomIdentifierOfLength() {
	s := RandomIdentifierOfLength(64)
	fmt.Println(len(s))
	// Output: 64
}

Use examples instead of explicit tests


package main

import (
	log "github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"time"
)

func RunPeriodically(c *cli.Context) error {

	log.SetFormatter(_makeFormatter(c.String("format")))

	log.WithFields(log.Fields{
		"appName": c.App.Name,
	}).Info("Running periodically")

	var period time.Duration = 1 * time.Second

	for {
		go func() {
			PrintHeartbeat()
		}()

		time.Sleep(period)
	}

	return nil
}

func PrintHeartbeat() {
	log.Info("Every heartbeat bears your name")
}

func _makeFormatter(format string) log.Formatter {
	switch format {
	case "text":
		return &log.TextFormatter{DisableColors: true}
	case "json":
		return &log.JSONFormatter{}
	default:
		return &log.JSONFormatter{}
	}
}

package main

import (
	log "github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"time"
)

func RunPeriodically(c *cli.Context) error {

	log.SetFormatter(_makeFormatter(c.String("format")))

	log.WithFields(log.Fields{
		"appName": c.App.Name,
	}).Info("Running periodically")

	period := 1 * time.Second

	for {
		go func() {
			PrintHeartbeat()
		}()

		time.Sleep(period)
	}

	return nil
}

func PrintHeartbeat() {
	log.Info("Every heartbeat bears your name")
}

func _makeFormatter(format string) log.Formatter {
	switch format {
	case "text":
		return &log.TextFormatter{DisableColors: true}
	case "json":
		return &log.JSONFormatter{}
	default:
		return &log.JSONFormatter{}
	}
}

Switch period from var to val.


package main

import (
	"flag"
	"fmt"
)

const CompareAndSwapUsage = `usage: etcdctl [etcd flags] compareAndSwap <key> <value> [testAndSet flags]
either prevValue or prevIndex needs to be given
special flags: --ttl to set a key with ttl
			   --pvalue to set the previous value
			   --pindex to set the previous index`

var (
	compareAndSwapFlag   = flag.NewFlagSet("testAndSet", flag.ExitOnError)
	compareAndSwapTtl    = compareAndSwapFlag.Uint64("ttl", 0, "ttl of the key")
	compareAndSwapPvalue = compareAndSwapFlag.String("pvalue", "", "previous value")
	compareAndSwapPindex = compareAndSwapFlag.Uint64("pindex", 0, "previous index")
)

func init() {
	// The minimum number of arguments is 3 because
	// there needs to be either pvalue or pindex
	registerCommand("compareAndSwap", CompareAndSwapUsage, 3, 6, compareAndSwap)
}

func compareAndSwap(args []string) error {
	key := args[0]
	value := args[1]
	compareAndSwapFlag.Parse(args[2:])
	resp, err := client.CompareAndSwap(key, value,
		*compareAndSwapTtl, *compareAndSwapPvalue, *compareAndSwapPindex)
	if debug {
		fmt.Println(<-curlChan)
	}
	if err != nil {
		return err
	}

	output(resp)
	return nil
}

package main

import (
	"flag"
	"fmt"
)

const CompareAndSwapUsage = `usage: etcdctl [etcd flags] compareAndSwap <key> <value> [testAndSet flags]
either prevValue or prevIndex needs to be given
special flags: --ttl to set a key with ttl
			   --prevValue to set the previous value
			   --prevIndex to set the previous index`

var (
	compareAndSwapFlag   = flag.NewFlagSet("testAndSet", flag.ExitOnError)
	compareAndSwapTtl    = compareAndSwapFlag.Uint64("ttl", 0, "ttl of the key")
	compareAndSwapPvalue = compareAndSwapFlag.String("prevValue", "", "previous value")
	compareAndSwapPindex = compareAndSwapFlag.Uint64("prevIndex", 0, "previous index")
)

func init() {
	// The minimum number of arguments is 3 because
	// there needs to be either pvalue or pindex
	registerCommand("compareAndSwap", CompareAndSwapUsage, 3, 6, compareAndSwap)
}

func compareAndSwap(args []string) error {
	key := args[0]
	value := args[1]
	compareAndSwapFlag.Parse(args[2:])
	resp, err := client.CompareAndSwap(key, value,
		*compareAndSwapTtl, *compareAndSwapPvalue, *compareAndSwapPindex)
	if debug {
		fmt.Println(<-curlChan)
	}
	if err != nil {
		return err
	}

	output(resp)
	return nil
}

Change flag names to match API params


package data

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type Project struct {
	ID         bson.ObjectId   `bson:"_id"`
	Name       string          `bson:"name"`
	OwnerId    bson.ObjectId   `bson:"owner_id"`
	MemberIds  []bson.ObjectId `bson:"member_ids"`
	CreatedAt  time.Time       `bson:"created_at"`
	ModifiedAt time.Time       `bson:"modified_at"`
}

func GetProject(id bson.ObjectId) (*Project, error) {
	pro := Project{}
	err := sess.DB("").C(projectC).FindId(id).One(&pro)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &pro, nil
}

package data

import (
	"time"

	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type Project struct {
	ID         bson.ObjectId   `bson:"_id"`
	Name       string          `bson:"name"`
	OwnerID    bson.ObjectId   `bson:"owner_id"`
	MemberIDs  []bson.ObjectId `bson:"member_ids"`
	CreatedAt  time.Time       `bson:"created_at"`
	ModifiedAt time.Time       `bson:"modified_at"`
}

func GetProject(id bson.ObjectId) (*Project, error) {
	pro := Project{}
	err := sess.DB("").C(projectC).FindId(id).One(&pro)
	if err == mgo.ErrNotFound {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &pro, nil
}

func (p *Project) Put() error {
	p.ModifiedAt = time.Now()

	if p.ID == "" {
		p.ID = bson.NewObjectId()
		p.CreatedAt = p.ModifiedAt
	}
	_, err := sess.DB("").C(organizationC).UpsertId(p.ID, p)
	return err
}

Implement Put for Project struct


package dsl

import (
	"goa.design/goa/v3/eval"
	"goa.design/goa/v3/expr"
)

// Value sets the example value.
//
// Value must appear in Example.
//
// Value takes one argument: the example value.
//
// Example:
//
//    Example("A simple bottle", func() {
//        Description("This bottle has an ID set to 1")
//        Value(Val{"ID": 1})
//    })
//
func Value(val interface{}) {
	switch e := eval.Current().(type) {
	case *expr.ExampleExpr:
		if v, ok := val.(expr.Val); ok {
			val = map[string]interface{}(v)
		}
		e.Value = val
	default:
		eval.IncompatibleDSL()
	}
}

package dsl

import (
	"goa.design/goa/v3/eval"
	"goa.design/goa/v3/expr"
)

// Val is an alias for expr.Val.
type Val expr.Val

// Value sets the example value.
//
// Value must appear in Example.
//
// Value takes one argument: the example value.
//
// Example:
//
//    Example("A simple bottle", func() {
//        Description("This bottle has an ID set to 1")
//        Value(Val{"ID": 1})
//    })
//
func Value(val interface{}) {
	switch e := eval.Current().(type) {
	case *expr.ExampleExpr:
		if v, ok := val.(expr.Val); ok {
			val = map[string]interface{}(v)
		}
		e.Value = val
	default:
		eval.IncompatibleDSL()
	}
}

Make 'Val' usable directly as DSL.


package tools

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"strings"
	"unicode"
	"unicode/utf8"
)

func ComputeHmac256(message string, secret string) string {
	key := []byte(secret)
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

func Capitalize(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

func JsonToGolang(in *string) (out string) {
	res := strings.Split(*in, "_")
	out = ""
	for _, s := range res {
		out += Capitalize(s)
	}
	return out
}

func CaseInsensitiveContains(s, substr string) bool {
	s, substr = strings.ToUpper(s), strings.ToUpper(substr)
	return strings.Contains(s, substr)
}

package tools

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"strings"
	"unicode"
	"unicode/utf8"
)

func ComputeHmac256(message string, secret string) string {
	key := []byte(secret)
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
func ComputeHmac256Html(message string, secret string) string {
	t := ComputeHmac256(message, secret)
	return strings.Replace(t, "/", "_", -1)
}

func Capitalize(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

func JsonToGolang(in *string) (out string) {
	res := strings.Split(*in, "_")
	out = ""
	for _, s := range res {
		out += Capitalize(s)
	}
	return out
}

func CaseInsensitiveContains(s, substr string) bool {
	s, substr = strings.ToUpper(s), strings.ToUpper(substr)
	return strings.Contains(s, substr)
}

Add special method for HTML urls issue with / when using the default hmac method


package migrate

type rev20140522205400 struct{}

var SaveDroneYml = &rev20140522205400{}

func (r *rev20140522205400) Revision() int64 {
	return 20140522205400
}

func (r *rev20140522205400) Up(mg *MigrationDriver) error {
	_, err := mg.AddColumn("builds", "buildscript TEXT")
	return err
}

func (r *rev20140522205400) Down(mg *MigrationDriver) error {
	_, err := mg.DropColumns("builds", "buildscript")
	return err
}

package migrate

type rev20140522205400 struct{}

var SaveDroneYml = &rev20140522205400{}

func (r *rev20140522205400) Revision() int64 {
	return 20140522205400
}

func (r *rev20140522205400) Up(mg *MigrationDriver) error {
	_, err := mg.AddColumn("builds", "buildscript TEXT")
	_, err = mg.Tx.Exec("UPDATE builds SET buildscript = '' WHERE buildscript IS NULL")
	return err
}

func (r *rev20140522205400) Down(mg *MigrationDriver) error {
	_, err := mg.DropColumns("builds", "buildscript")
	return err
}

Update buildscript for old builds


package iter

// Callback receives a value and returns true if another value should be
// received or false to stop iteration.
type Callback func(value interface{}) (more bool)

// Func iterates by calling Callback for each of its values.
type Func func(Callback)

func All(cb Callback, fs ...Func) bool {
	for _, f := range fs {
		all := true
		f(func(v interface{}) bool {
			all = all && cb(v)
			return all
		})
		if !all {
			return false
		}
	}
	return true
}

// Calls `cb` with the first value yielded by `f` and then stops iteration. `ok` if `cb` was called
// with a value.
func First(cb func(value interface{}),f Func) (ok bool) {
	f(func(value interface{}) bool {
		ok = true
		cb(value)
		return false
	})
	return
}

package iter

// Callback receives a value and returns true if another value should be
// received or false to stop iteration.
type Callback func(value interface{}) (more bool)

// Func iterates by calling Callback for each of its values.
type Func func(Callback)

func All(cb Callback, fs ...Func) bool {
	for _, f := range fs {
		all := true
		f(func(v interface{}) bool {
			all = all && cb(v)
			return all
		})
		if !all {
			return false
		}
	}
	return true
}

// Calls `cb` with the first value yielded by `f` and then stops iteration. `ok` if `cb` was called
// with a value. Returning the value interface{} would require the caller to keep a
func First(f Func) (value interface{}, ok bool) {
	f(func(x interface{}) bool {
		value = x
		ok = true
		return false
	})
	return
}

Change iter.First to return the value


package api

import (
	"io/ioutil"
	"net/http"
)

type LinodeClient struct {
	APIKey string
}

func NewLinodeClient() *LinodeClient {
	return NewLinodeClient()
}

func NewLinodeClientWithKey(apiKey string) *LinodeClient {
	return &LinodeClient{
		APIKey: apiKey,
	}
}

func (c *LinodeClient) ListLinodes() ([]byte, error) {
	response, err := http.Get(API_ENDPOINT + "/?api_key=" + c.APIKey +
		"&api_action=linode.list")
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

package api

import (
	"io/ioutil"
	"net/http"
	"net/url"
)

type LinodeClient struct {
	APIKey string
}

func NewLinodeClient() *LinodeClient {
	return NewLinodeClient()
}

func NewLinodeClientWithKey(apiKey string) *LinodeClient {
	return &LinodeClient{
		APIKey: apiKey,
	}
}

func (c *LinodeClient) APICall(query string) ([]byte, error) {
	response, err := http.Get(API_ENDPOINT + "/?" + query)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (c *LinodeClient) ListLinodes() ([]byte, error) {
	params := url.Values{}
	params.Add("api_key", c.APIKey)
	params.Add("api_action", "linode.list")
	return c.APICall(query)
}

Refactor HTTP call out of function


// Copyright 2014 GoIncremental Limited. All Rights Reserved.
//
// 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 web

import "github.com/joho/godotenv"

type Environment interface {
	Load(filenames ...string) error
}

type environment struct{}

func (e *environment) Load(s ...string) (err error) {
	err = godotenv.Load(s...)
	return
}

func newEnvironment() Environment {
	return &environment{}
}

func LoadEnv() error {
	env := newEnvironment()
	return env.Load()
}

// Copyright 2014 GoIncremental Limited. All Rights Reserved.
//
// 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 web

import "github.com/joho/godotenv"

type Environment interface {
	Load(filenames ...string) error
}

type environment struct{}

func (e *environment) Load(s ...string) (err error) {
	err = godotenv.Load(s...)
	return
}

func newEnvironment() Environment {
	return &environment{}
}

func LoadEnv(filenames ...string) error {
	env := newEnvironment()
	return env.Load(filenames...)
}

Support loading env file from custom file path


package compress

import "bytes"
import "strconv"

func compress(uncompressed string) string {
	var buf bytes.Buffer

	if len(uncompressed) == 0 {
		return buf.String()
	}

	var prev byte
	letter := uncompressed[0]
	last := 0
	for i := 1; i < len(uncompressed); i++ {
		prev = uncompressed[i-1]
		letter = uncompressed[i]
		if letter != prev {
			buf.WriteByte(prev)
			buf.WriteString(strconv.Itoa(i - last))
			last = i
		}
	}
	buf.WriteByte(letter)
	buf.WriteString(strconv.Itoa(len(uncompressed) - last))

	return buf.String()
}

package compress

import "strconv"

func compress(uncompressed string) string {
	var buf string

	if len(uncompressed) == 0 {
		return buf
	}

	var prev byte
	letter := uncompressed[0]
	last := 0
	for i := 1; i < len(uncompressed); i++ {
		prev = uncompressed[i-1]
		letter = uncompressed[i]
		if letter != prev {
			buf += string(prev)
			buf += strconv.Itoa(i - last)
			last = i
		}
	}
	buf += string(letter)
	buf += strconv.Itoa(len(uncompressed) - last)

	return buf
}

Use a string instead of bytes buffer


package main

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestBuildRunList(t *testing.T) {
	tests := []struct {
		cookbookName string
		recipes      []string
		runList      []string
	}{
		{"cats", []string{}, []string{"cats::default"}},
		{"cats", []string{"recipes/foo.rb"}, []string{"cats::foo"}},
		{"cats", []string{"./recipes//foo.rb"}, []string{"cats::foo"}},
		{"cats", []string{"foo"}, []string{"cats::foo"}},
		{"cats", []string{"dogs::bar"}, []string{"dogs::bar"}},
		{"cats", []string{"recipes/foo.rb", "bar", "dogs::baz"},
			[]string{"cats::foo", "cats::bar", "dogs::baz"}},
	}
	for _, test := range tests {
		runList := buildRunList(test.cookbookName, test.recipes)
		assert.Equal(t, test.runList, runList)
	}
}

package main

import (
	"os"
	"testing"

	"github.com/mlafeldt/chef-runner/log"
	"github.com/stretchr/testify/assert"
)

func TestLogLevel(t *testing.T) {
	tests := map[string]int{
		"":      log.LevelInfo,
		"debug": log.LevelDebug,
		"info":  log.LevelInfo,
		"warn":  log.LevelWarn,
		"error": log.LevelError,
		"DEBUG": log.LevelDebug,
		"INFO":  log.LevelInfo,
		"WARN":  log.LevelWarn,
		"ERROR": log.LevelError,
		"foo":   log.LevelInfo,
	}
	defer os.Setenv("CHEF_RUNNER_LOG", "")
	for env, level := range tests {
		os.Setenv("CHEF_RUNNER_LOG", env)
		assert.Equal(t, level, logLevel())
	}
}

func TestBuildRunList(t *testing.T) {
	tests := []struct {
		cookbookName string
		recipes      []string
		runList      []string
	}{
		{"cats", []string{}, []string{"cats::default"}},
		{"cats", []string{"recipes/foo.rb"}, []string{"cats::foo"}},
		{"cats", []string{"./recipes//foo.rb"}, []string{"cats::foo"}},
		{"cats", []string{"foo"}, []string{"cats::foo"}},
		{"cats", []string{"dogs::bar"}, []string{"dogs::bar"}},
		{"cats", []string{"recipes/foo.rb", "bar", "dogs::baz"},
			[]string{"cats::foo", "cats::bar", "dogs::baz"}},
	}
	for _, test := range tests {
		runList := buildRunList(test.cookbookName, test.recipes)
		assert.Equal(t, test.runList, runList)
	}
}

Test setting of log level


/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 aws

import (
	"github.com/aws/aws-sdk-go/aws"
	"k8s.io/kubernetes/pkg/util/sets"
)

func stringSetToPointers(in sets.String) []*string {
	if in == nil {
		return nil
	}
	out := make([]*string, len(in))
	for k := range in {
		out = append(out, aws.String(k))
	}
	return out
}

func stringSetFromPointers(in []*string) sets.String {
	if in == nil {
		return nil
	}
	out := sets.NewString()
	for i := range in {
		out.Insert(orEmpty(in[i]))
	}
	return out
}

func orZero(v *int64) int64 {
	if v == nil {
		return 0
	}
	return *v
}

/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 aws

import (
	"github.com/aws/aws-sdk-go/aws"
	"k8s.io/kubernetes/pkg/util/sets"
)

func stringSetToPointers(in sets.String) []*string {
	if in == nil {
		return nil
	}
	out := make([]*string, 0, len(in))
	for k := range in {
		out = append(out, aws.String(k))
	}
	return out
}

func stringSetFromPointers(in []*string) sets.String {
	if in == nil {
		return nil
	}
	out := sets.NewString()
	for i := range in {
		out.Insert(orEmpty(in[i]))
	}
	return out
}

func orZero(v *int64) int64 {
	if v == nil {
		return 0
	}
	return *v
}

Fix long-standing bug in aws.stringSetToPointers


package main

import (
	"bigv.io/client/cmd"
	//	bigv "bigv.io/client/lib"
	"flag"
	"fmt"
	"os"
)

var (
	configDir  = flag.String("config", "", "Location of go-bigv's config store - defaults to ~/.go-bigv")
	help       = flag.Bool("help", false, "Display usage information")
	debugLevel = flag.Int("debug-level", 0, "How much debugging output to display - 0 is none, other values are 1 and 2.")
)

func main() {
	flag.Parse()
	config := cmd.NewConfig(*configDir, flag.CommandLine)

	fmt.Fprintf(os.Stderr, "Using config in %s \r\n\r\n", config.Dir)

	dispatch := cmd.NewDispatcher(config)

	dispatch.Do(flag.Args())
	os.Exit(0)
}

package main

import (
	"bigv.io/client/cmd"
	//	bigv "bigv.io/client/lib"
	"flag"
	"os"
)

var (
	configDir  = flag.String("config", "", "Location of go-bigv's config store - defaults to ~/.go-bigv")
	help       = flag.Bool("help", false, "Display usage information")
	debugLevel = flag.Int("debug-level", 0, "How much debugging output to display - 0 is none, other values are 1 and 2.")
)

func main() {
	flag.Parse()
	config := cmd.NewConfig(*configDir, flag.CommandLine)

	dispatch := cmd.NewDispatcher(config)

	dispatch.Do(flag.Args())
	os.Exit(0)
}

Remove the using-config-in-dir message from startup.


package cli

import (
	"context"

	"github.com/pkg/errors"

	"github.com/kopia/kopia/repo"
	"github.com/kopia/kopia/repo/blob"
)

var (
	blobDeleteCommand = blobCommands.Command("delete", "Show contents of blobs").Alias("rm")
	blobDeleteBlobIDs = blobDeleteCommand.Arg("blobIDs", "Blob IDs").Required().Strings()
)

func runDeleteBlobs(ctx context.Context, rep *repo.Repository) error {
	for _, b := range *blobDeleteBlobIDs {
		err := rep.Blobs.DeleteBlob(ctx, blob.ID(b))
		if err != nil {
			return errors.Wrapf(err, "error deleting %v", b)
		}
	}

	return nil
}

func init() {
	blobDeleteCommand.Action(repositoryAction(runDeleteBlobs))
}

package cli

import (
	"context"

	"github.com/pkg/errors"

	"github.com/kopia/kopia/repo"
	"github.com/kopia/kopia/repo/blob"
)

var (
	blobDeleteCommand = blobCommands.Command("delete", "Delete blobs by ID").Alias("rm")
	blobDeleteBlobIDs = blobDeleteCommand.Arg("blobIDs", "Blob IDs").Required().Strings()
)

func runDeleteBlobs(ctx context.Context, rep *repo.Repository) error {
	for _, b := range *blobDeleteBlobIDs {
		err := rep.Blobs.DeleteBlob(ctx, blob.ID(b))
		if err != nil {
			return errors.Wrapf(err, "error deleting %v", b)
		}
	}

	return nil
}

func init() {
	blobDeleteCommand.Action(repositoryAction(runDeleteBlobs))
}

Fix command description for blob delete


package dos

//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall.go syscall.go

//sys copyFile(src string,dst string,isFailIfExist bool)(n uint32,err error) = kernel32.CopyFileW
//sys moveFileEx(src string,dst string,flag uintptr)(n uint32,err error) = kernel32.MoveFileExW
//sys getDiskFreeSpaceEx(rootPathName string,free *uint64,total *uint64,totalFree *uint64)(n uint32,err error) = kernel32.GetDiskFreeSpaceExW
//sys GetLogicalDrives()(n uint32,err error) = kernel32.GetLogicalDrives
//sys GetDriveType(rootPathName string)(rc uintptr,err error) = kernel32.GetDriveTypeW
//sys CoInitializeEx(res uintptr,opt uintptr) = ole32.CoInitializeEx
//sys CoUninitialize() = ole32.CoUninitialize

package dos

//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output z$GOFILE $GOFILE

//sys copyFile(src string,dst string,isFailIfExist bool)(n uint32,err error) = kernel32.CopyFileW
//sys moveFileEx(src string,dst string,flag uintptr)(n uint32,err error) = kernel32.MoveFileExW
//sys getDiskFreeSpaceEx(rootPathName string,free *uint64,total *uint64,totalFree *uint64)(n uint32,err error) = kernel32.GetDiskFreeSpaceExW
//sys GetLogicalDrives()(n uint32,err error) = kernel32.GetLogicalDrives
//sys GetDriveType(rootPathName string)(rc uintptr,err error) = kernel32.GetDriveTypeW
//sys CoInitializeEx(res uintptr,opt uintptr) = ole32.CoInitializeEx
//sys CoUninitialize() = ole32.CoUninitialize

Rewrite go:generate line with macro $GOFILE


package slice_test

import (
    "testing"

    "github.com/xgfone/go-tools/slice"
)

func TestSlice(t *testing.T) {
    ss := []int{1,2,3,4,5,6}
    ok := true
    out := 0

    ok = slice.SetValueWithDefault(&out, ss, 2, 100)
    if !ok || out != 3 {
        t.Fail()
    }

    ok = slice.SetValueWithDefault(&out, ss, 6, 100)
    if !ok || out != 100 {
        t.Fail()
    }

    ok = slice.SetValue(out, ss, 6)
    if ok {
        t.Fail()
    }
}

package slice_test

import (
	"fmt"
	"testing"

	"github.com/xgfone/go-tools/slice"
)

func TestSlice(t *testing.T) {
	ss := []int{1, 2, 3, 4, 5, 6}
	ok := true
	out := 0

	ok = slice.SetValueWithDefault(&out, ss, 2, 100)
	if !ok || out != 3 {
		t.Fail()
	}

	ok = slice.SetValueWithDefault(&out, ss, 6, 100)
	if !ok || out != 100 {
		t.Fail()
	}

	ok = slice.SetValue(out, ss, 6)
	if ok {
		t.Fail()
	}
}

func ExampleSetValue() {
	ss := []int{1, 2, 3, 4, 5, 6}
	out := -1
	ok1 := slice.SetValue(&out, ss, 1)
	fmt.Println(out, ok1)

	out = -1
	ok2 := slice.SetValue(&out, ss, 6)
	fmt.Println(out, ok2)
	// Output:
	// 2 true
	// -1 false
}

func ExampleSetValueWithDefault() {
	ss := []int{1, 2, 3, 4, 5, 6}
	out := 0
	ok1 := slice.SetValue(&out, ss, 1, -1)
	fmt.Println(out, ok1)

	out = 0
	ok2 := slice.SetValue(&out, ss, 6, -1)
	fmt.Println(out, ok2)
	// Output:
	// 2 true
	// -1 fasle
}

Add the example for slice


package statsdurl

import (
	"os"
	"fmt"
	"net/url"
	"strings"
	"github.com/quipo/statsd"
)

func Connect() (*statsd.StatsdClient, error) {
	return ConnectToURL(os.Getenv("STATSD_URL"))
}

func ConnectToURL(s string) (c *statsd.StatsdClient, err error) {
	statsdUrl, err := url.Parse(s)

	if err != nil {
		return
	}

	prefix := ""

	if len(statsdUrl.Path) > 1 {
		prefix = strings.TrimPrefix(statsdUrl.Path, "/")
		prefix = fmt.Sprintf("/%v", prefix)
	}

	c = statsd.NewStatsdClient(statsdUrl.Host, prefix)
	err = c.CreateSocket()
	return c, err
}

package statsdurl

import (
	"net/url"
	"os"

	"github.com/quipo/statsd"
)

func Connect(prefix string) (*statsd.StatsdClient, error) {
	return ConnectToURL(os.Getenv("STATSD_URL"))
}

func ConnectToURL(s string, prefix string) (c *statsd.StatsdClient, err error) {
	statsdUrl, err := url.Parse(s)

	if err != nil {
		return statsdUrl, err
	}

	c = statsd.NewStatsdClient(statsdUrl.Host, prefix)
	err = c.CreateSocket()
	return c, err
}

Allow prefix to be set by each client


package main

import (
	"context"
	"fmt"
	"time"

	"github.com/mattn/go-mastodon"
	"github.com/urfave/cli"
)

func cmdFollowers(c *cli.Context) error {
	client := c.App.Metadata["client"].(*mastodon.Client)
	config := c.App.Metadata["config"].(*mastodon.Config)

	account, err := client.GetAccountCurrentUser(context.Background())
	if err != nil {
		return err
	}
	var followers []*mastodon.Account
	var pg mastodon.Pagination
	for {
		fs, err := client.GetAccountFollowers(context.Background(), account.ID, &pg)
		if err != nil {
			return err
		}
		followers = append(followers, fs...)
		if pg.MaxID == "" {
			break
		}
		pg.SinceID = ""
		time.Sleep(10 * time.Second)
	}
	s := newScreen(config)
	for _, follower := range followers {
		fmt.Fprintf(c.App.Writer, "%v,%v\n", follower.ID, s.acct(follower.Acct))
	}
	return nil
}

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/mattn/go-mastodon"
	"github.com/urfave/cli"
)

func cmdFollowers(c *cli.Context) error {
	client := c.App.Metadata["client"].(*mastodon.Client)
	config := c.App.Metadata["config"].(*mastodon.Config)

	account, err := client.GetAccountCurrentUser(context.Background())
	if err != nil {
		return err
	}
	var followers []*mastodon.Account
	var pg mastodon.Pagination
	for {
		fs, err := client.GetAccountFollowers(context.Background(), account.ID, &pg)
		if err != nil {
			return err
		}
		followers = append(followers, fs...)
		if pg.MaxID == "" {
			break
		}
		pg.SinceID = ""
		pg.MinID = ""
		time.Sleep(10 * time.Second)
	}
	s := newScreen(config)
	for _, follower := range followers {
		fmt.Fprintf(c.App.Writer, "%v,%v\n", follower.ID, s.acct(follower.Acct))
	}
	return nil
}

Fix follower pagination in cmd/mstdn