<commit_before>package cli

import (
	"bytes"
	"context"
	"hash/fnv"
	"io/ioutil"
	"sort"

	"github.com/pkg/errors"

	"github.com/kopia/kopia/internal/timetrack"
	"github.com/kopia/kopia/internal/units"
	"github.com/kopia/kopia/repo/compression"
)

const defaultCompressedDataByMethod = 128 << 20 // 128 MB

type commandBenchmarkCompression struct {
	repeat       int
	dataFile     string
	bySize       bool
	verifyStable bool
	optionPrint  bool

	out textOutput
}

func (c *commandBenchmarkCompression) setup(svc appServices, parent commandParent) {
	cmd := parent.Command("compression", "Run compression benchmarks")
	cmd.Flag("repeat", "Number of repetitions").Default("0").IntVar(&c.repeat)
	cmd.Flag("data-file", "Use data from the given file").Required().ExistingFileVar(&c.dataFile)
	cmd.Flag("by-size", "Sort results by size").BoolVar(&c.bySize)
	cmd.Flag("verify-stable", "Verify that compression is stable").BoolVar(&c.verifyStable)
	cmd.Flag("print-options", "Print out options usable for repository creation").BoolVar(&c.optionPrint)
	cmd.Action(svc.noRepositoryAction(c.run))
	c.out.setup(svc)
}

func (c *commandBenchmarkCompression) run(ctx context.Context) error {
	type benchResult struct {
		compression    compression.Name
		throughput     float64
		compressedSize int64
	}

	var results []benchResult

	data, err := ioutil.ReadFile(c.dataFile)
	if err != nil {
		return errors.Wrap(err, "error reading compression data file")
	}

	if len(data) == 0 {
		return errors.Errorf("empty data file")
	}

	log(ctx).Infof("Compressing input file %q (%v) using all compression methods.", c.dataFile, units.BytesStringBase2(int64(len(data))))

	repeatCount := c.repeat

	if repeatCount == 0 {
		repeatCount = defaultCompressedDataByMethod / len(data)

		if repeatCount == 0 {
			repeatCount = 1
		}
	}

	log(ctx).Infof("Repeating %v times per compression method (total %v). Override with --repeat=N.", repeatCount, units.BytesStringBase2(int64(repeatCount*len(data))))

	for name, comp := range compression.ByName {
		log(ctx).Infof("Benchmarking compressor '%v'...", name)

		tt := timetrack.Start()
		cnt := repeatCount

		var (
			compressedSize int64
			lastHash       uint64
			compressed     bytes.Buffer
		)

		input := bytes.NewReader(nil)

		for i := 0; i < cnt; i++ {
			compressed.Reset()
			input.Reset(data)

			if err := comp.Compress(&compressed, input); err != nil {
				log(ctx).Errorf("compression %q failed: %v", name, err)
				continue
			}

			compressedSize = int64(compressed.Len())

			if c.verifyStable {
				h := hashOf(compressed.Bytes())

				if i == 0 {
					lastHash = h
				} else if h != lastHash {
					log(ctx).Errorf("compression %q is not stable", name)
					continue
				}
			}
		}

		_, perSecond := tt.Completed(float64(len(data)) * float64(cnt))

		results = append(results, benchResult{compression: name, throughput: perSecond, compressedSize: compressedSize})
	}

	if c.bySize {
		sort.Slice(results, func(i, j int) bool {
			return results[i].compressedSize < results[j].compressedSize
		})
	} else {
		sort.Slice(results, func(i, j int) bool {
			return results[i].throughput > results[j].throughput
		})
	}

	c.out.printStdout("     %-30v %-15v %v\n", "Compression", "Compressed Size", "Throughput")
	c.out.printStdout("-----------------------------------------------------------------\n")

	for ndx, r := range results {
		c.out.printStdout("%3d. %-30v %-15v %v / second", ndx, r.compression, r.compressedSize, units.BytesStringBase2(int64(r.throughput)))

		if c.optionPrint {
			c.out.printStdout(", --compression=%s", r.compression)
		}

		c.out.printStdout("\n")
	}

	return nil
}

func hashOf(b []byte) uint64 {
	h := fnv.New64a()
	h.Write(b)

	return h.Sum64()
}
<commit_msg>cli: only read first 128 MiB of provided file for compression benchmark (#1317)<commit_after>package cli

import (
	"bytes"
	"context"
	"hash/fnv"
	"io"
	"os"
	"sort"

	"github.com/pkg/errors"

	"github.com/kopia/kopia/internal/timetrack"
	"github.com/kopia/kopia/internal/units"
	"github.com/kopia/kopia/repo/compression"
)

const defaultCompressedDataByMethod = 128 << 20 // 128 MB

type commandBenchmarkCompression struct {
	repeat       int
	dataFile     string
	bySize       bool
	verifyStable bool
	optionPrint  bool

	out textOutput
}

func (c *commandBenchmarkCompression) setup(svc appServices, parent commandParent) {
	cmd := parent.Command("compression", "Run compression benchmarks")
	cmd.Flag("repeat", "Number of repetitions").Default("0").IntVar(&c.repeat)
	cmd.Flag("data-file", "Use data from the given file").Required().ExistingFileVar(&c.dataFile)
	cmd.Flag("by-size", "Sort results by size").BoolVar(&c.bySize)
	cmd.Flag("verify-stable", "Verify that compression is stable").BoolVar(&c.verifyStable)
	cmd.Flag("print-options", "Print out options usable for repository creation").BoolVar(&c.optionPrint)
	cmd.Action(svc.noRepositoryAction(c.run))
	c.out.setup(svc)
}

func (c *commandBenchmarkCompression) readInputFile(ctx context.Context) ([]byte, error) {
	f, err := os.Open(c.dataFile)
	if err != nil {
		return nil, errors.Wrap(err, "error opening input file")
	}

	defer f.Close() // nolint:errcheck,gosec

	st, err := f.Stat()
	if err != nil {
		return nil, errors.Wrap(err, "stat error")
	}

	dataLength := st.Size()
	if dataLength > defaultCompressedDataByMethod {
		dataLength = defaultCompressedDataByMethod

		log(ctx).Infof("NOTICE: The provided input file is too big, using first %v.", units.BytesStringBase2(dataLength))
	}

	data := make([]byte, dataLength)

	if _, err := io.ReadFull(f, data); err != nil {
		return nil, errors.Wrap(err, "error reading file")
	}

	return data, nil
}

func (c *commandBenchmarkCompression) run(ctx context.Context) error {
	type benchResult struct {
		compression    compression.Name
		throughput     float64
		compressedSize int64
	}

	var results []benchResult

	data, err := c.readInputFile(ctx)
	if err != nil {
		return err
	}

	if len(data) == 0 {
		return errors.Errorf("empty data file")
	}

	log(ctx).Infof("Compressing input file %q (%v) using all compression methods.", c.dataFile, units.BytesStringBase2(int64(len(data))))

	repeatCount := c.repeat

	if repeatCount == 0 {
		repeatCount = defaultCompressedDataByMethod / len(data)

		if repeatCount == 0 {
			repeatCount = 1
		}
	}

	log(ctx).Infof("Repeating %v times per compression method (total %v). Override with --repeat=N.", repeatCount, units.BytesStringBase2(int64(repeatCount*len(data))))

	for name, comp := range compression.ByName {
		log(ctx).Infof("Benchmarking compressor '%v'...", name)

		tt := timetrack.Start()
		cnt := repeatCount

		var (
			compressedSize int64
			lastHash       uint64
			compressed     bytes.Buffer
		)

		input := bytes.NewReader(nil)

		for i := 0; i < cnt; i++ {
			compressed.Reset()
			input.Reset(data)

			if err := comp.Compress(&compressed, input); err != nil {
				log(ctx).Errorf("compression %q failed: %v", name, err)
				continue
			}

			compressedSize = int64(compressed.Len())

			if c.verifyStable {
				h := hashOf(compressed.Bytes())

				if i == 0 {
					lastHash = h
				} else if h != lastHash {
					log(ctx).Errorf("compression %q is not stable", name)
					continue
				}
			}
		}

		_, perSecond := tt.Completed(float64(len(data)) * float64(cnt))

		results = append(results, benchResult{compression: name, throughput: perSecond, compressedSize: compressedSize})
	}

	if c.bySize {
		sort.Slice(results, func(i, j int) bool {
			return results[i].compressedSize < results[j].compressedSize
		})
	} else {
		sort.Slice(results, func(i, j int) bool {
			return results[i].throughput > results[j].throughput
		})
	}

	c.out.printStdout("     %-30v %-15v %v\n", "Compression", "Compressed Size", "Throughput")
	c.out.printStdout("-----------------------------------------------------------------\n")

	for ndx, r := range results {
		c.out.printStdout("%3d. %-30v %-15v %v / second", ndx, r.compression, r.compressedSize, units.BytesStringBase2(int64(r.throughput)))

		if c.optionPrint {
			c.out.printStdout(", --compression=%s", r.compression)
		}

		c.out.printStdout("\n")
	}

	return nil
}

func hashOf(b []byte) uint64 {
	h := fnv.New64a()
	h.Write(b)

	return h.Sum64()
}
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

		// get the keyname
		key, ok := redis.RedisKeyIndex[params[0]]
		if !ok {
			c.Next()
			return
		}

		// set the key minus the base
		key.SetKey(params[1:]...)

		// check the cache
		result, err := key.Get()
		if result == nil {
			// go to the controller if it wasnt found
			c.Next()

			// Check if there was an error from the controller
			_, controllerError := c.Get("controllerError")
			if controllerError {
				c.Abort()
				return
			}

			// set the data returned from the controller
			err = key.Set(c.MustGet("data").([]byte))
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			return

		}
		if err != nil {
			c.Error(err)
			c.Abort()
			return
		}

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}
<commit_msg>shared mutex<commit_after>package middleware

import (
	"github.com/gin-gonic/gin"
	"strings"

	"github.com/eirka/eirka-libs/redis"
)

// Cache will check for the key in Redis and serve it. If not found, it will
// take the marshalled JSON from the controller and set it in Redis
func Cache() gin.HandlerFunc {
	return func(c *gin.Context) {

		// bool for analytics middleware
		c.Set("cached", false)

		// break cache if there is a query
		if c.Request.URL.RawQuery != "" {
			c.Next()
			return
		}

		// Trim leading / from path and split
		params := strings.Split(strings.Trim(c.Request.URL.Path, "/"), "/")

		// get the keyname
		key, ok := redis.RedisKeyIndex[params[0]]
		if !ok {
			c.Next()
			return
		}

		// set the key minus the base
		key.SetKey(params[1:]...)

		// check the cache
		result, err := key.Get()
		if result == nil {
			// go to the controller if it wasnt found
			c.Next()

			// Check if there was an error from the controller
			_, controllerError := c.Get("controllerError")
			if controllerError {
				c.Abort()
				return
			}

			// set the data returned from the controller
			err = key.Set(c.MustGet("data").([]byte))
			if err != nil {
				c.Error(err)
				c.Abort()
				return
			}

			// unlock shared mutex
			redis.RedisCache.Unlock()

			return

		}
		if err != nil {
			c.Error(err)
			c.Abort()
			return
		}

		// if we made it this far then the page was cached
		c.Set("cached", true)

		c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Write(result)
		c.Abort()
		return
	}

}
<|endoftext|>


<commit_before>package internet

