<commit_before>package fstree

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

	"github.com/caelifer/scheduler"
)

// Distributed file system tree walker

// Heler type - matches parameter signature of filepath.Walk()
type nodeFn func(path string, info os.FileInfo, err error) error

// Walk is a primary interface to this package. It matches signature of filepath.Walk().
func Walk(sched scheduler.Scheduler, path string, fn nodeFn) error {
	// Create walker object
	w := newWalker(sched, path)

	// Construct node from provided path
	info, err := os.Lstat(path)

	// On success ...
	if err == nil {
		// Process node
		err = w.walkNode(newNode(path, info), nil, fn)
	}

	// Wait util all nodes are processed
	w.wg.Wait()

	return err
}

type node struct {
	path string
	info os.FileInfo
}

func newNode(path string, info os.FileInfo) *node {
	return &node{path: filepath.Clean(path), info: info}
}

type walker struct {
	root  string
	sched scheduler.Scheduler
	wg    sync.WaitGroup
}

func newWalker(sched scheduler.Scheduler, root string) *walker {
	return &walker{
		root:  root,
		sched: sched,
	}
}

func (w *walker) walkNode(node *node, err error, fn nodeFn) error {
	// Make sure we are not finished until all recursive calls are done
	w.wg.Add(1)
	defer w.wg.Done()

	// Process node by calling client function
	err = fn(node.path, node.info, err)

	// ... then, recursively process directories
	if node.info.IsDir() {
		// Traverse directrory asnyncronously using balancer
		w.walkDir(node, err, fn)
	}

	return err
}

func (w *walker) walkDir(node *node, err error, fn nodeFn) {
	if err != nil {
		log.Println("WARN", err)
		return
	}

	// Make sure we are not finished until all recursive calls are done
	w.wg.Add(1)

	// Send to be processed in the workpool
	// log.Printf("Scheduling async walk of %s", node.path)
	go func() {
		w.sched.Schedule(func() {
			defer w.wg.Done() // Signal done at the end of the function

			// Read directory entries
			dirents, err := ioutil.ReadDir(node.path)
			if err != nil {
				log.Println("WARN", err)

				// early termination if we cannot read directory
				return
			}

			// Read all entries in current directory
			for _, entry := range dirents {
				// path := node.path + string(os.PathSeparator) + entry.Name()

				// Use custom fast string concatenation rutine
				path := fastStringConcat(node.path, os.PathSeparator, entry.Name())

				// Process node, ignore errors
				w.walkNode(newNode(path, entry), nil, fn)
			}
		})
	}()
	// log.Println("Done scheduling")
}

// Little helper for specialized fast string + byte + string concatenation
// Inspired by http://golang-examples.tumblr.com/post/86169510884/fastest-string-contatenation
func fastStringConcat(first string, second byte, third string) string {
	res := make([]byte, 0, len(first)+1+len(third))
	res = append(res, []byte(first)...)
	res = append(res, second)
	res = append(res, []byte(third)...)
	return string(res)
}
<commit_msg>Fixed typos and added missing error check<commit_after>package fstree

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

	"github.com/caelifer/scheduler"
)

// Distributed file system tree walker

// Helper type - matches parameter signature of filepath.Walk()
type nodeFn func(path string, info os.FileInfo, err error) error

// Walk is a primary interface to this package. It matches signature of filepath.Walk().
func Walk(sched scheduler.Scheduler, path string, fn nodeFn) error {
	// Create walker object
	w := newWalker(sched, path)

	// Construct node from provided path
	info, err := os.Lstat(path)

	// On success ...
	if err == nil {
		// Process node
		err = w.walkNode(newNode(path, info), nil, fn)
	}

	// Wait util all nodes are processed
	w.wg.Wait()

	return err
}

type node struct {
	path string
	info os.FileInfo
}

func newNode(path string, info os.FileInfo) *node {
	return &node{path: filepath.Clean(path), info: info}
}

type walker struct {
	root  string
	sched scheduler.Scheduler
	wg    sync.WaitGroup
}

func newWalker(sched scheduler.Scheduler, root string) *walker {
	return &walker{
		root:  root,
		sched: sched,
	}
}

func (w *walker) walkNode(node *node, err error, fn nodeFn) error {
	// Make sure we are not finished until all recursive calls are done
	w.wg.Add(1)
	defer w.wg.Done()

	// Process node by calling client function
	err = fn(node.path, node.info, err)

	// ... then, recursively process directories
	if node.info.IsDir() {
		// Traverse directory in parallel using balancer with fixed number of workers to avoid FD exhaustion.
		w.walkDir(node, err, fn)
	}

	return err
}

func (w *walker) walkDir(node *node, err error, fn nodeFn) {
	if err != nil {
		log.Println("WARN", err)
		return
	}

	// Make sure we are not finished until all recursive calls are done
	w.wg.Add(1)

	// Send to be processed in the workpool
	// log.Printf("Scheduling async walk of %s", node.path)
	go func() {
		w.sched.Schedule(func() {
			defer w.wg.Done() // Signal done at the end of the function

			// Read directory entries
			dirents, err := ioutil.ReadDir(node.path)
			if err != nil {
				log.Println("WARN", err)

				// early termination if we cannot read directory
				return
			}

			// Read all entries in current directory
			for _, entry := range dirents {
				// path := node.path + string(os.PathSeparator) + entry.Name()

				// Use custom fast string concatenation rutine
				path := fastStringConcat(node.path, os.PathSeparator, entry.Name())

				// Process node, ignore errors
				if err := w.walkNode(newNode(path, entry), nil, fn); err != nil {
					log.Printf("unable to walk %q: %v", path, err)
				}
			}
		})
	}()
	// log.Println("Done scheduling")
}

// Little helper for specialized fast string + byte + string concatenation
// Inspired by http://golang-examples.tumblr.com/post/86169510884/fastest-string-contatenation
func fastStringConcat(first string, second byte, third string) string {
	res := make([]byte, 0, len(first)+1+len(third))
	res = append(res, []byte(first)...)
	res = append(res, second)
	res = append(res, []byte(third)...)
	return string(res)
}
<|endoftext|>


<commit_before>package identitydoc

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"time"
)

// ErrInvalidDocument represents the failure when the document is not verified
// by the signature
var ErrInvalidDocument = errors.New("The provided identify document does not match the signature")

var (
	// IdentityDocURL is the URL to retrieve the identity doc from
	IdentityDocURL = "http://169.254.169.254/latest/dynamic/instance-identity/document"
	// SignatureURL is the URL to retrieve the signed identity doc from
	SignatureURL = "http://169.254.169.254/latest/dynamic/instance-identity/signature"
)

// InstanceIdentityDocument represents the information containe in an instances
// identity document
// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
type InstanceIdentityDocument struct {
	InstanceID       string    `json:"instanceId"`
	AccountID        string    `json:"accountId"`
	PrivateIP        string    `json:"privateIp"`
	Region           string    `json:"region"`
	AvailabilityZone string    `json:"availabilityZone"`
	PendingTime      time.Time `json:"pendingTime"`
	InstanceType     string    `json:"instanceType"`
	ImageID          string    `json:"imageId"`
}

// VerifyDocumentAndSignature will confirm that the document is correct by
// validating it against the signature and cert for the given region. It will
// return the parsed document if it's valid, or ErrInvalidDocument if it's not.
func VerifyDocumentAndSignature(region string, document, signature []byte) (*InstanceIdentityDocument, error) {
	c, err := CertForRegion(region)
	if err != nil {
		return nil, err
	}

	ds, err := base64.StdEncoding.DecodeString(string(signature))
	if err != nil {
		return nil, err
	}

	err = c.CheckSignature(x509.SHA256WithRSA, document, []byte(ds))
	if err != nil {
		return nil, ErrInvalidDocument
	}

	iid := &InstanceIdentityDocument{}
	err = json.Unmarshal(document, iid)
	if err != nil {
		return nil, err
	}
	return iid, nil
}
<commit_msg>Don't need to keep those as vars<commit_after>package identitydoc

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"errors"
	"time"
)

// ErrInvalidDocument represents the failure when the document is not verified
// by the signature
var ErrInvalidDocument = errors.New("The provided identify document does not match the signature")

// InstanceIdentityDocument represents the information containe in an instances
// identity document
// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
type InstanceIdentityDocument struct {
	InstanceID       string    `json:"instanceId"`
	AccountID        string    `json:"accountId"`
	PrivateIP        string    `json:"privateIp"`
	Region           string    `json:"region"`
	AvailabilityZone string    `json:"availabilityZone"`
	PendingTime      time.Time `json:"pendingTime"`
	InstanceType     string    `json:"instanceType"`
	ImageID          string    `json:"imageId"`
}

// VerifyDocumentAndSignature will confirm that the document is correct by
// validating it against the signature and cert for the given region. It will
// return the parsed document if it's valid, or ErrInvalidDocument if it's not.
// The document can be retrieved from:
// http://169.254.169.254/latest/dynamic/instance-identity/document
// And the signature:
// http://169.254.169.254/latest/dynamic/instance-identity/signature
func VerifyDocumentAndSignature(region string, document, signature []byte) (*InstanceIdentityDocument, error) {
	c, err := CertForRegion(region)
	if err != nil {
		return nil, err
	}

	ds, err := base64.StdEncoding.DecodeString(string(signature))
	if err != nil {
		return nil, err
	}

	err = c.CheckSignature(x509.SHA256WithRSA, document, []byte(ds))
	if err != nil {
		return nil, ErrInvalidDocument
	}

	iid := &InstanceIdentityDocument{}
	err = json.Unmarshal(document, iid)
	if err != nil {
		return nil, err
	}
	return iid, nil
}
<|endoftext|>


<commit_before>package main

import (
	"testing"
	"time"
)

func TestStopWatch(t *testing.T) {
	testData := []int{1, 2}
	for _, value := range testData {
		sw := &StopWatch{}

		sw.Start()
		time.Sleep(time.Duration(value) * time.Second)
		sw.Stop()

		if int64(sw.Elapsed)/1000000 == int64(time.Duration(value)*time.Second) {
			t.Errorf("expected %d, get %d", time.Duration(value)*time.Second, sw.Elapsed)
		}
	}

}
<commit_msg>fix malfunction of stopwatch unit test and reduce testing time<commit_after>package main

import (
	"testing"
	"time"
)

func TestStopWatch(t *testing.T) {
	testData := []int{100, 200} //Millisecond
	for _, value := range testData {
		sw := &StopWatch{}

		sw.Start()
		time.Sleep(time.Duration(value) * time.Millisecond)
		sw.Stop()

		if int64(sw.Elapsed)/1000000 != int64(time.Duration(value)) {
			t.Errorf("expected %d, get %d", time.Duration(value)*time.Millisecond, sw.Elapsed)
		}
	}

}
<|endoftext|>


<commit_before>package image

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

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

const (
	testAPIServerString = `
{
	"data": [
		{
			"id": 1,
			"infra": "test",
			"name": "travis-ci-awesome"
		}
	]
}
`
	testAPIServerEmptyResponseString = `{"data": []}`
)

