<commit_before>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Package gcs provides wrappers around Google Cloud Storage (GCS) APIs.
// Package uses Application Default Credentials assuming that the program runs on GCE.
//
// See the following links for details and API reference:
// https://cloud.google.com/go/getting-started/using-cloud-storage
// https://godoc.org/cloud.google.com/go/storage
package gcs

import (
	"context"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"cloud.google.com/go/storage"
)

type Client struct {
	client *storage.Client
	ctx    context.Context
}

type File struct {
	Updated time.Time

	ctx    context.Context
	handle *storage.ObjectHandle
}

func (file *File) Reader() (io.ReadCloser, error) {
	return file.handle.NewReader(file.ctx)
}

func NewClient() (*Client, error) {
	ctx := context.Background()
	storageClient, err := storage.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	client := &Client{
		client: storageClient,
		ctx:    ctx,
	}
	return client, nil
}

func (client *Client) Close() {
	client.client.Close()
}

func (client *Client) Read(gcsFile string) (*File, error) {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return nil, err
	}
	bkt := client.client.Bucket(bucket)
	f := bkt.Object(filename)
	attrs, err := f.Attrs(client.ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to read %v attributes: %v", gcsFile, err)
	}
	if !attrs.Deleted.IsZero() {
		return nil, fmt.Errorf("file %v is deleted", gcsFile)
	}
	handle := f.If(storage.Conditions{
		GenerationMatch:     attrs.Generation,
		MetagenerationMatch: attrs.Metageneration,
	})
	file := &File{
		Updated: attrs.Updated,
		ctx:     client.ctx,
		handle:  handle,
	}
	return file, nil
}

func (client *Client) UploadFile(localFile, gcsFile string) error {
	local, err := os.Open(localFile)
	if err != nil {
		return err
	}
	defer local.Close()

	w, err := client.FileWriter(gcsFile)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, local)
	return err
}

func (client *Client) FileWriter(gcsFile string) (io.WriteCloser, error) {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return nil, err
	}
	bkt := client.client.Bucket(bucket)
	f := bkt.Object(filename)
	w := f.NewWriter(client.ctx)
	return w, nil
}

// Publish lets any user read gcsFile.
func (client *Client) Publish(gcsFile string) error {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return err
	}
	obj := client.client.Bucket(bucket).Object(filename)
	return obj.ACL().Set(client.ctx, storage.AllUsers, storage.RoleReader)
}

// Where things get published.
const PublicPrefix = "https://storage.googleapis.com/"

func split(file string) (bucket, filename string, err error) {
	pos := strings.IndexByte(file, '/')
	if pos == -1 {
		return "", "", fmt.Errorf("invalid GCS file name: %v", file)
	}
	return file[:pos], file[pos+1:], nil
}
<commit_msg>pkg/gcs: add attributes, listing and deletion support<commit_after>// Copyright 2017 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

// Package gcs provides wrappers around Google Cloud Storage (GCS) APIs.
// Package uses Application Default Credentials assuming that the program runs on GCE.
//
// See the following links for details and API reference:
// https://cloud.google.com/go/getting-started/using-cloud-storage
// https://godoc.org/cloud.google.com/go/storage
package gcs

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"cloud.google.com/go/storage"
	"google.golang.org/api/iterator"
)

type Client struct {
	client *storage.Client
	ctx    context.Context
}

type File struct {
	Updated time.Time

	ctx    context.Context
	handle *storage.ObjectHandle
}

func (file *File) Reader() (io.ReadCloser, error) {
	return file.handle.NewReader(file.ctx)
}

func NewClient() (*Client, error) {
	ctx := context.Background()
	storageClient, err := storage.NewClient(ctx)
	if err != nil {
		return nil, err
	}
	client := &Client{
		client: storageClient,
		ctx:    ctx,
	}
	return client, nil
}

func (client *Client) Close() {
	client.client.Close()
}

func (client *Client) Read(gcsFile string) (*File, error) {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return nil, err
	}
	bkt := client.client.Bucket(bucket)
	f := bkt.Object(filename)
	attrs, err := f.Attrs(client.ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to read %v attributes: %v", gcsFile, err)
	}
	if !attrs.Deleted.IsZero() {
		return nil, fmt.Errorf("file %v is deleted", gcsFile)
	}
	handle := f.If(storage.Conditions{
		GenerationMatch:     attrs.Generation,
		MetagenerationMatch: attrs.Metageneration,
	})
	file := &File{
		Updated: attrs.Updated,
		ctx:     client.ctx,
		handle:  handle,
	}
	return file, nil
}

func (client *Client) UploadFile(localFile, gcsFile, contentType, contentEncoding string) error {
	local, err := os.Open(localFile)
	if err != nil {
		return err
	}
	defer local.Close()

	w, err := client.FileWriterExt(gcsFile, contentType, contentEncoding)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, local)
	return err
}

func (client *Client) FileWriterExt(gcsFile, contentType, contentEncoding string) (io.WriteCloser, error) {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return nil, err
	}
	bkt := client.client.Bucket(bucket)
	f := bkt.Object(filename)
	w := f.NewWriter(client.ctx)
	if contentType != "" {
		w.ContentType = contentType
	}
	if contentEncoding != "" {
		w.ContentEncoding = contentEncoding
	}
	return w, nil
}

func (client *Client) FileWriter(gcsFile string) (io.WriteCloser, error) {
	return client.FileWriterExt(gcsFile, "", "")
}

// Publish lets any user read gcsFile.
func (client *Client) Publish(gcsFile string) error {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return err
	}
	obj := client.client.Bucket(bucket).Object(filename)
	return obj.ACL().Set(client.ctx, storage.AllUsers, storage.RoleReader)
}

var ErrFileNotFound = errors.New("the requested files does not exist")

func (client *Client) DeleteFile(gcsFile string) error {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return err
	}
	err = client.client.Bucket(bucket).Object(filename).Delete(client.ctx)
	if err == storage.ErrObjectNotExist {
		return ErrFileNotFound
	}
	return err
}

func (client *Client) GetDownloadURL(gcsFile string) (string, error) {
	bucket, filename, err := split(gcsFile)
	if err != nil {
		return "", err
	}
	f := client.client.Bucket(bucket).Object(filename)
	attrs, err := f.Attrs(client.ctx)
	if err != nil {
		return "", err
	}
	return attrs.MediaLink, nil
}

type Object struct {
	DownloadURL string
	CreatedAt   time.Time
}

func (client *Client) ListObjects(bucket string) ([]*Object, error) {
	ctx := context.Background()
	it := client.client.Bucket(bucket).Objects(ctx, nil)
	ret := []*Object{}
	for {
		objAttrs, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("failed to query GCS objects: %w", err)
		}
		ret = append(ret, &Object{
			DownloadURL: objAttrs.MediaLink,
			CreatedAt:   objAttrs.Created,
		})
	}
	return ret, nil
}

// Where things get published.
const PublicPrefix = "https://storage.googleapis.com/"

func split(file string) (bucket, filename string, err error) {
	pos := strings.IndexByte(file, '/')
	if pos == -1 {
		return "", "", fmt.Errorf("invalid GCS file name: %v", file)
	}
	return file[:pos], file[pos+1:], nil
}
<|endoftext|>


<commit_before>package scm

import (
	"fmt"

	"github.com/golang/glog"

	"github.com/openshift/source-to-image/pkg/build"
	"github.com/openshift/source-to-image/pkg/scm/empty"
	"github.com/openshift/source-to-image/pkg/scm/file"
	"github.com/openshift/source-to-image/pkg/scm/git"
	"github.com/shrutikamendhe/source-to-image/pkg/scm/tfs"
	"github.com/openshift/source-to-image/pkg/util"
)

// DownloaderForSource determines what SCM plugin should be used for downloading
// the sources from the repository.
func DownloaderForSource(s string, forceCopy bool) (build.Downloader, string, error) {
	glog.V(4).Infof("DownloadForSource %s", s)

	if len(s) == 0 {
		return &empty.Noop{}, s, nil
	}

	details, mods := git.ParseFile(s)
	glog.V(4).Infof("return from ParseFile file exists %v proto specified %v use copy %v", details.FileExists, details.ProtoSpecified, details.UseCopy)

	if details.FileExists && details.BadRef {
		return nil, s, fmt.Errorf("local location referenced by %s exists but the input after the # is malformed", s)
	}

	if details.FileExists && mods != nil {
		glog.V(4).Infof("new source from parse file %s", mods.Path)
		if details.ProtoSpecified {
			s = mods.Path
		} else {
			// prepending with file:// is a precautionary step which previous incarnations of this code did; we
			// preserve that behavior (it is more explicit, if not absolutely necessary; but we do it here as was done before
			// vs. down in our generic git layer (which is leveraged separately in origin)
			s = "file://" + mods.Path
		}
	}

	if details.FileExists && (details.UseCopy || forceCopy) {
		return &file.File{util.NewFileSystem()}, s, nil
	}

	if CheckIsTFSSourceCode(s){
		return nil, s, fmt.Errorf("no downloader defined for location: %q", s)
	} else {
		// If the source is valid  Git protocol (file://, ssh://, git://, git@, etc..) use Git
		// binary to download the sources
		g := git.New()
		if g.ValidCloneSpec(s) {
			return &git.Clone{g, util.NewFileSystem()}, s, nil
		}
	}

	return nil, s, fmt.Errorf("no downloader defined for location: %q", s)
}

func CheckIsTFSSourceCode(s string) bool{
	glog.Infof("CheckIsTFSSourceCode %q ...", s)
	//t := tfs.New()
	//glog.Infof("CheckIsTFSSourceCode %q ...", s)
	return true
}<commit_msg>removed error<commit_after>package scm

import (
	"fmt"

	"github.com/golang/glog"

	"github.com/openshift/source-to-image/pkg/build"
	"github.com/openshift/source-to-image/pkg/scm/empty"
	"github.com/openshift/source-to-image/pkg/scm/file"
	"github.com/openshift/source-to-image/pkg/scm/git"
	"github.com/openshift/source-to-image/pkg/util"
)

// DownloaderForSource determines what SCM plugin should be used for downloading
// the sources from the repository.
func DownloaderForSource(s string, forceCopy bool) (build.Downloader, string, error) {
	glog.V(4).Infof("DownloadForSource %s", s)

	if len(s) == 0 {
		return &empty.Noop{}, s, nil
	}

	details, mods := git.ParseFile(s)
	glog.V(4).Infof("return from ParseFile file exists %v proto specified %v use copy %v", details.FileExists, details.ProtoSpecified, details.UseCopy)

	if details.FileExists && details.BadRef {
		return nil, s, fmt.Errorf("local location referenced by %s exists but the input after the # is malformed", s)
	}

	if details.FileExists && mods != nil {
		glog.V(4).Infof("new source from parse file %s", mods.Path)
		if details.ProtoSpecified {
			s = mods.Path
		} else {
			// prepending with file:// is a precautionary step which previous incarnations of this code did; we
			// preserve that behavior (it is more explicit, if not absolutely necessary; but we do it here as was done before
			// vs. down in our generic git layer (which is leveraged separately in origin)
			s = "file://" + mods.Path
		}
	}

	if details.FileExists && (details.UseCopy || forceCopy) {
		return &file.File{util.NewFileSystem()}, s, nil
	}

	if CheckIsTFSSourceCode(s){
		return nil, s, fmt.Errorf("no downloader defined for location: %q", s)
	} else {
		// If the source is valid  Git protocol (file://, ssh://, git://, git@, etc..) use Git
		// binary to download the sources
		g := git.New()
		if g.ValidCloneSpec(s) {
			return &git.Clone{g, util.NewFileSystem()}, s, nil
		}
	}

	return nil, s, fmt.Errorf("no downloader defined for location: %q", s)
}