import (
	"crypto/tls"
	"net"
)

type ConnectionHandler func(Connection)

type Reusable interface {
	Reusable() bool
	SetReusable(reuse bool)
}

type StreamConnectionType int

const (
	StreamConnectionTypeRawTCP StreamConnectionType = 1
	StreamConnectionTypeTCP    StreamConnectionType = 2
	StreamConnectionTypeKCP    StreamConnectionType = 4
)

type StreamSecurityType int

const (
	StreamSecurityTypeNone StreamSecurityType = 0
	StreamSecurityTypeTLS  StreamSecurityType = 1
)

type TLSSettings struct {
	AllowInsecure bool
	Certs         []tls.Certificate
}

func (this *TLSSettings) GetTLSConfig() *tls.Config {
	config := &tls.Config{
		InsecureSkipVerify: this.AllowInsecure,
	}

	config.Certificates = this.Certs
	config.BuildNameToCertificate()

	return config
}

type StreamSettings struct {
	Type        StreamConnectionType
	Security    StreamSecurityType
	TLSSettings *TLSSettings
}

func (this *StreamSettings) IsCapableOf(streamType StreamConnectionType) bool {
	return (this.Type & streamType) == streamType
}

type Connection interface {
	net.Conn
	Reusable
}

type SysFd interface {
	SysFd() (int, error)
}
<commit_msg>Add Websocket Stream type<commit_after>package internet

import (
	"crypto/tls"
	"net"
)

type ConnectionHandler func(Connection)

type Reusable interface {
	Reusable() bool
	SetReusable(reuse bool)
}

type StreamConnectionType int

const (
	StreamConnectionTypeRawTCP    StreamConnectionType = 1
	StreamConnectionTypeTCP       StreamConnectionType = 2
	StreamConnectionTypeKCP       StreamConnectionType = 4
	StreamConnectionTypeWebSocket StreamConnectionType = 8
)

type StreamSecurityType int

const (
	StreamSecurityTypeNone StreamSecurityType = 0
	StreamSecurityTypeTLS  StreamSecurityType = 1
)

type TLSSettings struct {
	AllowInsecure bool
	Certs         []tls.Certificate
}

func (this *TLSSettings) GetTLSConfig() *tls.Config {
	config := &tls.Config{
		InsecureSkipVerify: this.AllowInsecure,
	}

	config.Certificates = this.Certs
	config.BuildNameToCertificate()

	return config
}

type StreamSettings struct {
	Type        StreamConnectionType
	Security    StreamSecurityType
	TLSSettings *TLSSettings
}

func (this *StreamSettings) IsCapableOf(streamType StreamConnectionType) bool {
	return (this.Type & streamType) == streamType
}

type Connection interface {
	net.Conn
	Reusable
}

type SysFd interface {
	SysFd() (int, error)
}
<|endoftext|>


<commit_before>package obj

import (
	"reflect"

	"github.com/polydawn/go-xlate/obj2/atlas"
)

/*
	A lovely mechanism to stash marshalMachine objects pre-allocated and avoid mallocs.
	Works together with the Atlas: the Atlas says what kind of machinery is needed;
	the marshalSlab "allocates" it and returns it upon your request.
*/
type marshalSlab struct {
	atlas atlas.Atlas
	rows  []marshalSlabRow
}

type marshalSlabRow struct {
	//	ptrDerefDelegateMarshalMachine
	//	marshalMachineLiteral
	//	marshalMachineMapWildcard
	//	marshalMachineSliceWildcard
	//	marshalMachineWildcard
	//	marshalMachineStructAtlas
}

/*
	Return a reference to a machine from the slab.
	*You must release() when done.*

	Errors -- including "no info in Atlas for this type" -- are expressed by
	returning a machine that is a constantly-erroring thunk.
*/
func (slab *marshalSlab) requisitionMachine(forThis reflect.Type) MarshalMachine {
	return nil // TODO
}
<commit_msg>Implement the errThunk marshalmachine and return that when we can't find a machine.  (Currently, always in this package :) placeholders continue...)<commit_after>package obj

import (
	"fmt"
	"reflect"

	"github.com/polydawn/go-xlate/obj2/atlas"
	. "github.com/polydawn/go-xlate/tok"
)

/*
	A lovely mechanism to stash marshalMachine objects pre-allocated and avoid mallocs.
	Works together with the Atlas: the Atlas says what kind of machinery is needed;
	the marshalSlab "allocates" it and returns it upon your request.
*/
type marshalSlab struct {
	atlas atlas.Atlas
	rows  []marshalSlabRow
}

type marshalSlabRow struct {
	//	ptrDerefDelegateMarshalMachine
	//	marshalMachineLiteral
	//	marshalMachineMapWildcard
	//	marshalMachineSliceWildcard
	//	marshalMachineWildcard
	//	marshalMachineStructAtlas

	errThunkMarshalMachine
}

/*
	Return a reference to a machine from the slab.
	*You must release() when done.*

	Errors -- including "no info in Atlas for this type" -- are expressed by
	returning a machine that is a constantly-erroring thunk.
*/
func (slab *marshalSlab) requisitionMachine(forThis reflect.Type) MarshalMachine {
	off := len(slab.rows)
	slab.grow()
	row := &slab.rows[off]
	m := &row.errThunkMarshalMachine
	m.err = fmt.Errorf("no machine found")
	return m
}

func (s *marshalSlab) grow() {
	s.rows = append(s.rows, marshalSlabRow{})
}

func (s *marshalSlab) release() {
	s.rows = s.rows[0 : len(s.rows)-1]
}

type errThunkMarshalMachine struct {
	err error
}

func (m *errThunkMarshalMachine) Reset(_ *marshalSlab, _ reflect.Value, _ reflect.Type) error {
	return m.err
}
func (m *errThunkMarshalMachine) Step(d *MarshalDriver, s *marshalSlab, tok *Token) (done bool, err error) {
	return true, m.err
}
<|endoftext|>


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

package gobuild

import (
	"bufio";
	"exec";
	"fmt";
	"io";
	"go/ast";
	"go/parser";
	"os";
	"path";
	"sort";
	"strconv";
	"strings";
)

const (
	ShowErrors = 1<<iota;
	ForceDisplay;
)

var (
	theChar string;
	goarch string;
	goos string;
	bin = make(map[string] string);
)

var theChars = map[string] string {
	"amd64": "6",
	"386": "8",
	"arm": "5"
}

const ObjDir = "_obj"

func fatal(format string, args ...) {
	fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprintf(format, args));
	os.Exit(1);
}

func init() {
	goarch = os.Getenv("GOARCH");
	goos = os.Getenv("GOOS");

	var ok bool;
	theChar, ok = theChars[goarch];
	if !ok {
		fatal("unknown $GOARCH: %s", goarch);
	}

	var binaries = []string{
		theChar + "g",
		theChar + "c",
		theChar + "a",
		"gopack",
	};

	for i, v := range binaries {
		var s string;
		var err os.Error;
		if s, err = exec.LookPath(v); err != nil {
			fatal("cannot find binary %s", v);
		}
		bin[v] = s;
	}
}

func PushString(vp *[]string, p string) {
	v := *vp;
	n := len(v);
	if n >= cap(v) {
		m := 2*n + 10;
		a := make([]string, n, m);
		for i := range v {
			a[i] = v[i];
		}
		v = a;
	}
	v = v[0:n+1];
	v[n] = p;
	*vp = v;
}

func run(argv []string, flag int) (ok bool) {
	argv0 := bin[argv[0]];
	null, err := os.Open("/dev/null", os.O_RDWR, 0);
	if err != nil {
		fatal("open /dev/null: %s", err);
	}
	defer null.Close();
	r, w, err := os.Pipe();
	if err != nil {
		fatal("pipe: %s", err);
	}
	pid, err := os.ForkExec(argv0, argv, os.Environ(), "", []*os.File{null, w, w});
	defer r.Close();
	w.Close();
	if err != nil {
		fmt.Fprintln(os.Stderr, err);
		return false;
	}

	// Read the first line of output, if any.  Discard the rest.
	// If there is output and ShowErrors is set, show it,
	// preceded by a shell command line.
	// If ForceDisplay is set, we show the command even
	// if there's no output; this gets set if we're just trying
	// to keep the user informed.
	b := bufio.NewReader(r);
	line, err := b.ReadLineString('\n', true);
	if flag & ShowErrors != 0 && line != "" || flag & ForceDisplay != 0 {
		fmt.Fprint(os.Stderr, "$ ");
		for i, s := range argv {
			fmt.Fprint(os.Stderr, s, " ");
		}
		fmt.Fprint(os.Stderr, "\n");
		fmt.Fprint(os.Stderr, "  ", line);
		io.Copy(r, null);	// don't let process block on pipe
	}
	waitmsg, err := os.Wait(pid, 0);
	if err != nil {
		fmt.Fprintln(os.Stderr, err);
		return false;
	}
	return waitmsg.Exited() && waitmsg.ExitStatus() == 0;
}

func Build(cmd []string, file string, flag int) (ok bool) {
	var argv []string;
	for i, c := range cmd {
		PushString(&argv, c);
	}
	PushString(&argv, file);
	return run(argv, flag);
}

func Archive(pkg string, files []string) {
	argv := []string{ "gopack", "grc", pkg };
	for i, file := range files {
		PushString(&argv, file);
	}
	if !run(argv, ShowErrors) {
		fatal("archive failed");
	}
}

func Compiler(file string) []string {
	switch {
	case strings.HasSuffix(file, ".go"):
		return []string{ theChar + "g", "-I", ObjDir };
	case strings.HasSuffix(file, ".c"):
		return []string{ theChar + "c", "-FVw" };
	case strings.HasSuffix(file, ".s"):
		return []string{ theChar + "a" };
	}
	fatal("don't know how to compile %s", file);
	return nil;
}

func Object(file, suffix string) string {
	ext := path.Ext(file);
	return file[0:len(file)-len(ext)] + "." + suffix;
}

// Dollarstring returns s with literal goarch/goos values
// replaced by $lGOARCHr where l and r are the specified delimeters.
func dollarString(s, l, r string) string {
	out := "";
	j := 0;	// index of last byte in s copied to out.
	for i := 0; i < len(s); {
		switch {
		case i+len(goarch) <= len(s) && s[i:i+len(goarch)] == goarch:
			out += s[j:i];
			out += "$" + l + "GOARCH" + r;
			i += len(goarch);
			j = i;
		case i+len(goos) <= len(s) && s[i:i+len(goos)] == goos:
			out += s[j:i];
			out += "$" + l + "GOOS" + r;
			i += len(goos);
			j = i;
		default:
			i++;
		}
	}
	out += s[j:len(s)];
	return out;
}

// dollarString wrappers.
// Print ShellString(s) or MakeString(s) depending on
// the context in which the result will be interpreted.
type ShellString string;
func (s ShellString) String() string {
	return dollarString(string(s), "{", "}");
}

type MakeString string;
func (s MakeString) String() string {
	return dollarString(string(s), "(", ")");
}

// TODO(rsc): Should this be in the AST library?
func LitString(p []*ast.StringLit) (string, os.Error) {
	s := "";
	for i, lit := range p {
		t, err := strconv.Unquote(string(lit.Value));
		if err != nil {
			return "", err;
		}
		s += t;
	}
	return s, nil;
}