var (
	testAPITagTestCases = []struct {
		P []*Params
		E [][]*tagSet
	}{
		{
			P: []*Params{
				{
					Infra:    "gce",
					Language: "ruby",
					OS:       "linux",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "gce",
					Language: "go",
					OS:       "linux",
					Group:    "dev",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "gce",
					Language: "ruby",
					Dist:     "precise",
					Group:    "edge",
					OS:       "linux",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "python",
					OS:       "osx",
					OsxImage: "xcode7",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "objective-c",
					OS:       "osx",
					OsxImage: "xcode6.4",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "node_js",
					OsxImage: "xcode6.1",
					Dist:     "yosammity",
					Group:    "fancy",
					OS:       "osx",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
			},
			E: [][]*tagSet{
				{
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"group_dev:true", "language_go:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_dev:true", "language_go:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_go:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_go:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_dev:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"dist:precise", "group_edge:true", "language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise", "group_edge:true", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_edge:true", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_edge:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"language_python:true", "os:osx", "osx_image:xcode7"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode7"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_python:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_python:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode7"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"language_objective-c:true", "os:osx", "osx_image:xcode6.4"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode6.4"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_objective-c:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_objective-c:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode6.4"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"dist:yosammity", "group_fancy:true", "language_node_js:true", "os:osx", "osx_image:xcode6.1"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode6.1"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity", "group_fancy:true", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_fancy:true", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_node_js:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_node_js:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode6.1"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_fancy:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
			},
		},
	}
)

func TestNewAPISelector(t *testing.T) {
	u, _ := url.Parse("https://foo:bar@whatever.example.com/images")
	assert.NotNil(t, NewAPISelector(u))
}

func TestAPISelector_Select(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerString)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)

	as := NewAPISelector(u)

	actual, _ := as.Select(&Params{
		Infra:    "test",
		Language: "ruby",
		OsxImage: "meow",
		Dist:     "yosamitty",
		Group:    "dev",
		OS:       "osx",
	})
	assert.Equal(t, actual, "travis-ci-awesome")
}

func TestAPISelector_SelectDefault(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerEmptyResponseString)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.NoError(t, err)
}

func TestAPISelector_SelectDefaultWhenBadResponse(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "expected 200 status code from job-board, received status=500")
}

func TestAPISelector_SelectDefaultWhenBadJSON(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, `{"data`)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.Error(t, err, "unexpected end of JSON input")
}

func TestAPISelector_SelectTrailingComma(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerString)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)

	as := NewAPISelector(u)

	actual, err := as.Select(&Params{
		Infra:    "test,",
		Language: "ruby,",
		OsxImage: "meow,",
		Dist:     "yosamitty,",
		Group:    "dev,",
		OS:       "osx,",
	})
	assert.Equal(t, actual, "default")
	assert.Error(t, err, "tag \"a\" contained \",\", which is not supported by job-board -- check .travis.yml for trailing comma")
}

func TestAPISelector_buildCandidateTags(t *testing.T) {
	as := NewAPISelector(nil)

	for _, tc := range testAPITagTestCases {
		for i, params := range tc.P {
			expectedJSON, _ := json.MarshalIndent(tc.E[i], "", "  ")
			tagSets, _ := as.buildCandidateTags(params)
			actualJSON, _ := json.MarshalIndent(tagSets, "", "  ")
			assert.JSONEq(t, string(expectedJSON), string(actualJSON))
		}
	}
}
<commit_msg>use assert.EqualError instead of assert.Error to check error message<commit_after>package image

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

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

const (
	testAPIServerString = `
{
	"data": [
		{
			"id": 1,
			"infra": "test",
			"name": "travis-ci-awesome"
		}
	]
}
`
	testAPIServerEmptyResponseString = `{"data": []}`
)

var (
	testAPITagTestCases = []struct {
		P []*Params
		E [][]*tagSet
	}{
		{
			P: []*Params{
				{
					Infra:    "gce",
					Language: "ruby",
					OS:       "linux",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "gce",
					Language: "go",
					OS:       "linux",
					Group:    "dev",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "gce",
					Language: "ruby",
					Dist:     "precise",
					Group:    "edge",
					OS:       "linux",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "python",
					OS:       "osx",
					OsxImage: "xcode7",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "objective-c",
					OS:       "osx",
					OsxImage: "xcode6.4",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
				{
					Infra:    "jupiterbrain",
					Language: "node_js",
					OsxImage: "xcode6.1",
					Dist:     "yosammity",
					Group:    "fancy",
					OS:       "osx",
					JobID:    uint64(4),
					Repo:     "corp/frob",
				},
			},
			E: [][]*tagSet{
				{
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"group_dev:true", "language_go:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_dev:true", "language_go:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_go:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_go:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_dev:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"dist:precise", "group_edge:true", "language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise", "group_edge:true", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_edge:true", "language_ruby:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true", "os:linux"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_ruby:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:precise"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_edge:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:linux"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"language_python:true", "os:osx", "osx_image:xcode7"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode7"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_python:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_python:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode7"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"language_objective-c:true", "os:osx", "osx_image:xcode6.4"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode6.4"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_objective-c:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_objective-c:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode6.4"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
				{
					&tagSet{[]string{"dist:yosammity", "group_fancy:true", "language_node_js:true", "os:osx", "osx_image:xcode6.1"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx", "osx_image:xcode6.1"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity", "group_fancy:true", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_fancy:true", "language_node_js:true"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_node_js:true", "os:osx"}, false, uint64(4), "corp/frob"},
					&tagSet{[]string{"language_node_js:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"osx_image:xcode6.1"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"dist:yosammity"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"group_fancy:true"}, true, uint64(4), "corp/frob"},
					&tagSet{[]string{"os:osx"}, true, uint64(4), "corp/frob"},
				},
			},
		},
	}
)

func TestNewAPISelector(t *testing.T) {
	u, _ := url.Parse("https://foo:bar@whatever.example.com/images")
	assert.NotNil(t, NewAPISelector(u))
}

func TestAPISelector_Select(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerString)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)

	as := NewAPISelector(u)

	actual, _ := as.Select(&Params{
		Infra:    "test",
		Language: "ruby",
		OsxImage: "meow",
		Dist:     "yosamitty",
		Group:    "dev",
		OS:       "osx",
	})
	assert.Equal(t, actual, "travis-ci-awesome")
}

func TestAPISelector_SelectDefault(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerEmptyResponseString)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.NoError(t, err)
}

func TestAPISelector_SelectDefaultWhenBadResponse(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.EqualError(t, err, "expected 200 status code from job-board, received status=500")
}

func TestAPISelector_SelectDefaultWhenBadJSON(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, `{"data`)
	}))
	defer ts.Close()
	u, _ := url.Parse(ts.URL)
	actual, err := NewAPISelector(u).Select(&Params{})
	assert.Equal(t, actual, "default")
	assert.EqualError(t, err, "unexpected end of JSON input")
}

func TestAPISelector_SelectTrailingComma(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, testAPIServerString)
	}))
	defer ts.Close()

	u, _ := url.Parse(ts.URL)

	as := NewAPISelector(u)

	actual, err := as.Select(&Params{
		Infra:    "test,",
		Language: "ruby,",
		OsxImage: "meow,",
		Dist:     "yosamitty,",
		Group:    "dev,",
		OS:       "osx,",
	})
	assert.Equal(t, actual, "default")
	assert.EqualError(t, err, "tag \"a\" contained \",\", which is not supported by job-board -- check .travis.yml for trailing comma")
}

func TestAPISelector_buildCandidateTags(t *testing.T) {
	as := NewAPISelector(nil)

	for _, tc := range testAPITagTestCases {
		for i, params := range tc.P {
			expectedJSON, _ := json.MarshalIndent(tc.E[i], "", "  ")
			tagSets, _ := as.buildCandidateTags(params)
			actualJSON, _ := json.MarshalIndent(tagSets, "", "  ")
			assert.JSONEq(t, string(expectedJSON), string(actualJSON))
		}
	}
}
<|endoftext|>


<commit_before>package imageutil

import (
	"fmt"
	"image"
	"image/color"
	"strings"

	"golang.org/x/image/draw"
)

func OverlayCenterYLeftAlign(imgBg, imgOver image.Image) image.Image {
	output := image.NewRGBA(imgBg.Bounds())
	draw.Draw(output, imgBg.Bounds(), imgBg, image.ZP, draw.Src)

	h1 := imgBg.Bounds().Dy()
	h2 := imgOver.Bounds().Dy()
	offset := image.Pt(0, (h1-h2)/2)

	draw.Draw(output, imgOver.Bounds().Add(offset), imgOver, image.Point{}, draw.Src)
	return output
}

func debugImagesDimensions(note string, images []image.Image) {
	dimensions := []string{note}
	for i, img := range images {
		dimensions = append(dimensions,
			fmt.Sprintf("X%d[%v]y%d[%v]",
				i+1, img.Bounds().Dx(), i+1, img.Bounds().Dy()))
	}
	fmt.Printf(strings.Join(dimensions, " ") + "\n")
}

func MergeXSameY(images []image.Image, larger bool) image.Image {
	if len(images) == 0 {
		return nil
	} else if len(images) == 1 {
		return images[0]
	}
	images = ResizeSameY(images, larger)
	_, _, minY, _, sumX, _ := SliceXY(images, -1)
	output := image.NewRGBA(image.Rect(0, 0, sumX, minY))
	sumXPrev := 0
	for _, img := range images {
		if IsNilOrEmpty(img) {
			continue
		}
		draw.Draw(output, img.Bounds().Add(image.Pt(sumXPrev, 0)),
			img, image.Point{}, draw.Src)
		sumXPrev += img.Bounds().Dx()
	}
	return output
}

func MergeXSameYRead(locations []string, larger bool) (image.Image, error) {
	images, err := ReadImages(locations)
	if err != nil {
		return nil, err
	}
	return MergeXSameY(images, true), nil
}

func MergeYSameX(images []image.Image, larger bool) image.Image {
	if len(images) == 0 {
		return nil
	} else if len(images) == 1 {
		return images[0]
	}
	images = ResizeSameX(images, larger)
	minX, _, _, _, _, sumY := SliceXY(images, -1)
	output := image.NewRGBA(image.Rect(0, 0, minX, sumY))
	sumYPrev := 0
	for _, img := range images {
		if IsNilOrEmpty(img) {
			continue
		}
		draw.Draw(output, img.Bounds().Add(image.Pt(0, sumYPrev)),
			img, image.Point{}, draw.Src)
		sumYPrev += img.Bounds().Dy()
	}
	return output
}

func MergeYSameXRead(locations []string, larger bool) (image.Image, error) {
	images, err := ReadImages(locations)
	if err != nil {
		return nil, err
	}
	return MergeYSameX(images, true), nil
}

type Matrix [][]image.Image

// AddBackgroundColor adds a background of `color.Color` to the images.
// It is is useful when the image has a transparent background. Use
// `colornames` for more colors, e.g. `colornames.Blue`.
func (matrix Matrix) AddBackgroundColor(clr color.Color) {
	for i, row := range matrix {
		for j, img := range row {
			matrix[i][j] = AddBackgroundColor(img, clr)
		}
	}
}

// Merge combines a set of images resizing each row element's
// height for consistent rows, an each row's width for consistent
// widths.
func (matrix Matrix) Merge(largerX, largerY bool) image.Image {
	if len(matrix) == 0 {
		return nil
	}
	rowImages := []image.Image{}
	for _, rowParts := range matrix {
		if len(rowParts) > 0 {
			rowImages = append(rowImages, MergeXSameY(rowParts, largerY))
		}
	}
	if len(rowImages) == 0 {
		return nil
	}
	return MergeYSameX(rowImages, largerX)
}

func MatrixRead(imglocations [][]string) (Matrix, error) {
	matrixImages := Matrix{}
	for _, row := range imglocations {
		if len(row) == 0 {
			continue
		}
		images, err := ReadImages(row)
		if err != nil {
			return nil, err
		}
		matrixImages = append(matrixImages, images)
	}
	return matrixImages, nil
}

func MatrixMergeRead(imglocations [][]string, largerX, largerY bool) (image.Image, error) {
	matrixImages, err := MatrixRead(imglocations)
	if err != nil {
		return nil, err
	}

	return matrixImages.Merge(largerX, largerY), nil
}
<commit_msg>refactor: imageutil: delete MatrixMergeRead() in favor of MatrixRead() and Matrix.Merge()<commit_after>package imageutil