func CheckIsTFSSourceCode(s string) bool{
	glog.Infof("CheckIsTFSSourceCode %q ...", s)
	//t := tfs.New()
	//glog.Infof("CheckIsTFSSourceCode %q ...", s)
	return true
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func TestInitialiseKubeconfig(t *testing.T) {

	plugin := Plugin{
		Config: Config{
			APIServer:      "http://myapiserver",
			Token:          "secret-token",
			ServiceAccount: "default-account",
			HelmCommand:    "",
			Namespace:      "default",
			SkipTLSVerify:  true,
		},
	}

	configfile := "config3.test"
	initialiseKubeconfig(&plugin.Config, "kubeconfig", configfile)
	data, err := ioutil.ReadFile(configfile)
	if err != nil {
		t.Errorf("Error reading file %v", err)
	}
	kubeConfigStr := string(data)

	if !strings.Contains(kubeConfigStr, "secret-token") {
		t.Errorf("Kubeconfig doesn't render token")
	}
	if !strings.Contains(kubeConfigStr, "http://myapiserver") {
		t.Errorf("Kubeconfig doesn't render APIServer")
	}
	if !strings.Contains(kubeConfigStr, "default-account") {
		t.Errorf("Kubeconfig doesn't render serviceaccount")
	}

}

func TestGetHelmCommandEmptyPushEvent(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "push")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Version:       "1.2.3",
			Release:       "test-release",
			Values:        `"image.tag=v.0.1.0,nameOverride=my-over-app"`,
			Wait:          true,
			ReuseValues:   true,
			Timeout:       "500",
			Force:         true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "upgrade --install test-release ./chart/test --version 1.2.3 --set image.tag=v.0.1.0,nameOverride=my-over-app --namespace default --dry-run --debug --wait --reuse-values --timeout 500 --force"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestGetHelmCommandUpgrade(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "push")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "upgrade",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Version:       "1.2.3",
			Release:       "test-release",
			Values:        `"image.tag=v.0.1.0,nameOverride=my-over-app"`,
			Wait:          true,
			ReuseValues:   true,
			Timeout:       "500",
			Force:         true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "upgrade --install test-release ./chart/test --version 1.2.3 --set image.tag=v.0.1.0,nameOverride=my-over-app --namespace default --dry-run --debug --wait --reuse-values --timeout 500 --force"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestResolveSecrets(t *testing.T) {

	testEnvs := []struct {
		prefix  string
		tag     string
		api     string
		token   string
		account string
	}{
		{prefix: "PROD", tag: "v0.1.1", api: "http://apiserver", token: "12345", account: "helm"},
		{prefix: "STAGING", tag: "12345678", api: "http://apiserver", token: "12345", account: "helm"},
	}
	for _, env := range testEnvs {
		envMap := map[string]string{
			"TAG":              env.tag,
			"API_SERVER":       env.api,
			"KUBERNETES_TOKEN": env.token,
			"SERVICE_ACCOUNT":  env.account,
		}

		for envKey, envValue := range envMap {
			os.Setenv(fmt.Sprintf("%s_%s", env.prefix, envKey), envValue)
		}

		plugin := &Plugin{
			Config: Config{
				HelmCommand:   "",
				Namespace:     "default",
				SkipTLSVerify: true,
				Debug:         true,
				DryRun:        true,
				Chart:         "./chart/test",
				Release:       "test-release",
				Prefix:        env.prefix,
				Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			},
		}

		resolveSecrets(plugin)
		// test that the subsitution works
		fmt.Println(plugin.Config.Values)
		if !strings.Contains(plugin.Config.Values, env.tag) {
			t.Errorf("env var ${TAG} not resolved %s", env.tag)
		}
		if strings.Contains(plugin.Config.Values, "${TAG}") {
			t.Errorf("env var ${TAG} not resolved %s", env.tag)
		}

		if plugin.Config.APIServer != env.api {
			t.Errorf("env var ${API_SERVER} not resolved %s", env.api)
		}
		if plugin.Config.Token != env.token {
			t.Errorf("env var ${KUBERNETES_TOKEN} not resolved %s", env.token)
		}
		if plugin.Config.ServiceAccount != env.account {
			t.Errorf("env var ${SERVICE_ACCOUNT} not resolved %s", env.account)
		}

		// clean up
		for envKey, _ := range envMap {
			os.Unsetenv(fmt.Sprintf("%s_%s", env.prefix, envKey))
		}
	}
}

func TestDetHelmRepoAdd(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			ClientOnly:    true,
			HelmRepos: []string{
				`"r1=http://r1.example.com"`, //handle quoted strings
				`r2=http://r2.example.com`,   //and unquoted strings
			},
		},
	}
	expected := []string{
		"repo add r1 http://r1.example.com",
		"repo add r2 http://r2.example.com",
	}

	for i, r := range plugin.Config.HelmRepos {
		repos, err := doHelmRepoAdd(r)
		if err != nil {
			t.Error(err)
		}
		result := strings.Join(repos, " ")
		if expected[i] != result {
			t.Errorf("Helm cannot add remote repositories - expected %q - got %q",
				expected[i],
				result,
			)
		}
	}
}

func TestHelmAddRepositoryError(t *testing.T) {
	_, err := doHelmRepoAdd("drone-helm=bad://drone-helm.example.com:443/stable")
	if err == nil {
		t.Errorf("Expect to see error when repo URL is invalid")
	}
}

func TestGetEnvVars(t *testing.T) {

	testText := "this should be ${TAG} now"
	result := getEnvVars(testText)
	if len(result) == 0 {
		t.Error("No envvar was found")
	}
	envvar := result[0]
	if !strings.Contains(envvar[2], "TAG") {
		t.Errorf("envvar not found in %s", testText)
	}
}

func TestReplaceEnvvars(t *testing.T) {
	tag := "tagged"
	os.Setenv("MY_TAG", tag)
	prefix := "MY"
	testText := "this should be ${TAG} now ${TAG}"
	result := getEnvVars(testText)
	resolved := replaceEnvvars(result, prefix, testText, false)
	if !strings.Contains(resolved, tag) {
		t.Errorf("EnvVar MY_TAG no replaced by %s  -- %s \n", tag, resolved)
	}
}

func TestSetHelpCommand(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
		},
	}
	setHelpCommand(plugin)
	if plugin.command == nil {
		t.Error("Helm help is not displayed")
	}
}

func TestDetHelmInit(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			TillerNs:      "system-test",
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init --tiller-namespace " + plugin.Config.TillerNs

	if expected != result {
		t.Error("Tiller not installed in proper namespace")
	}
}

func TestDetHelmInitClient(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			ClientOnly:    true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.ClientOnly {
		expected = expected + "--client-only"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}

func TestDetHelmInitUpgrade(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			Upgrade:       true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.Upgrade {
		expected = expected + "--upgrade"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}

func TestDetHelmInitCanary(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			CanaryImage:   true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.CanaryImage {
		expected = expected + "--canary-image"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}
func TestResolveSecretsFallback(t *testing.T) {
	tag := "v0.1.1"
	api := "http://apiserver"
	os.Setenv("MY_TAG", tag)
	os.Setenv("MY_API_SERVER", api)
	os.Setenv("MY_TOKEN", "12345")
	os.Setenv("NOTTOKEN", "99999")

	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nottoken=${NOTTOKEN},nameOverride=my-over-app,second.tag=${TAG}",
		},
	}

	resolveSecrets(plugin)
	// test that the subsitution works
	if !strings.Contains(plugin.Config.Values, tag) {
		t.Errorf("env var ${TAG} not resolved %s", tag)
	}
	if strings.Contains(plugin.Config.Values, "${TAG}") {
		t.Errorf("env var ${TAG} not resolved %s", tag)
	}

	if plugin.Config.APIServer != api {
		t.Errorf("env var ${API_SERVER} not resolved %s", api)
	}
	if !strings.Contains(plugin.Config.Values, "99999") {
		t.Errorf("envar ${NOTTOKEN} has not been resolved to 99999, not using prefix")
	}
}
<commit_msg>Add some tests for delete command<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func TestInitialiseKubeconfig(t *testing.T) {

	plugin := Plugin{
		Config: Config{
			APIServer:      "http://myapiserver",
			Token:          "secret-token",
			ServiceAccount: "default-account",
			HelmCommand:    "",
			Namespace:      "default",
			SkipTLSVerify:  true,
		},
	}

	configfile := "config3.test"
	initialiseKubeconfig(&plugin.Config, "kubeconfig", configfile)
	data, err := ioutil.ReadFile(configfile)
	if err != nil {
		t.Errorf("Error reading file %v", err)
	}
	kubeConfigStr := string(data)

	if !strings.Contains(kubeConfigStr, "secret-token") {
		t.Errorf("Kubeconfig doesn't render token")
	}
	if !strings.Contains(kubeConfigStr, "http://myapiserver") {
		t.Errorf("Kubeconfig doesn't render APIServer")
	}
	if !strings.Contains(kubeConfigStr, "default-account") {
		t.Errorf("Kubeconfig doesn't render serviceaccount")
	}

}

func TestGetHelmCommandEmptyPushEvent(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "push")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Version:       "1.2.3",
			Release:       "test-release",
			Values:        `"image.tag=v.0.1.0,nameOverride=my-over-app"`,
			Wait:          true,
			ReuseValues:   true,
			Timeout:       "500",
			Force:         true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "upgrade --install test-release ./chart/test --version 1.2.3 --set image.tag=v.0.1.0,nameOverride=my-over-app --namespace default --dry-run --debug --wait --reuse-values --timeout 500 --force"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestGetHelmCommandUpgrade(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "push")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "upgrade",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Version:       "1.2.3",
			Release:       "test-release",
			Values:        `"image.tag=v.0.1.0,nameOverride=my-over-app"`,
			Wait:          true,
			ReuseValues:   true,
			Timeout:       "500",
			Force:         true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "upgrade --install test-release ./chart/test --version 1.2.3 --set image.tag=v.0.1.0,nameOverride=my-over-app --namespace default --dry-run --debug --wait --reuse-values --timeout 500 --force"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestGetHelmDeleteCommand(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "delete")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "delete",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Values:        "image.tag=v.0.1.0,nameOverride=my-over-app",
			Wait:          true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "delete test-release"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestGetHelmDeleteCommandOverried(t *testing.T) {
	os.Setenv("DRONE_BUILD_EVENT", "deployment")
	plugin := &Plugin{
		Config: Config{
			APIServer:     "http://myapiserver",
			Token:         "secret-token",
			HelmCommand:   "delete",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Values:        "image.tag=v.0.1.0,nameOverride=my-over-app",
			Wait:          true,
		},
	}
	setHelmCommand(plugin)
	res := strings.Join(plugin.command[:], " ")
	expected := "delete test-release"
	if res != expected {
		t.Errorf("Result is %s and we expected %s", res, expected)
	}
}

func TestResolveSecrets(t *testing.T) {

	testEnvs := []struct {
		prefix  string
		tag     string
		api     string
		token   string
		account string
	}{
		{prefix: "PROD", tag: "v0.1.1", api: "http://apiserver", token: "12345", account: "helm"},
		{prefix: "STAGING", tag: "12345678", api: "http://apiserver", token: "12345", account: "helm"},
	}
	for _, env := range testEnvs {
		envMap := map[string]string{
			"TAG":              env.tag,
			"API_SERVER":       env.api,
			"KUBERNETES_TOKEN": env.token,
			"SERVICE_ACCOUNT":  env.account,
		}

		for envKey, envValue := range envMap {
			os.Setenv(fmt.Sprintf("%s_%s", env.prefix, envKey), envValue)
		}

		plugin := &Plugin{
			Config: Config{
				HelmCommand:   "",
				Namespace:     "default",
				SkipTLSVerify: true,
				Debug:         true,
				DryRun:        true,
				Chart:         "./chart/test",
				Release:       "test-release",
				Prefix:        env.prefix,
				Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			},
		}

		resolveSecrets(plugin)
		// test that the subsitution works
		fmt.Println(plugin.Config.Values)
		if !strings.Contains(plugin.Config.Values, env.tag) {
			t.Errorf("env var ${TAG} not resolved %s", env.tag)
		}
		if strings.Contains(plugin.Config.Values, "${TAG}") {
			t.Errorf("env var ${TAG} not resolved %s", env.tag)
		}

		if plugin.Config.APIServer != env.api {
			t.Errorf("env var ${API_SERVER} not resolved %s", env.api)
		}
		if plugin.Config.Token != env.token {
			t.Errorf("env var ${KUBERNETES_TOKEN} not resolved %s", env.token)
		}
		if plugin.Config.ServiceAccount != env.account {
			t.Errorf("env var ${SERVICE_ACCOUNT} not resolved %s", env.account)
		}

		// clean up
		for envKey, _ := range envMap {
			os.Unsetenv(fmt.Sprintf("%s_%s", env.prefix, envKey))
		}
	}
}

func TestDetHelmRepoAdd(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			ClientOnly:    true,
			HelmRepos: []string{
				`"r1=http://r1.example.com"`, //handle quoted strings
				`r2=http://r2.example.com`,   //and unquoted strings
			},
		},
	}
	expected := []string{
		"repo add r1 http://r1.example.com",
		"repo add r2 http://r2.example.com",
	}

	for i, r := range plugin.Config.HelmRepos {
		repos, err := doHelmRepoAdd(r)
		if err != nil {
			t.Error(err)
		}
		result := strings.Join(repos, " ")
		if expected[i] != result {
			t.Errorf("Helm cannot add remote repositories - expected %q - got %q",
				expected[i],
				result,
			)
		}
	}
}