func PackageImports(file string) (pkg string, imports []string, err1 os.Error) {
	prog, err := parser.ParseFile(file, nil, parser.ImportsOnly);
	if err != nil {
		return "", nil, err;
	}

	// Normally one must consult the types of decl and spec,
	// but we told the parser to return imports only,
	// so assume it did.
	var imp []string;
	for _, decl := range prog.Decls {
		for _, spec := range decl.(*ast.GenDecl).Specs {
			str, err := LitString(spec.(*ast.ImportSpec).Path);
			if err != nil {
				return "", nil, os.NewError("invalid import specifier");	// better than os.EINVAL
			}
			PushString(&imp, str);
		}
	}

	// TODO(rsc): should be prog.Package.Value
	return prog.Name.Value, imp, nil;
}

func SourceFiles(dir string) ([]string, os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0);
	if err != nil {
		return nil, err;
	}
	names, err1 := f.Readdirnames(-1);
	f.Close();
	out := make([]string, 0, len(names));
	for i, name := range names {
		if strings.HasSuffix(name, ".go")
		|| strings.HasSuffix(name, ".c")
		|| strings.HasSuffix(name, ".s") {
			n := len(out);
			out = out[0:n+1];
			out[n] = name;
		}
	}
	sort.SortStrings(out);
	return out, nil;
}

// TODO(rsc): Implement these for real as
// os.MkdirAll and os.RemoveAll and then
// make these wrappers that call fatal on error.

func MkdirAll(name string) {
	p, err := exec.Run("/bin/mkdir", []string{"mkdir", "-p", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/mkdir: %v", err);
	}
	w, err1 := p.Wait(0);
	if err1 != nil {
		fatal("wait /bin/mkdir: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/mkdir: %v", w);
	}
}

func RemoveAll(name string) {
	p, err := exec.Run("/bin/rm", []string{"rm", "-rf", name}, os.Environ(), exec.DevNull, exec.PassThrough, exec.PassThrough);
	if err != nil {
		fatal("run /bin/rm: %v", err);
	}
	w, err := p.Wait(0);
	if err != nil {
		fatal("wait /bin/rm: %v", err);
	}
	if !w.Exited() || w.ExitStatus() != 0 {
		fatal("/bin/rm: %v", w);
	}

}

<commit_msg>this time really clean up a TODO<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gobuild

import (
	"bufio";
	"exec";
	"fmt";
	"io";
	"go/ast";
	"go/parser";
	"os";
	"path";
	"sort";
	"strconv";
	"strings";
)

const (
	ShowErrors = 1<<iota;
	ForceDisplay;
)

var (
	theChar string;
	goarch string;
	goos string;
	bin = make(map[string] string);
)

var theChars = map[string] string {
	"amd64": "6",
	"386": "8",
	"arm": "5"
}

const ObjDir = "_obj"

func fatal(format string, args ...) {
	fmt.Fprintf(os.Stderr, "gobuild: %s\n", fmt.Sprintf(format, args));
	os.Exit(1);
}

func init() {
	goarch = os.Getenv("GOARCH");
	goos = os.Getenv("GOOS");

	var ok bool;
	theChar, ok = theChars[goarch];
	if !ok {
		fatal("unknown $GOARCH: %s", goarch);
	}

	var binaries = []string{
		theChar + "g",
		theChar + "c",
		theChar + "a",
		"gopack",
	};

	for i, v := range binaries {
		var s string;
		var err os.Error;
		if s, err = exec.LookPath(v); err != nil {
			fatal("cannot find binary %s", v);
		}
		bin[v] = s;
	}
}

func PushString(vp *[]string, p string) {
	v := *vp;
	n := len(v);
	if n >= cap(v) {
		m := 2*n + 10;
		a := make([]string, n, m);
		for i := range v {
			a[i] = v[i];
		}
		v = a;
	}
	v = v[0:n+1];
	v[n] = p;
	*vp = v;
}

func run(argv []string, flag int) (ok bool) {
	argv0 := bin[argv[0]];
	null, err := os.Open("/dev/null", os.O_RDWR, 0);
	if err != nil {
		fatal("open /dev/null: %s", err);
	}
	defer null.Close();
	r, w, err := os.Pipe();
	if err != nil {
		fatal("pipe: %s", err);
	}
	pid, err := os.ForkExec(argv0, argv, os.Environ(), "", []*os.File{null, w, w});
	defer r.Close();
	w.Close();
	if err != nil {
		fmt.Fprintln(os.Stderr, err);
		return false;
	}

	// Read the first line of output, if any.  Discard the rest.
	// If there is output and ShowErrors is set, show it,
	// preceded by a shell command line.
	// If ForceDisplay is set, we show the command even
	// if there's no output; this gets set if we're just trying
	// to keep the user informed.
	b := bufio.NewReader(r);
	line, err := b.ReadLineString('\n', true);
	if flag & ShowErrors != 0 && line != "" || flag & ForceDisplay != 0 {
		fmt.Fprint(os.Stderr, "$ ");
		for i, s := range argv {
			fmt.Fprint(os.Stderr, s, " ");
		}
		fmt.Fprint(os.Stderr, "\n");
		fmt.Fprint(os.Stderr, "  ", line);
		io.Copy(r, null);	// don't let process block on pipe
	}
	waitmsg, err := os.Wait(pid, 0);
	if err != nil {
		fmt.Fprintln(os.Stderr, err);
		return false;
	}
	return waitmsg.Exited() && waitmsg.ExitStatus() == 0;
}

func Build(cmd []string, file string, flag int) (ok bool) {
	var argv []string;
	for i, c := range cmd {
		PushString(&argv, c);
	}
	PushString(&argv, file);
	return run(argv, flag);
}

func Archive(pkg string, files []string) {
	argv := []string{ "gopack", "grc", pkg };
	for i, file := range files {
		PushString(&argv, file);
	}
	if !run(argv, ShowErrors) {
		fatal("archive failed");
	}
}

func Compiler(file string) []string {
	switch {
	case strings.HasSuffix(file, ".go"):
		return []string{ theChar + "g", "-I", ObjDir };
	case strings.HasSuffix(file, ".c"):
		return []string{ theChar + "c", "-FVw" };
	case strings.HasSuffix(file, ".s"):
		return []string{ theChar + "a" };
	}
	fatal("don't know how to compile %s", file);
	return nil;
}

func Object(file, suffix string) string {
	ext := path.Ext(file);
	return file[0:len(file)-len(ext)] + "." + suffix;
}

// Dollarstring returns s with literal goarch/goos values
// replaced by $lGOARCHr where l and r are the specified delimeters.
func dollarString(s, l, r string) string {
	out := "";
	j := 0;	// index of last byte in s copied to out.
	for i := 0; i < len(s); {
		switch {
		case i+len(goarch) <= len(s) && s[i:i+len(goarch)] == goarch:
			out += s[j:i];
			out += "$" + l + "GOARCH" + r;
			i += len(goarch);
			j = i;
		case i+len(goos) <= len(s) && s[i:i+len(goos)] == goos:
			out += s[j:i];
			out += "$" + l + "GOOS" + r;
			i += len(goos);
			j = i;
		default:
			i++;
		}
	}
	out += s[j:len(s)];
	return out;
}

// dollarString wrappers.
// Print ShellString(s) or MakeString(s) depending on
// the context in which the result will be interpreted.
type ShellString string;
func (s ShellString) String() string {
	return dollarString(string(s), "{", "}");
}

type MakeString string;
func (s MakeString) String() string {
	return dollarString(string(s), "(", ")");
}

// TODO(rsc): Should this be in the AST library?
func LitString(p []*ast.StringLit) (string, os.Error) {
	s := "";
	for i, lit := range p {
		t, err := strconv.Unquote(string(lit.Value));
		if err != nil {
			return "", err;
		}
		s += t;
	}
	return s, nil;
}

func PackageImports(file string) (pkg string, imports []string, err1 os.Error) {
	prog, err := parser.ParseFile(file, nil, parser.ImportsOnly);
	if err != nil {
		return "", nil, err;
	}

	// Normally one must consult the types of decl and spec,
	// but we told the parser to return imports only,
	// so assume it did.
	var imp []string;
	for _, decl := range prog.Decls {
		for _, spec := range decl.(*ast.GenDecl).Specs {
			str, err := LitString(spec.(*ast.ImportSpec).Path);
			if err != nil {
				return "", nil, os.NewError("invalid import specifier");	// better than os.EINVAL
			}
			PushString(&imp, str);
		}
	}

	// TODO(rsc): should be prog.Package.Value
	return prog.Name.Value, imp, nil;
}

func SourceFiles(dir string) ([]string, os.Error) {
	f, err := os.Open(dir, os.O_RDONLY, 0);
	if err != nil {
		return nil, err;
	}
	names, err1 := f.Readdirnames(-1);
	f.Close();
	out := make([]string, 0, len(names));
	for i, name := range names {
		if strings.HasSuffix(name, ".go")
		|| strings.HasSuffix(name, ".c")
		|| strings.HasSuffix(name, ".s") {
			n := len(out);
			out = out[0:n+1];
			out[n] = name;
		}
	}
	sort.SortStrings(out);
	return out, nil;
}

func MkdirAll(name string) {
	err := path.MkdirAll(name);
	if err != nil {
		fatal("MkdirAll: %v", err);
	}
}

func RemoveAll(name string) {
	err := path.RemoveAll(name);
	if err != nil {
		fatal("RemoveAll: %v", err);
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
	"time"

	"github.com/codeskyblue/go-sh"
	"github.com/pkg/errors"
)

func containerExists(dockerHost string, image string) (bool, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("set -e; docker ps --format '{{.Names}}' -a| awk '$1 ~ /%s$/ {print $1}'", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return false, errors.Wrapf(err, "container lookup on %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return false, nil
	}

	return true, nil
}

func containerIsRunning(dockerHost string, image string) (bool, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("set -e; docker ps --format '{{.Names}}'| awk '$1 ~ /%s$/ {print $1}'", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return false, errors.Wrapf(err, "container lookup on %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return false, nil
	}

	return true, nil
}

func containerRename(dockerHost string, name string, newName string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("docker rename %s %s", name, newName)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker rename %s %s failed %s", name, newName, output)
	}
	return nil
}

func containerStop(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("docker stop %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker stop %s failed %s", name, output)
	}
	return nil
}

func containerStart(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("docker start %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker start %s failed %s", name, output)
	}
	return nil
}

func containerRemove(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("docker rm -f %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker rm -f %s failed %s", name, output)
	}
	return nil
}

func imageGetTag(dockerHost string, image string) (string, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	cmd := fmt.Sprintf("set -e; docker ps --format '{{.Image}}' -a| awk '$1 ~ /%s/ {print $1}'| awk -F: '{print $NF}'| head -n1", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return "", errors.Wrapf(err, "acquiring image tag from %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return "", errors.Errorf("no image tag found on %s for %s", dockerHost, image)
	}
	tag := strings.TrimSpace(fmt.Sprintf("%s", output))
	return tag, nil
}

func imagePurge(dockerHost string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	output, err := session.Command("/bin/sh", "-c", "docker image prune -af").CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker image prune -af %s", output)
	}
	return nil
}

func imagePull(dockerHost string, dir string, image string, tag string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	session.SetDir(dir)
	ver := "VER_" + strings.ToUpper(strings.Replace(image, "-", "_", -1))
	session.SetEnv(ver, tag)
	cmd := fmt.Sprintf("docker-compose pull %s", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker-compose pull %s failed %s", image, output)
	}
	return nil
}