import (
	"fmt"
	"image"
	"image/color"
	"strings"

	"golang.org/x/image/draw"
)

func OverlayCenterYLeftAlign(imgBg, imgOver image.Image) image.Image {
	output := image.NewRGBA(imgBg.Bounds())
	draw.Draw(output, imgBg.Bounds(), imgBg, image.ZP, draw.Src)

	h1 := imgBg.Bounds().Dy()
	h2 := imgOver.Bounds().Dy()
	offset := image.Pt(0, (h1-h2)/2)

	draw.Draw(output, imgOver.Bounds().Add(offset), imgOver, image.Point{}, draw.Src)
	return output
}

func debugImagesDimensions(note string, images []image.Image) {
	dimensions := []string{note}
	for i, img := range images {
		dimensions = append(dimensions,
			fmt.Sprintf("X%d[%v]y%d[%v]",
				i+1, img.Bounds().Dx(), i+1, img.Bounds().Dy()))
	}
	fmt.Printf(strings.Join(dimensions, " ") + "\n")
}

func MergeXSameY(images []image.Image, larger bool) image.Image {
	if len(images) == 0 {
		return nil
	} else if len(images) == 1 {
		return images[0]
	}
	images = ResizeSameY(images, larger)
	_, _, minY, _, sumX, _ := SliceXY(images, -1)
	output := image.NewRGBA(image.Rect(0, 0, sumX, minY))
	sumXPrev := 0
	for _, img := range images {
		if IsNilOrEmpty(img) {
			continue
		}
		draw.Draw(output, img.Bounds().Add(image.Pt(sumXPrev, 0)),
			img, image.Point{}, draw.Src)
		sumXPrev += img.Bounds().Dx()
	}
	return output
}

func MergeXSameYRead(locations []string, larger bool) (image.Image, error) {
	images, err := ReadImages(locations)
	if err != nil {
		return nil, err
	}
	return MergeXSameY(images, true), nil
}

func MergeYSameX(images []image.Image, larger bool) image.Image {
	if len(images) == 0 {
		return nil
	} else if len(images) == 1 {
		return images[0]
	}
	images = ResizeSameX(images, larger)
	minX, _, _, _, _, sumY := SliceXY(images, -1)
	output := image.NewRGBA(image.Rect(0, 0, minX, sumY))
	sumYPrev := 0
	for _, img := range images {
		if IsNilOrEmpty(img) {
			continue
		}
		draw.Draw(output, img.Bounds().Add(image.Pt(0, sumYPrev)),
			img, image.Point{}, draw.Src)
		sumYPrev += img.Bounds().Dy()
	}
	return output
}

func MergeYSameXRead(locations []string, larger bool) (image.Image, error) {
	images, err := ReadImages(locations)
	if err != nil {
		return nil, err
	}
	return MergeYSameX(images, true), nil
}

type Matrix [][]image.Image

// AddBackgroundColor adds a background of `color.Color` to the images.
// It is is useful when the image has a transparent background. Use
// `colornames` for more colors, e.g. `colornames.Blue`.
func (matrix Matrix) AddBackgroundColor(clr color.Color) {
	for i, row := range matrix {
		for j, img := range row {
			matrix[i][j] = AddBackgroundColor(img, clr)
		}
	}
}

// Merge combines a set of images resizing each row element's
// height for consistent rows, an each row's width for consistent
// widths.
func (matrix Matrix) Merge(largerX, largerY bool) image.Image {
	if len(matrix) == 0 {
		return nil
	}
	rowImages := []image.Image{}
	for _, rowParts := range matrix {
		if len(rowParts) > 0 {
			rowImages = append(rowImages, MergeXSameY(rowParts, largerY))
		}
	}
	if len(rowImages) == 0 {
		return nil
	}
	return MergeYSameX(rowImages, largerX)
}