func TestHelmAddRepositoryError(t *testing.T) {
	_, err := doHelmRepoAdd("drone-helm=bad://drone-helm.example.com:443/stable")
	if err == nil {
		t.Errorf("Expect to see error when repo URL is invalid")
	}
}

func TestGetEnvVars(t *testing.T) {

	testText := "this should be ${TAG} now"
	result := getEnvVars(testText)
	if len(result) == 0 {
		t.Error("No envvar was found")
	}
	envvar := result[0]
	if !strings.Contains(envvar[2], "TAG") {
		t.Errorf("envvar not found in %s", testText)
	}
}

func TestReplaceEnvvars(t *testing.T) {
	tag := "tagged"
	os.Setenv("MY_TAG", tag)
	prefix := "MY"
	testText := "this should be ${TAG} now ${TAG}"
	result := getEnvVars(testText)
	resolved := replaceEnvvars(result, prefix, testText, false)
	if !strings.Contains(resolved, tag) {
		t.Errorf("EnvVar MY_TAG no replaced by %s  -- %s \n", tag, resolved)
	}
}

func TestSetHelpCommand(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
		},
	}
	setHelpCommand(plugin)
	if plugin.command == nil {
		t.Error("Helm help is not displayed")
	}
}

func TestDetHelmInit(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			TillerNs:      "system-test",
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init --tiller-namespace " + plugin.Config.TillerNs

	if expected != result {
		t.Error("Tiller not installed in proper namespace")
	}
}

func TestDetHelmInitClient(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			ClientOnly:    true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.ClientOnly {
		expected = expected + "--client-only"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}

func TestDetHelmInitUpgrade(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			Upgrade:       true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.Upgrade {
		expected = expected + "--upgrade"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}

func TestDetHelmInitCanary(t *testing.T) {
	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nameOverride=my-over-app,second.tag=${TAG}",
			CanaryImage:   true,
		},
	}
	init := doHelmInit(plugin)
	result := strings.Join(init, " ")
	expected := "init "
	if plugin.Config.CanaryImage {
		expected = expected + "--canary-image"
	}

	if expected != result {
		t.Error("Helm cannot init in client only")
	}
}
func TestResolveSecretsFallback(t *testing.T) {
	tag := "v0.1.1"
	api := "http://apiserver"
	os.Setenv("MY_TAG", tag)
	os.Setenv("MY_API_SERVER", api)
	os.Setenv("MY_TOKEN", "12345")
	os.Setenv("NOTTOKEN", "99999")

	plugin := &Plugin{
		Config: Config{
			HelmCommand:   "",
			Namespace:     "default",
			SkipTLSVerify: true,
			Debug:         true,
			DryRun:        true,
			Chart:         "./chart/test",
			Release:       "test-release",
			Prefix:        "MY",
			Values:        "image.tag=$TAG,api=${API_SERVER},nottoken=${NOTTOKEN},nameOverride=my-over-app,second.tag=${TAG}",
		},
	}

	resolveSecrets(plugin)
	// test that the subsitution works
	if !strings.Contains(plugin.Config.Values, tag) {
		t.Errorf("env var ${TAG} not resolved %s", tag)
	}
	if strings.Contains(plugin.Config.Values, "${TAG}") {
		t.Errorf("env var ${TAG} not resolved %s", tag)
	}

	if plugin.Config.APIServer != api {
		t.Errorf("env var ${API_SERVER} not resolved %s", api)
	}
	if !strings.Contains(plugin.Config.Values, "99999") {
		t.Errorf("envar ${NOTTOKEN} has not been resolved to 99999, not using prefix")
	}
}
<|endoftext|>


<commit_before>// +build amd64,!appengine

// This file tests the popcnt functions

package roaring

import (
	"testing"
)

func TestPopcntSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	resGo := popcntSliceGo(s)
	resAsm := popcntSliceAsm(s)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntSlice(s)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntMaskSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntMaskSliceGo(s, m)
	resAsm := popcntMaskSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntMaskSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntAndSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntAndSliceGo(s, m)
	resAsm := popcntAndSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntAndSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntOrSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntOrSliceGo(s, m)
	resAsm := popcntOrSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntOrSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntXorSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntXorSliceGo(s, m)
	resAsm := popcntXorSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntXorSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}
<commit_msg>BenchmarkPopcount<commit_after>// +build amd64,!appengine

// This file tests the popcnt functions

package roaring

import (
	"testing"
)

func TestPopcntSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	resGo := popcntSliceGo(s)
	resAsm := popcntSliceAsm(s)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntSlice(s)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntMaskSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntMaskSliceGo(s, m)
	resAsm := popcntMaskSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntMaskSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntAndSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntAndSliceGo(s, m)
	resAsm := popcntAndSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntAndSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntOrSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntOrSliceGo(s, m)
	resAsm := popcntOrSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntOrSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func TestPopcntXorSlice(t *testing.T) {
	s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29}
	m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71}
	resGo := popcntXorSliceGo(s, m)
	resAsm := popcntXorSliceAsm(s, m)
	if resGo != resAsm {
		t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm)
	}
	res := popcntXorSlice(s, m)
	if res != resGo {
		t.Errorf("The implementations are different")
	}
}

func BenchmarkPopcount(b *testing.B) {
	b.StopTimer()

	r := getRandomUint64Set(64)

	b.ResetTimer()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		popcntSlice(r)
	}
}
<|endoftext|>


<commit_before>package standardtracer

import (
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"

	opentracing "github.com/opentracing/opentracing-go"
)

type splitTextPropagator struct {
	tracer *tracerImpl
}
type splitBinaryPropagator struct {
	tracer *tracerImpl
}
type goHTTPPropagator struct {
	*splitBinaryPropagator
}

const (
	fieldNameTraceID = "traceid"
	fieldNameSpanID  = "spanid"
	fieldNameSampled = "sampled"
)

func (p *splitTextPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	sc := sp.(*spanImpl)
	splitTextCarrier, ok := carrier.(*opentracing.SplitTextCarrier)
	if !ok {
		return opentracing.ErrInvalidCarrier
	}
	splitTextCarrier.TracerState = map[string]string{
		fieldNameTraceID: strconv.FormatInt(sc.raw.TraceID, 10),
		fieldNameSpanID:  strconv.FormatInt(sc.raw.SpanID, 10),
		fieldNameSampled: strconv.FormatBool(sc.raw.Sampled),
	}
	sc.Lock()
	if l := len(sc.raw.Attributes); l > 0 {
		splitTextCarrier.TraceAttributes = make(map[string]string, l)
		for k, v := range sc.raw.Attributes {
			splitTextCarrier.TraceAttributes[k] = v
		}
	}
	sc.Unlock()
	return nil
}

func (p *splitTextPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	splitTextCarrier, ok := carrier.(*opentracing.SplitTextCarrier)
	if !ok {
		return nil, opentracing.ErrInvalidCarrier
	}
	requiredFieldCount := 0
	var traceID, propagatedSpanID int64
	var sampled bool
	var err error
	for k, v := range splitTextCarrier.TracerState {
		switch strings.ToLower(k) {
		case fieldNameTraceID:
			traceID, err = strconv.ParseInt(v, 10, 64)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		case fieldNameSpanID:
			propagatedSpanID, err = strconv.ParseInt(v, 10, 64)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		case fieldNameSampled:
			sampled, err = strconv.ParseBool(v)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		default:
			continue
		}
		requiredFieldCount++
	}
	if requiredFieldCount < 3 {
		if len(splitTextCarrier.TracerState) == 0 {
			return nil, opentracing.ErrTraceNotFound
		}
		return nil, opentracing.ErrTraceCorrupted
	}

	sp := p.tracer.getSpan()
	sp.raw = RawSpan{
		StandardContext: StandardContext{
			TraceID:      traceID,
			SpanID:       randomID(),
			ParentSpanID: propagatedSpanID,
			Sampled:      sampled,
		},
	}
	sp.raw.Attributes = splitTextCarrier.TraceAttributes

	return p.tracer.startSpanInternal(
		sp,
		operationName,
		time.Now(),
		nil,
	), nil
}

func (p *splitBinaryPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	sc := sp.(*spanImpl)
	splitBinaryCarrier, ok := carrier.(*opentracing.SplitBinaryCarrier)
	if !ok {
		return opentracing.ErrInvalidCarrier
	}
	var err error
	var sampledByte byte
	if sc.raw.Sampled {
		sampledByte = 1
	}

	// Handle the trace and span ids, and sampled status.
	contextBuf := bytes.NewBuffer(splitBinaryCarrier.TracerState[:0])
	err = binary.Write(contextBuf, binary.BigEndian, sc.raw.TraceID)
	if err != nil {
		return err
	}

	err = binary.Write(contextBuf, binary.BigEndian, sc.raw.SpanID)
	if err != nil {
		return err
	}

	err = binary.Write(contextBuf, binary.BigEndian, sampledByte)
	if err != nil {
		return err
	}

	// Handle the attributes.
	attrsBuf := bytes.NewBuffer(splitBinaryCarrier.TraceAttributes[:0])
	err = binary.Write(attrsBuf, binary.BigEndian, int32(len(sc.raw.Attributes)))
	if err != nil {
		return err
	}
	for k, v := range sc.raw.Attributes {
		if err = binary.Write(attrsBuf, binary.BigEndian, int32(len(k))); err != nil {
			return err
		}
		attrsBuf.WriteString(k)
		if err = binary.Write(attrsBuf, binary.BigEndian, int32(len(v))); err != nil {
			return err
		}
		attrsBuf.WriteString(v)
	}

	splitBinaryCarrier.TracerState = contextBuf.Bytes()
	splitBinaryCarrier.TraceAttributes = attrsBuf.Bytes()
	return nil
}