func containerCreate(dockerHost string, dir string, image string, tag string, ticket string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("HTTP_PROXY", "")
	session.SetEnv("HTTPS_PROXY", "")
	session.SetEnv("TICKET", ticket)
	ver := "VER_" + strings.ToUpper(strings.Replace(image, "-", "_", -1))
	session.SetEnv(ver, tag)
	session.SetDir(dir)
	id := fmt.Sprintf("%d", time.Now().UnixNano())
	cmd := fmt.Sprintf("docker-compose -p %s create --force-recreate %s", id, image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker-compose -p %s create --force-recreate %s failed %s", id, image, output)
	}
	return nil
}
<commit_msg>ignore the http proxy for docker commands<commit_after>package main

import (
	"fmt"
	"strings"
	"time"

	"github.com/codeskyblue/go-sh"
	"github.com/pkg/errors"
)

func containerExists(dockerHost string, image string) (bool, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("set -e; http_proxy='' https_proxy='' docker ps --format '{{.Names}}' -a| awk '$1 ~ /%s$/ {print $1}'", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return false, errors.Wrapf(err, "container lookup on %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return false, nil
	}

	return true, nil
}

func containerIsRunning(dockerHost string, image string) (bool, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("set -e; http_proxy='' https_proxy='' docker ps --format '{{.Names}}'| awk '$1 ~ /%s$/ {print $1}'", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return false, errors.Wrapf(err, "container lookup on %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return false, nil
	}

	return true, nil
}

func containerRename(dockerHost string, name string, newName string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker rename %s %s", name, newName)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker rename %s %s failed %s", name, newName, output)
	}
	return nil
}

func containerStop(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker stop %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker stop %s failed %s", name, output)
	}
	return nil
}

func containerStart(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker start %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker start %s failed %s", name, output)
	}
	return nil
}

func containerRemove(dockerHost string, name string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker rm -f %s", name)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker rm -f %s failed %s", name, output)
	}
	return nil
}

func imageGetTag(dockerHost string, image string) (string, error) {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	cmd := fmt.Sprintf("set -e; http_proxy='' https_proxy='' docker ps --format '{{.Image}}' -a| awk '$1 ~ /%s/ {print $1}'| awk -F: '{print $NF}'| head -n1", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return "", errors.Wrapf(err, "acquiring image tag from %s for %s failed %s", dockerHost, image, output)
	}
	if len(output) < 1 {
		return "", errors.Errorf("no image tag found on %s for %s", dockerHost, image)
	}
	tag := strings.TrimSpace(fmt.Sprintf("%s", output))
	return tag, nil
}

func imagePurge(dockerHost string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	output, err := session.Command("/bin/sh", "-c", "docker image prune -af").CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "http_proxy='' https_proxy='' docker image prune -af %s", output)
	}
	return nil
}

func imagePull(dockerHost string, dir string, image string, tag string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetDir(dir)
	ver := "VER_" + strings.ToUpper(strings.Replace(image, "-", "_", -1))
	session.SetEnv(ver, tag)
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker-compose pull %s", image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker-compose pull %s failed %s", image, output)
	}
	return nil
}

func containerCreate(dockerHost string, dir string, image string, tag string, ticket string) error {
	session := sh.NewSession()
	session.SetEnv("DOCKER_HOST", dockerHost)
	session.SetEnv("TICKET", ticket)
	ver := "VER_" + strings.ToUpper(strings.Replace(image, "-", "_", -1))
	session.SetEnv(ver, tag)
	session.SetDir(dir)
	id := fmt.Sprintf("%d", time.Now().UnixNano())
	cmd := fmt.Sprintf("http_proxy='' https_proxy='' docker-compose -p %s create --force-recreate %s", id, image)
	output, err := session.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		return errors.Wrapf(err, "docker-compose -p %s create --force-recreate %s failed %s", id, image, output)
	}
	return nil
}
<|endoftext|>


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

package maps

import (
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/context"
)

var directionsAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/directions/json",
	acceptsClientID: true,
}

// Directions issues the Directions request and retrieves the Response
func (c *Client) Directions(ctx context.Context, r *DirectionsRequest) ([]Route, []GeocodedWaypoint, error) {
	if r.Origin == "" {
		return nil, nil, errors.New("maps: origin missing")
	}
	if r.Destination == "" {
		return nil, nil, errors.New("maps: destination missing")
	}
	if r.Mode != "" && TravelModeDriving != r.Mode && TravelModeWalking != r.Mode && TravelModeBicycling != r.Mode && TravelModeTransit != r.Mode {
		return nil, nil, fmt.Errorf("maps: unknown Mode: '%s'", r.Mode)
	}
	if r.DepartureTime != "" && r.ArrivalTime != "" {
		return nil, nil, errors.New("maps: DepartureTime and ArrivalTime both specified")
	}
	if len(r.TransitMode) != 0 && r.Mode != TravelModeTransit {
		return nil, nil, errors.New("maps: TransitMode specified while Mode != TravelModeTransit")
	}
	if r.TransitRoutingPreference != "" && r.Mode != TravelModeTransit {
		return nil, nil, errors.New("maps: mode of transit '" + string(r.Mode) + "' invalid for TransitRoutingPreference")
	}

	var response struct {
		Routes            []Route            `json:"routes"`
		GeocodedWaypoints []GeocodedWaypoint `json:"geocoded_waypoints"`
		commonResponse
	}

	if err := c.getJSON(ctx, directionsAPI, r, &response); err != nil {
		return nil, nil, err
	}

	if err := response.StatusError(); err != nil {
		return nil, nil, err
	}

	return response.Routes, response.GeocodedWaypoints, nil
}

func (r *DirectionsRequest) params() url.Values {
	q := make(url.Values)
	q.Set("origin", r.Origin)
	q.Set("destination", r.Destination)
	if r.Mode != "" {
		q.Set("mode", string(r.Mode))
	}
	if r.DepartureTime != "" {
		q.Set("departure_time", r.DepartureTime)
	}
	if r.ArrivalTime != "" {
		q.Set("arrival_time", r.ArrivalTime)
	}
	if len(r.Waypoints) != 0 {
		q.Set("waypoints", strings.Join(r.Waypoints, "|"))
	}
	if r.Alternatives {
		q.Set("alternatives", "true")
	}
	if len(r.Avoid) > 0 {
		var avoid []string
		for _, a := range r.Avoid {
			avoid = append(avoid, string(a))
		}
		q.Set("avoid", strings.Join(avoid, "|"))
	}
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	if r.Units != "" {
		q.Set("units", string(r.Units))
	}
	if r.Region != "" {
		q.Set("region", r.Region)
	}
	if len(r.TransitMode) != 0 {
		var transitMode []string
		for _, t := range r.TransitMode {
			transitMode = append(transitMode, string(t))
		}
		q.Set("transit_mode", strings.Join(transitMode, "|"))
	}
	if r.TransitRoutingPreference != "" {
		q.Set("transit_routing_preference", string(r.TransitRoutingPreference))
	}
	if r.TrafficModel != "" {
		q.Set("traffic_model", string(r.TrafficModel))
	}
	return q
}

// DirectionsRequest is the functional options struct for directions.Get
type DirectionsRequest struct {
	// Origin is the address or textual latitude/longitude value from which you wish to calculate directions. Required.
	Origin string
	// Destination is the address or textual latitude/longitude value from which you wish to calculate directions. Required.
	Destination string
	// Mode specifies the mode of transport to use when calculating directions. Optional.
	Mode Mode
	// DepartureTime specifies the desired time of departure. You can specify the time as an integer in seconds since midnight, January 1, 1970 UTC. Alternatively, you can specify a value of `"now"`. Optional.
	DepartureTime string
	// ArrivalTime specifies the desired time of arrival for transit directions, in seconds since midnight, January 1, 1970 UTC. Optional. You cannot specify both `DepartureTime` and `ArrivalTime`.
	ArrivalTime string
	// Waypoints specifies an array of points to add to a route. Optional.
	Waypoints []string
	// Alternatives specifies if Directions service may provide more than one route alternative in the response. Optional.
	Alternatives bool
	// Avoid indicates that the calculated route(s) should avoid the indicated features. Optional.
	Avoid []Avoid
	// Language specifies the language in which to return results. Optional.
	Language string
	// Units specifies the unit system to use when displaying results. Optional.
	Units Units
	// Region specifies the region code, specified as a ccTLD two-character value. Optional.
	Region string
	// TransitMode specifies one or more preferred modes of transit. This parameter may only be specified for transit directions. Optional.
	TransitMode []TransitMode
	// TransitRoutingPreference specifies preferences for transit routes. Optional.
	TransitRoutingPreference TransitRoutingPreference
	//TrafficModel specifies traffic prediction model when requesting future directions. Optional.
	TrafficModel TrafficModel
}

// GeocodedWaypoint represents the geocoded point for origin, supplied waypoints, or destination for a requested direction request.
type GeocodedWaypoint struct {
	// GeocoderStatus indicates the status code resulting from the geocoding operation. This field may contain the following values.
	GeocoderStatus string `json:"geocoder_status"`
	// partial_match indicates that the geocoder did not return an exact match for the original request, though it was able to match part of the requested address.
	PartialMatch bool `json:"partial_match"`
	// PlaceID is a unique identifier that can be used with other Google APIs.
	PlaceID string `json:"place_id"`
	// Types indicates the address type of the geocoding result used for calculating directions.
	Types []string `json:"types"`
}

// Route represents a single route between an origin and a destination.
type Route struct {
	// Summary contains a short textual description for the route, suitable for
	// naming and disambiguating the route from alternatives.
	Summary string `json:"summary"`

	// Legs contains information about a leg of the route, between two locations within the
	// given route. A separate leg will be present for each waypoint or destination specified.
	// (A route with no waypoints will contain exactly one leg within the legs array.)
	Legs []*Leg `json:"legs"`

	// WaypointOrder contains an array indicating the order of any waypoints in the calculated route.
	WaypointOrder []int `json:"waypoint_order"`

	// OverviewPolyline contains an approximate (smoothed) path of the resulting directions.
	OverviewPolyline Polyline `json:"overview_polyline"`

	// Bounds contains the viewport bounding box of the overview polyline.
	Bounds LatLngBounds `json:"bounds"`

	// Copyrights contains the copyrights text to be displayed for this route. You must handle
	// and display this information yourself.
	Copyrights string `json:"copyrights"`

	// Warnings contains an array of warnings to be displayed when showing these directions.
	// You must handle and display these warnings yourself.
	Warnings []string `json:"warnings"`
}

// Leg represents a single leg of a route.
type Leg struct {
	// Steps contains an array of steps denoting information about each separate step of the
	// leg of the journey.
	Steps []*Step `json:"steps"`

	// Distance indicates the total distance covered by this leg.
	Distance `json:"distance"`

	// Duration indicates total time required for this leg.
	Duration time.Duration `json:"duration"`

	// DurationInTraffic indicates the total duration of this leg. This value is an estimate of the time in traffic based on current and historical traffic conditions.
	DurationInTraffic time.Duration `json:"duration_in_traffic"`

	// ArrivalTime contains the estimated time of arrival for this leg. This property is only
	// returned for transit directions.
	ArrivalTime time.Time `json:"arrival_time"`

	// DepartureTime contains the estimated time of departure for this leg. This property is
	// only returned for transit directions.
	DepartureTime time.Time `json:"departure_time"`

	// StartLocation contains the latitude/longitude coordinates of the origin of this leg.
	StartLocation LatLng `json:"start_location"`

	// EndLocation contains the latitude/longitude coordinates of the destination of this leg.
	EndLocation LatLng `json:"end_location"`

	// StartAddress contains the human-readable address (typically a street address)
	// reflecting the start location of this leg.
	StartAddress string `json:"start_address"`

	// EndAddress contains the human-readable address (typically a street address)
	// reflecting the end location of this leg.
	EndAddress string `json:"end_address"`
}