func MatrixRead(imglocations [][]string) (Matrix, error) {
	matrixImages := Matrix{}
	for _, row := range imglocations {
		if len(row) == 0 {
			continue
		}
		images, err := ReadImages(row)
		if err != nil {
			return nil, err
		}
		matrixImages = append(matrixImages, images)
	}
	return matrixImages, nil
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//

package influxdb

import (
	"errors"
	"strconv"
	"sync"
	"time"

	"github.com/mainflux/mainflux/writers"

	influxdata "github.com/influxdata/influxdb/client/v2"
	"github.com/mainflux/mainflux"
)

const pointName = "messages"

var _ writers.MessageRepository = (*influxRepo)(nil)

var (
	errZeroValueSize    = errors.New("zero value batch size")
	errZeroValueTimeout = errors.New("zero value batch timeout")
	errNilBatch         = errors.New("nil batch")
)

type influxRepo struct {
	client    influxdata.Client
	batch     influxdata.BatchPoints
	batchSize int
	mu        sync.Mutex
	tick      <-chan time.Time
	cfg       influxdata.BatchPointsConfig
}

type fields map[string]interface{}
type tags map[string]string

// New returns new InfluxDB writer.
func New(client influxdata.Client, database string, batchSize int, batchTimeout time.Duration) (writers.MessageRepository, error) {
	if batchSize <= 0 {
		return &influxRepo{}, errZeroValueSize
	}

	if batchTimeout <= 0 {
		return &influxRepo{}, errZeroValueTimeout
	}

	repo := &influxRepo{
		client: client,
		cfg: influxdata.BatchPointsConfig{
			Database: database,
		},
		batchSize: batchSize,
	}

	var err error
	repo.batch, err = influxdata.NewBatchPoints(repo.cfg)
	if err != nil {
		return &influxRepo{}, err
	}

	repo.tick = time.NewTicker(batchTimeout).C
	go func() {
		for {
			<-repo.tick
			// Nil point indicates that savePoint method is triggered by the ticker.
			repo.savePoint(nil)
		}
	}()

	return repo, nil
}

func (repo *influxRepo) savePoint(point *influxdata.Point) error {
	repo.mu.Lock()
	defer repo.mu.Unlock()
	if repo.batch == nil {
		return errNilBatch
	}

	// Ignore ticker if there is nothing to save.
	if len(repo.batch.Points()) == 0 && point == nil {
		return nil
	}

	if point != nil {
		repo.batch.AddPoint(point)
	}

	if len(repo.batch.Points())%repo.batchSize == 0 || point == nil {
		if err := repo.client.Write(repo.batch); err != nil {
			return err
		}
		// It would be nice to reset ticker at this point, which
		// implies creating a new ticker and goroutine. It would
		// introduce unnecessary complexity with no justified benefits.
		var err error
		repo.batch, err = influxdata.NewBatchPoints(repo.cfg)
		if err != nil {
			return err
		}
	}

	return nil
}

func (repo *influxRepo) Save(msg mainflux.Message) error {
	tgs, flds := repo.tagsOf(&msg), repo.fieldsOf(&msg)
	t := time.Unix(int64(msg.Time), 0)

	pt, err := influxdata.NewPoint(pointName, tgs, flds, t)
	if err != nil {
		return err
	}

	return repo.savePoint(pt)
}

func (repo *influxRepo) tagsOf(msg *mainflux.Message) tags {
	return tags{
		"channel":   msg.Channel,
		"publisher": msg.Publisher,
	}
}

func (repo *influxRepo) fieldsOf(msg *mainflux.Message) fields {
	updateTime := strconv.FormatFloat(msg.UpdateTime, 'f', -1, 64)
	ret := fields{
		"protocol":   msg.Protocol,
		"name":       msg.Name,
		"unit":       msg.Unit,
		"link":       msg.Link,
		"updateTime": updateTime,
	}

	switch msg.Value.(type) {
	case *mainflux.Message_FloatValue:
		ret["value"] = msg.GetFloatValue()
	case *mainflux.Message_StringValue:
		ret["stringValue"] = msg.GetStringValue()
	case *mainflux.Message_DataValue:
		ret["dataValue"] = msg.GetDataValue()
	case *mainflux.Message_BoolValue:
		ret["boolValue"] = msg.GetBoolValue()
	}

	if msg.ValueSum != nil {
		ret["valueSum"] = msg.GetValueSum().GetValue()
	}

	return ret
}
<commit_msg>Add name to influx tagset (#501)<commit_after>//
// Copyright (c) 2018
// Mainflux
//
// SPDX-License-Identifier: Apache-2.0
//

package influxdb

import (
	"errors"
	"strconv"
	"sync"
	"time"

	"github.com/mainflux/mainflux/writers"

	influxdata "github.com/influxdata/influxdb/client/v2"
	"github.com/mainflux/mainflux"
)

const pointName = "messages"

var _ writers.MessageRepository = (*influxRepo)(nil)

var (
	errZeroValueSize    = errors.New("zero value batch size")
	errZeroValueTimeout = errors.New("zero value batch timeout")
	errNilBatch         = errors.New("nil batch")
)

type influxRepo struct {
	client    influxdata.Client
	batch     influxdata.BatchPoints
	batchSize int
	mu        sync.Mutex
	tick      <-chan time.Time
	cfg       influxdata.BatchPointsConfig
}

type fields map[string]interface{}
type tags map[string]string

// New returns new InfluxDB writer.
func New(client influxdata.Client, database string, batchSize int, batchTimeout time.Duration) (writers.MessageRepository, error) {
	if batchSize <= 0 {
		return &influxRepo{}, errZeroValueSize
	}

	if batchTimeout <= 0 {
		return &influxRepo{}, errZeroValueTimeout
	}

	repo := &influxRepo{
		client: client,
		cfg: influxdata.BatchPointsConfig{
			Database: database,
		},
		batchSize: batchSize,
	}

	var err error
	repo.batch, err = influxdata.NewBatchPoints(repo.cfg)
	if err != nil {
		return &influxRepo{}, err
	}

	repo.tick = time.NewTicker(batchTimeout).C
	go func() {
		for {
			<-repo.tick
			// Nil point indicates that savePoint method is triggered by the ticker.
			repo.savePoint(nil)
		}
	}()

	return repo, nil
}

func (repo *influxRepo) savePoint(point *influxdata.Point) error {
	repo.mu.Lock()
	defer repo.mu.Unlock()
	if repo.batch == nil {
		return errNilBatch
	}

	// Ignore ticker if there is nothing to save.
	if len(repo.batch.Points()) == 0 && point == nil {
		return nil
	}

	if point != nil {
		repo.batch.AddPoint(point)
	}

	if len(repo.batch.Points())%repo.batchSize == 0 || point == nil {
		if err := repo.client.Write(repo.batch); err != nil {
			return err
		}
		// It would be nice to reset ticker at this point, which
		// implies creating a new ticker and goroutine. It would
		// introduce unnecessary complexity with no justified benefits.
		var err error
		repo.batch, err = influxdata.NewBatchPoints(repo.cfg)
		if err != nil {
			return err
		}
	}

	return nil
}

func (repo *influxRepo) Save(msg mainflux.Message) error {
	tgs, flds := repo.tagsOf(&msg), repo.fieldsOf(&msg)
	t := time.Unix(int64(msg.Time), 0)

	pt, err := influxdata.NewPoint(pointName, tgs, flds, t)
	if err != nil {
		return err
	}

	return repo.savePoint(pt)
}

func (repo *influxRepo) tagsOf(msg *mainflux.Message) tags {
	return tags{
		"channel":   msg.Channel,
		"publisher": msg.Publisher,
		"name":      msg.Name,
	}
}

func (repo *influxRepo) fieldsOf(msg *mainflux.Message) fields {
	updateTime := strconv.FormatFloat(msg.UpdateTime, 'f', -1, 64)
	ret := fields{
		"protocol":   msg.Protocol,
		"unit":       msg.Unit,
		"link":       msg.Link,
		"updateTime": updateTime,
	}

	switch msg.Value.(type) {
	case *mainflux.Message_FloatValue:
		ret["value"] = msg.GetFloatValue()
	case *mainflux.Message_StringValue:
		ret["stringValue"] = msg.GetStringValue()
	case *mainflux.Message_DataValue:
		ret["dataValue"] = msg.GetDataValue()
	case *mainflux.Message_BoolValue:
		ret["boolValue"] = msg.GetBoolValue()
	}

	if msg.ValueSum != nil {
		ret["valueSum"] = msg.GetValueSum().GetValue()
	}

	return ret
}
<|endoftext|>


<commit_before>package github

import (
	"errors"
	"fmt"
	"github.com/jingweno/octokat"
)

const (
	GitHubHost  string = "github.com"
	OAuthAppURL string = "http://owenou.com/gh"
)

type GitHub struct {
	Project *Project
	Config  *Config
}

func (gh *GitHub) PullRequest(id string) (*octokat.PullRequest, error) {
	client := gh.client()

	return client.PullRequest(gh.repo(), id)
}

func (gh *GitHub) CreatePullRequest(base, head, title, body string) (string, error) {
	client := gh.client()
	params := octokat.PullRequestParams{Base: base, Head: head, Title: title, Body: body}
	pullRequest, err := client.CreatePullRequest(gh.repo(), params)
	if err != nil {
		return "", err
	}

	return pullRequest.HTMLURL, nil
}

func (gh *GitHub) Repository(project Project) (*octokat.Repository, error) {
	client := gh.client()

	return client.Repository(octokat.Repo{Name: project.Name, UserName: project.Owner})
}

// TODO: detach GitHub from Project
func (gh *GitHub) IsRepositoryExist(project Project) bool {
	repo, err := gh.Repository(project)

	return err == nil && repo != nil
}

func (gh *GitHub) CreateRepository(project Project, description, homepage string, isPrivate bool) (*octokat.Repository, error) {
	params := octokat.Params{"description": description, "homepage": homepage, "private": isPrivate}
	if project.Owner != gh.Config.FetchUser() {
		params.Put("organization", project.Owner)
	}

	client := gh.client()

	return client.CreateRepository(project.Name, &params)
}

func (gh *GitHub) CreatePullRequestForIssue(base, head, issue string) (string, error) {
	client := gh.client()
	params := octokat.PullRequestForIssueParams{Base: base, Head: head, Issue: issue}
	pullRequest, err := client.CreatePullRequestForIssue(gh.repo(), params)
	if err != nil {
		return "", err
	}

	return pullRequest.HTMLURL, nil
}

func (gh *GitHub) CiStatus(sha string) (*octokat.Status, error) {
	client := gh.client()
	statuses, err := client.Statuses(gh.repo(), sha)
	if err != nil {
		return nil, err
	}

	if len(statuses) == 0 {
		return nil, nil
	}

	return &statuses[0], nil
}

func (gh *GitHub) ForkRepository(name, owner string, noRemote bool) (repo *octokat.Repository, err error) {
	client := gh.client()
	config := gh.Config
	repo, err = client.Repository(octokat.Repo{Name: name, UserName: config.User})
	if repo != nil && err == nil {
		msg := fmt.Sprintf("Error creating fork: %s exists on %s", repo.FullName, GitHubHost)
		err = errors.New(msg)
		return
	}

	repo, err = client.Fork(octokat.Repo{Name: name, UserName: owner}, nil)

	return
}

func (gh *GitHub) ExpandRemoteUrl(owner, name string, isSSH bool) (url string) {
	project := gh.Project
	if owner == "origin" {
		config := gh.Config
		owner = config.FetchUser()
	}

	return project.GitURL(name, owner, isSSH)
}

func (gh *GitHub) repo() octokat.Repo {
	project := gh.Project
	return octokat.Repo{Name: project.Name, UserName: project.Owner}
}

func findOrCreateToken(user, password string) (string, error) {
	client := octokat.NewClient().WithLogin(user, password)
	auths, err := client.Authorizations()
	if err != nil {
		return "", err
	}

	var token string
	for _, auth := range auths {
		if auth.NoteUrl == OAuthAppURL {
			token = auth.Token
			break
		}
	}

	if token == "" {
		authParam := octokat.AuthorizationParams{}
		authParam.Scopes = append(authParam.Scopes, "repo")
		authParam.Note = "gh"
		authParam.NoteUrl = OAuthAppURL

		auth, err := client.CreatedAuthorization(authParam)
		if err != nil {
			return "", err
		}

		token = auth.Token
	}

	return token, nil
}

func (gh *GitHub) client() *octokat.Client {
	config := gh.Config
	config.FetchCredentials()

	return octokat.NewClient().WithToken(config.Token)
}

func New() *GitHub {
	project := CurrentProject()
	c := CurrentConfig()
	c.FetchUser()

	return &GitHub{project, c}
}

// TODO: detach project from GitHub
func NewWithoutProject() *GitHub {
	c := CurrentConfig()
	c.FetchUser()

	return &GitHub{nil, c}
}
<commit_msg>Fix bug that ci-status always return the first one<commit_after>package github

import (
	"errors"
	"fmt"
	"github.com/jingweno/octokat"
)

const (
	GitHubHost  string = "github.com"
	OAuthAppURL string = "http://owenou.com/gh"
)

type GitHub struct {
	Project *Project
	Config  *Config
}

func (gh *GitHub) PullRequest(id string) (*octokat.PullRequest, error) {
	client := gh.client()

	return client.PullRequest(gh.repo(), id)
}

func (gh *GitHub) CreatePullRequest(base, head, title, body string) (string, error) {
	client := gh.client()
	params := octokat.PullRequestParams{Base: base, Head: head, Title: title, Body: body}
	pullRequest, err := client.CreatePullRequest(gh.repo(), params)
	if err != nil {
		return "", err
	}

	return pullRequest.HTMLURL, nil
}

func (gh *GitHub) Repository(project Project) (*octokat.Repository, error) {
	client := gh.client()

	return client.Repository(octokat.Repo{Name: project.Name, UserName: project.Owner})
}

// TODO: detach GitHub from Project
func (gh *GitHub) IsRepositoryExist(project Project) bool {
	repo, err := gh.Repository(project)

	return err == nil && repo != nil
}

func (gh *GitHub) CreateRepository(project Project, description, homepage string, isPrivate bool) (*octokat.Repository, error) {
	params := octokat.Params{"description": description, "homepage": homepage, "private": isPrivate}
	if project.Owner != gh.Config.FetchUser() {
		params.Put("organization", project.Owner)
	}

	client := gh.client()

	return client.CreateRepository(project.Name, &params)
}

func (gh *GitHub) CreatePullRequestForIssue(base, head, issue string) (string, error) {
	client := gh.client()
	params := octokat.PullRequestForIssueParams{Base: base, Head: head, Issue: issue}
	pullRequest, err := client.CreatePullRequestForIssue(gh.repo(), params)
	if err != nil {
		return "", err
	}

	return pullRequest.HTMLURL, nil
}

func (gh *GitHub) CiStatus(sha string) (*octokat.Status, error) {
	client := gh.client()
	statuses, err := client.Statuses(gh.repo(), sha)
	if err != nil {
		return nil, err
	}

	if len(statuses) == 0 {
		return nil, nil
	}

	return &statuses[len(statuses) - 1], nil
}

func (gh *GitHub) ForkRepository(name, owner string, noRemote bool) (repo *octokat.Repository, err error) {
	client := gh.client()
	config := gh.Config
	repo, err = client.Repository(octokat.Repo{Name: name, UserName: config.User})
	if repo != nil && err == nil {
		msg := fmt.Sprintf("Error creating fork: %s exists on %s", repo.FullName, GitHubHost)
		err = errors.New(msg)
		return
	}

	repo, err = client.Fork(octokat.Repo{Name: name, UserName: owner}, nil)

	return
}

func (gh *GitHub) ExpandRemoteUrl(owner, name string, isSSH bool) (url string) {
	project := gh.Project
	if owner == "origin" {
		config := gh.Config
		owner = config.FetchUser()
	}

	return project.GitURL(name, owner, isSSH)
}

func (gh *GitHub) repo() octokat.Repo {
	project := gh.Project
	return octokat.Repo{Name: project.Name, UserName: project.Owner}
}

func findOrCreateToken(user, password string) (string, error) {
	client := octokat.NewClient().WithLogin(user, password)
	auths, err := client.Authorizations()
	if err != nil {
		return "", err
	}

	var token string
	for _, auth := range auths {
		if auth.NoteUrl == OAuthAppURL {
			token = auth.Token
			break
		}
	}

	if token == "" {
		authParam := octokat.AuthorizationParams{}
		authParam.Scopes = append(authParam.Scopes, "repo")
		authParam.Note = "gh"
		authParam.NoteUrl = OAuthAppURL

		auth, err := client.CreatedAuthorization(authParam)
		if err != nil {
			return "", err
		}

		token = auth.Token
	}

	return token, nil
}

func (gh *GitHub) client() *octokat.Client {
	config := gh.Config
	config.FetchCredentials()

	return octokat.NewClient().WithToken(config.Token)
}

func New() *GitHub {
	project := CurrentProject()
	c := CurrentConfig()
	c.FetchUser()

	return &GitHub{project, c}
}

// TODO: detach project from GitHub
func NewWithoutProject() *GitHub {
	c := CurrentConfig()
	c.FetchUser()

	return &GitHub{nil, c}
}
<|endoftext|>


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

import (
	"fmt"
	"net/url"
	"path"
	"path/filepath"
	"strings"

	git "github.com/libgit2/git2go"
)

// repoWalker walks a tree, recursing into submodules.
type repoWalker struct {
	repo *git.Repository

	repoURL *url.URL
	tree    map[FileKey]BlobLocation

	// Path => SubmoduleEntry
	submodules map[string]*SubmoduleEntry

	// Path => commit SHA1
	subRepoVersions map[string]git.Oid
	err             error
	repoCache       *RepoCache

	// If set, don't gasp on missing submodules.
	ignoreMissingSubmodules bool
}

// subURL returns the URL for a submodule.
func (w *repoWalker) subURL(relURL string) (*url.URL, error) {
	if w.repoURL == nil {
		return nil, fmt.Errorf("no URL for base repo.")
	}
	if strings.HasPrefix(relURL, "../") {
		u := *w.repoURL
		u.Path = path.Join(u.Path, relURL)
		return &u, nil
	}

	return url.Parse(relURL)
}

// newRepoWalker creates a new repoWalker.
func newRepoWalker(r *git.Repository, repoURL string, repoCache *RepoCache) *repoWalker {
	u, _ := url.Parse(repoURL)
	return &repoWalker{
		repo:                    r,
		repoURL:                 u,
		tree:                    map[FileKey]BlobLocation{},
		repoCache:               repoCache,
		subRepoVersions:         map[string]git.Oid{},
		ignoreMissingSubmodules: true,
	}
}

// parseModuleMap initializes rw.submodules.
func (rw *repoWalker) parseModuleMap(t *git.Tree) error {
	modEntry := t.EntryByName(".gitmodules")
	if modEntry != nil {
		blob, err := rw.repo.LookupBlob(modEntry.Id)
		if err != nil {
			return err
		}

		mods, err := ParseGitModules(blob.Contents())
		if err != nil {
			return err
		}
		rw.submodules = map[string]*SubmoduleEntry{}
		for _, entry := range mods {
			rw.submodules[entry.Path] = entry
		}
	}
	return nil
}

// TreeToFiles fetches the blob SHA1s for a tree. If repoCache is
// non-nil, recurse into submodules. In addition, it returns a mapping
// that indicates in which repo each SHA1 can be found.
func TreeToFiles(r *git.Repository, t *git.Tree,
	repoURL string, repoCache *RepoCache) (map[FileKey]BlobLocation, map[string]git.Oid, error) {
	ref := newRepoWalker(r, repoURL, repoCache)

	if err := ref.parseModuleMap(t); err != nil {
		return nil, nil, err
	}

	t.Walk(ref.cbInt)
	if ref.err != nil {
		return nil, nil, ref.err
	}
	return ref.tree, ref.subRepoVersions, nil
}

// cb is the git2go callback
func (r *repoWalker) cb(n string, e *git.TreeEntry) error {
	p := filepath.Join(n, e.Name)
	if e.Type == git.ObjectCommit && r.repoCache != nil {
		submod := r.submodules[p]
		if submod == nil {
			if r.ignoreMissingSubmodules {
				return nil
			}
			return fmt.Errorf("in repo %s: no entry for submodule path %q", r.repoURL, p)
		}

		subURL, err := r.subURL(submod.URL)
		if err != nil {
			return err
		}

		subRepo, err := r.repoCache.Open(subURL)
		if err != nil {
			return err
		}

		obj, err := subRepo.Lookup(e.Id)
		if err != nil {
			return err
		}
		defer obj.Free()

		r.subRepoVersions[p] = *e.Id
		treeObj, err := obj.Peel(git.ObjectTree)
		if err != nil {
			return err
		}
		if treeObj != obj {
			defer treeObj.Free()
		}
		tree, err := treeObj.AsTree()
		if err != nil {
			return err
		}
		subTree, subVersions, err := TreeToFiles(subRepo, tree, subURL.String(), r.repoCache)
		if err != nil {
			return err
		}
		for k, repo := range subTree {
			r.tree[FileKey{
				SubRepoPath: filepath.Join(p, k.SubRepoPath),
				Path:        k.Path,
				ID:          k.ID,
			}] = repo
		}
		for k, v := range subVersions {
			r.subRepoVersions[filepath.Join(p, k)] = v
		}
		return nil
	}

	switch e.Filemode {
	case git.FilemodeBlob, git.FilemodeBlobExecutable:
	default:
		return nil
	}

	if e.Type != git.ObjectBlob {
		return nil
	}
	r.tree[FileKey{
		Path: p,
		ID:   *e.Id,
	}] = BlobLocation{
		Repo: r.repo,
		URL:  r.repoURL,
	}
	return nil
}

// cbInt is the callback suitable for use with git2go.
func (r *repoWalker) cbInt(n string, e *git.TreeEntry) int {
	err := r.cb(n, e)
	if err != nil {
		r.err = err
		return 1
	}
	return 0
}

// FileKey describes a blob at a location in the final tree. We also
// record the subrepository from where it came.
type FileKey struct {
	SubRepoPath string
	Path        string
	ID          git.Oid
}

func (k *FileKey) FullPath() string {
	return filepath.Join(k.SubRepoPath, k.Path)
}

// BlobLocation holds data where a blob can be found.
type BlobLocation struct {
	Repo *git.Repository
	URL  *url.URL
}

func (l *BlobLocation) Blob(id *git.Oid) ([]byte, error) {
	blob, err := l.Repo.LookupBlob(id)
	if err != nil {
		return nil, err
	}
	defer blob.Free()
	return blob.Contents(), nil
}
<commit_msg>Refactor submodule handling to get better error messages.<commit_after>// Copyright 2016 Google Inc. 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 gitindex

import (
	"fmt"
	"net/url"
	"path"
	"path/filepath"
	"strings"

	git "github.com/libgit2/git2go"
)

// repoWalker walks a tree, recursing into submodules.
type repoWalker struct {
	repo *git.Repository

	repoURL *url.URL
	tree    map[FileKey]BlobLocation

	// Path => SubmoduleEntry
	submodules map[string]*SubmoduleEntry

	// Path => commit SHA1
	subRepoVersions map[string]git.Oid
	err             error
	repoCache       *RepoCache

	// If set, don't gasp on missing submodules.
	ignoreMissingSubmodules bool
}

// subURL returns the URL for a submodule.
func (w *repoWalker) subURL(relURL string) (*url.URL, error) {
	if w.repoURL == nil {
		return nil, fmt.Errorf("no URL for base repo.")
	}
	if strings.HasPrefix(relURL, "../") {
		u := *w.repoURL
		u.Path = path.Join(u.Path, relURL)
		return &u, nil
	}

	return url.Parse(relURL)
}

// newRepoWalker creates a new repoWalker.
func newRepoWalker(r *git.Repository, repoURL string, repoCache *RepoCache) *repoWalker {
	u, _ := url.Parse(repoURL)
	return &repoWalker{
		repo:                    r,
		repoURL:                 u,
		tree:                    map[FileKey]BlobLocation{},
		repoCache:               repoCache,
		subRepoVersions:         map[string]git.Oid{},
		ignoreMissingSubmodules: true,
	}
}

// parseModuleMap initializes rw.submodules.
func (rw *repoWalker) parseModuleMap(t *git.Tree) error {
	modEntry := t.EntryByName(".gitmodules")
	if modEntry != nil {
		blob, err := rw.repo.LookupBlob(modEntry.Id)
		if err != nil {
			return err
		}

		mods, err := ParseGitModules(blob.Contents())
		if err != nil {
			return err
		}
		rw.submodules = map[string]*SubmoduleEntry{}
		for _, entry := range mods {
			rw.submodules[entry.Path] = entry
		}
	}
	return nil
}

// TreeToFiles fetches the blob SHA1s for a tree. If repoCache is
// non-nil, recurse into submodules. In addition, it returns a mapping
// that indicates in which repo each SHA1 can be found.
func TreeToFiles(r *git.Repository, t *git.Tree,
	repoURL string, repoCache *RepoCache) (map[FileKey]BlobLocation, map[string]git.Oid, error) {
	ref := newRepoWalker(r, repoURL, repoCache)

	if err := ref.parseModuleMap(t); err != nil {
		return nil, nil, err
	}

	t.Walk(ref.cbInt)
	if ref.err != nil {
		return nil, nil, ref.err
	}
	return ref.tree, ref.subRepoVersions, nil
}

func (r *repoWalker) handleSubmodule(p string, id *git.Oid) error {
	submod := r.submodules[p]
	if submod == nil {
		if r.ignoreMissingSubmodules {
			return nil
		}
		return fmt.Errorf("no entry for submodule path %q", r.repoURL)
	}

	subURL, err := r.subURL(submod.URL)
	if err != nil {
		return err
	}

	subRepo, err := r.repoCache.Open(subURL)
	if err != nil {
		return err
	}

	obj, err := subRepo.Lookup(id)
	if err != nil {
		return err
	}
	defer obj.Free()

	r.subRepoVersions[p] = *id
	treeObj, err := obj.Peel(git.ObjectTree)
	if err != nil {
		return err
	}
	if treeObj != obj {
		defer treeObj.Free()
	}
	tree, err := treeObj.AsTree()
	if err != nil {
		return err
	}
	subTree, subVersions, err := TreeToFiles(subRepo, tree, subURL.String(), r.repoCache)
	if err != nil {
		return err
	}
	for k, repo := range subTree {
		r.tree[FileKey{
			SubRepoPath: filepath.Join(p, k.SubRepoPath),
			Path:        k.Path,
			ID:          k.ID,
		}] = repo
	}
	for k, v := range subVersions {
		r.subRepoVersions[filepath.Join(p, k)] = v
	}
	return nil
}

// cb is the git2go callback
func (r *repoWalker) cb(n string, e *git.TreeEntry) error {
	p := filepath.Join(n, e.Name)
	if e.Type == git.ObjectCommit && r.repoCache != nil {
		if err := r.handleSubmodule(p, e.Id); err != nil {
			return fmt.Errorf("submodule %s: %v", p, err)
		}
	}

	switch e.Filemode {
	case git.FilemodeBlob, git.FilemodeBlobExecutable:
	default:
		return nil
	}

	if e.Type != git.ObjectBlob {
		return nil
	}
	r.tree[FileKey{
		Path: p,
		ID:   *e.Id,
	}] = BlobLocation{
		Repo: r.repo,
		URL:  r.repoURL,
	}
	return nil
}

// cbInt is the callback suitable for use with git2go.
func (r *repoWalker) cbInt(n string, e *git.TreeEntry) int {
	err := r.cb(n, e)
	if err != nil {
		r.err = err
		return 1
	}
	return 0
}

// FileKey describes a blob at a location in the final tree. We also
// record the subrepository from where it came.
type FileKey struct {
	SubRepoPath string
	Path        string
	ID          git.Oid
}

func (k *FileKey) FullPath() string {
	return filepath.Join(k.SubRepoPath, k.Path)
}

// BlobLocation holds data where a blob can be found.
type BlobLocation struct {
	Repo *git.Repository
	URL  *url.URL
}

func (l *BlobLocation) Blob(id *git.Oid) ([]byte, error) {
	blob, err := l.Repo.LookupBlob(id)
	if err != nil {
		return nil, err
	}
	defer blob.Free()
	return blob.Contents(), nil
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package avmwallet

import (
	"errors"
	"fmt"

	stdmath "math"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow"
	"github.com/ava-labs/gecko/utils/crypto"
	"github.com/ava-labs/gecko/utils/hashing"
	"github.com/ava-labs/gecko/utils/logging"
	"github.com/ava-labs/gecko/utils/math"
	"github.com/ava-labs/gecko/utils/timer"
	"github.com/ava-labs/gecko/utils/wrappers"
	"github.com/ava-labs/gecko/vms/avm"
	"github.com/ava-labs/gecko/vms/components/codec"
	"github.com/ava-labs/gecko/vms/secp256k1fx"
)

// Wallet is a holder for keys and UTXOs for the Ava DAG.
type Wallet struct {
	networkID uint32
	chainID   ids.ID

	clock timer.Clock
	codec codec.Codec
	log   logging.Logger

	keychain *secp256k1fx.Keychain // Mapping from public address to the SigningKeys
	utxoSet  *UTXOSet              // Mapping from utxoIDs to UTXOs

	balance map[[32]byte]uint64
	txFee   uint64

	txsSent int32
	txs     []*avm.Tx
}

// NewWallet returns a new Wallet
func NewWallet(log logging.Logger, networkID uint32, chainID ids.ID, txFee uint64) (*Wallet, error) {
	c := codec.NewDefault()
	errs := wrappers.Errs{}
	errs.Add(
		c.RegisterType(&avm.BaseTx{}),
		c.RegisterType(&avm.CreateAssetTx{}),
		c.RegisterType(&avm.OperationTx{}),
		c.RegisterType(&secp256k1fx.MintOutput{}),
		c.RegisterType(&secp256k1fx.TransferOutput{}),
		c.RegisterType(&secp256k1fx.MintInput{}),
		c.RegisterType(&secp256k1fx.TransferInput{}),
		c.RegisterType(&secp256k1fx.Credential{}),
	)
	return &Wallet{
		networkID: networkID,
		chainID:   chainID,
		codec:     c,
		log:       log,
		keychain:  secp256k1fx.NewKeychain(),
		utxoSet:   &UTXOSet{},
		balance:   make(map[[32]byte]uint64),
		txFee:     txFee,
	}, errs.Err
}

// Codec returns the codec used for serialization
func (w *Wallet) Codec() codec.Codec { return w.codec }

// GetAddress returns one of the addresses this wallet manages. If no address
// exists, one will be created.
func (w *Wallet) GetAddress() (ids.ShortID, error) {
	if w.keychain.Addrs.Len() == 0 {
		return w.CreateAddress()
	}
	return w.keychain.Addrs.CappedList(1)[0], nil
}

// CreateAddress returns a new address.
// It also saves the address and the private key that controls it
// so the address can be used later
func (w *Wallet) CreateAddress() (ids.ShortID, error) {
	privKey, err := w.keychain.New()
	return privKey.PublicKey().Address(), err
}

// ImportKey imports a private key into this wallet
func (w *Wallet) ImportKey(sk *crypto.PrivateKeySECP256K1R) { w.keychain.Add(sk) }

// AddUTXO adds a new UTXO to this wallet if this wallet may spend it
// The UTXO's output must be an OutputPayment
func (w *Wallet) AddUTXO(utxo *avm.UTXO) {
	out, ok := utxo.Out.(avm.FxTransferable)
	if !ok {
		return
	}

	if _, _, err := w.keychain.Spend(out, stdmath.MaxUint64); err == nil {
		w.utxoSet.Put(utxo)
		w.balance[utxo.AssetID().Key()] += out.Amount()
	}
}

// RemoveUTXO from this wallet
func (w *Wallet) RemoveUTXO(utxoID ids.ID) {
	utxo := w.utxoSet.Get(utxoID)
	if utxo == nil {
		return
	}

	assetID := utxo.AssetID()
	assetKey := assetID.Key()
	newBalance := w.balance[assetKey] - utxo.Out.(avm.FxTransferable).Amount()
	if newBalance == 0 {
		delete(w.balance, assetKey)
	} else {
		w.balance[assetKey] = newBalance
	}

	w.utxoSet.Remove(utxoID)
}

// Balance returns the amount of the assets in this wallet
func (w *Wallet) Balance(assetID ids.ID) uint64 { return w.balance[assetID.Key()] }

// CreateTx returns a tx that sends [amount] of [assetID] to [destAddr]
func (w *Wallet) CreateTx(assetID ids.ID, amount uint64, destAddr ids.ShortID) (*avm.Tx, error) {
	if amount == 0 {
		return nil, errors.New("invalid amount")
	}

	amountSpent := uint64(0)
	time := w.clock.Unix()

	ins := []*avm.TransferableInput{}
	keys := [][]*crypto.PrivateKeySECP256K1R{}
	for _, utxo := range w.utxoSet.UTXOs {
		if !utxo.AssetID().Equals(assetID) {
			continue
		}
		inputIntf, signers, err := w.keychain.Spend(utxo.Out, time)
		if err != nil {
			continue
		}
		input, ok := inputIntf.(avm.FxTransferable)
		if !ok {
			continue
		}
		spent, err := math.Add64(amountSpent, input.Amount())
		if err != nil {
			return nil, err
		}
		amountSpent = spent

		in := &avm.TransferableInput{
			UTXOID: utxo.UTXOID,
			Asset:  avm.Asset{ID: assetID},
			In:     input,
		}

		ins = append(ins, in)
		keys = append(keys, signers)

		if amountSpent >= amount {
			break
		}
	}

	if amountSpent < amount {
		return nil, errors.New("insufficient funds")
	}

	avm.SortTransferableInputsWithSigners(ins, keys)

	outs := []*avm.TransferableOutput{
		&avm.TransferableOutput{
			Asset: avm.Asset{ID: assetID},
			Out: &secp256k1fx.TransferOutput{
				Amt:      amount,
				Locktime: 0,
				OutputOwners: secp256k1fx.OutputOwners{
					Threshold: 1,
					Addrs:     []ids.ShortID{destAddr},
				},
			},
		},
	}

	if amountSpent > amount {
		changeAddr, err := w.GetAddress()
		if err != nil {
			return nil, err
		}
		outs = append(outs,
			&avm.TransferableOutput{
				Asset: avm.Asset{ID: assetID},
				Out: &secp256k1fx.TransferOutput{
					Amt:      amountSpent - amount,
					Locktime: 0,
					OutputOwners: secp256k1fx.OutputOwners{
						Threshold: 1,
						Addrs:     []ids.ShortID{changeAddr},
					},
				},
			},
		)
	}

	avm.SortTransferableOutputs(outs, w.codec)

	tx := &avm.Tx{
		UnsignedTx: &avm.BaseTx{
			NetID: w.networkID,
			BCID:  w.chainID,
			Outs:  outs,
			Ins:   ins,
		},
	}

	unsignedBytes, err := w.codec.Marshal(&tx.UnsignedTx)
	if err != nil {
		return nil, err
	}
	hash := hashing.ComputeHash256(unsignedBytes)

	for _, credKeys := range keys {
		cred := &secp256k1fx.Credential{}
		for _, key := range credKeys {
			sig, err := key.SignHash(hash)
			if err != nil {
				return nil, err
			}
			fixedSig := [crypto.SECP256K1RSigLen]byte{}
			copy(fixedSig[:], sig)

			cred.Sigs = append(cred.Sigs, fixedSig)
		}
		tx.Creds = append(tx.Creds, &avm.Credential{Cred: cred})
	}

	b, err := w.codec.Marshal(tx)
	if err != nil {
		return nil, err
	}
	tx.Initialize(b)

	return tx, nil
}

// GenerateTxs generates the transactions that will be sent
// during the test
// Generate them all on test initialization so tx generation is not bottleneck
// in testing
func (w *Wallet) GenerateTxs(numTxs int, assetID ids.ID) error {
	w.log.Info("Generating %d transactions", numTxs)

	ctx := snow.DefaultContextTest()
	ctx.NetworkID = w.networkID
	ctx.ChainID = w.chainID

	frequency := numTxs / 50
	if frequency > 1000 {
		frequency = 1000
	}

	w.txs = make([]*avm.Tx, numTxs)
	for i := 0; i < numTxs; i++ {
		addr, err := w.CreateAddress()
		if err != nil {
			return err
		}
		tx, err := w.CreateTx(assetID, 1, addr)
		if err != nil {
			return err
		}

		for _, utxoID := range tx.InputUTXOs() {
			w.RemoveUTXO(utxoID.InputID())
		}
		for _, utxo := range tx.UTXOs() {
			w.AddUTXO(utxo)
		}

		if numGenerated := i + 1; numGenerated%frequency == 0 {
			w.log.Info("Generated %d out of %d transactions", numGenerated, numTxs)
		}

		w.txs[i] = tx
	}

	w.log.Info("Finished generating %d transactions", numTxs)
	return nil
}

// NextTx returns the next tx to be sent as part of xput test
func (w *Wallet) NextTx() *avm.Tx {
	if len(w.txs) == 0 {
		return nil
	}
	tx := w.txs[0]
	w.txs = w.txs[1:]
	return tx
}

func (w *Wallet) String() string {
	return fmt.Sprintf(
		"Keychain:\n"+
			"%s\n"+
			"%s",
		w.keychain.PrefixedString("    "),
		w.utxoSet.PrefixedString("    "),
	)
}
<commit_msg>Fixed xput test<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package avmwallet

import (
	"errors"
	"fmt"

	stdmath "math"

	"github.com/ava-labs/gecko/ids"
	"github.com/ava-labs/gecko/snow"
	"github.com/ava-labs/gecko/utils/crypto"
	"github.com/ava-labs/gecko/utils/hashing"
	"github.com/ava-labs/gecko/utils/logging"
	"github.com/ava-labs/gecko/utils/math"
	"github.com/ava-labs/gecko/utils/timer"
	"github.com/ava-labs/gecko/utils/wrappers"
	"github.com/ava-labs/gecko/vms/avm"
	"github.com/ava-labs/gecko/vms/components/codec"
	"github.com/ava-labs/gecko/vms/secp256k1fx"
)

// Wallet is a holder for keys and UTXOs for the Ava DAG.
type Wallet struct {
	networkID uint32
	chainID   ids.ID

	clock timer.Clock
	codec codec.Codec
	log   logging.Logger

	keychain *secp256k1fx.Keychain // Mapping from public address to the SigningKeys
	utxoSet  *UTXOSet              // Mapping from utxoIDs to UTXOs

	balance map[[32]byte]uint64
	txFee   uint64

	txsSent int32
	txs     []*avm.Tx
}

// NewWallet returns a new Wallet
func NewWallet(log logging.Logger, networkID uint32, chainID ids.ID, txFee uint64) (*Wallet, error) {
	c := codec.NewDefault()
	errs := wrappers.Errs{}
	errs.Add(
		c.RegisterType(&avm.BaseTx{}),
		c.RegisterType(&avm.CreateAssetTx{}),
		c.RegisterType(&avm.OperationTx{}),
		c.RegisterType(&secp256k1fx.MintOutput{}),
		c.RegisterType(&secp256k1fx.TransferOutput{}),
		c.RegisterType(&secp256k1fx.MintInput{}),
		c.RegisterType(&secp256k1fx.TransferInput{}),
		c.RegisterType(&secp256k1fx.Credential{}),
	)
	return &Wallet{
		networkID: networkID,
		chainID:   chainID,
		codec:     c,
		log:       log,
		keychain:  secp256k1fx.NewKeychain(),
		utxoSet:   &UTXOSet{},
		balance:   make(map[[32]byte]uint64),
		txFee:     txFee,
	}, errs.Err
}

// Codec returns the codec used for serialization
func (w *Wallet) Codec() codec.Codec { return w.codec }

// GetAddress returns one of the addresses this wallet manages. If no address
// exists, one will be created.
func (w *Wallet) GetAddress() (ids.ShortID, error) {
	if w.keychain.Addrs.Len() == 0 {
		return w.CreateAddress()
	}
	return w.keychain.Addrs.CappedList(1)[0], nil
}

// CreateAddress returns a new address.
// It also saves the address and the private key that controls it
// so the address can be used later
func (w *Wallet) CreateAddress() (ids.ShortID, error) {
	privKey, err := w.keychain.New()
	return privKey.PublicKey().Address(), err
}

// ImportKey imports a private key into this wallet
func (w *Wallet) ImportKey(sk *crypto.PrivateKeySECP256K1R) { w.keychain.Add(sk) }

// AddUTXO adds a new UTXO to this wallet if this wallet may spend it
// The UTXO's output must be an OutputPayment
func (w *Wallet) AddUTXO(utxo *avm.UTXO) {
	out, ok := utxo.Out.(avm.FxTransferable)
	if !ok {
		return
	}

	if _, _, err := w.keychain.Spend(out, stdmath.MaxUint64); err == nil {
		w.utxoSet.Put(utxo)
		w.balance[utxo.AssetID().Key()] += out.Amount()
	}
}

// RemoveUTXO from this wallet
func (w *Wallet) RemoveUTXO(utxoID ids.ID) {
	utxo := w.utxoSet.Get(utxoID)
	if utxo == nil {
		return
	}

	assetID := utxo.AssetID()
	assetKey := assetID.Key()
	newBalance := w.balance[assetKey] - utxo.Out.(avm.FxTransferable).Amount()
	if newBalance == 0 {
		delete(w.balance, assetKey)
	} else {
		w.balance[assetKey] = newBalance
	}

	w.utxoSet.Remove(utxoID)
}

// Balance returns the amount of the assets in this wallet
func (w *Wallet) Balance(assetID ids.ID) uint64 { return w.balance[assetID.Key()] }

// CreateTx returns a tx that sends [amount] of [assetID] to [destAddr]
func (w *Wallet) CreateTx(assetID ids.ID, amount uint64, destAddr ids.ShortID) (*avm.Tx, error) {
	if amount == 0 {
		return nil, errors.New("invalid amount")
	}

	amountSpent := uint64(0)
	time := w.clock.Unix()

	ins := []*avm.TransferableInput{}
	keys := [][]*crypto.PrivateKeySECP256K1R{}
	for _, utxo := range w.utxoSet.UTXOs {
		if !utxo.AssetID().Equals(assetID) {
			continue
		}
		inputIntf, signers, err := w.keychain.Spend(utxo.Out, time)
		if err != nil {
			continue
		}
		input, ok := inputIntf.(avm.FxTransferable)
		if !ok {
			continue
		}
		spent, err := math.Add64(amountSpent, input.Amount())
		if err != nil {
			return nil, err
		}
		amountSpent = spent

		in := &avm.TransferableInput{
			UTXOID: utxo.UTXOID,
			Asset:  avm.Asset{ID: assetID},
			In:     input,
		}

		ins = append(ins, in)
		keys = append(keys, signers)

		if amountSpent >= amount {
			break
		}
	}

	if amountSpent < amount {
		return nil, errors.New("insufficient funds")
	}

	avm.SortTransferableInputsWithSigners(ins, keys)

	outs := []*avm.TransferableOutput{
		&avm.TransferableOutput{
			Asset: avm.Asset{ID: assetID},
			Out: &secp256k1fx.TransferOutput{
				Amt:      amount,
				Locktime: 0,
				OutputOwners: secp256k1fx.OutputOwners{
					Threshold: 1,
					Addrs:     []ids.ShortID{destAddr},
				},
			},
		},
	}

	if amountSpent > amount {
		changeAddr, err := w.GetAddress()
		if err != nil {
			return nil, err
		}
		outs = append(outs,
			&avm.TransferableOutput{
				Asset: avm.Asset{ID: assetID},
				Out: &secp256k1fx.TransferOutput{
					Amt:      amountSpent - amount,
					Locktime: 0,
					OutputOwners: secp256k1fx.OutputOwners{
						Threshold: 1,
						Addrs:     []ids.ShortID{changeAddr},
					},
				},
			},
		)
	}

	avm.SortTransferableOutputs(outs, w.codec)

	tx := &avm.Tx{
		UnsignedTx: &avm.BaseTx{
			NetID: w.networkID,
			BCID:  w.chainID,
			Outs:  outs,
			Ins:   ins,
		},
	}

	unsignedBytes, err := w.codec.Marshal(&tx.UnsignedTx)
	if err != nil {
		return nil, err
	}
	hash := hashing.ComputeHash256(unsignedBytes)

	for _, credKeys := range keys {
		cred := &secp256k1fx.Credential{}
		for _, key := range credKeys {
			sig, err := key.SignHash(hash)
			if err != nil {
				return nil, err
			}
			fixedSig := [crypto.SECP256K1RSigLen]byte{}
			copy(fixedSig[:], sig)

			cred.Sigs = append(cred.Sigs, fixedSig)
		}
		tx.Creds = append(tx.Creds, cred)
	}

	b, err := w.codec.Marshal(tx)
	if err != nil {
		return nil, err
	}
	tx.Initialize(b)

	return tx, nil
}

// GenerateTxs generates the transactions that will be sent
// during the test
// Generate them all on test initialization so tx generation is not bottleneck
// in testing
func (w *Wallet) GenerateTxs(numTxs int, assetID ids.ID) error {
	w.log.Info("Generating %d transactions", numTxs)

	ctx := snow.DefaultContextTest()
	ctx.NetworkID = w.networkID
	ctx.ChainID = w.chainID

	frequency := numTxs / 50
	if frequency > 1000 {
		frequency = 1000
	}

	w.txs = make([]*avm.Tx, numTxs)
	for i := 0; i < numTxs; i++ {
		addr, err := w.CreateAddress()
		if err != nil {
			return err
		}
		tx, err := w.CreateTx(assetID, 1, addr)
		if err != nil {
			return err
		}

		for _, utxoID := range tx.InputUTXOs() {
			w.RemoveUTXO(utxoID.InputID())
		}
		for _, utxo := range tx.UTXOs() {
			w.AddUTXO(utxo)
		}

		if numGenerated := i + 1; numGenerated%frequency == 0 {
			w.log.Info("Generated %d out of %d transactions", numGenerated, numTxs)
		}

		w.txs[i] = tx
	}

	w.log.Info("Finished generating %d transactions", numTxs)
	return nil
}

// NextTx returns the next tx to be sent as part of xput test
func (w *Wallet) NextTx() *avm.Tx {
	if len(w.txs) == 0 {
		return nil
	}
	tx := w.txs[0]
	w.txs = w.txs[1:]
	return tx
}

func (w *Wallet) String() string {
	return fmt.Sprintf(
		"Keychain:\n"+
			"%s\n"+
			"%s",
		w.keychain.PrefixedString("    "),
		w.utxoSet.PrefixedString("    "),
	)
}
<|endoftext|>


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

// Package google provides support for making
// OAuth2 authorized and authenticated HTTP requests
// to Google APIs. It supports Web server, client-side,
// service accounts, Google Compute Engine service accounts,
// and Google App Engine service accounts authorization
// and authentications flows:
//
// For more information, please read
// https://developers.google.com/accounts/docs/OAuth2.
package google // import "golang.org/x/oauth2/google"

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/jwt"
	"google.golang.org/cloud/compute/metadata"
)

// TODO(bradfitz,jbd): import "google.golang.org/cloud/compute/metadata" instead of
// the metaClient and metadata.google.internal stuff below.

// Endpoint is Google's OAuth 2.0 endpoint.
var Endpoint = oauth2.Endpoint{
	AuthURL:  "https://accounts.google.com/o/oauth2/auth",
	TokenURL: "https://accounts.google.com/o/oauth2/token",
}

// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"

// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
// the credentials that authorize and authenticate the requests.
// Create a service account on "Credentials" page under "APIs & Auth" for your
// project at https://console.developers.google.com to download a JSON key file.
func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
	var key struct {
		Email      string `json:"client_email"`
		PrivateKey string `json:"private_key"`
	}
	if err := json.Unmarshal(jsonKey, &key); err != nil {
		return nil, err
	}
	return &jwt.Config{
		Email:      key.Email,
		PrivateKey: []byte(key.PrivateKey),
		Scopes:     scope,
		TokenURL:   JWTTokenURL,
	}, nil
}

// ComputeTokenSource returns a token source that fetches access tokens
// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
// this token source if your program is running on a GCE instance.
// If no account is specified, "default" is used.
// Further information about retrieving access tokens from the GCE metadata
// server can be found at https://cloud.google.com/compute/docs/authentication.
func ComputeTokenSource(account string) oauth2.TokenSource {
	return oauth2.ReuseTokenSource(nil, computeSource{account: account})
}

type computeSource struct {
	account string
}

func (cs computeSource) Token() (*oauth2.Token, error) {
	if !metadata.OnGCE() {
		return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
	}
	acct := cs.account
	if acct == "" {
		acct = "default"
	}
	tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
	if err != nil {
		return nil, err
	}
	var res struct {
		AccessToken  string `json:"access_token"`
		ExpiresInSec int    `json:"expires_in"`
		TokenType    string `json:"token_type"`
	}
	err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
	if err != nil {
		return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
	}
	if res.ExpiresInSec == 0 || res.AccessToken == "" {
		return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
	}
	return &oauth2.Token{
		AccessToken: res.AccessToken,
		TokenType:   res.TokenType,
		Expiry:      time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
	}, nil
}
<commit_msg>oauth2: remove stale comment<commit_after>// Copyright 2014 The oauth2 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package google provides support for making
// OAuth2 authorized and authenticated HTTP requests
// to Google APIs. It supports Web server, client-side,
// service accounts, Google Compute Engine service accounts,
// and Google App Engine service accounts authorization
// and authentications flows:
//
// For more information, please read
// https://developers.google.com/accounts/docs/OAuth2.
package google // import "golang.org/x/oauth2/google"

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/jwt"
	"google.golang.org/cloud/compute/metadata"
)