func (p *splitBinaryPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	var err error
	splitBinaryCarrier, ok := carrier.(*opentracing.SplitBinaryCarrier)
	if !ok {
		return nil, opentracing.ErrInvalidCarrier
	}
	if len(splitBinaryCarrier.TracerState) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	// Handle the trace, span ids, and sampled status.
	contextReader := bytes.NewReader(splitBinaryCarrier.TracerState)
	var traceID, propagatedSpanID int64
	var sampledByte byte

	err = binary.Read(contextReader, binary.BigEndian, &traceID)
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	err = binary.Read(contextReader, binary.BigEndian, &propagatedSpanID)
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	err = binary.Read(contextReader, binary.BigEndian, &sampledByte)
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}

	// Handle the attributes.
	attrsReader := bytes.NewReader(splitBinaryCarrier.TraceAttributes)
	var numAttrs int32
	err = binary.Read(attrsReader, binary.BigEndian, &numAttrs)
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	iNumAttrs := int(numAttrs)
	var attrMap map[string]string
	if iNumAttrs > 0 {
		var buf bytes.Buffer // TODO(tschottdorf): candidate for sync.Pool
		attrMap = make(map[string]string, iNumAttrs)
		var keyLen, valLen int32
		for i := 0; i < iNumAttrs; i++ {
			err = binary.Read(attrsReader, binary.BigEndian, &keyLen)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
			buf.Grow(int(keyLen))
			if n, err := io.CopyN(&buf, attrsReader, int64(keyLen)); err != nil || int32(n) != keyLen {
				return nil, opentracing.ErrTraceCorrupted
			}
			key := buf.String()
			buf.Reset()

			err = binary.Read(attrsReader, binary.BigEndian, &valLen)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
			if n, err := io.CopyN(&buf, attrsReader, int64(valLen)); err != nil || int32(n) != valLen {
				return nil, opentracing.ErrTraceCorrupted
			}
			attrMap[key] = buf.String()
			buf.Reset()
		}
	}

	sp := p.tracer.getSpan()
	sp.raw = RawSpan{
		StandardContext: StandardContext{
			TraceID:      traceID,
			SpanID:       randomID(),
			ParentSpanID: propagatedSpanID,
			Sampled:      sampledByte != 0,
		},
	}
	sp.raw.Attributes = attrMap

	return p.tracer.startSpanInternal(
		sp,
		operationName,
		time.Now(),
		nil,
	), nil
}

const (
	tracerStateHeaderName = "Tracer-State"
	traceAttrsHeaderName  = "Trace-Attributes"
)

func (p *goHTTPPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	// Defer to SplitBinary for the real work.
	splitBinaryCarrier := opentracing.NewSplitBinaryCarrier()
	if err := p.splitBinaryPropagator.InjectSpan(sp, splitBinaryCarrier); err != nil {
		return err
	}

	// Encode into the HTTP header as two base64 strings.
	header := carrier.(http.Header)
	header.Add(tracerStateHeaderName, base64.StdEncoding.EncodeToString(
		splitBinaryCarrier.TracerState))
	header.Add(traceAttrsHeaderName, base64.StdEncoding.EncodeToString(
		splitBinaryCarrier.TraceAttributes))

	return nil
}