// Step represents a single step of a leg.
type Step struct {
	// HTMLInstructions contains formatted instructions for this step, presented as an HTML text string.
	HTMLInstructions string `json:"html_instructions"`

	// Distance contains the distance covered by this step until the next step.
	Distance `json:"distance"`

	// Duration contains the typical time required to perform the step, until the next step.
	time.Duration `json:"duration"`

	// StartLocation contains the location of the starting point of this step, as a single set of lat
	// and lng fields.
	StartLocation LatLng `json:"start_location"`

	// EndLocation contains the location of the last point of this step, as a single set of lat and
	// lng fields.
	EndLocation LatLng `json:"end_location"`

	// Polyline contains a single points object that holds an encoded polyline representation of the
	// step. This polyline is an approximate (smoothed) path of the step.
	Polyline `json:"polyline"`

	// Steps contains detailed directions for walking or driving steps in transit directions. Substeps
	// are only available when travel_mode is set to "transit". The inner steps array is of the same
	// type as steps.
	Steps []*Step `json:"steps"`

	// TransitDetails contains transit specific information. This field is only returned with travel
	// mode is set to "transit".
	TransitDetails *TransitDetails `json:"transit_details"`

	// TravelMode indicates the travel mode of this step.
	TravelMode string `json:"travel_mode"`
}

// TransitDetails contains additional information about the transit stop, transit line and transit agency.
type TransitDetails struct {
	// ArrivalStop contains information about the stop/station for this part of the trip.
	ArrivalStop TransitStop `json:"arrival_stop"`
	// DepartureStop contains information about the stop/station for this part of the trip.
	DepartureStop TransitStop `json:"departure_stop"`
	// ArrivalTime contains the arrival time for this leg of the journey
	ArrivalTime time.Time `json:"arrival_time"`
	// DepartureTime contains the departure time for this leg of the journey
	DepartureTime time.Time `json:"departure_time"`
	// Headsign specifies the direction in which to travel on this line, as it is marked on the vehicle or at the departure stop.
	Headsign string `json:"headsign"`
	// Headway specifies the expected number of seconds between departures from the same stop at this time
	Headway time.Duration `json:"headway"`
	// NumStops contains the number of stops in this step, counting the arrival stop, but not the departure stop
	NumStops uint `json:"num_stops"`
	// Line contains information about the transit line used in this step
	Line TransitLine `json:"line"`
}

// TransitStop contains information about the stop/station for this part of the trip.
type TransitStop struct {
	// Location of the transit station/stop.
	Location LatLng `json:"location"`
	// Name of the transit station/stop. eg. "Union Square".
	Name string `json:"name"`
}

// TransitLine contains information about the transit line used in this step
type TransitLine struct {
	// Name contains the full name of this transit line. eg. "7 Avenue Express".
	Name string `json:"name"`
	// ShortName contains the short name of this transit line.
	ShortName string `json:"short_name"`
	// Color contains the color commonly used in signage for this transit line.
	Color string `json:"color"`
	// Agencies contains information about the operator of the line
	Agencies []*TransitAgency `json:"agencies"`
	// URL contains the URL for this transit line as provided by the transit agency
	URL *url.URL `json:"url"`
	// Icon contains the URL for the icon associated with this line
	Icon *url.URL `json:"icon"`
	// TextColor contains the color of text commonly used for signage of this line
	TextColor string `json:"text_color"`
	// Vehicle contains the type of vehicle used on this line
	Vehicle TransitLineVehicle `json:"vehicle"`
}

// TransitAgency contains information about the operator of the line
type TransitAgency struct {
	// Name contains the name of the transit agency
	Name string `json:"name"`
	// URL contains the URL for the transit agency
	URL *url.URL `json:"url"`
	// Phone contains the phone number of the transit agency
	Phone string `json:"phone"`
}

// TransitLineVehicle contains the type of vehicle used on this line
type TransitLineVehicle struct {
	// Name contains the name of the vehicle on this line
	Name string `json:"name"`
	// Type contains the type of vehicle that runs on this line
	Type string `json:"type"`
	// Icon contains the URL for an icon associated with this vehicle type
	Icon *url.URL `json:"icon"`
}
<commit_msg>Doc updates<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package maps

import (
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"golang.org/x/net/context"
)

var directionsAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/directions/json",
	acceptsClientID: true,
}

// Directions issues the Directions request and retrieves the Response
func (c *Client) Directions(ctx context.Context, r *DirectionsRequest) ([]Route, []GeocodedWaypoint, error) {
	if r.Origin == "" {
		return nil, nil, errors.New("maps: origin missing")
	}
	if r.Destination == "" {
		return nil, nil, errors.New("maps: destination missing")
	}
	if r.Mode != "" && TravelModeDriving != r.Mode && TravelModeWalking != r.Mode && TravelModeBicycling != r.Mode && TravelModeTransit != r.Mode {
		return nil, nil, fmt.Errorf("maps: unknown Mode: '%s'", r.Mode)
	}
	if r.DepartureTime != "" && r.ArrivalTime != "" {
		return nil, nil, errors.New("maps: DepartureTime and ArrivalTime both specified")
	}
	if len(r.TransitMode) != 0 && r.Mode != TravelModeTransit {
		return nil, nil, errors.New("maps: TransitMode specified while Mode != TravelModeTransit")
	}
	if r.TransitRoutingPreference != "" && r.Mode != TravelModeTransit {
		return nil, nil, errors.New("maps: mode of transit '" + string(r.Mode) + "' invalid for TransitRoutingPreference")
	}

	var response struct {
		Routes            []Route            `json:"routes"`
		GeocodedWaypoints []GeocodedWaypoint `json:"geocoded_waypoints"`
		commonResponse
	}

	if err := c.getJSON(ctx, directionsAPI, r, &response); err != nil {
		return nil, nil, err
	}

	if err := response.StatusError(); err != nil {
		return nil, nil, err
	}

	return response.Routes, response.GeocodedWaypoints, nil
}

func (r *DirectionsRequest) params() url.Values {
	q := make(url.Values)
	q.Set("origin", r.Origin)
	q.Set("destination", r.Destination)
	if r.Mode != "" {
		q.Set("mode", string(r.Mode))
	}
	if r.DepartureTime != "" {
		q.Set("departure_time", r.DepartureTime)
	}
	if r.ArrivalTime != "" {
		q.Set("arrival_time", r.ArrivalTime)
	}
	if len(r.Waypoints) != 0 {
		q.Set("waypoints", strings.Join(r.Waypoints, "|"))
	}
	if r.Alternatives {
		q.Set("alternatives", "true")
	}
	if len(r.Avoid) > 0 {
		var avoid []string
		for _, a := range r.Avoid {
			avoid = append(avoid, string(a))
		}
		q.Set("avoid", strings.Join(avoid, "|"))
	}
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	if r.Units != "" {
		q.Set("units", string(r.Units))
	}
	if r.Region != "" {
		q.Set("region", r.Region)
	}
	if len(r.TransitMode) != 0 {
		var transitMode []string
		for _, t := range r.TransitMode {
			transitMode = append(transitMode, string(t))
		}
		q.Set("transit_mode", strings.Join(transitMode, "|"))
	}
	if r.TransitRoutingPreference != "" {
		q.Set("transit_routing_preference", string(r.TransitRoutingPreference))
	}
	if r.TrafficModel != "" {
		q.Set("traffic_model", string(r.TrafficModel))
	}
	return q
}

// DirectionsRequest is the functional options struct for directions.Get
type DirectionsRequest struct {
	// Origin is the address or textual latitude/longitude value from which you wish to calculate directions. Required.
	Origin string
	// Destination is the address or textual latitude/longitude value from which you wish to calculate directions. Required.
	Destination string
	// Mode specifies the mode of transport to use when calculating directions. Optional.
	Mode Mode
	// DepartureTime specifies the desired time of departure. You can specify the time as an integer in seconds since midnight, January 1, 1970 UTC. Alternatively, you can specify a value of `"now"`. Optional.
	DepartureTime string
	// ArrivalTime specifies the desired time of arrival for transit directions, in seconds since midnight, January 1, 1970 UTC. Optional. You cannot specify both `DepartureTime` and `ArrivalTime`.
	ArrivalTime string
	// Waypoints specifies an array of points to add to a route. Optional.
	Waypoints []string
	// Alternatives specifies if Directions service may provide more than one route alternative in the response. Optional.
	Alternatives bool
	// Avoid indicates that the calculated route(s) should avoid the indicated features. Optional.
	Avoid []Avoid
	// Language specifies the language in which to return results. Optional.
	Language string
	// Units specifies the unit system to use when displaying results. Optional.
	Units Units
	// Region specifies the region code, specified as a ccTLD two-character value. Optional.
	Region string
	// TransitMode specifies one or more preferred modes of transit. This parameter may only be specified for transit directions. Optional.
	TransitMode []TransitMode
	// TransitRoutingPreference specifies preferences for transit routes. Optional.
	TransitRoutingPreference TransitRoutingPreference
	// TrafficModel specifies traffic prediction model when requesting future directions. Optional.
	TrafficModel TrafficModel
}

// GeocodedWaypoint represents the geocoded point for origin, supplied waypoints, or destination for a requested direction request.
type GeocodedWaypoint struct {
	// GeocoderStatus indicates the status code resulting from the geocoding operation. This field may contain the following values.
	GeocoderStatus string `json:"geocoder_status"`
	// PartialMatch indicates that the geocoder did not return an exact match for the original request, though it was able to match part of the requested address.
	PartialMatch bool `json:"partial_match"`
	// PlaceID is a unique identifier that can be used with other Google APIs.
	PlaceID string `json:"place_id"`
	// Types indicates the address type of the geocoding result used for calculating directions.
	Types []string `json:"types"`
}

// Route represents a single route between an origin and a destination.
type Route struct {
	// Summary contains a short textual description for the route, suitable for
	// naming and disambiguating the route from alternatives.
	Summary string `json:"summary"`

	// Legs contains information about a leg of the route, between two locations within the
	// given route. A separate leg will be present for each waypoint or destination specified.
	// (A route with no waypoints will contain exactly one leg within the legs array.)
	Legs []*Leg `json:"legs"`

	// WaypointOrder contains an array indicating the order of any waypoints in the calculated route.
	WaypointOrder []int `json:"waypoint_order"`

	// OverviewPolyline contains an approximate (smoothed) path of the resulting directions.
	OverviewPolyline Polyline `json:"overview_polyline"`

	// Bounds contains the viewport bounding box of the overview polyline.
	Bounds LatLngBounds `json:"bounds"`

	// Copyrights contains the copyrights text to be displayed for this route. You must handle
	// and display this information yourself.
	Copyrights string `json:"copyrights"`

	// Warnings contains an array of warnings to be displayed when showing these directions.
	// You must handle and display these warnings yourself.
	Warnings []string `json:"warnings"`
}