// Endpoint is Google's OAuth 2.0 endpoint.
var Endpoint = oauth2.Endpoint{
	AuthURL:  "https://accounts.google.com/o/oauth2/auth",
	TokenURL: "https://accounts.google.com/o/oauth2/token",
}

// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"

// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
// the credentials that authorize and authenticate the requests.
// Create a service account on "Credentials" page under "APIs & Auth" for your
// project at https://console.developers.google.com to download a JSON key file.
func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
	var key struct {
		Email      string `json:"client_email"`
		PrivateKey string `json:"private_key"`
	}
	if err := json.Unmarshal(jsonKey, &key); err != nil {
		return nil, err
	}
	return &jwt.Config{
		Email:      key.Email,
		PrivateKey: []byte(key.PrivateKey),
		Scopes:     scope,
		TokenURL:   JWTTokenURL,
	}, nil
}

// ComputeTokenSource returns a token source that fetches access tokens
// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
// this token source if your program is running on a GCE instance.
// If no account is specified, "default" is used.
// Further information about retrieving access tokens from the GCE metadata
// server can be found at https://cloud.google.com/compute/docs/authentication.
func ComputeTokenSource(account string) oauth2.TokenSource {
	return oauth2.ReuseTokenSource(nil, computeSource{account: account})
}