func (p *goHTTPPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	// Decode the two base64-encoded data blobs from the HTTP header.
	header := carrier.(http.Header)
	tracerStateBase64, found := header[http.CanonicalHeaderKey(tracerStateHeaderName)]
	if !found || len(tracerStateBase64) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	traceAttrsBase64, found := header[http.CanonicalHeaderKey(traceAttrsHeaderName)]
	if !found || len(traceAttrsBase64) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	tracerStateBinary, err := base64.StdEncoding.DecodeString(tracerStateBase64[0])
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	traceAttrsBinary, err := base64.StdEncoding.DecodeString(traceAttrsBase64[0])
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}

	// Defer to SplitBinary for the real work.
	splitBinaryCarrier := &opentracing.SplitBinaryCarrier{
		TracerState:     tracerStateBinary,
		TraceAttributes: traceAttrsBinary,
	}
	return p.splitBinaryPropagator.JoinTrace(operationName, splitBinaryCarrier)
}
<commit_msg>Use `if err := X(); err != nil { ... }<commit_after>package standardtracer

import (
	"bytes"
	"encoding/base64"
	"encoding/binary"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"

	opentracing "github.com/opentracing/opentracing-go"
)

type splitTextPropagator struct {
	tracer *tracerImpl
}
type splitBinaryPropagator struct {
	tracer *tracerImpl
}
type goHTTPPropagator struct {
	*splitBinaryPropagator
}

const (
	fieldNameTraceID = "traceid"
	fieldNameSpanID  = "spanid"
	fieldNameSampled = "sampled"
)

func (p *splitTextPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	sc := sp.(*spanImpl)
	splitTextCarrier, ok := carrier.(*opentracing.SplitTextCarrier)
	if !ok {
		return opentracing.ErrInvalidCarrier
	}
	splitTextCarrier.TracerState = map[string]string{
		fieldNameTraceID: strconv.FormatInt(sc.raw.TraceID, 10),
		fieldNameSpanID:  strconv.FormatInt(sc.raw.SpanID, 10),
		fieldNameSampled: strconv.FormatBool(sc.raw.Sampled),
	}
	sc.Lock()
	if l := len(sc.raw.Attributes); l > 0 {
		splitTextCarrier.TraceAttributes = make(map[string]string, l)
		for k, v := range sc.raw.Attributes {
			splitTextCarrier.TraceAttributes[k] = v
		}
	}
	sc.Unlock()
	return nil
}

func (p *splitTextPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	splitTextCarrier, ok := carrier.(*opentracing.SplitTextCarrier)
	if !ok {
		return nil, opentracing.ErrInvalidCarrier
	}
	requiredFieldCount := 0
	var traceID, propagatedSpanID int64
	var sampled bool
	var err error
	for k, v := range splitTextCarrier.TracerState {
		switch strings.ToLower(k) {
		case fieldNameTraceID:
			traceID, err = strconv.ParseInt(v, 10, 64)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		case fieldNameSpanID:
			propagatedSpanID, err = strconv.ParseInt(v, 10, 64)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		case fieldNameSampled:
			sampled, err = strconv.ParseBool(v)
			if err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
		default:
			continue
		}
		requiredFieldCount++
	}
	if requiredFieldCount < 3 {
		if len(splitTextCarrier.TracerState) == 0 {
			return nil, opentracing.ErrTraceNotFound
		}
		return nil, opentracing.ErrTraceCorrupted
	}

	sp := p.tracer.getSpan()
	sp.raw = RawSpan{
		StandardContext: StandardContext{
			TraceID:      traceID,
			SpanID:       randomID(),
			ParentSpanID: propagatedSpanID,
			Sampled:      sampled,
		},
	}
	sp.raw.Attributes = splitTextCarrier.TraceAttributes

	return p.tracer.startSpanInternal(
		sp,
		operationName,
		time.Now(),
		nil,
	), nil
}

func (p *splitBinaryPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	sc := sp.(*spanImpl)
	splitBinaryCarrier, ok := carrier.(*opentracing.SplitBinaryCarrier)
	if !ok {
		return opentracing.ErrInvalidCarrier
	}
	var err error
	var sampledByte byte
	if sc.raw.Sampled {
		sampledByte = 1
	}

	// Handle the trace and span ids, and sampled status.
	contextBuf := bytes.NewBuffer(splitBinaryCarrier.TracerState[:0])
	err = binary.Write(contextBuf, binary.BigEndian, sc.raw.TraceID)
	if err != nil {
		return err
	}

	err = binary.Write(contextBuf, binary.BigEndian, sc.raw.SpanID)
	if err != nil {
		return err
	}

	err = binary.Write(contextBuf, binary.BigEndian, sampledByte)
	if err != nil {
		return err
	}

	// Handle the attributes.
	attrsBuf := bytes.NewBuffer(splitBinaryCarrier.TraceAttributes[:0])
	err = binary.Write(attrsBuf, binary.BigEndian, int32(len(sc.raw.Attributes)))
	if err != nil {
		return err
	}
	for k, v := range sc.raw.Attributes {
		if err = binary.Write(attrsBuf, binary.BigEndian, int32(len(k))); err != nil {
			return err
		}
		attrsBuf.WriteString(k)
		if err = binary.Write(attrsBuf, binary.BigEndian, int32(len(v))); err != nil {
			return err
		}
		attrsBuf.WriteString(v)
	}

	splitBinaryCarrier.TracerState = contextBuf.Bytes()
	splitBinaryCarrier.TraceAttributes = attrsBuf.Bytes()
	return nil
}

func (p *splitBinaryPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	splitBinaryCarrier, ok := carrier.(*opentracing.SplitBinaryCarrier)
	if !ok {
		return nil, opentracing.ErrInvalidCarrier
	}
	if len(splitBinaryCarrier.TracerState) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	// Handle the trace, span ids, and sampled status.
	contextReader := bytes.NewReader(splitBinaryCarrier.TracerState)
	var traceID, propagatedSpanID int64
	var sampledByte byte

	if err := binary.Read(contextReader, binary.BigEndian, &traceID); err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	if err := binary.Read(contextReader, binary.BigEndian, &propagatedSpanID); err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	if err := binary.Read(contextReader, binary.BigEndian, &sampledByte); err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}

	// Handle the attributes.
	attrsReader := bytes.NewReader(splitBinaryCarrier.TraceAttributes)
	var numAttrs int32
	if err := binary.Read(attrsReader, binary.BigEndian, &numAttrs); err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	iNumAttrs := int(numAttrs)
	var attrMap map[string]string
	if iNumAttrs > 0 {
		var buf bytes.Buffer // TODO(tschottdorf): candidate for sync.Pool
		attrMap = make(map[string]string, iNumAttrs)
		var keyLen, valLen int32
		for i := 0; i < iNumAttrs; i++ {
			if err := binary.Read(attrsReader, binary.BigEndian, &keyLen); err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
			buf.Grow(int(keyLen))
			if n, err := io.CopyN(&buf, attrsReader, int64(keyLen)); err != nil || int32(n) != keyLen {
				return nil, opentracing.ErrTraceCorrupted
			}
			key := buf.String()
			buf.Reset()

			if err := binary.Read(attrsReader, binary.BigEndian, &valLen); err != nil {
				return nil, opentracing.ErrTraceCorrupted
			}
			if n, err := io.CopyN(&buf, attrsReader, int64(valLen)); err != nil || int32(n) != valLen {
				return nil, opentracing.ErrTraceCorrupted
			}
			attrMap[key] = buf.String()
			buf.Reset()
		}
	}

	sp := p.tracer.getSpan()
	sp.raw = RawSpan{
		StandardContext: StandardContext{
			TraceID:      traceID,
			SpanID:       randomID(),
			ParentSpanID: propagatedSpanID,
			Sampled:      sampledByte != 0,
		},
	}
	sp.raw.Attributes = attrMap

	return p.tracer.startSpanInternal(
		sp,
		operationName,
		time.Now(),
		nil,
	), nil
}

const (
	tracerStateHeaderName = "Tracer-State"
	traceAttrsHeaderName  = "Trace-Attributes"
)

func (p *goHTTPPropagator) InjectSpan(
	sp opentracing.Span,
	carrier interface{},
) error {
	// Defer to SplitBinary for the real work.
	splitBinaryCarrier := opentracing.NewSplitBinaryCarrier()
	if err := p.splitBinaryPropagator.InjectSpan(sp, splitBinaryCarrier); err != nil {
		return err
	}

	// Encode into the HTTP header as two base64 strings.
	header := carrier.(http.Header)
	header.Add(tracerStateHeaderName, base64.StdEncoding.EncodeToString(
		splitBinaryCarrier.TracerState))
	header.Add(traceAttrsHeaderName, base64.StdEncoding.EncodeToString(
		splitBinaryCarrier.TraceAttributes))

	return nil
}

func (p *goHTTPPropagator) JoinTrace(
	operationName string,
	carrier interface{},
) (opentracing.Span, error) {
	// Decode the two base64-encoded data blobs from the HTTP header.
	header := carrier.(http.Header)
	tracerStateBase64, found := header[http.CanonicalHeaderKey(tracerStateHeaderName)]
	if !found || len(tracerStateBase64) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	traceAttrsBase64, found := header[http.CanonicalHeaderKey(traceAttrsHeaderName)]
	if !found || len(traceAttrsBase64) == 0 {
		return nil, opentracing.ErrTraceNotFound
	}
	tracerStateBinary, err := base64.StdEncoding.DecodeString(tracerStateBase64[0])
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}
	traceAttrsBinary, err := base64.StdEncoding.DecodeString(traceAttrsBase64[0])
	if err != nil {
		return nil, opentracing.ErrTraceCorrupted
	}

	// Defer to SplitBinary for the real work.
	splitBinaryCarrier := &opentracing.SplitBinaryCarrier{
		TracerState:     tracerStateBinary,
		TraceAttributes: traceAttrsBinary,
	}
	return p.splitBinaryPropagator.JoinTrace(operationName, splitBinaryCarrier)
}
<|endoftext|>


<commit_before>package python

import (
	"encoding/json"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/kr/fs"

	"sourcegraph.com/sourcegraph/srclib/repo"
	"sourcegraph.com/sourcegraph/srclib/toolchain"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

// Scan a directory, listing all source units
func Scan(srcdir string, repoURI string, repoSubdir string) ([]*unit.SourceUnit, error) {
	if units, isSpecial := specialUnits[repoURI]; isSpecial {
		return units, nil
	}

	cmd := exec.Command("pydep-run.py", "list", srcdir)

	cmd.Stderr = os.Stderr
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}

	var pkgs []*pkgInfo
	if err := json.NewDecoder(stdout).Decode(&pkgs); err != nil {
		return nil, err
	}

	if err := cmd.Wait(); err != nil {
		return nil, err
	}

	// Keep track of all files that have been successfully discovered
	discoveredScripts := make(map[string]bool)

	units := make([]*unit.SourceUnit, len(pkgs))
	for i, pkg := range pkgs {
		units[i] = pkg.SourceUnit()
		units[i].Files = pythonSourceFiles(pkg.RootDir, discoveredScripts)
		units[i].Repo = repo.URI(repoURI) // override whatever's in the setup.py file with the actual repository URI

		reqs, err := requirements(pkg.RootDir)
		if err != nil {
			return nil, err
		}
		reqs_ := make([]interface{}, len(reqs))
		for i, req := range reqs {
			reqs_[i] = req
		}
		units[i].Dependencies = reqs_
	}

	// Scan for independant scripts, appending to the current set of source units
	scripts := pythonSourceFiles(srcdir, discoveredScripts)
	if len(scripts) > 0 {
		scriptsUnit := unit.SourceUnit{
			Name:  ".",
			Type:  "PythonProgram",
			Files: scripts,
			Dir:   ".",
			Ops:   map[string]*toolchain.ToolRef{"depresolve": nil, "graph": nil},
		}

		reqs, err := requirements(srcdir)
		if err == nil {
			reqs_ := make([]interface{}, len(reqs))
			for i, req := range reqs {
				reqs_[i] = req
			}
			scriptsUnit.Dependencies = reqs_
		}

		units = append(units, &scriptsUnit)
	}

	return units, nil
}

func requirements(unitDir string) ([]*requirement, error) {
	depCmd := exec.Command("pydep-run.py", "dep", unitDir)
	depCmd.Stderr = os.Stderr
	b, err := depCmd.Output()
	if err != nil {
		return nil, err
	}

	var reqs []*requirement
	err = json.Unmarshal(b, &reqs)
	if err != nil {
		return nil, err
	}
	reqs, ignoredReqs := pruneReqs(reqs)
	if len(ignoredReqs) > 0 {
		ignoredKeys := make([]string, len(ignoredReqs))
		for r, req := range ignoredReqs {
			ignoredKeys[r] = req.Key
		}
		log.Printf("(warn) ignoring dependencies %v because repo URL absent", ignoredKeys)
	}

	return reqs, nil
}

// Get all python source files under dir
func pythonSourceFiles(dir string, discoveredScripts map[string]bool) (files []string) {
	walker := fs.Walk(dir)
	for walker.Step() {
		if err := walker.Err(); err == nil && !walker.Stat().IsDir() && filepath.Ext(walker.Path()) == ".py" {
			file, _ := filepath.Rel(dir, walker.Path())
			_, found := discoveredScripts[file]

			if !found {
				files = append(files, file)
				discoveredScripts[file] = true
			}
		}
	}
	return
}

// Remove unresolvable requirements (i.e., requirements with no clone URL)
func pruneReqs(reqs []*requirement) (kept, ignored []*requirement) {
	for _, req := range reqs {
		if req.RepoURL != "" { // cannot resolve dependencies with no clone URL
			kept = append(kept, req)
		} else {
			ignored = append(ignored, req)
		}
	}
	return
}
<commit_msg>relativize source unit file paths to the repo root, not the pip package root<commit_after>package python

import (
	"encoding/json"
	"log"
	"os"
	"os/exec"
	"path/filepath"

	"github.com/kr/fs"

	"sourcegraph.com/sourcegraph/srclib/repo"
	"sourcegraph.com/sourcegraph/srclib/toolchain"
	"sourcegraph.com/sourcegraph/srclib/unit"
)

// Scan a directory, listing all source units
func Scan(srcdir string, repoURI string, repoSubdir string) ([]*unit.SourceUnit, error) {
	if units, isSpecial := specialUnits[repoURI]; isSpecial {
		return units, nil
	}

	cmd := exec.Command("pydep-run.py", "list", srcdir)

	cmd.Stderr = os.Stderr
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}

	var pkgs []*pkgInfo
	if err := json.NewDecoder(stdout).Decode(&pkgs); err != nil {
		return nil, err
	}

	if err := cmd.Wait(); err != nil {
		return nil, err
	}

	// Keep track of all files that have been successfully discovered
	discoveredScripts := make(map[string]bool)

	units := make([]*unit.SourceUnit, len(pkgs))
	for i, pkg := range pkgs {
		units[i] = pkg.SourceUnit()
		units[i].Files = pythonSourceFiles(pkg.RootDir, discoveredScripts)
		units[i].Repo = repo.URI(repoURI) // override whatever's in the setup.py file with the actual repository URI

		reqs, err := requirements(pkg.RootDir)
		if err != nil {
			return nil, err
		}
		reqs_ := make([]interface{}, len(reqs))
		for i, req := range reqs {
			reqs_[i] = req
		}
		units[i].Dependencies = reqs_
	}

	// Scan for independant scripts, appending to the current set of source units
	scripts := pythonSourceFiles(srcdir, discoveredScripts)
	if len(scripts) > 0 {
		scriptsUnit := unit.SourceUnit{
			Name:  ".",
			Type:  "PythonProgram",
			Files: scripts,
			Dir:   ".",
			Ops:   map[string]*toolchain.ToolRef{"depresolve": nil, "graph": nil},
		}

		reqs, err := requirements(srcdir)
		if err == nil {
			reqs_ := make([]interface{}, len(reqs))
			for i, req := range reqs {
				reqs_[i] = req
			}
			scriptsUnit.Dependencies = reqs_
		}

		units = append(units, &scriptsUnit)
	}

	return units, nil
}

func requirements(unitDir string) ([]*requirement, error) {
	depCmd := exec.Command("pydep-run.py", "dep", unitDir)
	depCmd.Stderr = os.Stderr
	b, err := depCmd.Output()
	if err != nil {
		return nil, err
	}

	var reqs []*requirement
	err = json.Unmarshal(b, &reqs)
	if err != nil {
		return nil, err
	}
	reqs, ignoredReqs := pruneReqs(reqs)
	if len(ignoredReqs) > 0 {
		ignoredKeys := make([]string, len(ignoredReqs))
		for r, req := range ignoredReqs {
			ignoredKeys[r] = req.Key
		}
		log.Printf("(warn) ignoring dependencies %v because repo URL absent", ignoredKeys)
	}

	return reqs, nil
}

// Get all python source files under dir
func pythonSourceFiles(dir string, discoveredScripts map[string]bool) (files []string) {
	walker := fs.Walk(dir)
	for walker.Step() {
		if err := walker.Err(); err == nil && !walker.Stat().IsDir() && filepath.Ext(walker.Path()) == ".py" {
			file := walker.Path()
			_, found := discoveredScripts[file]

			if !found {
				files = append(files, file)
				discoveredScripts[file] = true
			}
		}
	}
	return
}

// Remove unresolvable requirements (i.e., requirements with no clone URL)
func pruneReqs(reqs []*requirement) (kept, ignored []*requirement) {
	for _, req := range reqs {
		if req.RepoURL != "" { // cannot resolve dependencies with no clone URL
			kept = append(kept, req)
		} else {
			ignored = append(ignored, req)
		}
	}
	return
}
<|endoftext|>


<commit_before>package bytepool

import (
	"io"
)

type Item struct {
	pool   *Pool
	length int
	read   int
	bytes  []byte
}

func newItem(capacity int, pool *Pool) *Item {
	return &Item{
		pool:  pool,
		bytes: make([]byte, capacity),
	}
}

func (item *Item) Write(b []byte) (int, error) {
	if item.Full() {
		return 0, io.ErrShortWrite
	}
	n := copy(item.bytes[item.length:], b)
	item.length += n
	return n, nil
}

func (item *Item) WriteByte(b byte) bool {
	if item.Full() {
		return false
	}
	item.bytes[item.length] = b
	item.length += 1
	return true
}

func (item *Item) WriteString(s string) int {
	if item.Full() {
		return 0
	}
	n := copy(item.bytes[item.length:], s)
	item.length += n
	return n
}

func (item *Item) ReadFrom(reader io.Reader) (int64, error) {
	var read int64
	for {
		r, err := reader.Read(item.bytes[item.length:])
		read += int64(r)
		item.length += r
		if err == io.EOF || item.Full() {
			return read, nil
		}
		if err != nil {
			return read, err
		}
	}
}

func (item *Item) Read(p []byte) (int, error) {
	if item.Drained() {
		return 0, io.EOF
	}
	n := copy(p, item.bytes[item.read:item.length])
	item.read += n
	if item.Drained() {
		return n, io.EOF
	}
	return n, nil
}

func (item *Item) Bytes() []byte {
	return item.bytes[0:item.length]
}

func (item *Item) Clone() []byte {
	b := make([]byte, item.length)
	copy(b, item.Bytes())
	return b
}

func (item *Item) Raw() []byte {
	return item.bytes
}

func (item *Item) String() string {
	return string(item.Bytes())
}

func (item *Item) Len() int {
	return item.length
}

func (item *Item) TrimLastIf(b byte) bool {
	l := item.Len() - 1
	if l == -1 || item.bytes[l] != b {
		return false
	}
	item.Position(l)
	return true
}

func (item *Item) Position(position int) bool {
	if position < 0 || position > cap(item.bytes) {
		return false
	}
	item.length = position
	return true
}

func (item *Item) Full() bool {
	return item.length == cap(item.bytes)
}

func (item *Item) Drained() bool {
	return item.length == item.read
}

func (item *Item) Close() error {
	if item.pool != nil {
		item.pool.track(int64(item.length))
		item.read = 0
		item.length = 0
		item.pool.list <- item
	}
	return nil
}
<commit_msg>quick method to overwrite last byte<commit_after>package bytepool

import (
	"io"
)

type Item struct {
	pool   *Pool
	length int
	read   int
	bytes  []byte
}

func newItem(capacity int, pool *Pool) *Item {
	return &Item{
		pool:  pool,
		bytes: make([]byte, capacity),
	}
}

func (item *Item) Write(b []byte) (int, error) {
	if item.Full() {
		return 0, io.ErrShortWrite
	}
	n := copy(item.bytes[item.length:], b)
	item.length += n
	return n, nil
}

func (item *Item) WriteByte(b byte) bool {
	if item.Full() {
		return false
	}
	item.bytes[item.length] = b
	item.length += 1
	return true
}

func (item *Item) WriteString(s string) int {
	if item.Full() {
		return 0
	}
	n := copy(item.bytes[item.length:], s)
	item.length += n
	return n
}

func (item *Item) ReadFrom(reader io.Reader) (int64, error) {
	var read int64
	for {
		r, err := reader.Read(item.bytes[item.length:])
		read += int64(r)
		item.length += r
		if err == io.EOF || item.Full() {
			return read, nil
		}
		if err != nil {
			return read, err
		}
	}
}

func (item *Item) Read(p []byte) (int, error) {
	if item.Drained() {
		return 0, io.EOF
	}
	n := copy(p, item.bytes[item.read:item.length])
	item.read += n
	if item.Drained() {
		return n, io.EOF
	}
	return n, nil
}

func (item *Item) Bytes() []byte {
	return item.bytes[0:item.length]
}

func (item *Item) Clone() []byte {
	b := make([]byte, item.length)
	copy(b, item.Bytes())
	return b
}

func (item *Item) Raw() []byte {
	return item.bytes
}

func (item *Item) String() string {
	return string(item.Bytes())
}

func (item *Item) Len() int {
	return item.length
}

func (item *Item) TrimLastIf(b byte) bool {
	l := item.Len() - 1
	if l == -1 || item.bytes[l] != b {
		return false
	}
	item.Position(l)
	return true
}

func (item *Item) Last(b byte) {
	if l := item.Len(); l > 0 {
		item.bytes[l-1] = b
	}
}

func (item *Item) Position(position int) bool {
	if position < 0 || position > cap(item.bytes) {
		return false
	}
	item.length = position
	return true
}

func (item *Item) Full() bool {
	return item.length == cap(item.bytes)
}

func (item *Item) Drained() bool {
	return item.length == item.read
}

func (item *Item) Close() error {
	if item.pool != nil {
		item.pool.track(int64(item.length))
		item.read = 0
		item.length = 0
		item.pool.list <- item
	}
	return nil
}
<|endoftext|>


<commit_before>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.5"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<commit_msg>version bump<commit_after>package jira

import (
	"github.com/coryb/oreo"
	logging "gopkg.in/op/go-logging.v1"
)

var log = logging.MustGetLogger("jira")

const VERSION = "1.0.6"

type Jira struct {
	Endpoint string     `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
	UA       HttpClient `json:"-" yaml:"-"`
}