// Leg represents a single leg of a route.
type Leg struct {
	// Steps contains an array of steps denoting information about each separate step of the
	// leg of the journey.
	Steps []*Step `json:"steps"`

	// Distance indicates the total distance covered by this leg.
	Distance `json:"distance"`

	// Duration indicates total time required for this leg.
	Duration time.Duration `json:"duration"`

	// DurationInTraffic indicates the total duration of this leg. This value is an estimate of the time in traffic based on current and historical traffic conditions.
	DurationInTraffic time.Duration `json:"duration_in_traffic"`

	// ArrivalTime contains the estimated time of arrival for this leg. This property is only
	// returned for transit directions.
	ArrivalTime time.Time `json:"arrival_time"`

	// DepartureTime contains the estimated time of departure for this leg. This property is
	// only returned for transit directions.
	DepartureTime time.Time `json:"departure_time"`

	// StartLocation contains the latitude/longitude coordinates of the origin of this leg.
	StartLocation LatLng `json:"start_location"`

	// EndLocation contains the latitude/longitude coordinates of the destination of this leg.
	EndLocation LatLng `json:"end_location"`

	// StartAddress contains the human-readable address (typically a street address)
	// reflecting the start location of this leg.
	StartAddress string `json:"start_address"`

	// EndAddress contains the human-readable address (typically a street address)
	// reflecting the end location of this leg.
	EndAddress string `json:"end_address"`
}

// Step represents a single step of a leg.
type Step struct {
	// HTMLInstructions contains formatted instructions for this step, presented as an HTML text string.
	HTMLInstructions string `json:"html_instructions"`

	// Distance contains the distance covered by this step until the next step.
	Distance `json:"distance"`

	// Duration contains the typical time required to perform the step, until the next step.
	time.Duration `json:"duration"`

	// StartLocation contains the location of the starting point of this step, as a single set of lat
	// and lng fields.
	StartLocation LatLng `json:"start_location"`

	// EndLocation contains the location of the last point of this step, as a single set of lat and
	// lng fields.
	EndLocation LatLng `json:"end_location"`

	// Polyline contains a single points object that holds an encoded polyline representation of the
	// step. This polyline is an approximate (smoothed) path of the step.
	Polyline `json:"polyline"`

	// Steps contains detailed directions for walking or driving steps in transit directions. Substeps
	// are only available when travel_mode is set to "transit". The inner steps array is of the same
	// type as steps.
	Steps []*Step `json:"steps"`

	// TransitDetails contains transit specific information. This field is only returned with travel
	// mode is set to "transit".
	TransitDetails *TransitDetails `json:"transit_details"`

	// TravelMode indicates the travel mode of this step.
	TravelMode string `json:"travel_mode"`
}

// TransitDetails contains additional information about the transit stop, transit line and transit agency.
type TransitDetails struct {
	// ArrivalStop contains information about the stop/station for this part of the trip.
	ArrivalStop TransitStop `json:"arrival_stop"`
	// DepartureStop contains information about the stop/station for this part of the trip.
	DepartureStop TransitStop `json:"departure_stop"`
	// ArrivalTime contains the arrival time for this leg of the journey
	ArrivalTime time.Time `json:"arrival_time"`
	// DepartureTime contains the departure time for this leg of the journey
	DepartureTime time.Time `json:"departure_time"`
	// Headsign specifies the direction in which to travel on this line, as it is marked on the vehicle or at the departure stop.
	Headsign string `json:"headsign"`
	// Headway specifies the expected number of seconds between departures from the same stop at this time
	Headway time.Duration `json:"headway"`
	// NumStops contains the number of stops in this step, counting the arrival stop, but not the departure stop
	NumStops uint `json:"num_stops"`
	// Line contains information about the transit line used in this step
	Line TransitLine `json:"line"`
}

// TransitStop contains information about the stop/station for this part of the trip.
type TransitStop struct {
	// Location of the transit station/stop.
	Location LatLng `json:"location"`
	// Name of the transit station/stop. eg. "Union Square".
	Name string `json:"name"`
}

// TransitLine contains information about the transit line used in this step
type TransitLine struct {
	// Name contains the full name of this transit line. eg. "7 Avenue Express".
	Name string `json:"name"`
	// ShortName contains the short name of this transit line.
	ShortName string `json:"short_name"`
	// Color contains the color commonly used in signage for this transit line.
	Color string `json:"color"`
	// Agencies contains information about the operator of the line
	Agencies []*TransitAgency `json:"agencies"`
	// URL contains the URL for this transit line as provided by the transit agency
	URL *url.URL `json:"url"`
	// Icon contains the URL for the icon associated with this line
	Icon *url.URL `json:"icon"`
	// TextColor contains the color of text commonly used for signage of this line
	TextColor string `json:"text_color"`
	// Vehicle contains the type of vehicle used on this line
	Vehicle TransitLineVehicle `json:"vehicle"`
}

// TransitAgency contains information about the operator of the line
type TransitAgency struct {
	// Name contains the name of the transit agency
	Name string `json:"name"`
	// URL contains the URL for the transit agency
	URL *url.URL `json:"url"`
	// Phone contains the phone number of the transit agency
	Phone string `json:"phone"`
}