type computeSource struct {
	account string
}

func (cs computeSource) Token() (*oauth2.Token, error) {
	if !metadata.OnGCE() {
		return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
	}
	acct := cs.account
	if acct == "" {
		acct = "default"
	}
	tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
	if err != nil {
		return nil, err
	}
	var res struct {
		AccessToken  string `json:"access_token"`
		ExpiresInSec int    `json:"expires_in"`
		TokenType    string `json:"token_type"`
	}
	err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
	if err != nil {
		return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
	}
	if res.ExpiresInSec == 0 || res.AccessToken == "" {
		return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
	}
	return &oauth2.Token{
		AccessToken: res.AccessToken,
		TokenType:   res.TokenType,
		Expiry:      time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
	}, nil
}
<|endoftext|>


<commit_before>package grace

import (
	"fmt"
	"net/http"
)

type graceHandlerFunc func(http.ResponseWriter, *http.Request)

// All magic happends here.
//
// We track all the HTTP requests that will finally invoke the corresponding
// handler function. This is the last function that will be called before the
// actual handler function.
//
// The reason we do it here to increase and decrease the count of currently
// handling HTTP requests is that all the valid HTTP requests will be here and
// we should serve them all seriously :). The other invalid HTTP requests refer
// to those that are accepted but filtered out before reaching
// `graceHandlerFunc.ServeHTTP`
func (f graceHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defaultGraceHTTPBarrier.Increase()
	fmt.Print("enter\n")
	fmt.Print(defaultGraceHTTPBarrier.GetCounter())
	defer func() {
		fmt.Print("exit\n")
		defaultGraceHTTPBarrier.Decrease()
	}()
	// invoke the actual handler function
	f(w, r)
}
<commit_msg>remove debug clause<commit_after>package grace