func NewJira(endpoint string) *Jira {
	return &Jira{
		Endpoint: endpoint,
		UA:       oreo.New(),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"syscall"
	"unsafe"
)

/*** data ***/

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

type editorConfig struct {
	screenRows  int
	screenCols  int
	origTermios *Termios
}

type WinSize struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}

var E editorConfig

/*** terminal ***/

func die(err error) {
	disableRawMode()
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	log.Fatal(err)
}

func TcSetAttr(fd uintptr, termios *Termios) error {
	// TCSETS+1 == TCSETSW, because TCSAFLUSH doesn't exist
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS+1), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) *Termios {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		log.Fatalf("Problem getting terminal attributes: %s\n", err)
	}
	return termios
}

func enableRawMode() {
	E.origTermios = TcGetAttr(os.Stdin.Fd())
	var raw Termios
	raw = *E.origTermios
	raw.Iflag &^= syscall.BRKINT | syscall.ICRNL | syscall.INPCK | syscall.ISTRIP | syscall.IXON
	raw.Oflag &^= syscall.OPOST
	raw.Cflag |= syscall.CS8
	raw.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.IEXTEN | syscall.ISIG
	raw.Cc[syscall.VMIN+1] = 0
	raw.Cc[syscall.VTIME+1] = 1
	if e := TcSetAttr(os.Stdin.Fd(), &raw); e != nil {
		log.Fatalf("Problem enabling raw mode: %s\n", e)
	}
}

func disableRawMode() {
	if e := TcSetAttr(os.Stdin.Fd(), E.origTermios); e != nil {
		log.Fatalf("Problem disabling raw mode: %s\n", e)
	}
}

func editorReadKey() byte {
	var buffer [1]byte
	var cc int
	var err error
	for cc, err = os.Stdin.Read(buffer[:]); cc != 1; cc, err = os.Stdin.Read(buffer[:]) {
	}
	if err != nil {
		die(err)
	}
	return buffer[0]
}

func getCursorPosition(rows *int, cols *int) int {
	io.WriteString(os.Stdout, "\x1b[6n")
	var buffer [1]byte
	var buf []byte
	var cc int
	for cc, _ = os.Stdin.Read(buffer[:]); cc == 1; cc, _ = os.Stdin.Read(buffer[:]) {
		if buffer[0] == 'R' {
			break
		}
		buf = append(buf, buffer[0])
	}
	if string(buf[0:2]) != "\x1b[" {
		log.Printf("Failed to read rows;cols from tty\n")
		return -1
	}
	if n, e := fmt.Sscanf(string(buf[2:]), "%d;%d", rows, cols); n != 2 || e != nil {
		if e != nil {
			log.Printf("getCursorPosition: fmt.Sscanf() failed: %s\n", e)
		}
		if n != 2 {
			log.Printf("getCursorPosition: got %d items, wanted 2\n", n)
		}
		return -1
	}
	return 0
}

func getWindowSize(rows *int, cols *int) int {
	var w WinSize
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL,
		os.Stdout.Fd(),
		syscall.TIOCGWINSZ,
		uintptr(unsafe.Pointer(&w)),
	)
	if true {
		io.WriteString(os.Stdout, "\x1b[999C\x1b[999B")
		return getCursorPosition(rows, cols)
	}
	if err == 0 { // type syscall.Errno
		*rows = int(w.Row)
		*cols = int(w.Col)
		return 0
	}
	return -1
}

/*** input ***/

func editorProcessKeypress() {
	c := editorReadKey()
	switch c {
	case ('q' & 0x1f):
		io.WriteString(os.Stdout, "\x1b[2J")
		io.WriteString(os.Stdout, "\x1b[H")
		disableRawMode()
		os.Exit(0)
	}
}

/*** output ***/

func editorRefreshScreen() {
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	editorDrawRows()
	io.WriteString(os.Stdout, "\x1b[H")
}

func editorDrawRows() {
	for y := 0; y < E.screenRows; y++ {
		io.WriteString(os.Stdout, "~\r\n")
	}
}

/*** init ***/

func initEditor() {
	if getWindowSize(&E.screenRows, &E.screenCols) == -1 {
		die(fmt.Errorf("couldn't get screen size"))
	}
}

func main() {
	enableRawMode()
	defer disableRawMode()
	initEditor()

	for {
		editorRefreshScreen()
		editorProcessKeypress()
	}
}
<commit_msg>Step 34<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"syscall"
	"unsafe"
)

/*** data ***/

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

type editorConfig struct {
	screenRows  int
	screenCols  int
	origTermios *Termios
}

type WinSize struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}

var E editorConfig

/*** terminal ***/

func die(err error) {
	disableRawMode()
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	log.Fatal(err)
}

func TcSetAttr(fd uintptr, termios *Termios) error {
	// TCSETS+1 == TCSETSW, because TCSAFLUSH doesn't exist
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS+1), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) *Termios {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		log.Fatalf("Problem getting terminal attributes: %s\n", err)
	}
	return termios
}

func enableRawMode() {
	E.origTermios = TcGetAttr(os.Stdin.Fd())
	var raw Termios
	raw = *E.origTermios
	raw.Iflag &^= syscall.BRKINT | syscall.ICRNL | syscall.INPCK | syscall.ISTRIP | syscall.IXON
	raw.Oflag &^= syscall.OPOST
	raw.Cflag |= syscall.CS8
	raw.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.IEXTEN | syscall.ISIG
	raw.Cc[syscall.VMIN+1] = 0
	raw.Cc[syscall.VTIME+1] = 1
	if e := TcSetAttr(os.Stdin.Fd(), &raw); e != nil {
		log.Fatalf("Problem enabling raw mode: %s\n", e)
	}
}

func disableRawMode() {
	if e := TcSetAttr(os.Stdin.Fd(), E.origTermios); e != nil {
		log.Fatalf("Problem disabling raw mode: %s\n", e)
	}
}

func editorReadKey() byte {
	var buffer [1]byte
	var cc int
	var err error
	for cc, err = os.Stdin.Read(buffer[:]); cc != 1; cc, err = os.Stdin.Read(buffer[:]) {
	}
	if err != nil {
		die(err)
	}
	return buffer[0]
}

func getCursorPosition(rows *int, cols *int) int {
	io.WriteString(os.Stdout, "\x1b[6n")
	var buffer [1]byte
	var buf []byte
	var cc int
	for cc, _ = os.Stdin.Read(buffer[:]); cc == 1; cc, _ = os.Stdin.Read(buffer[:]) {
		if buffer[0] == 'R' {
			break
		}
		buf = append(buf, buffer[0])
	}
	if string(buf[0:2]) != "\x1b[" {
		log.Printf("Failed to read rows;cols from tty\n")
		return -1
	}
	if n, e := fmt.Sscanf(string(buf[2:]), "%d;%d", rows, cols); n != 2 || e != nil {
		if e != nil {
			log.Printf("getCursorPosition: fmt.Sscanf() failed: %s\n", e)
		}
		if n != 2 {
			log.Printf("getCursorPosition: got %d items, wanted 2\n", n)
		}
		return -1
	}
	return 0
}

func getWindowSize(rows *int, cols *int) int {
	var w WinSize
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL,
		os.Stdout.Fd(),
		syscall.TIOCGWINSZ,
		uintptr(unsafe.Pointer(&w)),
	)
	if err != 0 { // type syscall.Errno
		io.WriteString(os.Stdout, "\x1b[999C\x1b[999B")
		return getCursorPosition(rows, cols)
	} else {
		*rows = int(w.Row)
		*cols = int(w.Col)
		return 0
	}
	return -1
}

/*** input ***/