// TransitLineVehicle contains the type of vehicle used on this line
type TransitLineVehicle struct {
	// Name contains the name of the vehicle on this line
	Name string `json:"name"`
	// Type contains the type of vehicle that runs on this line
	Type string `json:"type"`
	// Icon contains the URL for an icon associated with this vehicle type
	Icon *url.URL `json:"icon"`
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "19.0+"          // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.19.0-dev"    // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<commit_msg>Kubernetes version v0.19.1<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the Kubernetes
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// The "-dev" suffix in the version info indicates that fact, and it means the
// current build is from a version greater that version. For example, v0.7-dev
// means version > 0.7 and < 0.8. (There's exceptions to this rule, see
// docs/releasing.md for more details.)
//
// When releasing a new Kubernetes version, this file should be updated to
// reflect the new version, and then a git annotated tag (using format vX.Y
// where X == Major version and Y == Minor version) should be created to point
// to the commit that updates pkg/version/base.go

var (
	// TODO: Deprecate gitMajor and gitMinor, use only gitVersion instead.
	gitMajor     string = "0"              // major version, always numeric
	gitMinor     string = "19.1"           // minor version, numeric possibly followed by "+"
	gitVersion   string = "v0.19.1"        // version from git, output of $(git describe)
	gitCommit    string = ""               // sha1 from git, output of $(git rev-parse HEAD)
	gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
)
<|endoftext|>


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

package disasm

import (
	"io/ioutil"
	"log"
	"os"
)

var PrintDebugInfo = false

var logger *log.Logger

func init() {
	w := ioutil.Discard

	if PrintDebugInfo {
		w = os.Stderr
	}

	logger = log.New(w, "", log.Lshortfile)
	logger.SetFlags(log.Lshortfile)
}
<commit_msg>disasm: Replace PrintDegbugInfo with function SetDebugMode.<commit_after>// Copyright 2017 The go-interpreter Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package disasm

import (
	"io/ioutil"
	"log"
	"os"
)

var logger *log.Logger

func SetDebugMode(l bool) {
	w := ioutil.Discard

	if l {
		w = os.Stderr
	}

	logger = log.New(w, "", log.Lshortfile)
	logger.SetFlags(log.Lshortfile)

}

func init() {
	SetDebugMode(false)
}
<|endoftext|>


<commit_before>package vfs

import (
	"image"
	"io"

	// Packages image/... are not used explicitly in the code below,
	// but are imported for its initialization side-effect
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	// Same for image/webp
	_ "golang.org/x/image/webp"

	"github.com/xor-gate/goexif2/exif"
)

// MetadataExtractorVersion is the version number of the metadata extractor.
// It will be used later to know which files can be re-examined to get more
// metadata when the extractor is improved.
const MetadataExtractorVersion = 1

// Metadata is a list of metadata specific to each mimetype:
// id3 for music, exif for jpegs, etc.
type Metadata map[string]interface{}

// NewMetadata returns a new metadata object, with the version field set
func NewMetadata() Metadata {
	m := Metadata{}
	m["extractor_version"] = MetadataExtractorVersion
	return m
}

// MetaExtractor is an interface for extracting metadata from a file
type MetaExtractor interface {
	io.WriteCloser
	Abort(error)
	Result() Metadata
}

// NewMetaExtractor returns an extractor for metadata if the mime type has one,
// or null else
func NewMetaExtractor(doc *FileDoc) *MetaExtractor {
	var e MetaExtractor
	switch doc.Mime {
	case "image/jpeg":
		e = NewExifExtractor()
	case "image/png", "image/gif":
		e = NewImageExtractor()
	}
	if e != nil {
		return &e
	}
	return nil
}

// ImageExtractor is used to extract width/height from images
type ImageExtractor struct {
	w  *io.PipeWriter
	r  *io.PipeReader
	ch chan interface{}
}

// NewImageExtractor returns an extractor for images
func NewImageExtractor() *ImageExtractor {
	e := &ImageExtractor{}
	e.r, e.w = io.Pipe()
	e.ch = make(chan interface{})
	go e.Start()
	return e
}

// Start is used in a goroutine to start the metadata extraction
func (e *ImageExtractor) Start() {
	cfg, _, err := image.DecodeConfig(e.r)
	e.r.Close()
	if err != nil {
		e.ch <- err
	} else {
		e.ch <- cfg
	}
}

// Write is called to push some bytes to the extractor
func (e *ImageExtractor) Write(p []byte) (n int, err error) {
	return e.w.Write(p)
}

// Close is called when all the bytes has been pushed, to finalize the extraction
func (e *ImageExtractor) Close() error {
	return e.w.Close()
}

// Abort is called when the extractor can be discarded
func (e *ImageExtractor) Abort(err error) {
	e.w.CloseWithError(err)
	<-e.ch
}

// Result is called to get the extracted metadata
func (e *ImageExtractor) Result() Metadata {
	m := NewMetadata()
	cfg := <-e.ch
	switch cfg := cfg.(type) {
	case image.Config:
		m["width"] = cfg.Width
		m["height"] = cfg.Height
	}
	return m
}

// ExifExtractor is used to extract EXIF metadata from jpegs
type ExifExtractor struct {
	w  *io.PipeWriter
	r  *io.PipeReader
	im *ImageExtractor
	ch chan interface{}
}

// NewExifExtractor returns an extractor for EXIF metadata
func NewExifExtractor() *ExifExtractor {
	e := &ExifExtractor{}
	e.im = NewImageExtractor()
	e.r, e.w = io.Pipe()
	e.ch = make(chan interface{})
	go e.Start()
	return e
}

// Start is used in a goroutine to start the metadata extraction
func (e *ExifExtractor) Start() {
	x, err := exif.Decode(e.r)
	e.r.Close()
	if err != nil {
		e.ch <- err
	} else {
		e.ch <- x
	}
}

// Write is called to push some bytes to the extractor
func (e *ExifExtractor) Write(p []byte) (n int, err error) {
	e.im.Write(p)
	return e.w.Write(p)
}

// Close is called when all the bytes has been pushed, to finalize the extraction
func (e *ExifExtractor) Close() error {
	e.im.Close()
	return e.w.Close()
}

// Abort is called when the extractor can be discarded
func (e *ExifExtractor) Abort(err error) {
	e.im.Abort(err)
	e.w.CloseWithError(err)
	<-e.ch
}

// Result is called to get the extracted metadata
func (e *ExifExtractor) Result() Metadata {
	m := e.im.Result()
	x := <-e.ch
	switch x := x.(type) {
	case *exif.Exif:
		if dt, err := x.DateTime(); err == nil {
			m["datetime"] = dt
		}
		if flash, err := x.Flash(); err == nil {
			m["flash"] = flash
		}
		if lat, long, err := x.LatLong(); err == nil {
			m["gps"] = map[string]float64{
				"lat":  lat,
				"long": long,
			}
		}
	}
	return m
}
<commit_msg>default image metada to now<commit_after>package vfs

import (
	"image"
	"io"
	"time"

	// Packages image/... are not used explicitly in the code below,
	// but are imported for its initialization side-effect
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	// Same for image/webp
	_ "golang.org/x/image/webp"

	"github.com/xor-gate/goexif2/exif"
)

// MetadataExtractorVersion is the version number of the metadata extractor.
// It will be used later to know which files can be re-examined to get more
// metadata when the extractor is improved.
const MetadataExtractorVersion = 2

// Metadata is a list of metadata specific to each mimetype:
// id3 for music, exif for jpegs, etc.
type Metadata map[string]interface{}

// NewMetadata returns a new metadata object, with the version field set
func NewMetadata() Metadata {
	m := Metadata{}
	m["extractor_version"] = MetadataExtractorVersion
	return m
}

// MetaExtractor is an interface for extracting metadata from a file
type MetaExtractor interface {
	io.WriteCloser
	Abort(error)
	Result() Metadata
}

// NewMetaExtractor returns an extractor for metadata if the mime type has one,
// or null else
func NewMetaExtractor(doc *FileDoc) *MetaExtractor {
	var e MetaExtractor
	switch doc.Mime {
	case "image/jpeg":
		e = NewExifExtractor()
	case "image/png", "image/gif":
		e = NewImageExtractor()
	}
	if e != nil {
		return &e
	}
	return nil
}

// ImageExtractor is used to extract width/height from images
type ImageExtractor struct {
	w  *io.PipeWriter
	r  *io.PipeReader
	ch chan interface{}
}

// NewImageExtractor returns an extractor for images
func NewImageExtractor() *ImageExtractor {
	e := &ImageExtractor{}
	e.r, e.w = io.Pipe()
	e.ch = make(chan interface{})
	go e.Start()
	return e
}

// Start is used in a goroutine to start the metadata extraction
func (e *ImageExtractor) Start() {
	cfg, _, err := image.DecodeConfig(e.r)
	e.r.Close()
	if err != nil {
		e.ch <- err
	} else {
		e.ch <- cfg
	}
}

// Write is called to push some bytes to the extractor
func (e *ImageExtractor) Write(p []byte) (n int, err error) {
	return e.w.Write(p)
}

// Close is called when all the bytes has been pushed, to finalize the extraction
func (e *ImageExtractor) Close() error {
	return e.w.Close()
}

// Abort is called when the extractor can be discarded
func (e *ImageExtractor) Abort(err error) {
	e.w.CloseWithError(err)
	<-e.ch
}

// Result is called to get the extracted metadata
func (e *ImageExtractor) Result() Metadata {
	m := NewMetadata()
	m["datetime"] = time.Now()
	cfg := <-e.ch
	switch cfg := cfg.(type) {
	case image.Config:
		m["width"] = cfg.Width
		m["height"] = cfg.Height
	}
	return m
}

// ExifExtractor is used to extract EXIF metadata from jpegs
type ExifExtractor struct {
	w  *io.PipeWriter
	r  *io.PipeReader
	im *ImageExtractor
	ch chan interface{}
}

// NewExifExtractor returns an extractor for EXIF metadata
func NewExifExtractor() *ExifExtractor {
	e := &ExifExtractor{}
	e.im = NewImageExtractor()
	e.r, e.w = io.Pipe()
	e.ch = make(chan interface{})
	go e.Start()
	return e
}

// Start is used in a goroutine to start the metadata extraction
func (e *ExifExtractor) Start() {
	x, err := exif.Decode(e.r)
	e.r.Close()
	if err != nil {
		e.ch <- err
	} else {
		e.ch <- x
	}
}

// Write is called to push some bytes to the extractor
func (e *ExifExtractor) Write(p []byte) (n int, err error) {
	e.im.Write(p)
	return e.w.Write(p)
}

// Close is called when all the bytes has been pushed, to finalize the extraction
func (e *ExifExtractor) Close() error {
	e.im.Close()
	return e.w.Close()
}

// Abort is called when the extractor can be discarded
func (e *ExifExtractor) Abort(err error) {
	e.im.Abort(err)
	e.w.CloseWithError(err)
	<-e.ch
}

// Result is called to get the extracted metadata
func (e *ExifExtractor) Result() Metadata {
	m := e.im.Result()
	x := <-e.ch
	switch x := x.(type) {
	case *exif.Exif:
		if dt, err := x.DateTime(); err == nil {
			m["datetime"] = dt
		}
		if flash, err := x.Flash(); err == nil {
			m["flash"] = flash
		}
		if lat, long, err := x.LatLong(); err == nil {
			m["gps"] = map[string]float64{
				"lat":  lat,
				"long": long,
			}
		}
	}
	return m
}
<|endoftext|>


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

package stompngo

/*
	Disconnect from a STOMP broker.

	Shut down heart beats if necessary.
	Set connection status to false to disable further actions with this
	connection.

	Obtain a receipt if the client asks for one.

	Example:
		h := stompngo.Headers{"receipt", "receipt-id1"} // Ask for a receipt
		e := c.Disconnect(h)
		if e != nil {
			// Do something sane ...
		}
		fmt.Printf("%q\n", c.DisconnectReceipt)

*/
func (c *Connection) Disconnect(h Headers) error {
	c.log(DISCONNECT, "start")
	if !c.connected {
		return ECONBAD
	}
	_, e := checkHeaders(h, c)
	if e != nil {
		return e
	}
	ch := h.Clone()
	// Add a receipt request if caller did not ask for one.  This is in the spirit
	// of the specification, and allows reasonable resource cleanup in both the
	// client and the message broker.
	if _, ok := ch.Contains("receipt"); !ok {
		ch = ch.Add("receipt", Uuid())
	}
	//
	c.connected = false
	c.rsd <- true
	f := Frame{DISCONNECT, ch, NULLBUFF}
	//
	r := make(chan error)
	c.output <- wiredata{f, r}
	e = <-r
	//
	if e != nil {
		return e
	}
	// Drive shutdown logic
	c.shutdown()
	// Receipt
	c.DisconnectReceipt = <-c.input
	c.log(DISCONNECT, "end")
	return nil
}
<commit_msg>Correctly document current DISCONNECT behavior.<commit_after>//
// Copyright © 2011-2013 Guy M. Allard
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package stompngo

/*
	Disconnect from a STOMP broker.

	Shut down heart beats if necessary.
	Set connection status to false to disable further actions with this
	connection.

	Obtain a receipt.  If the client asks for a receipt, use the supplied receipt
	id.  Otherwise generate a uniqueue receipt id and add that to the DISCONNECT
	headers.

	Example:
		h := stompngo.Headers{"receipt", "receipt-id1"} // Ask for a receipt
		e := c.Disconnect(h)
		if e != nil {
			// Do something sane ...
		}
		fmt.Printf("%q\n", c.DisconnectReceipt)

*/
func (c *Connection) Disconnect(h Headers) error {
	c.log(DISCONNECT, "start")
	if !c.connected {
		return ECONBAD
	}
	_, e := checkHeaders(h, c)
	if e != nil {
		return e
	}
	ch := h.Clone()
	// Add a receipt request if caller did not ask for one.  This is in the spirit
	// of the specification, and allows reasonable resource cleanup in both the
	// client and the message broker.
	if _, ok := ch.Contains("receipt"); !ok {
		ch = ch.Add("receipt", Uuid())
	}
	//
	c.connected = false
	c.rsd <- true
	f := Frame{DISCONNECT, ch, NULLBUFF}
	//
	r := make(chan error)
	c.output <- wiredata{f, r}
	e = <-r
	//
	if e != nil {
		return e
	}
	// Drive shutdown logic
	c.shutdown()
	// Receipt
	c.DisconnectReceipt = <-c.input
	c.log(DISCONNECT, "end")
	return nil
}
<|endoftext|>


<commit_before>package glib

/*
#include <glib-object.h>
*/
import "C"

import (
	"reflect"
	"fmt"
)

type ValueGetter interface {
	Value() *Value
}

type Value C.GValue

func (v *Value) g() *C.GValue {
	return (*C.GValue)(v)
}

// Returns v's type.
func (v *Value) Type() Type {
	return Type(v.g_type)
}

// Set value to i
func (v *Value) Set(i interface{}) {
	if vg, ok := i.(ValueGetter); ok {
		vg.Value().Copy(v)
		return
	}
	// Other types
	r := reflect.ValueOf(i)
	switch r.Kind() {
	case reflect.Invalid:
		C.g_value_reset(v.g())

	case reflect.Bool:
		C.g_value_set_boolean(v.g(), gBoolean(r.Bool()))

	case reflect.Int:
		if TYPE_GO_INT == TYPE_INT {
			C.g_value_set_int(v.g(), C.gint(i.(int)))
		} else {
			C.g_value_set_long(v.g(), C.glong(i.(int)))
		}

	case reflect.Int8:
		C.g_value_set_char(v.g(), C.gchar(i.(int8)))

	case reflect.Int32:
		if TYPE_GO_INT32 == TYPE_INT {
			C.g_value_set_int(v.g(), C.gint(i.(int32)))
		} else {
			C.g_value_set_long(v.g(), C.glong(i.(int32)))
		}

	case reflect.Int64:
		C.g_value_set_int64(v.g(), C.gint64(i.(int64)))

	case reflect.Uint:
		if TYPE_GO_INT == TYPE_INT {
			C.g_value_set_uint(v.g(), C.guint(i.(uint)))
		} else {
			C.g_value_set_ulong(v.g(), C.gulong(i.(uint)))
		}

	case reflect.Uint8:
		C.g_value_set_uchar(v.g(), C.guchar(i.(uint8)))

	case reflect.Uint32:
		if TYPE_GO_INT32 == TYPE_INT {
			C.g_value_set_uint(v.g(), C.guint(i.(uint32)))
		} else {
			C.g_value_set_ulong(v.g(), C.gulong(i.(uint32)))
		}

	case reflect.Uint64:
		C.g_value_set_uint64(v.g(), C.guint64(i.(uint64)))

	case reflect.Float32:
		C.g_value_set_float(v.g(), C.gfloat(i.(float32)))

	case reflect.Float64:
		C.g_value_set_double(v.g(), C.gdouble(i.(float64)))

	case reflect.Ptr:
		C.g_value_set_pointer(v.g(), C.gpointer(r.Pointer()))

	case reflect.String:
		C.g_value_set_static_string(v.g(), (*C.gchar)(C.CString(r.String())))

	default:
		panic("Can't represent Go value in Glib type system.")
	}
}

// Initializes value with the default value of type.
func (v *Value) Init(t Type) {
	C.g_value_init(v.g(), t.g())
}

// Clears the current value in value and "unsets" the type,
func (v *Value) Unset() {
	C.g_value_unset(v.g())
}

// Returns new initializes value
func NewValue(t Type) (v *Value) {
	v = new(Value)
	v.Init(t)
	return
}

// Returns a pointer to new Value initialized to the value stored in the
// interface i. If i contains pointer to Value returns this pointer.
func ValueOf(i interface{}) *Value {
	if v, ok := i.(*Value); ok {
		return v
	}
	v := NewValue(TypeOf(i))
	v.Set(i)
	return v
}

// Copies the value into dst.
func (v *Value) Copy(dst *Value) {
	C.g_value_copy(v.g(), dst.g())
}

func (v *Value) Get() interface{} {
	t := Type(v.g().g_type)
	switch t {
	case TYPE_INVALID:
		return nil

	case TYPE_STRING:
		return C.GoString((*C.char)(C.g_value_get_string(v.g())))

	case TYPE_GO_INT:
		if TYPE_GO_INT == TYPE_INT {
			return int(C.g_value_get_int(v.g()))
		} else {
			return int(C.g_value_get_long(v.g()))
		}

	case TYPE_GO_UINT:
		if TYPE_GO_INT == TYPE_INT {
			return uint(C.g_value_get_uint(v.g()))
		} else {
			return uint(C.g_value_get_ulong(v.g()))
		}

	case TYPE_CHAR:
		return int8(C.g_value_get_char(v.g()))

	case TYPE_UCHAR:
		return uint8(C.g_value_get_uchar(v.g()))

	case TYPE_GO_INT32:
		if TYPE_GO_INT32 == TYPE_INT {
			return int32(C.g_value_get_int(v.g()))
		} else {
			return int32(C.g_value_get_long(v.g()))
		}

	case TYPE_GO_UINT32:
		if TYPE_GO_INT32 == TYPE_INT {
			return uint32(C.g_value_get_uint(v.g()))
		} else {
			return uint32(C.g_value_get_ulong(v.g()))
		}

	case TYPE_INT64:
		return int64(C.g_value_get_int64(v.g()))

	case TYPE_UINT64:
		return uint64(C.g_value_get_uint64(v.g()))

	case TYPE_BOOLEAN:
		return (C.g_value_get_boolean(v.g()) != C.gboolean(0))

	case TYPE_FLOAT:
		return float32(C.g_value_get_float(v.g()))

	case TYPE_DOUBLE:
		return float64(C.g_value_get_double(v.g()))

	case TYPE_POINTER:
		return Pointer(C.g_value_get_pointer(v.g()))

	case TYPE_GTYPE:
		return Type(C.g_value_get_gtype(v.g()))
	}
	if t.IsA(TYPE_OBJECT) {
		o := new(Object)
		o.SetPtr(Pointer(C.g_value_get_object(v.g())))
		return o
	}
	if C.g_value_fits_pointer(v.g()) != 0 {
		return Pointer(C.g_value_peek_pointer(v.g()))
	}
	// Value of unknown type is returned as is
	return v
}

func (v *Value) GetString() string {
	return v.Get().(string)
}

func (v *Value) GetInt() int {
	return v.Get().(int)
}

func (v *Value) GetUint() uint {
	return v.Get().(uint)
}

func (v *Value) GetInt8() int8 {
	return v.Get().(int8)
}

func (v *Value) GetUint8() uint8 {
	return v.Get().(uint8)
}

func (v *Value) GetInt32() int32 {
	return v.Get().(int32)
}

func (v *Value) GetUint32() uint32 {
	return v.Get().(uint32)
}

func (v *Value) GetInt64() int64 {
	return v.Get().(int64)
}

func (v *Value) GetUint64() uint64 {
	return v.Get().(uint64)
}

func (v *Value) GetBool() bool {
	return v.Get().(bool)
}

func (v *Value) GetFloat32() float32 {
	return v.Get().(float32)
}

func (v *Value) GetFloat64() float64 {
	return v.Get().(float64)
}

func (v *Value) GetPointer() Pointer {
	return v.Get().(Pointer)
}

func (v *Value) GetObject() *Object {
	return v.Get().(*Object)
}

func (v *Value) GetType() Type {
	return v.Get().(Type)
}

func (v *Value) String() string {
	return fmt.Sprint(v.Get())
}
<commit_msg>fix install error<commit_after>package glib

/*
#include <glib-object.h>
*/
import "C"

import (
	"reflect"
	"fmt"
)

type ValueGetter interface {
	Value() *Value
}

type Value C.GValue

func (v *Value) g() *C.GValue {
	return (*C.GValue)(v)
}

// Returns v's type.
func (v *Value) Type() Type {
	return Type(v.g_type)
}

// Set value to i
func (v *Value) Set(i interface{}) {
	if vg, ok := i.(ValueGetter); ok {
		vg.Value().Copy(v)
		return
	}
	// Other types
	r := reflect.ValueOf(i)
	switch r.Kind() {
	case reflect.Invalid:
		C.g_value_reset(v.g())

	case reflect.Bool:
		C.g_value_set_boolean(v.g(), gBoolean(r.Bool()))

	case reflect.Int:
		if TYPE_GO_INT == TYPE_INT {
			C.g_value_set_int(v.g(), C.gint(i.(int)))
		} else {
			C.g_value_set_long(v.g(), C.glong(i.(int)))
		}

	case reflect.Int8:
		C.g_value_set_schar(v.g(), C.gint8(i.(int8)))

	case reflect.Int32:
		if TYPE_GO_INT32 == TYPE_INT {
			C.g_value_set_int(v.g(), C.gint(i.(int32)))
		} else {
			C.g_value_set_long(v.g(), C.glong(i.(int32)))
		}

	case reflect.Int64:
		C.g_value_set_int64(v.g(), C.gint64(i.(int64)))

	case reflect.Uint:
		if TYPE_GO_INT == TYPE_INT {
			C.g_value_set_uint(v.g(), C.guint(i.(uint)))
		} else {
			C.g_value_set_ulong(v.g(), C.gulong(i.(uint)))
		}

	case reflect.Uint8:
		C.g_value_set_uchar(v.g(), C.guchar(i.(uint8)))

	case reflect.Uint32:
		if TYPE_GO_INT32 == TYPE_INT {
			C.g_value_set_uint(v.g(), C.guint(i.(uint32)))
		} else {
			C.g_value_set_ulong(v.g(), C.gulong(i.(uint32)))
		}

	case reflect.Uint64:
		C.g_value_set_uint64(v.g(), C.guint64(i.(uint64)))

	case reflect.Float32:
		C.g_value_set_float(v.g(), C.gfloat(i.(float32)))

	case reflect.Float64:
		C.g_value_set_double(v.g(), C.gdouble(i.(float64)))

	case reflect.Ptr:
		C.g_value_set_pointer(v.g(), C.gpointer(r.Pointer()))

	case reflect.String:
		C.g_value_set_static_string(v.g(), (*C.gchar)(C.CString(r.String())))

	default:
		panic("Can't represent Go value in Glib type system.")
	}
}

// Initializes value with the default value of type.
func (v *Value) Init(t Type) {
	C.g_value_init(v.g(), t.g())
}

// Clears the current value in value and "unsets" the type,
func (v *Value) Unset() {
	C.g_value_unset(v.g())
}

// Returns new initializes value
func NewValue(t Type) (v *Value) {
	v = new(Value)
	v.Init(t)
	return
}

// Returns a pointer to new Value initialized to the value stored in the
// interface i. If i contains pointer to Value returns this pointer.
func ValueOf(i interface{}) *Value {
	if v, ok := i.(*Value); ok {
		return v
	}
	v := NewValue(TypeOf(i))
	v.Set(i)
	return v
}

// Copies the value into dst.
func (v *Value) Copy(dst *Value) {
	C.g_value_copy(v.g(), dst.g())
}

func (v *Value) Get() interface{} {
	t := Type(v.g().g_type)
	switch t {
	case TYPE_INVALID:
		return nil

	case TYPE_STRING:
		return C.GoString((*C.char)(C.g_value_get_string(v.g())))

	case TYPE_GO_INT:
		if TYPE_GO_INT == TYPE_INT {
			return int(C.g_value_get_int(v.g()))
		} else {
			return int(C.g_value_get_long(v.g()))
		}

	case TYPE_GO_UINT:
		if TYPE_GO_INT == TYPE_INT {
			return uint(C.g_value_get_uint(v.g()))
		} else {
			return uint(C.g_value_get_ulong(v.g()))
		}

	case TYPE_CHAR:
		return int8(C.g_value_get_schar(v.g()))

	case TYPE_UCHAR:
		return uint8(C.g_value_get_uchar(v.g()))

	case TYPE_GO_INT32:
		if TYPE_GO_INT32 == TYPE_INT {
			return int32(C.g_value_get_int(v.g()))
		} else {
			return int32(C.g_value_get_long(v.g()))
		}

	case TYPE_GO_UINT32:
		if TYPE_GO_INT32 == TYPE_INT {
			return uint32(C.g_value_get_uint(v.g()))
		} else {
			return uint32(C.g_value_get_ulong(v.g()))
		}

	case TYPE_INT64:
		return int64(C.g_value_get_int64(v.g()))

	case TYPE_UINT64:
		return uint64(C.g_value_get_uint64(v.g()))

	case TYPE_BOOLEAN:
		return (C.g_value_get_boolean(v.g()) != C.gboolean(0))

	case TYPE_FLOAT:
		return float32(C.g_value_get_float(v.g()))

	case TYPE_DOUBLE:
		return float64(C.g_value_get_double(v.g()))

	case TYPE_POINTER:
		return Pointer(C.g_value_get_pointer(v.g()))

	case TYPE_GTYPE:
		return Type(C.g_value_get_gtype(v.g()))
	}
	if t.IsA(TYPE_OBJECT) {
		o := new(Object)
		o.SetPtr(Pointer(C.g_value_get_object(v.g())))
		return o
	}
	if C.g_value_fits_pointer(v.g()) != 0 {
		return Pointer(C.g_value_peek_pointer(v.g()))
	}
	// Value of unknown type is returned as is
	return v
}

func (v *Value) GetString() string {
	return v.Get().(string)
}

func (v *Value) GetInt() int {
	return v.Get().(int)
}

func (v *Value) GetUint() uint {
	return v.Get().(uint)
}

func (v *Value) GetInt8() int8 {
	return v.Get().(int8)
}

func (v *Value) GetUint8() uint8 {
	return v.Get().(uint8)
}

func (v *Value) GetInt32() int32 {
	return v.Get().(int32)
}

func (v *Value) GetUint32() uint32 {
	return v.Get().(uint32)
}

func (v *Value) GetInt64() int64 {
	return v.Get().(int64)
}

func (v *Value) GetUint64() uint64 {
	return v.Get().(uint64)
}

func (v *Value) GetBool() bool {
	return v.Get().(bool)
}

func (v *Value) GetFloat32() float32 {
	return v.Get().(float32)
}

func (v *Value) GetFloat64() float64 {
	return v.Get().(float64)
}

func (v *Value) GetPointer() Pointer {
	return v.Get().(Pointer)
}

func (v *Value) GetObject() *Object {
	return v.Get().(*Object)
}

func (v *Value) GetType() Type {
	return v.Get().(Type)
}

func (v *Value) String() string {
	return fmt.Sprint(v.Get())
}
<|endoftext|>