import "net/http"

type graceHandlerFunc func(http.ResponseWriter, *http.Request)

// All magic happends here.
//
// We track all the HTTP requests that will finally invoke the corresponding
// handler function. This is the last function that will be called before the
// actual handler function.
//
// The reason we do it here to increase and decrease the count of currently
// handling HTTP requests is that all the valid HTTP requests will be here and
// we should serve them all seriously :). The other invalid HTTP requests refer
// to those that are accepted but filtered out before reaching
// `graceHandlerFunc.ServeHTTP`
func (f graceHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defaultGraceHTTPBarrier.Increase()
	// fmt.Print("enter\n")
	// fmt.Print(defaultGraceHTTPBarrier.GetCounter())
	defer func() {
		// fmt.Print("exit\n")
		defaultGraceHTTPBarrier.Decrease()
	}()
	// invoke the actual handler function
	f(w, r)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"

	graph "github.com/andrei-m/jira-graph"
)

var (
	jiraHost             = flag.String("jira-host", "", "JIRA hostname")
	initialEstimateField = flag.String("initial-estimate-field", "customfield_11000", "the name of the custom field an epic's initial estimate (story points, etc.)")
	estimateField        = flag.String("estimate-field", "customfield_10004", "the name of the custom field for work estimation (story points, etc.)")
	flaggedField         = flag.String("flagged-field", "customfield_10002", "the name of the custom field for impediment flagging")
	sprintsField         = flag.String("sprints-field", "customfield_10007", "the name of the custom field for Greenhopper sprints")
	epicLinkField        = flag.String("epic-link-field", "customfield_10200", "the name of the custom field for Epic Link")
)