func editorProcessKeypress() {
	c := editorReadKey()
	switch c {
	case ('q' & 0x1f):
		io.WriteString(os.Stdout, "\x1b[2J")
		io.WriteString(os.Stdout, "\x1b[H")
		disableRawMode()
		os.Exit(0)
	}
}

/*** output ***/

func editorRefreshScreen() {
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	editorDrawRows()
	io.WriteString(os.Stdout, "\x1b[H")
}

func editorDrawRows() {
	for y := 0; y < E.screenRows; y++ {
		io.WriteString(os.Stdout, "~\r\n")
	}
}

/*** init ***/

func initEditor() {
	if getWindowSize(&E.screenRows, &E.screenCols) == -1 {
		die(fmt.Errorf("couldn't get screen size"))
	}
}

func main() {
	enableRawMode()
	defer disableRawMode()
	initEditor()

	for {
		editorRefreshScreen()
		editorProcessKeypress()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"syscall"
	"unsafe"
)

/*** defines ***/

const KILO_VERSION = "0.0.1"
const (
	ARROW_LEFT  = 1000 + iota
	ARROW_RIGHT = 1000 + iota
	ARROW_UP    = 1000 + iota
	ARROW_DOWN  = 1000 + iota
	PAGE_UP     = 1000 + iota
	PAGE_DOWN   = 1000 + iota
)

/*** data ***/

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

type editorConfig struct {
	cx          int
	cy          int
	screenRows  int
	screenCols  int
	origTermios *Termios
}

type WinSize struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}

var E editorConfig

/*** terminal ***/

func die(err error) {
	disableRawMode()
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	log.Fatal(err)
}

func TcSetAttr(fd uintptr, termios *Termios) error {
	// TCSETS+1 == TCSETSW, because TCSAFLUSH doesn't exist
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS+1), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) *Termios {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		log.Fatalf("Problem getting terminal attributes: %s\n", err)
	}
	return termios
}

func enableRawMode() {
	E.origTermios = TcGetAttr(os.Stdin.Fd())
	var raw Termios
	raw = *E.origTermios
	raw.Iflag &^= syscall.BRKINT | syscall.ICRNL | syscall.INPCK | syscall.ISTRIP | syscall.IXON
	raw.Oflag &^= syscall.OPOST
	raw.Cflag |= syscall.CS8
	raw.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.IEXTEN | syscall.ISIG
	raw.Cc[syscall.VMIN+1] = 0
	raw.Cc[syscall.VTIME+1] = 1
	if e := TcSetAttr(os.Stdin.Fd(), &raw); e != nil {
		log.Fatalf("Problem enabling raw mode: %s\n", e)
	}
}

func disableRawMode() {
	if e := TcSetAttr(os.Stdin.Fd(), E.origTermios); e != nil {
		log.Fatalf("Problem disabling raw mode: %s\n", e)
	}
}

func editorReadKey() int {
	var buffer [1]byte
	var cc int
	var err error
	for cc, err = os.Stdin.Read(buffer[:]); cc != 1; cc, err = os.Stdin.Read(buffer[:]) {
	}
	if err != nil {
		die(err)
	}
	if buffer[0] == '\x1b' {
		var seq [2]byte
		if cc, _ = os.Stdin.Read(seq[:]); cc != 2 {
			return '\x1b'
		}

		if seq[0] == '[' {
			if seq[1] >= '0' && seq[1] <= '9' {
				if cc, err = os.Stdin.Read(buffer[:]); cc != 1 {
					return '\x1b'
				}
				if buffer[0] == '~' {
					switch seq[1] {
					case '5':
						return PAGE_UP
					case '6':
						return PAGE_DOWN
					}
				}
				// XXX - what happens here?
			} else {
				switch seq[1] {
				case 'A':
					return ARROW_UP
				case 'B':
					return ARROW_DOWN
				case 'C':
					return ARROW_RIGHT
				case 'D':
					return ARROW_LEFT
				}
			}
		}

		return '\x1b'
	}
	return int(buffer[0])
}

func getCursorPosition(rows *int, cols *int) int {
	io.WriteString(os.Stdout, "\x1b[6n")
	var buffer [1]byte
	var buf []byte
	var cc int
	for cc, _ = os.Stdin.Read(buffer[:]); cc == 1; cc, _ = os.Stdin.Read(buffer[:]) {
		if buffer[0] == 'R' {
			break
		}
		buf = append(buf, buffer[0])
	}
	if string(buf[0:2]) != "\x1b[" {
		log.Printf("Failed to read rows;cols from tty\n")
		return -1
	}
	if n, e := fmt.Sscanf(string(buf[2:]), "%d;%d", rows, cols); n != 2 || e != nil {
		if e != nil {
			log.Printf("getCursorPosition: fmt.Sscanf() failed: %s\n", e)
		}
		if n != 2 {
			log.Printf("getCursorPosition: got %d items, wanted 2\n", n)
		}
		return -1
	}
	return 0
}

func getWindowSize(rows *int, cols *int) int {
	var w WinSize
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL,
		os.Stdout.Fd(),
		syscall.TIOCGWINSZ,
		uintptr(unsafe.Pointer(&w)),
	)
	if err != 0 { // type syscall.Errno
		io.WriteString(os.Stdout, "\x1b[999C\x1b[999B")
		return getCursorPosition(rows, cols)
	} else {
		*rows = int(w.Row)
		*cols = int(w.Col)
		return 0
	}
	return -1
}

/*** input ***/

func editorMoveCursor(key int) {
	switch key {
	case ARROW_LEFT:
		if E.cx != 0 {
			E.cx--
		}
	case ARROW_RIGHT:
		if E.cx != E.screenCols-1 {
			E.cx++
		}
	case ARROW_UP:
		if E.cy != 0 {
			E.cy--
		}
	case ARROW_DOWN:
		if E.cy != E.screenRows-1 {
			E.cy++
		}
	}
}

func editorProcessKeypress() {
	c := editorReadKey()
	switch c {
	case ('q' & 0x1f):
		io.WriteString(os.Stdout, "\x1b[2J")
		io.WriteString(os.Stdout, "\x1b[H")
		disableRawMode()
		os.Exit(0)
	case ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT:
		editorMoveCursor(c)
	}
}

/*** append buffer ***/

type abuf struct {
	buf []byte
}

func (p abuf) String() string {
	return string(p.buf)
}

func (p *abuf) abAppend(s string) {
	p.buf = append(p.buf, []byte(s)...)
}

/*** output ***/

func editorRefreshScreen() {
	var ab abuf
	ab.abAppend("\x1b[25l")
	ab.abAppend("\x1b[H")
	editorDrawRows(&ab)
	ab.abAppend(fmt.Sprintf("\x1b[%d;%dH", E.cy+1, E.cx+1))
	ab.abAppend("\x1b[25h")
	io.WriteString(os.Stdout, ab.String())
}

func editorDrawRows(ab *abuf) {
	for y := 0; y < E.screenRows-1; y++ {
		if y == E.screenRows/3 {
			w := fmt.Sprintf("Kilo editor -- version %s", KILO_VERSION)
			if len(w) > E.screenCols {
				w = w[0:E.screenCols]
			}
			pad := "~ "
			for padding := (E.screenCols - len(w)) / 2; padding > 0; padding-- {
				ab.abAppend(pad)
				pad = " "
			}
			ab.abAppend(w)
		} else {
			ab.abAppend("~")
		}
		ab.abAppend("\x1b[K")
		if y < E.screenRows-1 {
			ab.abAppend("\r\n")
		}
	}
}

/*** init ***/

func initEditor() {
	if getWindowSize(&E.screenRows, &E.screenCols) == -1 {
		die(fmt.Errorf("couldn't get screen size"))
	}
}

func main() {
	enableRawMode()
	defer disableRawMode()
	initEditor()

	for {
		editorRefreshScreen()
		editorProcessKeypress()
	}
}
<commit_msg>Step 51 - Page up and Page down do something<commit_after>package main

import (
	"fmt"
	"io"
	"log"
	"os"
	"syscall"
	"unsafe"
)

/*** defines ***/

const KILO_VERSION = "0.0.1"
const (
	ARROW_LEFT  = 1000 + iota
	ARROW_RIGHT = 1000 + iota
	ARROW_UP    = 1000 + iota
	ARROW_DOWN  = 1000 + iota
	PAGE_UP     = 1000 + iota
	PAGE_DOWN   = 1000 + iota
)

/*** data ***/

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

type editorConfig struct {
	cx          int
	cy          int
	screenRows  int
	screenCols  int
	origTermios *Termios
}

type WinSize struct {
	Row    uint16
	Col    uint16
	Xpixel uint16
	Ypixel uint16
}

var E editorConfig

/*** terminal ***/

func die(err error) {
	disableRawMode()
	io.WriteString(os.Stdout, "\x1b[2J")
	io.WriteString(os.Stdout, "\x1b[H")
	log.Fatal(err)
}

func TcSetAttr(fd uintptr, termios *Termios) error {
	// TCSETS+1 == TCSETSW, because TCSAFLUSH doesn't exist
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS+1), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) *Termios {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		log.Fatalf("Problem getting terminal attributes: %s\n", err)
	}
	return termios
}

func enableRawMode() {
	E.origTermios = TcGetAttr(os.Stdin.Fd())
	var raw Termios
	raw = *E.origTermios
	raw.Iflag &^= syscall.BRKINT | syscall.ICRNL | syscall.INPCK | syscall.ISTRIP | syscall.IXON
	raw.Oflag &^= syscall.OPOST
	raw.Cflag |= syscall.CS8
	raw.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.IEXTEN | syscall.ISIG
	raw.Cc[syscall.VMIN+1] = 0
	raw.Cc[syscall.VTIME+1] = 1
	if e := TcSetAttr(os.Stdin.Fd(), &raw); e != nil {
		log.Fatalf("Problem enabling raw mode: %s\n", e)
	}
}

func disableRawMode() {
	if e := TcSetAttr(os.Stdin.Fd(), E.origTermios); e != nil {
		log.Fatalf("Problem disabling raw mode: %s\n", e)
	}
}

func editorReadKey() int {
	var buffer [1]byte
	var cc int
	var err error
	for cc, err = os.Stdin.Read(buffer[:]); cc != 1; cc, err = os.Stdin.Read(buffer[:]) {
	}
	if err != nil {
		die(err)
	}
	if buffer[0] == '\x1b' {
		var seq [2]byte
		if cc, _ = os.Stdin.Read(seq[:]); cc != 2 {
			return '\x1b'
		}

		if seq[0] == '[' {
			if seq[1] >= '0' && seq[1] <= '9' {
				if cc, err = os.Stdin.Read(buffer[:]); cc != 1 {
					return '\x1b'
				}
				if buffer[0] == '~' {
					switch seq[1] {
					case '5':
						return PAGE_UP
					case '6':
						return PAGE_DOWN
					}
				}
				// XXX - what happens here?
			} else {
				switch seq[1] {
				case 'A':
					return ARROW_UP
				case 'B':
					return ARROW_DOWN
				case 'C':
					return ARROW_RIGHT
				case 'D':
					return ARROW_LEFT
				}
			}
		}

		return '\x1b'
	}
	return int(buffer[0])
}