func main() {
	user := os.Getenv("JIRA_USER")
	if len(user) == 0 {
		log.Fatal("JIRA_USER is required")
	}
	pass := os.Getenv("JIRA_PASS")
	if len(pass) == 0 {
		log.Fatal("JIRA_PASS is required")
	}

	flag.Parse()
	if len(*jiraHost) == 0 {
		log.Fatal("-jira-host flag is required")
	}

	fc := graph.FieldConfig{
		InitialEstimate: *initialEstimateField,
		Estimate:        *estimateField,
		Flagged:         *flaggedField,
		Sprints:         *sprintsField,
		EpicLink:        *epicLinkField,
	}

	if err := graph.StartServer(user, pass, *jiraHost, fc); err != nil {
		log.Fatalf("server failed with error: %v", err)
	}
}
<commit_msg>Update Jira defaults<commit_after>package main

import (
	"flag"
	"log"
	"os"

	graph "github.com/andrei-m/jira-graph"
)

var (
	jiraHost             = flag.String("jira-host", "", "JIRA hostname")
	initialEstimateField = flag.String("initial-estimate-field", "timeoriginalestimate", "the name of the custom field an epic's initial estimate (story points, etc.)")
	estimateField        = flag.String("estimate-field", "customfield_10031", "the name of the custom field for work estimation (story points, etc.)")
	flaggedField         = flag.String("flagged-field", "customfield_10002", "the name of the custom field for impediment flagging")
	sprintsField         = flag.String("sprints-field", "Sprint", "the name of the custom field for Greenhopper sprints")
	epicLinkField        = flag.String("epic-link-field", "Epic Link", "the name of the custom field for Epic Link")
)

func main() {
	user := os.Getenv("JIRA_USER")
	if len(user) == 0 {
		log.Fatal("JIRA_USER is required")
	}
	pass := os.Getenv("JIRA_PASS")
	if len(pass) == 0 {
		log.Fatal("JIRA_PASS is required")
	}

	flag.Parse()
	if len(*jiraHost) == 0 {
		log.Fatal("-jira-host flag is required")
	}

	fc := graph.FieldConfig{
		InitialEstimate: *initialEstimateField,
		Estimate:        *estimateField,
		Flagged:         *flaggedField,
		Sprints:         *sprintsField,
		EpicLink:        *epicLinkField,
	}

	if err := graph.StartServer(user, pass, *jiraHost, fc); err != nil {
		log.Fatalf("server failed with error: %v", err)
	}
}
<|endoftext|>


<commit_before>package instagram_scraper

type Media struct {
	Caption        string
	Code           string
	Comments_count float64
	Date           uint64
	Display_src    string
	Id             string
	Is_ad          bool
	Likes_bount    float64
	Owner          Account
	Media_type     string
}

func GetFromMediaPage(info map[string]interface{}) (media Media) {
	media_info := info["media"].(map[string]interface{})

	media.Caption, _ = media_info["caption"].(string)
	media.Code, _ = media_info["code"].(string)
	media.Display_src = media_info["display_src"].(string)
	media.Id = media_info["id"].(string)
	media.Is_ad = media_info["is_ad"].(bool)

	comments, _ := media_info["comments"].(map[string]interface{})
	media.Comments_count, _ = comments["count"].(float64)

	fdate, _ := media_info["date"].(float64)
	media.Date = uint64(fdate)

	likes, _ := media_info["likes"].(map[string]interface{})
	media.Likes_bount = likes["count"].(float64)

	if media_info["is_video"].(bool) {
		media.Media_type = "video"
	} else {
		media.Media_type = "image"
	}

	owner, _ := media_info["owner"].(map[string]interface{})
	media.Owner.Id, _ = owner["id"].(string)
	media.Owner.Profile_pic_url, _ = owner["profile_pic_url"].(string)
	media.Owner.Username, _ = owner["username"].(string)
	media.Owner.Full_name, _ = owner["full_name"].(string)
	media.Owner.Is_private, _ = owner["is_private"].(bool)

	return
}
<commit_msg>Refactor: Media display_src to media_url for video-urls too<commit_after>package instagram_scraper

type Media struct {
	Caption        string
	Code           string
	Comments_count float64
	Date           uint64
	Id             string
	Is_ad          bool
	Likes_bount    float64
	Media_url      string
	Media_type     string
	Owner          Account
}

func GetFromMediaPage(info map[string]interface{}) (media Media) {
	media_info := info["media"].(map[string]interface{})

	media.Caption, _ = media_info["caption"].(string)
	media.Code, _ = media_info["code"].(string)
	media.Id = media_info["id"].(string)
	media.Is_ad = media_info["is_ad"].(bool)

	comments, _ := media_info["comments"].(map[string]interface{})
	media.Comments_count, _ = comments["count"].(float64)

	fdate, _ := media_info["date"].(float64)
	media.Date = uint64(fdate)

	likes, _ := media_info["likes"].(map[string]interface{})
	media.Likes_bount = likes["count"].(float64)

	if media_info["is_video"].(bool) {
		media.Media_type = "video"
		media.Media_url = media_info["video_url"].(string)
	} else {
		media.Media_type = "image"
		media.Media_url = media_info["display_src"].(string)
	}

	owner, _ := media_info["owner"].(map[string]interface{})
	media.Owner.Id, _ = owner["id"].(string)
	media.Owner.Profile_pic_url, _ = owner["profile_pic_url"].(string)
	media.Owner.Username, _ = owner["username"].(string)
	media.Owner.Full_name, _ = owner["full_name"].(string)
	media.Owner.Is_private, _ = owner["is_private"].(bool)

	return
}
<|endoftext|>


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

package integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"testing"
)

// TestGoTest effectively runs "go test ./..." inside a QEMU instance. The
// tests run as root and can do all sorts of things not possible otherwise.
func TestGoTest(t *testing.T) {
	// Create a temporary directory.
	tmpDir, err := ioutil.TempDir("", "uroot-integration")
	if err != nil {
		t.Fatal(err)
	}

	// Create list of packages to test.
	// TODO: include all packages in cmds
	pkgs := []string{
		"github.com/u-root/u-root/cmds/ls",
		"github.com/u-root/u-root/cmds/mknod",
	}

	// Statically build tests and add them to the temporary directory.
	os.Setenv("CGO_ENABLED", "0")
	testDir := filepath.Join(tmpDir, "tests")
	for _, pkg := range pkgs {
		testFile := filepath.Join(testDir, path.Base(pkg))
		cmd := exec.Command("go", "test", "-c", pkg, "-o", testFile)
		cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
		if err := cmd.Run(); err != nil {
			t.Fatalf("could not build %s: %v", pkg, err)
		}
	}

	// Create the CPIO and start QEMU.
	tmpDir, q := testWithQEMU(t, options{
		uinitName: "gotest",
		tmpDir:    tmpDir,
	})
	defer cleanup(t, tmpDir, q)

	// Check that each test passed.
	bases := []string{}
	for _, pkg := range pkgs {
		bases = append(bases, path.Base(pkg))
	}
	sort.Strings(bases) // Tests are run and checked in sorted order.
	t.Log("TAP: TAP version 12")
	t.Logf("TAP: 1..%d", len(bases))
	for i, base := range bases {
		runMsg := fmt.Sprintf("TAP: # running %d - %s", i, base)
		passMsg := fmt.Sprintf("TAP: ok %d - %s", i, base)
		failMsg := fmt.Sprintf("TAP: not ok %d - %s", i, base)

		t.Log(runMsg)
		if err := q.Expect(passMsg); err == nil {
			t.Logf(passMsg)
		} else {
			t.Errorf(failMsg)
		}
	}
}
<commit_msg>integration: Run more tests in QEMU<commit_after>// Copyright 2018 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package integration

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"testing"
	"time"
)

// testPkgs returns a slice of tests to run.
func testPkgs(t *testing.T) []string {
	// Packages which do not contain tests (or do not contain tests for the
	// build target) will still compile a test binary which vacuously pass.
	cmd := exec.Command("go", "list",
		"github.com/u-root/u-root/cmds/...",
		// TODO: only running tests in cmds because tests in pkg have
		// duplicate names which confuses the test runner. This should
		// get fixed.
		// "github.com/u-root/u-root/xcmds/...",
		// "github.com/u-root/u-root/pkg/...",
	)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatal(err)
	}
	pkgs := strings.Fields(strings.TrimSpace(string(out)))

	// TODO: Some tests do not run properly in QEMU at the moment. They are
	// blacklisted. These tests fail for mostly two reasons:
	// 1. either it requires networking (not enabled in the kernel)
	// 2. or it depends on some test files (for example /bin/sleep)
	blacklist := []string{
		"github.com/u-root/u-root/cmds/cmp",
		"github.com/u-root/u-root/cmds/dhclient",
		"github.com/u-root/u-root/cmds/fmap",
		"github.com/u-root/u-root/cmds/kill",
		"github.com/u-root/u-root/cmds/tail",
		"github.com/u-root/u-root/cmds/wget",
		"github.com/u-root/u-root/cmds/which",
		"github.com/u-root/u-root/cmds/wifi",
	}
	for i := 0; i < len(pkgs); i++ {
		for _, b := range blacklist {
			if pkgs[i] == b {
				pkgs = append(pkgs[:i], pkgs[i+1:]...)
			}
		}
	}

	return pkgs
}

// TestGoTest effectively runs "go test ./..." inside a QEMU instance. The
// tests run as root and can do all sorts of things not possible otherwise.
func TestGoTest(t *testing.T) {
	// Create a temporary directory.
	tmpDir, err := ioutil.TempDir("", "uroot-integration")
	if err != nil {
		t.Fatal(err)
	}

	// Statically build tests and add them to the temporary directory.
	pkgs := testPkgs(t)
	os.Setenv("CGO_ENABLED", "0")
	testDir := filepath.Join(tmpDir, "tests")
	for _, pkg := range pkgs {
		testFile := filepath.Join(testDir, path.Base(pkg))
		cmd := exec.Command("go", "test", "-ldflags", "-s -w", "-c", pkg, "-o", testFile)
		cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
		if err := cmd.Run(); err != nil {
			t.Fatalf("could not build %s: %v", pkg, err)
		}
	}

	// Create the CPIO and start QEMU.
	tmpDir, q := testWithQEMU(t, options{
		uinitName: "gotest",
		tmpDir:    tmpDir,
	})
	defer cleanup(t, tmpDir, q)

	// Check that each test passed.
	bases := []string{}
	for _, pkg := range pkgs {
		bases = append(bases, path.Base(pkg))
	}
	sort.Strings(bases) // Tests are run and checked in sorted order.
	t.Log("TAP: TAP version 12")
	t.Logf("TAP: 1..%d", len(bases))
	for i, base := range bases {
		runMsg := fmt.Sprintf("TAP: # running %d - %s", i, base)
		passMsg := fmt.Sprintf("TAP: ok %d - %s", i, base)
		failMsg := fmt.Sprintf("TAP: not ok %d - %s", i, base)

		t.Log(runMsg)
		if err := q.Expect(passMsg); err == nil {
			t.Logf(passMsg)
		} else {
			t.Errorf(failMsg)
		}
	}
}
<|endoftext|>