func getCursorPosition(rows *int, cols *int) int {
	io.WriteString(os.Stdout, "\x1b[6n")
	var buffer [1]byte
	var buf []byte
	var cc int
	for cc, _ = os.Stdin.Read(buffer[:]); cc == 1; cc, _ = os.Stdin.Read(buffer[:]) {
		if buffer[0] == 'R' {
			break
		}
		buf = append(buf, buffer[0])
	}
	if string(buf[0:2]) != "\x1b[" {
		log.Printf("Failed to read rows;cols from tty\n")
		return -1
	}
	if n, e := fmt.Sscanf(string(buf[2:]), "%d;%d", rows, cols); n != 2 || e != nil {
		if e != nil {
			log.Printf("getCursorPosition: fmt.Sscanf() failed: %s\n", e)
		}
		if n != 2 {
			log.Printf("getCursorPosition: got %d items, wanted 2\n", n)
		}
		return -1
	}
	return 0
}

func getWindowSize(rows *int, cols *int) int {
	var w WinSize
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL,
		os.Stdout.Fd(),
		syscall.TIOCGWINSZ,
		uintptr(unsafe.Pointer(&w)),
	)
	if err != 0 { // type syscall.Errno
		io.WriteString(os.Stdout, "\x1b[999C\x1b[999B")
		return getCursorPosition(rows, cols)
	} else {
		*rows = int(w.Row)
		*cols = int(w.Col)
		return 0
	}
	return -1
}

/*** input ***/

func editorMoveCursor(key int) {
	switch key {
	case ARROW_LEFT:
		if E.cx != 0 {
			E.cx--
		}
	case ARROW_RIGHT:
		if E.cx != E.screenCols-1 {
			E.cx++
		}
	case ARROW_UP:
		if E.cy != 0 {
			E.cy--
		}
	case ARROW_DOWN:
		if E.cy != E.screenRows-1 {
			E.cy++
		}
	}
}

func editorProcessKeypress() {
	c := editorReadKey()
	switch c {
	case ('q' & 0x1f):
		io.WriteString(os.Stdout, "\x1b[2J")
		io.WriteString(os.Stdout, "\x1b[H")
		disableRawMode()
		os.Exit(0)
	case PAGE_UP, PAGE_DOWN:
		dir := ARROW_DOWN
		if c == PAGE_UP {
			dir = ARROW_UP
		}
		for times := E.screenRows; times > 0; times-- {
			editorMoveCursor(dir)
		}
	case ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT:
		editorMoveCursor(c)
	}
}

/*** append buffer ***/

type abuf struct {
	buf []byte
}

func (p abuf) String() string {
	return string(p.buf)
}

func (p *abuf) abAppend(s string) {
	p.buf = append(p.buf, []byte(s)...)
}

/*** output ***/

func editorRefreshScreen() {
	var ab abuf
	ab.abAppend("\x1b[25l")
	ab.abAppend("\x1b[H")
	editorDrawRows(&ab)
	ab.abAppend(fmt.Sprintf("\x1b[%d;%dH", E.cy+1, E.cx+1))
	ab.abAppend("\x1b[25h")
	io.WriteString(os.Stdout, ab.String())
}

func editorDrawRows(ab *abuf) {
	for y := 0; y < E.screenRows-1; y++ {
		if y == E.screenRows/3 {
			w := fmt.Sprintf("Kilo editor -- version %s", KILO_VERSION)
			if len(w) > E.screenCols {
				w = w[0:E.screenCols]
			}
			pad := "~ "
			for padding := (E.screenCols - len(w)) / 2; padding > 0; padding-- {
				ab.abAppend(pad)
				pad = " "
			}
			ab.abAppend(w)
		} else {
			ab.abAppend("~")
		}
		ab.abAppend("\x1b[K")
		if y < E.screenRows-1 {
			ab.abAppend("\r\n")
		}
	}
}

/*** init ***/

func initEditor() {
	if getWindowSize(&E.screenRows, &E.screenCols) == -1 {
		die(fmt.Errorf("couldn't get screen size"))
	}
}

func main() {
	enableRawMode()
	defer disableRawMode()
	initEditor()

	for {
		editorRefreshScreen()
		editorProcessKeypress()
	}
}
<|endoftext|>


<commit_before>package dbr

import (
	"database/sql"
	"fmt"
	"reflect"
)

// Load loads any value from sql.Rows
func Load(rows *sql.Rows, value interface{}) (int, error) {
	defer rows.Close()

	column, err := rows.Columns()
	if err != nil {
		return 0, err
	}

	v := reflect.ValueOf(value)
	if v.Kind() != reflect.Ptr || v.IsNil() {
		return 0, ErrInvalidPointer
	}
	v = v.Elem()
	isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8
	count := 0
	var elemType reflect.Type
	if isSlice {
		elemType = v.Type().Elem()
	} else {
		elemType = v.Type()
	}
	extractor, err := findExtractor(elemType)
	if err != nil {
		return count, err
	}
	for rows.Next() {
		var elem reflect.Value
		if isSlice {
			elem = reflect.New(v.Type().Elem()).Elem()
		} else {
			elem = v
		}
		ptr := extractor(column, elem)
		err = rows.Scan(ptr...)
		if err != nil {
			return count, err
		}
		count++
		if isSlice {
			v.Set(reflect.Append(v, elem))
		} else {
			break
		}
	}
	return count, nil
}

type dummyScanner struct{}

func (dummyScanner) Scan(interface{}) error {
	return nil
}

type keyValueMap map[string]interface{}

type kvScanner struct {
	column string
	m      keyValueMap
}

func (kv *kvScanner) Scan(v interface{}) error {
	if b, ok := v.([]byte); ok {
		tmp := make([]byte, len(b))
		copy(tmp, b)
		kv.m[kv.column] = tmp
	} else {
		// int64, float64, bool, string, time.Time, nil
		kv.m[kv.column] = v
	}
	return nil
}

type pointersExtractor func(columns []string, value reflect.Value) []interface{}

var (
	dummyDest       sql.Scanner = dummyScanner{}
	typeScanner                 = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
	typeKeyValueMap             = reflect.TypeOf(keyValueMap(nil))
)

func getStructFieldsExtractor(t reflect.Type) pointersExtractor {
	mapping := structMap(t)
	return func(columns []string, value reflect.Value) []interface{} {
		var ptr []interface{}
		for _, key := range columns {
			if index, ok := mapping[key]; ok {
				ptr = append(ptr, value.FieldByIndex(index).Addr().Interface())
			} else {
				ptr = append(ptr, dummyDest)
			}
		}
		return ptr
	}
}

func getIndirectExtractor(extractor pointersExtractor) pointersExtractor {
	return func(columns []string, value reflect.Value) []interface{} {
		if value.IsNil() {
			value.Set(reflect.New(value.Type().Elem()))
		}
		return extractor(columns, value.Elem())
	}
}

func mapExtractor(columns []string, value reflect.Value) []interface{} {
	if value.IsNil() {
		value.Set(reflect.MakeMap(value.Type()))
	}
	m := value.Convert(typeKeyValueMap).Interface().(keyValueMap)
	var ptr = make([]interface{}, 0, len(columns))
	for _, c := range columns {
		ptr = append(ptr, &kvScanner{column: c, m: m})
	}
	return ptr
}

func dummyExtractor(columns []string, value reflect.Value) []interface{} {
	return []interface{}{value.Addr().Interface()}
}

func findExtractor(t reflect.Type) (pointersExtractor, error) {
	if reflect.PtrTo(t).Implements(typeScanner) {
		return dummyExtractor, nil
	}

	switch t.Kind() {
	case reflect.Map:
		if !t.ConvertibleTo(typeKeyValueMap) {
			return nil, fmt.Errorf("expected %v, got %v", typeKeyValueMap, t)
		}
		return mapExtractor, nil
	case reflect.Ptr:
		inner, err := findExtractor(t.Elem())
		if err != nil {
			return nil, err
		}
		return getIndirectExtractor(inner), nil
	case reflect.Struct:
		return getStructFieldsExtractor(t), nil
	}
	return dummyExtractor, nil
}
<commit_msg>Check last error in Load method.<commit_after>package dbr

import (
	"database/sql"
	"fmt"
	"reflect"
)

// Load loads any value from sql.Rows
func Load(rows *sql.Rows, value interface{}) (int, error) {
	defer rows.Close()

	column, err := rows.Columns()
	if err != nil {
		return 0, err
	}

	v := reflect.ValueOf(value)
	if v.Kind() != reflect.Ptr || v.IsNil() {
		return 0, ErrInvalidPointer
	}
	v = v.Elem()
	isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8
	count := 0
	var elemType reflect.Type
	if isSlice {
		elemType = v.Type().Elem()
	} else {
		elemType = v.Type()
	}
	extractor, err := findExtractor(elemType)
	if err != nil {
		return count, err
	}
	for rows.Next() {
		var elem reflect.Value
		if isSlice {
			elem = reflect.New(v.Type().Elem()).Elem()
		} else {
			elem = v
		}
		ptr := extractor(column, elem)
		err = rows.Scan(ptr...)
		if err != nil {
			return count, err
		}
		count++
		if isSlice {
			v.Set(reflect.Append(v, elem))
		} else {
			break
		}
	}
	return count, rows.Err()
}

type dummyScanner struct{}

func (dummyScanner) Scan(interface{}) error {
	return nil
}

type keyValueMap map[string]interface{}

type kvScanner struct {
	column string
	m      keyValueMap
}

func (kv *kvScanner) Scan(v interface{}) error {
	if b, ok := v.([]byte); ok {
		tmp := make([]byte, len(b))
		copy(tmp, b)
		kv.m[kv.column] = tmp
	} else {
		// int64, float64, bool, string, time.Time, nil
		kv.m[kv.column] = v
	}
	return nil
}

type pointersExtractor func(columns []string, value reflect.Value) []interface{}

var (
	dummyDest       sql.Scanner = dummyScanner{}
	typeScanner                 = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
	typeKeyValueMap             = reflect.TypeOf(keyValueMap(nil))
)

func getStructFieldsExtractor(t reflect.Type) pointersExtractor {
	mapping := structMap(t)
	return func(columns []string, value reflect.Value) []interface{} {
		var ptr []interface{}
		for _, key := range columns {
			if index, ok := mapping[key]; ok {
				ptr = append(ptr, value.FieldByIndex(index).Addr().Interface())
			} else {
				ptr = append(ptr, dummyDest)
			}
		}
		return ptr
	}
}

func getIndirectExtractor(extractor pointersExtractor) pointersExtractor {
	return func(columns []string, value reflect.Value) []interface{} {
		if value.IsNil() {
			value.Set(reflect.New(value.Type().Elem()))
		}
		return extractor(columns, value.Elem())
	}
}

func mapExtractor(columns []string, value reflect.Value) []interface{} {
	if value.IsNil() {
		value.Set(reflect.MakeMap(value.Type()))
	}
	m := value.Convert(typeKeyValueMap).Interface().(keyValueMap)
	var ptr = make([]interface{}, 0, len(columns))
	for _, c := range columns {
		ptr = append(ptr, &kvScanner{column: c, m: m})
	}
	return ptr
}

func dummyExtractor(columns []string, value reflect.Value) []interface{} {
	return []interface{}{value.Addr().Interface()}
}

func findExtractor(t reflect.Type) (pointersExtractor, error) {
	if reflect.PtrTo(t).Implements(typeScanner) {
		return dummyExtractor, nil
	}

	switch t.Kind() {
	case reflect.Map:
		if !t.ConvertibleTo(typeKeyValueMap) {
			return nil, fmt.Errorf("expected %v, got %v", typeKeyValueMap, t)
		}
		return mapExtractor, nil
	case reflect.Ptr:
		inner, err := findExtractor(t.Elem())
		if err != nil {
			return nil, err
		}
		return getIndirectExtractor(inner), nil
	case reflect.Struct:
		return getStructFieldsExtractor(t), nil
	}
	return dummyExtractor, nil
}
<|endoftext|>