<commit_before>package go_bitpay_client

import (
	"fmt"
	"math/big"

	"github.com/drewwells/btcaddr"
)

// Keygen generates a new private/public key pair.  These are used for pairing
// to the Bitpay API.
func Keygen() ([]byte, []byte, error) {

	p, b, err := btcaddr.Bitcoin_GenerateKeypair()
	_ = b
	fmt.Printf("Bitcoin len: %d\n", len(p.D.Bytes()))
	//privstr := gimme.Bitcoin_Prikey2WIF(p)

	fmt.Printf("int  %d %x\n", len(p.D.Bytes()), p.D.Bytes()) //THIS IS IT FUCK THESE ENCODING SCHEMAS
	//fmt.Printf("% #v\n", pretty.Formatter(b))
	pub := Public(b.X, b.Y)
	fmt.Printf("pub  %d %x\n", len(pub), pub)
	//fmt.Printf("pub %d %x\n", len(b.R.Bytes()), b.R.Bytes())

	//RIPEMD160 encode the int
	/*ripe := ripemd160.New()
	privhash := ripe.Sum(p.D.Bytes())
	fmt.Printf("hash %d %x\n", len(privhash), privhash)

	sha := sha256.New()
	shahash := sha.Sum(p.D.Bytes())
	fmt.Printf("sha  %d %x\n", len(shahash), shahash)

	md := md5.New()
	mdhash := md.Sum(p.D.Bytes())
	fmt.Printf("md5  %d %x\n", len(mdhash), mdhash)

	hx := make([]byte, hex.EncodedLen(len(p.D.Bytes())))
	hex.Encode(hx, p.D.Bytes())
	fmt.Printf("hex  %d %x\n", len(hx), hx)

	b58 := btcutil.Base58Encode(p.D.Bytes())
	fmt.Printf("b58  %d %s\n", len(b58), b58)

	ex := "2osLAeuhKKwu61eu7MnXpbGU7Rkb6j155aXo515mWoS91nDPRR5rJGgvG3VRGpPpGWo4AEU3HmqtsQUcuPm8aBancYp5kC81gWpY7PCPa7cFZg"
	fmt.Printf("ex  %d %s\n", len(ex), ex)*/

	return []byte{}, []byte{}, err
}

func Public(X, Y *big.Int) []byte {

	//sha256_h := sha256.New()
	/* Create a new RIPEMD160 Context */
	//ripemd160_h := ripemd160.New()

	/* Convert the public key to a byte sequence */
	pubkey_bytes := append(X.Bytes(), Y.Bytes()...)

	/* 1. Prepend 0x04 */
	return append([]byte{0x04}, pubkey_bytes...)

}
<commit_msg>New package name<commit_after>package go_bitpay_client

import (
	"fmt"
	"math/big"

	btcaddr "github.com/drewwells/gimme_bitcoin_address"
)

// Keygen generates a new private/public key pair.  These are used for pairing
// to the Bitpay API.
func Keygen() ([]byte, []byte, error) {

	p, b, err := btcaddr.Bitcoin_GenerateKeypair()
	_ = b
	fmt.Printf("Bitcoin len: %d\n", len(p.D.Bytes()))
	//privstr := gimme.Bitcoin_Prikey2WIF(p)

	fmt.Printf("int  %d %x\n", len(p.D.Bytes()), p.D.Bytes()) //THIS IS IT FUCK THESE ENCODING SCHEMAS
	//fmt.Printf("% #v\n", pretty.Formatter(b))
	pub := Public(b.X, b.Y)
	fmt.Printf("pub  %d %x\n", len(pub), pub)
	//fmt.Printf("pub %d %x\n", len(b.R.Bytes()), b.R.Bytes())

	//RIPEMD160 encode the int
	/*ripe := ripemd160.New()
	privhash := ripe.Sum(p.D.Bytes())
	fmt.Printf("hash %d %x\n", len(privhash), privhash)

	sha := sha256.New()
	shahash := sha.Sum(p.D.Bytes())
	fmt.Printf("sha  %d %x\n", len(shahash), shahash)

	md := md5.New()
	mdhash := md.Sum(p.D.Bytes())
	fmt.Printf("md5  %d %x\n", len(mdhash), mdhash)

	hx := make([]byte, hex.EncodedLen(len(p.D.Bytes())))
	hex.Encode(hx, p.D.Bytes())
	fmt.Printf("hex  %d %x\n", len(hx), hx)

	b58 := btcutil.Base58Encode(p.D.Bytes())
	fmt.Printf("b58  %d %s\n", len(b58), b58)

	ex := "2osLAeuhKKwu61eu7MnXpbGU7Rkb6j155aXo515mWoS91nDPRR5rJGgvG3VRGpPpGWo4AEU3HmqtsQUcuPm8aBancYp5kC81gWpY7PCPa7cFZg"
	fmt.Printf("ex  %d %s\n", len(ex), ex)*/

	return []byte{}, []byte{}, err
}

func Public(X, Y *big.Int) []byte {

	//sha256_h := sha256.New()
	/* Create a new RIPEMD160 Context */
	//ripemd160_h := ripemd160.New()

	/* Convert the public key to a byte sequence */
	pubkey_bytes := append(X.Bytes(), Y.Bytes()...)

	/* 1. Prepend 0x04 */
	return append([]byte{0x04}, pubkey_bytes...)

}
<|endoftext|>


<commit_before>package versions

import (
	"testing"
)

func TestCompareVersions(t *testing.T) {
	t.Log("Trivial compare")
	if res, err := CompareVersions("1.0.0", "1.0.1"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Reverse compare")
	if res, err := CompareVersions("1.0.2", "1.0.1"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Equal compare")
	if res, err := CompareVersions("1.0.2", "1.0.2"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("1.0.0 <-> 0.9.8")
	if res, err := CompareVersions("1.0.0", "0.9.8"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Missing last num in first")
	if res, err := CompareVersions("7.0", "7.0.2"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in first - eql")
	if res, err := CompareVersions("7.0", "7.0.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in second")
	if res, err := CompareVersions("7.0.2", "7.0"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in second - eql")
	if res, err := CompareVersions("7.0.0", "7.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in first")
	if res, err := CompareVersions("7", "7.0.2"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in first - eql")
	if res, err := CompareVersions("7", "7.0.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in second")
	if res, err := CompareVersions("7.0.2", "7"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in second - eql")
	if res, err := CompareVersions("7.0.0", "7"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	// specials are not handled but should not cause any issue / panic
	t.Log("Special / non number component")
	if res, err := CompareVersions("7.x.1.2.3", "7.0.1.x"); err == nil {
		t.Fatal("Not supported compare should return an error!")
	} else {
		t.Log("[expected] Failed, res:", res, "| err:", err)
	}
}

func TestIsVersionGreaterOrEqual(t *testing.T) {
	t.Log("Yes - Trivial")
	isGreaterOrEql, err := IsVersionGreaterOrEqual("1.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Trivial - eq")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - Trivial")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0", "1.1")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - major version 0")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.0", "0.9.8")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - bit more complex - eq")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.0", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - bit more complex")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - bit more complex")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("0.9.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isGreaterOrEql {
		t.Fatal("Invalid result")
	}
}

func TestIsVersionBetween(t *testing.T) {
	t.Log("Yes - Trivial")
	isBetween, err := IsVersionBetween("1.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("No - Trivial")
	isBetween, err = IsVersionBetween("1.3", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - eq lower")
	isBetween, err = IsVersionBetween("1.0", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - eq upper")
	isBetween, err = IsVersionBetween("1.2", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Bit more complex")
	isBetween, err = IsVersionBetween("1.0.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Bit more complex - eq")
	isBetween, err = IsVersionBetween("1.2.0", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("No - Bit more complex")
	isBetween, err = IsVersionBetween("1.2.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isBetween {
		t.Fatal("Invalid result")
	}
}
<commit_msg>added a bit more testing for version compare<commit_after>package versions

import (
	"testing"
)

func TestCompareVersions(t *testing.T) {
	t.Log("Trivial compare")
	if res, err := CompareVersions("1.0.0", "1.0.1"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Reverse compare")
	if res, err := CompareVersions("1.0.2", "1.0.1"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Equal compare")
	if res, err := CompareVersions("1.0.2", "1.0.2"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("1.0.0 <-> 0.9.8")
	if res, err := CompareVersions("1.0.0", "0.9.8"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("0.9.8 <-> 1.0.0")
	if res, err := CompareVersions("0.9.8", "1.0.0"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	t.Log("Missing last num in first")
	if res, err := CompareVersions("7.0", "7.0.2"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in first - eql")
	if res, err := CompareVersions("7.0", "7.0.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in second")
	if res, err := CompareVersions("7.0.2", "7.0"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing last num in second - eql")
	if res, err := CompareVersions("7.0.0", "7.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in first")
	if res, err := CompareVersions("7", "7.0.2"); res != 1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in first - eql")
	if res, err := CompareVersions("7", "7.0.0"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in second")
	if res, err := CompareVersions("7.0.2", "7"); res != -1 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}
	t.Log("Missing double-last num in second - eql")
	if res, err := CompareVersions("7.0.0", "7"); res != 0 || err != nil {
		t.Fatal("Failed, res:", res, "| err:", err)
	}

	// specials are not handled but should not cause any issue / panic
	t.Log("Special / non number component")
	if res, err := CompareVersions("7.x.1.2.3", "7.0.1.x"); err == nil {
		t.Fatal("Not supported compare should return an error!")
	} else {
		t.Log("[expected] Failed, res:", res, "| err:", err)
	}
}

func TestIsVersionGreaterOrEqual(t *testing.T) {
	t.Log("Yes - Trivial")
	isGreaterOrEql, err := IsVersionGreaterOrEqual("1.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Trivial - eq")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - Trivial")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0", "1.1")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - 1.0.0<->0.9.8")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.0", "0.9.8")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - 0.9.8<->1.0.0")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("0.9.8", "1.0.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - bit more complex - eq")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.0", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - bit more complex")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("1.0.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isGreaterOrEql {
		t.Fatal("Invalid result")
	}

	t.Log("No - bit more complex")
	isGreaterOrEql, err = IsVersionGreaterOrEqual("0.9.1", "1.0")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isGreaterOrEql {
		t.Fatal("Invalid result")
	}
}

func TestIsVersionBetween(t *testing.T) {
	t.Log("Yes - Trivial")
	isBetween, err := IsVersionBetween("1.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("No - Trivial")
	isBetween, err = IsVersionBetween("1.3", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - eq lower")
	isBetween, err = IsVersionBetween("1.0", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - eq upper")
	isBetween, err = IsVersionBetween("1.2", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Bit more complex")
	isBetween, err = IsVersionBetween("1.0.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("Yes - Bit more complex - eq")
	isBetween, err = IsVersionBetween("1.2.0", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if !isBetween {
		t.Fatal("Invalid result")
	}

	t.Log("No - Bit more complex")
	isBetween, err = IsVersionBetween("1.2.1", "1.0", "1.2")
	if err != nil {
		t.Fatal("Unexpected error:", err)
	}
	if isBetween {
		t.Fatal("Invalid result")
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package venv

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"testing"

	"github.com/luci/luci-go/vpython/api/vpython"
	"github.com/luci/luci-go/vpython/python"

	"github.com/luci/luci-go/common/errors"
	"github.com/luci/luci-go/common/system/filesystem"
	"github.com/luci/luci-go/common/testing/testfs"

	"golang.org/x/net/context"

	. "github.com/luci/luci-go/common/testing/assertions"
	. "github.com/smartystreets/goconvey/convey"
)

type resolvedInterpreter struct {
	py      *python.Interpreter
	version python.Version
}

func resolveFromPath(vers python.Version) *resolvedInterpreter {
	c := context.Background()
	py, err := python.Find(c, vers)
	if err != nil {
		return nil
	}
	if err := filesystem.AbsPath(&py.Python); err != nil {
		panic(err)
	}

	ri := resolvedInterpreter{
		py: py,
	}
	if ri.version, err = ri.py.GetVersion(c); err != nil {
		panic(err)
	}
	return &ri
}

var (
	pythonGeneric = resolveFromPath(python.Version{})
	python27      = resolveFromPath(python.Version{2, 7, 0})
	python3       = resolveFromPath(python.Version{3, 0, 0})
)

func TestResolvePythonInterpreter(t *testing.T) {
	t.Parallel()

	Convey(`Resolving a Python interpreter`, t, func() {
		c := context.Background()
		cfg := Config{
			Spec: &vpython.Spec{},
		}

		// Tests to run if we have Python 2.7 installed.
		if python27 != nil {
			Convey(`When Python 2.7 is requested, it gets resolved.`, func() {
				cfg.Spec.PythonVersion = "2.7"
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, python27.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(python27.version), ShouldBeTrue)
			})

			Convey(`Fails when Python 9999 is requested, but a Python 2 interpreter is forced.`, func() {
				cfg.Python = python27.py.Python
				cfg.Spec.PythonVersion = "9999"
				So(cfg.resolvePythonInterpreter(c), ShouldErrLike, "doesn't match specification")
			})
		}

		// Tests to run if we have Python 2.7 and a generic Python installed.
		if pythonGeneric != nil && python27 != nil {
			// Our generic Python resolves to a known version, so we can proceed.
			Convey(`When no Python version is specified, spec resolves to generic.`, func() {
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, pythonGeneric.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(pythonGeneric.version), ShouldBeTrue)
			})
		}

		// Tests to run if we have Python 3 installed.
		if python3 != nil {
			Convey(`When Python 3 is requested, it gets resolved.`, func() {
				cfg.Spec.PythonVersion = "3"
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, python3.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(python3.version), ShouldBeTrue)
			})

			Convey(`Fails when Python 9999 is requested, but a Python 3 interpreter is forced.`, func() {
				cfg.Python = python3.py.Python
				cfg.Spec.PythonVersion = "9999"
				So(cfg.resolvePythonInterpreter(c), ShouldErrLike, "doesn't match specification")
			})
		}
	})
}

type setupCheckManifest struct {
	Interpreter string `json:"interpreter"`
	Pants       string `json:"pants"`
	Shirt       string `json:"shirt"`
}

func testVirtualEnvWith(t *testing.T, ri *resolvedInterpreter) {
	t.Parallel()

	if ri == nil {
		t.Skipf("No python interpreter found.")
	}

	tl, err := loadTestEnvironment(context.Background(), t)
	if err != nil {
		t.Fatalf("could not set up test loader for %q: %s", ri.py.Python, err)
	}

	Convey(`Testing Setup`, t, testfs.MustWithTempDir(t, "vpython", func(tdir string) {
		c := context.Background()
		config := Config{
			BaseDir:    tdir,
			MaxHashLen: 4,
			Package: vpython.Spec_Package{
				Name:    "foo/bar/virtualenv",
				Version: "unresolved",
			},
			Python: ri.py.Python,
			Spec: &vpython.Spec{
				Wheel: []*vpython.Spec_Package{
					{Name: "foo/bar/shirt", Version: "unresolved"},
					{Name: "foo/bar/pants", Version: "unresolved"},
				},
			},
			Loader: tl,
		}

		// Load the bootstrap wheels for the next part of the test.
		So(tl.ensureWheels(c, t, ri.py, tdir), ShouldBeNil)

		err := With(c, config, false, func(c context.Context, v *Env) error {
			testScriptPath := filepath.Join(testDataDir, "setup_check.py")
			checkOut := filepath.Join(tdir, "output.json")
			i := v.InterpreterCommand()
			So(i.Run(c, testScriptPath, "--json-output", checkOut), ShouldBeNil)

			var m setupCheckManifest
			So(loadJSON(checkOut, &m), ShouldBeNil)
			So(m.Interpreter, ShouldStartWith, v.Root)
			So(m.Pants, ShouldStartWith, v.Root)
			So(m.Shirt, ShouldStartWith, v.Root)

			// We should be able to delete it.
			So(v.Delete(c), ShouldBeNil)
			return nil
		})
		So(err, ShouldBeNil)
	}))
}

func TestVirtualEnv(t *testing.T) {
	t.Parallel()

	for _, tc := range []struct {
		name string
		ri   *resolvedInterpreter
	}{
		{"python27", python27},
		{"python3", python3},
	} {
		tc := tc

		t.Run(fmt.Sprintf(`Testing Virtualenv for: %s`, tc.name), func(t *testing.T) {
			testVirtualEnvWith(t, tc.ri)
		})
	}
}

func loadJSON(path string, dst interface{}) error {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return errors.Annotate(err).Reason("failed to open file").Err()
	}
	if err := json.Unmarshal(content, dst); err != nil {
		return errors.Annotate(err).Reason("failed to unmarshal JSON").Err()
	}
	return nil
}
<commit_msg>Disable flaky test.<commit_after>// Copyright 2017 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

package venv

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"testing"

	"github.com/luci/luci-go/vpython/api/vpython"
	"github.com/luci/luci-go/vpython/python"

	"github.com/luci/luci-go/common/errors"
	"github.com/luci/luci-go/common/system/filesystem"
	"github.com/luci/luci-go/common/testing/testfs"

	"golang.org/x/net/context"

	. "github.com/luci/luci-go/common/testing/assertions"
	. "github.com/smartystreets/goconvey/convey"
)

type resolvedInterpreter struct {
	py      *python.Interpreter
	version python.Version
}

func resolveFromPath(vers python.Version) *resolvedInterpreter {
	c := context.Background()
	py, err := python.Find(c, vers)
	if err != nil {
		return nil
	}
	if err := filesystem.AbsPath(&py.Python); err != nil {
		panic(err)
	}

	ri := resolvedInterpreter{
		py: py,
	}
	if ri.version, err = ri.py.GetVersion(c); err != nil {
		panic(err)
	}
	return &ri
}

var (
	pythonGeneric = resolveFromPath(python.Version{})
	python27      = resolveFromPath(python.Version{2, 7, 0})
	python3       = resolveFromPath(python.Version{3, 0, 0})
)

func TestResolvePythonInterpreter(t *testing.T) {
	t.Parallel()

	Convey(`Resolving a Python interpreter`, t, func() {
		c := context.Background()
		cfg := Config{
			Spec: &vpython.Spec{},
		}

		// Tests to run if we have Python 2.7 installed.
		if python27 != nil {
			Convey(`When Python 2.7 is requested, it gets resolved.`, func() {
				cfg.Spec.PythonVersion = "2.7"
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, python27.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(python27.version), ShouldBeTrue)
			})

			Convey(`Fails when Python 9999 is requested, but a Python 2 interpreter is forced.`, func() {
				cfg.Python = python27.py.Python
				cfg.Spec.PythonVersion = "9999"
				So(cfg.resolvePythonInterpreter(c), ShouldErrLike, "doesn't match specification")
			})
		}

		// Tests to run if we have Python 2.7 and a generic Python installed.
		if pythonGeneric != nil && python27 != nil {
			// Our generic Python resolves to a known version, so we can proceed.
			Convey(`When no Python version is specified, spec resolves to generic.`, func() {
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, pythonGeneric.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(pythonGeneric.version), ShouldBeTrue)
			})
		}

		// Tests to run if we have Python 3 installed.
		if python3 != nil {
			Convey(`When Python 3 is requested, it gets resolved.`, func() {
				cfg.Spec.PythonVersion = "3"
				So(cfg.resolvePythonInterpreter(c), ShouldBeNil)
				So(cfg.Python, ShouldEqual, python3.py.Python)

				vers, err := python.ParseVersion(cfg.Spec.PythonVersion)
				So(err, ShouldBeNil)
				So(vers.IsSatisfiedBy(python3.version), ShouldBeTrue)
			})

			Convey(`Fails when Python 9999 is requested, but a Python 3 interpreter is forced.`, func() {
				cfg.Python = python3.py.Python
				cfg.Spec.PythonVersion = "9999"
				So(cfg.resolvePythonInterpreter(c), ShouldErrLike, "doesn't match specification")
			})
		}
	})
}

type setupCheckManifest struct {
	Interpreter string `json:"interpreter"`
	Pants       string `json:"pants"`
	Shirt       string `json:"shirt"`
}

func testVirtualEnvWith(t *testing.T, ri *resolvedInterpreter) {
	t.Parallel()

	if ri == nil {
		t.Skipf("No python interpreter found.")
	}

	tl, err := loadTestEnvironment(context.Background(), t)
	if err != nil {
		t.Fatalf("could not set up test loader for %q: %s", ri.py.Python, err)
	}

	Convey(`Testing Setup`, t, testfs.MustWithTempDir(t, "vpython", func(tdir string) {
		c := context.Background()
		config := Config{
			BaseDir:    tdir,
			MaxHashLen: 4,
			Package: vpython.Spec_Package{
				Name:    "foo/bar/virtualenv",
				Version: "unresolved",
			},
			Python: ri.py.Python,
			Spec: &vpython.Spec{
				Wheel: []*vpython.Spec_Package{
					{Name: "foo/bar/shirt", Version: "unresolved"},
					{Name: "foo/bar/pants", Version: "unresolved"},
				},
			},
			Loader: tl,
		}

		// Load the bootstrap wheels for the next part of the test.
		So(tl.ensureWheels(c, t, ri.py, tdir), ShouldBeNil)

		err := With(c, config, false, func(c context.Context, v *Env) error {
			testScriptPath := filepath.Join(testDataDir, "setup_check.py")
			checkOut := filepath.Join(tdir, "output.json")
			i := v.InterpreterCommand()
			So(i.Run(c, testScriptPath, "--json-output", checkOut), ShouldBeNil)

			var m setupCheckManifest
			So(loadJSON(checkOut, &m), ShouldBeNil)
			So(m.Interpreter, ShouldStartWith, v.Root)
			So(m.Pants, ShouldStartWith, v.Root)
			So(m.Shirt, ShouldStartWith, v.Root)

			// We should be able to delete it.
			So(v.Delete(c), ShouldBeNil)
			return nil
		})
		So(err, ShouldBeNil)
	}))
}

func TestVirtualEnv(t *testing.T) {
	t.Parallel()

	// TODO(dnj): Identify flake and fix.
	t.Skip("Test is currently flaky, will re-enable once resolved.")

	for _, tc := range []struct {
		name string
		ri   *resolvedInterpreter
	}{
		{"python27", python27},
		{"python3", python3},
	} {
		tc := tc

		t.Run(fmt.Sprintf(`Testing Virtualenv for: %s`, tc.name), func(t *testing.T) {
			testVirtualEnvWith(t, tc.ri)
		})
	}
}

func loadJSON(path string, dst interface{}) error {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return errors.Annotate(err).Reason("failed to open file").Err()
	}
	if err := json.Unmarshal(content, dst); err != nil {
		return errors.Annotate(err).Reason("failed to unmarshal JSON").Err()
	}
	return nil
}
<|endoftext|>


<commit_before>/* Copyright 2016 Google Inc.

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

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

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

package gonids

import (
	"errors"
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)

// item represents a token or text string returned from the lexer.
type item struct {
	typ   itemType // The type of this item.
	value string   // The value of this item.
}

// String returns a string describing an item.
func (i item) String() string {
	switch i.typ {
	case itemEOF:
		return "EOF"
	case itemError:
		return i.value
	}
	return fmt.Sprintf("%q: %s", i.typ, i.value)
}

type itemType int

const (
	itemError itemType = iota
	itemComment
	itemAction
	itemProtocol
	itemSourceAddress
	itemSourcePort
	itemDirection
	itemDestinationAddress
	itemDestinationPort
	itemNot
	itemOptionKey
	itemOptionValue
	itemOptionNoValue
	itemOptionValueString
	itemEOR
	itemEOF
)

const eof = -1

// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*lexer) stateFn

// lexer holds the state of the scanner.
type lexer struct {
	input string    // the string being scanned
	state stateFn   // the next lexing function to enter
	pos   int       // current position in the input
	start int       // start position of this item
	width int       // width of last rune read from input
	items chan item // channel of scanned items
}

// next returns the next rune in the input.
func (l *lexer) next() rune {
	if l.pos >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	if r == utf8.RuneError && w == 1 {
		// The whole input string has been validated at init.
		panic("invalid UTF-8 character")
	}
	l.width = w
	l.pos += l.width
	return r
}

// skipNext skips over the next rune in the input.
func (l *lexer) skipNext() {
	l.next()
	l.ignore()
}

// peek returns but does not consume the next rune in the input.
func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

// len returns the current length of the item in processing.
func (l *lexer) len() int {
	if l.pos >= len(l.input) {
		return -1
	}
	return l.pos - l.start
}

// backup steps back one rune. Can only be called once per call of next.
func (l *lexer) backup() {
	if l.width == -1 {
		panic("double backup")
	}
	l.pos -= l.width
	l.width = -1
}

// emit passes an item back to the client, trimSpaces can be used to trim spaces around item
// value before emiting.
func (l *lexer) emit(t itemType, trimSpaces bool) {
	input := l.input[l.start:l.pos]
	if trimSpaces {
		input = strings.TrimSpace(input)
	}

	// This is a bit of a hack. We lex until `;` now so we end up with extra `"`.
	input = strings.TrimSuffix(input, `"`)
	l.items <- item{t, input}
	l.start = l.pos
}

// ignore skips over the pending input before this point.
func (l *lexer) ignore() {
	l.start = l.pos
}

// accept consumes the next rune if it's from the valid set.
func (l *lexer) accept(valid string) bool {
	if strings.ContainsRune(valid, l.next()) {
		return true
	}
	l.backup()
	return false
}

// acceptRun consumes a run of runes from the valid set.
func (l *lexer) acceptRun(valid string) {
	for strings.ContainsRune(valid, l.next()) {
	}
	l.backup()
}

// ignoreSpaces ignores all spaces at the start of the input.
func (l *lexer) ignoreSpaces() {
	for unicode.IsSpace(l.next()) {
		l.ignore()
	}
	l.backup()
}

// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{itemError, fmt.Sprintf(format, args...)}
	return nil
}

func (l *lexer) unexpectedEOF() stateFn {
	return nil
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() item {
	r, more := <-l.items
	if !more {
		return item{itemError, "unexpected EOF"}
	}
	return r
}

// lex initializes and runs a new scanner for the input string.
func lex(input string) (*lexer, error) {
	if !utf8.ValidString(input) {
		return nil, errors.New("input is not a valid UTF-8 string")
	}
	l := &lexer{
		input: input,
		items: make(chan item, 0x1000),
	}
	go l.run()
	return l, nil
}

// TODO: handle error and corner case in all states.
// run runs the state machine for the lexer.
func (l *lexer) run() {
	for l.state = lexRule; l.state != nil; {
		l.state = l.state(l)
	}
	close(l.items)
}

func (l *lexer) close() {
	// Reads all items until channel close to be sure goroutine has ended.
	more := true
	for more {
		_, more = <-l.items
	}
}

// lexRule starts the scan of a rule.
func lexRule(l *lexer) stateFn {
	r := l.next()
	switch {
	case unicode.IsSpace(r):
		l.ignore()
		return lexRule
	case r == '#':
		return lexComment
	case r == eof:
		l.emit(itemEOF, false)
		return nil
	}
	return lexAction
}

// lexComment consumes a commented rule.
func lexComment(l *lexer) stateFn {
	// Ignore leading spaces and #.
	l.ignore()
	for {
		r := l.next()
		if unicode.IsSpace(r) || r == '#' {
			l.ignore()
		} else {
			break
		}
	}
	l.backup()

	for {
		switch l.next() {
		case '\r', '\n':
			l.emit(itemComment, false)
			return lexRule
		case eof:
			l.backup()
			l.emit(itemComment, false)
			return lexRule
		}
	}
}

// lexAction consumes a rule action.
func lexAction(l *lexer) stateFn {
	for {
		r := l.next()
		switch {
		case r == ' ':
			l.emit(itemAction, true)
			return lexProtocol
		case !unicode.IsLetter(r):
			return l.errorf("invalid character %q for a rule action", r)
		}
	}
}

// lexProtocol consumes a rule protocol.
func lexProtocol(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		r := l.next()
		switch {
		case r == ' ':
			l.emit(itemProtocol, true)
			return lexSourceAddress
		case !(unicode.IsLetter(r) || unicode.IsDigit(r) || (l.len() > 0 && r == '-')):
			return l.errorf("invalid character %q for a rule protocol", r)
		}
	}

}

// lexSourceAddress consumes a source address.
func lexSourceAddress(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemSourceAddress, true)
			return lexSourcePort
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexSourcePort consumes a source port.
func lexSourcePort(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemSourcePort, true)
			return lexDirection
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexDirection consumes a rule direction.
func lexDirection(l *lexer) stateFn {
	l.ignoreSpaces()
	l.acceptRun("<->")
	if r := l.next(); r != ' ' {
		return l.errorf("invalid character %q for a rule direction", r)
	}
	l.emit(itemDirection, true)
	return lexDestinationAddress
}

// lexDestinationAddress consumes a destination address.
func lexDestinationAddress(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemDestinationAddress, true)
			return lexDestinationPort
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexDestinationPort consumes a destination port.
func lexDestinationPort(l *lexer) stateFn {
	for {
		switch l.next() {
		case '(':
			l.backup()
			l.emit(itemDestinationPort, true)
			l.skipNext()
			return lexOptionKey
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionKey scans a key from the rule options.
func lexOptionKey(l *lexer) stateFn {
	for {
		switch l.next() {
		case ':':
			l.backup()
			l.emit(itemOptionKey, true)
			l.skipNext()
			return lexOptionValueBegin
		case ';':
			l.backup()
			if l.pos > l.start {
				l.emit(itemOptionKey, true)
				l.emit(itemOptionNoValue, true)
			}
			l.skipNext()
			return lexOptionKey
		case ')':
			l.backup()
			if l.pos > l.start {
				l.emit(itemOptionKey, true)
			}
			l.skipNext()
			return lexRuleEnd
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionValueBegin scans the beginning of a value from the rule option.
func lexOptionValueBegin(l *lexer) stateFn {
	switch l.next() {
	case '"':
		l.ignore()
		return lexOptionValueString
	case ' ':
		l.ignore()
		return lexOptionValueBegin
	case '!':
		l.emit(itemNot, true)
		return lexOptionValueBegin
	}
	return lexOptionValue
}

// lexOptionValueString consumes the inner content of a string value from the rule options.
func lexOptionValueString(l *lexer) stateFn {
	escaped := false
	for {
		switch l.next() {
		case ';':
			l.backup()
			l.emit(itemOptionValueString, false)
			l.skipNext()
			return lexOptionKey
		case '\\':
			escaped = !escaped
			if l.next() != ';' || !escaped {
				l.backup()
			}
		case eof:
			return l.unexpectedEOF()
		default:
			escaped = false
		}
	}
}

// lexOptionValue scans a value from the rule options.
func lexOptionValue(l *lexer) stateFn {
	for {
		switch l.next() {
		case ';':
			l.backup()
			l.emit(itemOptionValue, true)
			l.skipNext()
			return lexOptionKey
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionEnd marks the end of a rule.
func lexRuleEnd(l *lexer) stateFn {
	l.emit(itemEOR, false)
	return lexRule
}
<commit_msg>remove unused functions, YAGNI! (#163)<commit_after>/* Copyright 2016 Google Inc.

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

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

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

package gonids

import (
	"errors"
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"
)

// item represents a token or text string returned from the lexer.
type item struct {
	typ   itemType // The type of this item.
	value string   // The value of this item.
}

// String returns a string describing an item.
func (i item) String() string {
	switch i.typ {
	case itemEOF:
		return "EOF"
	case itemError:
		return i.value
	}
	return fmt.Sprintf("%q: %s", i.typ, i.value)
}

type itemType int

const (
	itemError itemType = iota
	itemComment
	itemAction
	itemProtocol
	itemSourceAddress
	itemSourcePort
	itemDirection
	itemDestinationAddress
	itemDestinationPort
	itemNot
	itemOptionKey
	itemOptionValue
	itemOptionNoValue
	itemOptionValueString
	itemEOR
	itemEOF
)

const eof = -1

// stateFn represents the state of the scanner as a function that returns the next state.
type stateFn func(*lexer) stateFn

// lexer holds the state of the scanner.
type lexer struct {
	input string    // the string being scanned
	state stateFn   // the next lexing function to enter
	pos   int       // current position in the input
	start int       // start position of this item
	width int       // width of last rune read from input
	items chan item // channel of scanned items
}

// next returns the next rune in the input.
func (l *lexer) next() rune {
	if l.pos >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	if r == utf8.RuneError && w == 1 {
		// The whole input string has been validated at init.
		panic("invalid UTF-8 character")
	}
	l.width = w
	l.pos += l.width
	return r
}

// skipNext skips over the next rune in the input.
func (l *lexer) skipNext() {
	l.next()
	l.ignore()
}

// len returns the current length of the item in processing.
func (l *lexer) len() int {
	if l.pos >= len(l.input) {
		return -1
	}
	return l.pos - l.start
}

// backup steps back one rune. Can only be called once per call of next.
func (l *lexer) backup() {
	if l.width == -1 {
		panic("double backup")
	}
	l.pos -= l.width
	l.width = -1
}

// emit passes an item back to the client, trimSpaces can be used to trim spaces around item
// value before emiting.
func (l *lexer) emit(t itemType, trimSpaces bool) {
	input := l.input[l.start:l.pos]
	if trimSpaces {
		input = strings.TrimSpace(input)
	}

	// This is a bit of a hack. We lex until `;` now so we end up with extra `"`.
	input = strings.TrimSuffix(input, `"`)
	l.items <- item{t, input}
	l.start = l.pos
}

// ignore skips over the pending input before this point.
func (l *lexer) ignore() {
	l.start = l.pos
}

// acceptRun consumes a run of runes from the valid set.
func (l *lexer) acceptRun(valid string) {
	for strings.ContainsRune(valid, l.next()) {
	}
	l.backup()
}

// ignoreSpaces ignores all spaces at the start of the input.
func (l *lexer) ignoreSpaces() {
	for unicode.IsSpace(l.next()) {
		l.ignore()
	}
	l.backup()
}

// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{itemError, fmt.Sprintf(format, args...)}
	return nil
}

func (l *lexer) unexpectedEOF() stateFn {
	return nil
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() item {
	r, more := <-l.items
	if !more {
		return item{itemError, "unexpected EOF"}
	}
	return r
}

// lex initializes and runs a new scanner for the input string.
func lex(input string) (*lexer, error) {
	if !utf8.ValidString(input) {
		return nil, errors.New("input is not a valid UTF-8 string")
	}
	l := &lexer{
		input: input,
		items: make(chan item, 0x1000),
	}
	go l.run()
	return l, nil
}

// TODO: handle error and corner case in all states.
// run runs the state machine for the lexer.
func (l *lexer) run() {
	for l.state = lexRule; l.state != nil; {
		l.state = l.state(l)
	}
	close(l.items)
}

func (l *lexer) close() {
	// Reads all items until channel close to be sure goroutine has ended.
	more := true
	for more {
		_, more = <-l.items
	}
}

// lexRule starts the scan of a rule.
func lexRule(l *lexer) stateFn {
	r := l.next()
	switch {
	case unicode.IsSpace(r):
		l.ignore()
		return lexRule
	case r == '#':
		return lexComment
	case r == eof:
		l.emit(itemEOF, false)
		return nil
	}
	return lexAction
}

// lexComment consumes a commented rule.
func lexComment(l *lexer) stateFn {
	// Ignore leading spaces and #.
	l.ignore()
	for {
		r := l.next()
		if unicode.IsSpace(r) || r == '#' {
			l.ignore()
		} else {
			break
		}
	}
	l.backup()

	for {
		switch l.next() {
		case '\r', '\n':
			l.emit(itemComment, false)
			return lexRule
		case eof:
			l.backup()
			l.emit(itemComment, false)
			return lexRule
		}
	}
}

// lexAction consumes a rule action.
func lexAction(l *lexer) stateFn {
	for {
		r := l.next()
		switch {
		case r == ' ':
			l.emit(itemAction, true)
			return lexProtocol
		case !unicode.IsLetter(r):
			return l.errorf("invalid character %q for a rule action", r)
		}
	}
}

// lexProtocol consumes a rule protocol.
func lexProtocol(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		r := l.next()
		switch {
		case r == ' ':
			l.emit(itemProtocol, true)
			return lexSourceAddress
		case !(unicode.IsLetter(r) || unicode.IsDigit(r) || (l.len() > 0 && r == '-')):
			return l.errorf("invalid character %q for a rule protocol", r)
		}
	}

}

// lexSourceAddress consumes a source address.
func lexSourceAddress(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemSourceAddress, true)
			return lexSourcePort
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexSourcePort consumes a source port.
func lexSourcePort(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemSourcePort, true)
			return lexDirection
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexDirection consumes a rule direction.
func lexDirection(l *lexer) stateFn {
	l.ignoreSpaces()
	l.acceptRun("<->")
	if r := l.next(); r != ' ' {
		return l.errorf("invalid character %q for a rule direction", r)
	}
	l.emit(itemDirection, true)
	return lexDestinationAddress
}

// lexDestinationAddress consumes a destination address.
func lexDestinationAddress(l *lexer) stateFn {
	l.ignoreSpaces()
	for {
		switch l.next() {
		case ' ':
			l.emit(itemDestinationAddress, true)
			return lexDestinationPort
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexDestinationPort consumes a destination port.
func lexDestinationPort(l *lexer) stateFn {
	for {
		switch l.next() {
		case '(':
			l.backup()
			l.emit(itemDestinationPort, true)
			l.skipNext()
			return lexOptionKey
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionKey scans a key from the rule options.
func lexOptionKey(l *lexer) stateFn {
	for {
		switch l.next() {
		case ':':
			l.backup()
			l.emit(itemOptionKey, true)
			l.skipNext()
			return lexOptionValueBegin
		case ';':
			l.backup()
			if l.pos > l.start {
				l.emit(itemOptionKey, true)
				l.emit(itemOptionNoValue, true)
			}
			l.skipNext()
			return lexOptionKey
		case ')':
			l.backup()
			if l.pos > l.start {
				l.emit(itemOptionKey, true)
			}
			l.skipNext()
			return lexRuleEnd
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionValueBegin scans the beginning of a value from the rule option.
func lexOptionValueBegin(l *lexer) stateFn {
	switch l.next() {
	case '"':
		l.ignore()
		return lexOptionValueString
	case ' ':
		l.ignore()
		return lexOptionValueBegin
	case '!':
		l.emit(itemNot, true)
		return lexOptionValueBegin
	}
	return lexOptionValue
}

// lexOptionValueString consumes the inner content of a string value from the rule options.
func lexOptionValueString(l *lexer) stateFn {
	escaped := false
	for {
		switch l.next() {
		case ';':
			l.backup()
			l.emit(itemOptionValueString, false)
			l.skipNext()
			return lexOptionKey
		case '\\':
			escaped = !escaped
			if l.next() != ';' || !escaped {
				l.backup()
			}
		case eof:
			return l.unexpectedEOF()
		default:
			escaped = false
		}
	}
}

// lexOptionValue scans a value from the rule options.
func lexOptionValue(l *lexer) stateFn {
	for {
		switch l.next() {
		case ';':
			l.backup()
			l.emit(itemOptionValue, true)
			l.skipNext()
			return lexOptionKey
		case eof:
			return l.unexpectedEOF()
		}
	}
}

// lexOptionEnd marks the end of a rule.
func lexRuleEnd(l *lexer) stateFn {
	l.emit(itemEOR, false)
	return lexRule
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
	"encoding/json"
	"flag"
)

type LastFmResponse struct {
	Toptracks struct {
				  Track []struct {
					  Name string `json:"name"`
					  Duration string `json:"duration"`
					  Playcount string `json:"playcount"`
					  Listeners string `json:"listeners"`
					  Mbid string `json:"mbid"`
					  URL string `json:"url"`
					  Streamable struct {
							   Text string `json:"#text"`
							   Fulltrack string `json:"fulltrack"`
						   } `json:"streamable"`
					  Artist struct {
							   Name string `json:"name"`

						   } `json:"artist"`
					  Image []struct {
						  Text string `json:"#text"`
						  Size string `json:"size"`
					  } `json:"image"`
					  Attr struct {
							   Rank string `json:"rank"`
						   } `json:"@attr"`
				  } `json:"track"`
				  Attr struct {
							Artist string `json:"artist"`
							Page string `json:"page"`
							Perpage string `json:"perPage"`
							Totalpages string `json:"totalPages"`
							Total string `json:"total"`
						} `json:"@attr"`
			  } `json:"toptracks"`
}

type ApiConfig struct {
	ApiKey string `json:"api_key"`
}

func resolveUrl(apiKey string, artist string, limit int) string {
	return fmt.Sprintf("http://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist=%s&api_key=%s&limit=%d&format=json", artist, apiKey, limit)
}

func readApiConfig() ApiConfig {
	data, err := ioutil.ReadFile("/Users/ojkic/.lfm/config")
	var auth ApiConfig

	if err != nil {
		fmt.Printf("%s", err)
	}

	parseJson(data, &auth)
	return auth
}

func executeRequest(url string) (body []byte, err error) {
	response, err := http.Get(url)

	if err != nil {
		return body, err
	} else {
		defer response.Body.Close()
		var ioError error
		body, ioError = ioutil.ReadAll(response.Body)
		if ioError != nil {
			return body, ioError
		}
	}
	return body, err
}

func parseJson(jsonBody []byte, result interface{}) error {
	return json.Unmarshal(jsonBody, &result)
}

func main() {
	apiConfig := readApiConfig()

	artistName := flag.String("a", "", "artist name")
	limit := flag.Int("l", 20, "limit")
	flag.Parse()

	var url = resolveUrl(apiConfig.ApiKey, *artistName, *limit)
	body, error := executeRequest(url)

	var reponse LastFmResponse
	parseJson(body, &reponse)

	if error != nil {
		fmt.Printf("%s", error)
	} else {
		fmt.Println(reponse.Toptracks.Track[1].Name)
	}

}

<commit_msg>moving artist part to function<commit_after>package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
	"encoding/json"
	"flag"
)

type LastFmResponse struct {
	Toptracks struct {
				  Track []struct {
					  Name string `json:"name"`
					  Duration string `json:"duration"`
					  Playcount string `json:"playcount"`
					  Listeners string `json:"listeners"`
					  Mbid string `json:"mbid"`
					  URL string `json:"url"`
					  Streamable struct {
							   Text string `json:"#text"`
							   Fulltrack string `json:"fulltrack"`
						   } `json:"streamable"`
					  Artist struct {
							   Name string `json:"name"`

						   } `json:"artist"`
					  Image []struct {
						  Text string `json:"#text"`
						  Size string `json:"size"`
					  } `json:"image"`
					  Attr struct {
							   Rank string `json:"rank"`
						   } `json:"@attr"`
				  } `json:"track"`
				  Attr struct {
							Artist string `json:"artist"`
							Page string `json:"page"`
							Perpage string `json:"perPage"`
							Totalpages string `json:"totalPages"`
							Total string `json:"total"`
						} `json:"@attr"`
			  } `json:"toptracks"`
}

type ApiConfig struct {
	ApiKey string `json:"api_key"`
}

func resolveUrl(apiKey string, artist string, limit int) string {
	return fmt.Sprintf("http://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist=%s&api_key=%s&limit=%d&format=json", artist, apiKey, limit)
}

func readApiConfig() ApiConfig {
	data, err := ioutil.ReadFile("/Users/goranojkic/.lfm/config")
	var auth ApiConfig

	if err != nil {
		fmt.Printf("%s", err)
	}

	parseJson(data, &auth)
	return auth
}

func executeRequest(url string) (body []byte, err error) {
	response, err := http.Get(url)

	if err != nil {
		return body, err
	} else {
		defer response.Body.Close()
		var ioError error
		body, ioError = ioutil.ReadAll(response.Body)
		if ioError != nil {
			return body, ioError
		}
	}
	return body, err
}

func parseJson(jsonBody []byte, result interface{}) error {
	return json.Unmarshal(jsonBody, &result)
}

func artistSongs(apiKey string, artist string, limit int) {
	var url = resolveUrl(apiKey, artist, limit)
	body, error := executeRequest(url)

	var reponse LastFmResponse
	parseJson(body, &reponse)

	if error != nil {
		fmt.Printf("%s", error)
	} else {
		fmt.Println(reponse.Toptracks.Track[1].Name)
	}
}

func main() {
	apiConfig := readApiConfig()

	artistName := flag.String("a", "", "artist name")
	limit := flag.Int("l", 20, "limit")

	//userNames := flag.String("u", "", "last.fm user names comma separated")
	//range := flag.String("r", "", "time range you are searching for")

	flag.Parse()

	if *artistName != "" {
		artistSongs(apiConfig.ApiKey, *artistName, *limit)
	} else {
		fmt.Println("Not yet implemented")
	}

}

<|endoftext|>


<commit_before>package middlewares

import (
	"fmt"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/labstack/echo"
)

type (
	// XFrameOption type for the values of the X-Frame-Options header.
	XFrameOption string

	// CSPSource type are the different types of CSP headers sources definitions.
	// Each source type defines a different acess policy.
	CSPSource int

	// SecureConfig defines the config for Secure middleware.
	SecureConfig struct {
		HSTSMaxAge     time.Duration
		CSPDefaultSrc  []CSPSource
		CSPScriptSrc   []CSPSource
		CSPFrameSrc    []CSPSource
		CSPConnectSrc  []CSPSource
		CSPFontSrc     []CSPSource
		CSPImgSrc      []CSPSource
		CSPManifestSrc []CSPSource
		CSPMediaSrc    []CSPSource
		CSPObjectSrc   []CSPSource
		CSPStyleSrc    []CSPSource
		CSPWorkerSrc   []CSPSource
		XFrameOptions  XFrameOption
		XFrameAllowed  string
	}
)

const (
	// XFrameDeny is the DENY option of the X-Frame-Options header.
	XFrameDeny XFrameOption = "DENY"
	// XFrameSameOrigin is the SAMEORIGIN option of the X-Frame-Options header.
	XFrameSameOrigin = "SAMEORIGIN"
	// XFrameAllowFrom is the ALLOW-FROM option of the X-Frame-Options header. It
	// should be used along with the XFrameAllowed field of SecureConfig.
	XFrameAllowFrom = "ALLOW-FROM"

	// CSPSrcSelf is the 'self' option of a CSP source.
	CSPSrcSelf CSPSource = iota
	// CSPSrcParent adds the parent domain as an eligible CSP source.
	CSPSrcParent
	// CSPSrcParentSubdomains add all the parent's subdomains as eligibles CSP
	// sources.
	CSPSrcParentSubdomains
	// CSPSrcAny is the '*' option. It allows any domain as an eligible source.
	CSPSrcAny
)

// Secure returns a Middlefunc that can be used to define all the necessary
// secure headers. It is configurable with a SecureConfig object.
func Secure(conf *SecureConfig) echo.MiddlewareFunc {
	var hstsHeader string
	if conf.HSTSMaxAge > 0 {
		hstsHeader = fmt.Sprintf("max-age=%.f; includeSubdomains",
			conf.HSTSMaxAge.Seconds())
	}

	var xFrameHeader string
	switch conf.XFrameOptions {
	case XFrameDeny:
		xFrameHeader = string(XFrameDeny)
	case XFrameSameOrigin:
		xFrameHeader = string(XFrameSameOrigin)
	case XFrameAllowFrom:
		xFrameHeader = fmt.Sprintf("%s %s", XFrameAllowFrom, conf.XFrameAllowed)
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			hsts := true
			if in := c.Get("instance"); in != nil && in.(*instance.Instance).Dev {
				hsts = false
			}
			h := c.Response().Header()
			if hsts && hstsHeader != "" {
				h.Set(echo.HeaderStrictTransportSecurity, hstsHeader)
			}
			if xFrameHeader != "" {
				h.Set(echo.HeaderXFrameOptions, xFrameHeader)
			}
			var cspHeader string
			parent, _ := SplitHost(c.Request().Host)
			if len(conf.CSPDefaultSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "default-src", conf.CSPDefaultSrc)
			}
			if len(conf.CSPScriptSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "script-src", conf.CSPScriptSrc)
			}
			if len(conf.CSPFrameSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "frame-src", conf.CSPFrameSrc)
			}
			if len(conf.CSPConnectSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "connect-src", conf.CSPConnectSrc)
			}
			if len(conf.CSPFontSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "font-src", conf.CSPFontSrc)
			}
			if len(conf.CSPImgSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "img-src", conf.CSPImgSrc)
			}
			if len(conf.CSPManifestSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "manifest-src", conf.CSPManifestSrc)
			}
			if len(conf.CSPMediaSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "media-src", conf.CSPMediaSrc)
			}
			if len(conf.CSPObjectSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "object-src", conf.CSPObjectSrc)
			}
			if len(conf.CSPStyleSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "style-src", conf.CSPStyleSrc)
			}
			if len(conf.CSPWorkerSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "worker-src", conf.CSPWorkerSrc)
			}
			if cspHeader != "" {
				h.Set(echo.HeaderContentSecurityPolicy, cspHeader)
			}
			h.Set(echo.HeaderXContentTypeOptions, "nosniff")
			return next(c)
		}
	}
}

func makeCSPHeader(parent, header string, sources []CSPSource) string {
	headers := make([]string, len(sources))
	for i, src := range sources {
		switch src {
		case CSPSrcSelf:
			headers[i] = "'self'"
		case CSPSrcParent:
			headers[i] = parent
		case CSPSrcParentSubdomains:
			headers[i] = "*." + parent
		case CSPSrcAny:
			headers[i] = "*"
		}
	}
	return header + " " + strings.Join(headers, " ") + ";"
}
<commit_msg>Deactivate HSTS if context is not TLS<commit_after>package middlewares

import (
	"fmt"
	"strings"
	"time"

	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/labstack/echo"
)

type (
	// XFrameOption type for the values of the X-Frame-Options header.
	XFrameOption string

	// CSPSource type are the different types of CSP headers sources definitions.
	// Each source type defines a different acess policy.
	CSPSource int

	// SecureConfig defines the config for Secure middleware.
	SecureConfig struct {
		HSTSMaxAge     time.Duration
		CSPDefaultSrc  []CSPSource
		CSPScriptSrc   []CSPSource
		CSPFrameSrc    []CSPSource
		CSPConnectSrc  []CSPSource
		CSPFontSrc     []CSPSource
		CSPImgSrc      []CSPSource
		CSPManifestSrc []CSPSource
		CSPMediaSrc    []CSPSource
		CSPObjectSrc   []CSPSource
		CSPStyleSrc    []CSPSource
		CSPWorkerSrc   []CSPSource
		XFrameOptions  XFrameOption
		XFrameAllowed  string
	}
)

const (
	// XFrameDeny is the DENY option of the X-Frame-Options header.
	XFrameDeny XFrameOption = "DENY"
	// XFrameSameOrigin is the SAMEORIGIN option of the X-Frame-Options header.
	XFrameSameOrigin = "SAMEORIGIN"
	// XFrameAllowFrom is the ALLOW-FROM option of the X-Frame-Options header. It
	// should be used along with the XFrameAllowed field of SecureConfig.
	XFrameAllowFrom = "ALLOW-FROM"

	// CSPSrcSelf is the 'self' option of a CSP source.
	CSPSrcSelf CSPSource = iota
	// CSPSrcParent adds the parent domain as an eligible CSP source.
	CSPSrcParent
	// CSPSrcParentSubdomains add all the parent's subdomains as eligibles CSP
	// sources.
	CSPSrcParentSubdomains
	// CSPSrcAny is the '*' option. It allows any domain as an eligible source.
	CSPSrcAny
)

// Secure returns a Middlefunc that can be used to define all the necessary
// secure headers. It is configurable with a SecureConfig object.
func Secure(conf *SecureConfig) echo.MiddlewareFunc {
	var hstsHeader string
	if conf.HSTSMaxAge > 0 {
		hstsHeader = fmt.Sprintf("max-age=%.f; includeSubdomains",
			conf.HSTSMaxAge.Seconds())
	}

	var xFrameHeader string
	switch conf.XFrameOptions {
	case XFrameDeny:
		xFrameHeader = string(XFrameDeny)
	case XFrameSameOrigin:
		xFrameHeader = string(XFrameSameOrigin)
	case XFrameAllowFrom:
		xFrameHeader = fmt.Sprintf("%s %s", XFrameAllowFrom, conf.XFrameAllowed)
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c echo.Context) error {
			hsts := true
			if !c.IsTLS() {
				hsts = false
			} else if in := c.Get("instance"); in != nil && in.(*instance.Instance).Dev {
				hsts = false
			}
			h := c.Response().Header()
			if hsts && hstsHeader != "" {
				h.Set(echo.HeaderStrictTransportSecurity, hstsHeader)
			}
			if xFrameHeader != "" {
				h.Set(echo.HeaderXFrameOptions, xFrameHeader)
			}
			var cspHeader string
			parent, _ := SplitHost(c.Request().Host)
			if len(conf.CSPDefaultSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "default-src", conf.CSPDefaultSrc)
			}
			if len(conf.CSPScriptSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "script-src", conf.CSPScriptSrc)
			}
			if len(conf.CSPFrameSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "frame-src", conf.CSPFrameSrc)
			}
			if len(conf.CSPConnectSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "connect-src", conf.CSPConnectSrc)
			}
			if len(conf.CSPFontSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "font-src", conf.CSPFontSrc)
			}
			if len(conf.CSPImgSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "img-src", conf.CSPImgSrc)
			}
			if len(conf.CSPManifestSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "manifest-src", conf.CSPManifestSrc)
			}
			if len(conf.CSPMediaSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "media-src", conf.CSPMediaSrc)
			}
			if len(conf.CSPObjectSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "object-src", conf.CSPObjectSrc)
			}
			if len(conf.CSPStyleSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "style-src", conf.CSPStyleSrc)
			}
			if len(conf.CSPWorkerSrc) > 0 {
				cspHeader += makeCSPHeader(parent, "worker-src", conf.CSPWorkerSrc)
			}
			if cspHeader != "" {
				h.Set(echo.HeaderContentSecurityPolicy, cspHeader)
			}
			h.Set(echo.HeaderXContentTypeOptions, "nosniff")
			return next(c)
		}
	}
}

func makeCSPHeader(parent, header string, sources []CSPSource) string {
	headers := make([]string, len(sources))
	for i, src := range sources {
		switch src {
		case CSPSrcSelf:
			headers[i] = "'self'"
		case CSPSrcParent:
			headers[i] = parent
		case CSPSrcParentSubdomains:
			headers[i] = "*." + parent
		case CSPSrcAny:
			headers[i] = "*"
		}
	}
	return header + " " + strings.Join(headers, " ") + ";"
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The tomb package helps with clean goroutine termination.
//
// See the Tomb type for details.
package tomb

import (
	"fmt"
	"os"
	"sync"
)

type nothing struct{}

// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead,
// and the reason for its death.
//
// The clean state of a Tomb informs that a goroutine is about to be
// created or already alive. Once Fatal or Fatalf is called with an
// argument that informs the reason for death, the goroutine is in
// a dying state and is expected to terminate soon. Right before the
// goroutine function or method returns, Done must be called to inform
// that the goroutine is indeed dead and about to stop running.
//
// A Tomb exposes Dying and Dead channels. These channels are closed
// when the Tomb state changes in the respective way. They enable
// explicit blocking until the state changes, and also to selectively
// unblock select statements accordingly.
//
// For background and a detailed example, see the following blog post:
//
//   http://blog.labix.org/2011/10/09/death-of-goroutines-under-control
//
type Tomb struct {
	m      sync.Mutex
	Dying  chan nothing
	Dead   chan nothing
	reason os.Error
}

// New creates a new Tomb to track the lifecycle of a goroutine
// that is already alive or about to be created.
func New() *Tomb {
	return &Tomb{Dying: make(chan nothing), Dead: make(chan nothing)}
}

// IsDying returns true if the goroutine is in a dying or already dead state.
func (t *Tomb) IsDying() bool {
	select {
	case <-t.Dying:
		return true
	default:
	}
	return false
}

// IsDead returns true if the goroutine is in a dead state.
func (t *Tomb) IsDead() bool {
	select {
	case <-t.Dead:
		return true
	default:
	}
	return false
}

// Wait blocks until the goroutine is in a dead state and returns the
// reason for its death. The reason may be nil.
func (t *Tomb) Wait() os.Error {
	<-t.Dead
	return t.reason
}

// Done informs that the goroutine in a dead state, and should be called a
// single time right before the goroutine function or method returns.
// If the goroutine was not already in a dying state before Done is
// called, it will flagged as dying and dead at once.
func (t *Tomb) Done() {
	t.Fatal(nil)
	close(t.Dead)
}

// Fatal informs that the goroutine in a dying state.
// The first non-nil reason parameter to Fatal or the first Fatalf-generated
// error is recorded as the reason for the goroutine death.
// This method may be safely called concurrently, and may be called both from
// within the goroutine and/or from outside to request the goroutine termination.
func (t *Tomb) Fatal(reason os.Error) {
	t.m.Lock()
	if t.reason == nil {
		t.reason = reason
	}
	select {
	case <-t.Dying:
	default:
		close(t.Dying)
	}
	t.m.Unlock()
}

// Fatalf works like Fatal, but builds the reason providing the received
// arguments to fmt.Errorf. The generated error is also returned.
func (t *Tomb) Fatalf(format string, args ...interface{}) os.Error {
	err := fmt.Errorf(format, args...)
	t.Fatal(err)
	return err
}

// Err returns the reason for the goroutine death provided via Fatal or Fatalf.
func (t *Tomb) Err() (reason os.Error) {
	t.m.Lock()
	reason = t.reason
	t.m.Unlock()
	return
}
<commit_msg>Another doc tweak.<commit_after>// Copyright (c) 2011 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of the copyright holder nor the names of its
//       contributors may be used to endorse or promote products derived from
//       this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The tomb package helps with clean goroutine termination.
//
// See the Tomb type for details.
package tomb

import (
	"fmt"
	"os"
	"sync"
)

type nothing struct{}

// A Tomb tracks the lifecycle of a goroutine as alive, dying or dead,
// and the reason for its death.
//
// The clean state of a Tomb informs that a goroutine is about to be
// created or already alive. Once Fatal or Fatalf is called with an
// argument that informs the reason for death, the goroutine is in
// a dying state and is expected to terminate soon. Right before the
// goroutine function or method returns, Done must be called to inform
// that the goroutine is indeed dead and about to stop running.
//
// A Tomb exposes Dying and Dead channels. These channels are closed
// when the Tomb state changes in the respective way. They enable
// explicit blocking until the state changes, and also to selectively
// unblock select statements accordingly.
//
// For background and a detailed example, see the following blog post:
//
//   http://blog.labix.org/2011/10/09/death-of-goroutines-under-control
//
type Tomb struct {
	m      sync.Mutex
	Dying  chan nothing
	Dead   chan nothing
	reason os.Error
}

// New creates a new Tomb to track the lifecycle of a goroutine
// that is already alive or about to be created.
func New() *Tomb {
	return &Tomb{Dying: make(chan nothing), Dead: make(chan nothing)}
}

// IsDying returns true if the goroutine is in a dying or already dead state.
func (t *Tomb) IsDying() bool {
	select {
	case <-t.Dying:
		return true
	default:
	}
	return false
}

// IsDead returns true if the goroutine is in a dead state.
func (t *Tomb) IsDead() bool {
	select {
	case <-t.Dead:
		return true
	default:
	}
	return false
}

// Wait blocks until the goroutine is in a dead state and returns the
// reason for its death. The reason may be nil.
func (t *Tomb) Wait() os.Error {
	<-t.Dead
	return t.reason
}

// Done flags the goroutine as dead, and should be called a single time
// right before the goroutine function or method returns.
// If the goroutine was not already in a dying state before Done is
// called, it will flagged as dying and dead at once.
func (t *Tomb) Done() {
	t.Fatal(nil)
	close(t.Dead)
}

// Fatal flags the goroutine as dying.
// The first non-nil reason parameter to Fatal or the first Fatalf-generated
// error is recorded as the reason for the goroutine death.
// This method may be safely called concurrently, and may be called both from
// within the goroutine and/or from outside to request the goroutine termination.
func (t *Tomb) Fatal(reason os.Error) {
	t.m.Lock()
	if t.reason == nil {
		t.reason = reason
	}
	select {
	case <-t.Dying:
	default:
		close(t.Dying)
	}
	t.m.Unlock()
}

// Fatalf works like Fatal, but builds the reason providing the received
// arguments to fmt.Errorf. The generated error is also returned.
func (t *Tomb) Fatalf(format string, args ...interface{}) os.Error {
	err := fmt.Errorf(format, args...)
	t.Fatal(err)
	return err
}

// Err returns the reason for the goroutine death provided via Fatal or Fatalf.
func (t *Tomb) Err() (reason os.Error) {
	t.m.Lock()
	reason = t.reason
	t.m.Unlock()
	return
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.tools/go/exact"
	"code.google.com/p/go.tools/go/types"
	"flag"
	"fmt"
	"github.com/neelance/gopherjs/translator"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"
)

type Package struct {
	*build.Package
	SrcModTime     time.Time
	JavaScriptCode []byte
}

var BuildContext = &build.Context{
	GOROOT:        build.Default.GOROOT,
	GOPATH:        build.Default.GOPATH,
	GOOS:          build.Default.GOOS,
	GOARCH:        build.Default.GOARCH,
	Compiler:      "gc",
	InstallSuffix: "js",
}
var TypesConfig = &types.Config{
	Packages: make(map[string]*types.Package),
}
var FileSet = token.NewFileSet()
var Packages = make(map[string]*Package)
var InstallMode = false

func main() {
	flag.Parse()

	cmd := flag.Arg(0)
	switch cmd {
	case "build":
		basename := path.Base(flag.Arg(1))
		err := Build(flag.Arg(1), basename[:len(basename)-3]+".js")
		HandleError(err)
		os.Exit(0)

	case "install":
		err := Install(flag.Arg(1))
		HandleError(err)
		os.Exit(0)

	case "run":
		tempfile, err := ioutil.TempFile("", path.Base(flag.Arg(1))+".")
		HandleError(err)
		defer func() {
			tempfile.Close()
			os.Remove(tempfile.Name())
		}()
		err = Build(flag.Arg(1), tempfile.Name())
		HandleError(err)

		node := exec.Command("node", append([]string{tempfile.Name()}, flag.Args()[2:]...)...)
		node.Stdin = os.Stdin
		node.Stdout = os.Stdout
		node.Stderr = os.Stderr
		if err = node.Run(); err != nil {
			if e, isExitError := err.(*exec.ExitError); isExitError {
				os.Exit(e.Sys().(syscall.WaitStatus).ExitStatus())
			}
			HandleError(err)
		}
		os.Exit(0)

	case "tool":
		tool := flag.Arg(1)
		toolFlags := flag.NewFlagSet("tool", flag.ContinueOnError)
		toolFlags.Bool("e", false, "")
		toolFlags.Bool("l", false, "")
		toolFlags.Bool("m", false, "")
		toolFlags.String("o", "", "")
		toolFlags.String("D", "", "")
		toolFlags.String("I", "", "")
		toolFlags.Parse(flag.Args()[2:])
		if len(tool) == 2 {
			switch tool[1] {
			case 'g':
				basename := path.Base(toolFlags.Arg(0))
				err := Build(toolFlags.Arg(0), basename[:len(basename)-3]+".js")
				HandleError(err)
				os.Exit(0)
			}
		}
		fmt.Fprintln(os.Stderr, "Tool not supported: "+tool)
		os.Exit(1)

	case "help", "":
		os.Stderr.WriteString(`GopherJS is a tool for compiling Go source code to JavaScript.

Usage:

    gopherjs command [arguments]

The commands are:

    build       compile packages and dependencies
    install     compile and install packages and dependencies
    run         compile and run Go program

`)
		os.Exit(0)

	default:
		fmt.Fprintf(os.Stderr, "gopherjs: unknown subcommand \"%s\"\nRun 'gopherjs help' for usage.\n", cmd)
		os.Exit(1)
	}
}

func HandleError(err error) {
	if err == nil {
		return
	}
	if list, isList := err.(translator.ErrorList); isList {
		for _, entry := range list {
			fmt.Fprintln(os.Stderr, entry)
		}
		os.Exit(1)
	}
	fmt.Fprintln(os.Stderr, err.Error())
	os.Exit(1)
}

func Build(filename, pkgObj string) error {
	file, err := parser.ParseFile(FileSet, filename, nil, parser.ImportsOnly)
	if err != nil {
		return err
	}

	imports := make([]string, len(file.Imports))
	for i, imp := range file.Imports {
		imports[i] = imp.Path.Value[1 : len(imp.Path.Value)-1]
	}

	pkg := &Package{
		Package: &build.Package{
			Name:       "main",
			ImportPath: "main",
			Imports:    imports,
			Dir:        path.Dir(filename),
			GoFiles:    []string{path.Base(filename)},
			PkgObj:     pkgObj,
		},
	}
	return BuildPackage(pkg)
}

func Install(filename string) error {
	buildPkg, err := BuildContext.Import(filename, "", 0)
	if err != nil {
		return err
	}
	pkg := &Package{Package: buildPkg}
	if pkg.IsCommand() {
		pkg.PkgObj = pkg.BinDir + "/" + path.Base(pkg.ImportPath) + ".js"
	}
	InstallMode = true
	return BuildPackage(pkg)
}

func BuildPackage(pkg *Package) error {
	if pkg.ImportPath == "unsafe" {
		TypesConfig.Packages["unsafe"] = types.Unsafe
		return nil
	}

	TypesConfig.Import = func(imports map[string]*types.Package, path string) (*types.Package, error) {
		if _, found := Packages[path]; found {
			return imports[path], nil
		}

		otherPkg, err := BuildContext.Import(path, pkg.Dir, build.AllowBinary)
		if err != nil {
			return nil, err
		}
		pkg := &Package{Package: otherPkg}
		Packages[path] = pkg
		if err := BuildPackage(pkg); err != nil {
			return nil, err
		}

		return imports[path], nil
	}

	if InstallMode {
		if fileInfo, err := os.Stat(os.Args[0]); err == nil { // gopherjs itself
			pkg.SrcModTime = fileInfo.ModTime()
		}

		for _, importedPkgPath := range pkg.Imports {
			_, err := TypesConfig.Import(TypesConfig.Packages, importedPkgPath)
			if err != nil {
				return err
			}
			impModeTime := Packages[importedPkgPath].SrcModTime
			if impModeTime.After(pkg.SrcModTime) {
				pkg.SrcModTime = impModeTime
			}
		}

		for _, name := range pkg.GoFiles {
			fileInfo, err := os.Stat(pkg.Dir + "/" + name)
			if err != nil {
				return err
			}
			if fileInfo.ModTime().After(pkg.SrcModTime) {
				pkg.SrcModTime = fileInfo.ModTime()
			}
		}

		pkgObjFileInfo, err := os.Stat(pkg.PkgObj)
		if err == nil && !pkg.SrcModTime.After(pkgObjFileInfo.ModTime()) {
			// package object is up to date, load from disk if library
			if pkg.IsCommand() {
				return nil
			}

			objFile, err := os.Open(pkg.PkgObj)
			if err != nil {
				return err
			}
			defer objFile.Close()

			pkg.JavaScriptCode, _, err = translator.ReadArchive(TypesConfig.Packages, pkg.PkgObj, pkg.ImportPath, objFile)
			if err != nil {
				return err
			}

			return nil
		}
	}

	files := make([]*ast.File, 0)
	var errList translator.ErrorList
	for _, name := range pkg.GoFiles {
		fullName := pkg.Dir + "/" + name
		r, err := os.Open(fullName)
		if err != nil {
			return err
		}
		file, err := parser.ParseFile(FileSet, fullName, r, 0)
		r.Close()
		if err != nil {
			if list, isList := err.(scanner.ErrorList); isList {
				for _, entry := range list {
					errList = append(errList, entry)
				}
				continue
			}
			errList = append(errList, err)
			continue
		}
		files = append(files, file)
	}
	if errList != nil {
		return errList
	}

	var err error
	pkg.JavaScriptCode, err = translator.TranslatePackage(pkg.ImportPath, files, FileSet, TypesConfig)
	if err != nil {
		return err
	}

	if !pkg.IsCommand() {
		if InstallMode {
			if err := os.MkdirAll(path.Dir(pkg.PkgObj), 0777); err != nil {
				return err
			}
			file, err := os.Create(pkg.PkgObj)
			if err != nil {
				return err
			}
			defer file.Close()
			translator.WriteArchive(pkg.JavaScriptCode, TypesConfig.Packages[pkg.ImportPath], file)
		}
		return nil
	}

	webMode := false
	webModeConst := TypesConfig.Packages[pkg.ImportPath].Scope().Lookup("gopherjsWebMode")
	if webModeConst != nil {
		webMode = exact.BoolVal(webModeConst.(*types.Const).Val())
	}

	if err := os.MkdirAll(path.Dir(pkg.PkgObj), 0777); err != nil {
		return err
	}
	var perm os.FileMode = 0666
	if !webMode {
		perm = 0777
	}
	file, err := os.OpenFile(pkg.PkgObj, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	defer file.Close()

	if !webMode {
		fmt.Fprintln(file, "#!/usr/bin/env node")
	}
	fmt.Fprintln(file, `"use strict";`)
	fmt.Fprintf(file, "var Go$webMode = %t;\n", webMode)
	file.WriteString(strings.TrimSpace(translator.Prelude))
	file.WriteString("\n")

	Packages[pkg.ImportPath] = pkg
	dependencies, err := translator.GetAllDependencies(pkg.ImportPath, TypesConfig)
	if err != nil {
		return err
	}

	for _, dep := range dependencies {
		file.WriteString("Go$packages[\"" + dep.Path() + "\"] = (function() {\n")
		file.Write(Packages[dep.Path()].JavaScriptCode)
		file.WriteString("})();\n")
	}

	translator.WriteInterfaces(dependencies, file, false)

	for _, dep := range dependencies {
		file.WriteString("Go$packages[\"" + dep.Path() + "\"].init();\n")
	}
	file.WriteString("Go$packages[\"" + pkg.ImportPath + "\"].main();\n")

	return nil
}
<commit_msg>tool: Allow multiple file/path arguments.<commit_after>package main

import (
	"code.google.com/p/go.tools/go/exact"
	"code.google.com/p/go.tools/go/types"
	"flag"
	"fmt"
	"github.com/neelance/gopherjs/translator"
	"go/ast"
	"go/build"
	"go/parser"
	"go/scanner"
	"go/token"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"
	"syscall"
	"time"
)

type Package struct {
	*build.Package
	SrcModTime     time.Time
	JavaScriptCode []byte
}

var BuildContext = &build.Context{
	GOROOT:        build.Default.GOROOT,
	GOPATH:        build.Default.GOPATH,
	GOOS:          build.Default.GOOS,
	GOARCH:        build.Default.GOARCH,
	Compiler:      "gc",
	InstallSuffix: "js",
}
var TypesConfig = &types.Config{
	Packages: make(map[string]*types.Package),
}
var FileSet = token.NewFileSet()
var Packages = make(map[string]*Package)
var InstallMode = false

func main() {
	flag.Parse()

	cmd := flag.Arg(0)
	switch cmd {
	case "build":
		basename := path.Base(flag.Arg(1))
		err := Build(flag.Args()[1:], basename[:len(basename)-3]+".js")
		HandleError(err)
		os.Exit(0)

	case "install":
		for _, pkgPath := range flag.Args()[1:] {
			err := Install(pkgPath)
			HandleError(err)
		}
		os.Exit(0)

	case "run":
		tempfile, err := ioutil.TempFile("", path.Base(flag.Arg(1))+".")
		HandleError(err)
		defer func() {
			tempfile.Close()
			os.Remove(tempfile.Name())
		}()
		err = Build(flag.Args()[1:], tempfile.Name())
		HandleError(err)

		node := exec.Command("node", append([]string{tempfile.Name()}, flag.Args()[2:]...)...)
		node.Stdin = os.Stdin
		node.Stdout = os.Stdout
		node.Stderr = os.Stderr
		if err = node.Run(); err != nil {
			if e, isExitError := err.(*exec.ExitError); isExitError {
				os.Exit(e.Sys().(syscall.WaitStatus).ExitStatus())
			}
			HandleError(err)
		}
		os.Exit(0)

	case "tool":
		tool := flag.Arg(1)
		toolFlags := flag.NewFlagSet("tool", flag.ContinueOnError)
		toolFlags.Bool("e", false, "")
		toolFlags.Bool("l", false, "")
		toolFlags.Bool("m", false, "")
		toolFlags.String("o", "", "")
		toolFlags.String("D", "", "")
		toolFlags.String("I", "", "")
		toolFlags.Parse(flag.Args()[2:])
		if len(tool) == 2 {
			switch tool[1] {
			case 'g':
				basename := path.Base(toolFlags.Arg(0))
				err := Build([]string{toolFlags.Arg(0)}, basename[:len(basename)-3]+".js")
				HandleError(err)
				os.Exit(0)
			}
		}
		fmt.Fprintln(os.Stderr, "Tool not supported: "+tool)
		os.Exit(1)

	case "help", "":
		os.Stderr.WriteString(`GopherJS is a tool for compiling Go source code to JavaScript.

Usage:

    gopherjs command [arguments]

The commands are:

    build       compile packages and dependencies
    install     compile and install packages and dependencies
    run         compile and run Go program

`)
		os.Exit(0)

	default:
		fmt.Fprintf(os.Stderr, "gopherjs: unknown subcommand \"%s\"\nRun 'gopherjs help' for usage.\n", cmd)
		os.Exit(1)
	}
}

func HandleError(err error) {
	if err == nil {
		return
	}
	if list, isList := err.(translator.ErrorList); isList {
		for _, entry := range list {
			fmt.Fprintln(os.Stderr, entry)
		}
		os.Exit(1)
	}
	fmt.Fprintln(os.Stderr, err.Error())
	os.Exit(1)
}

func Build(filenames []string, pkgObj string) error {
	wd, err := os.Getwd()
	if err != nil {
		return err
	}
	pkg := &Package{
		Package: &build.Package{
			Name:       "main",
			ImportPath: "main",
			Dir:        wd,
			GoFiles:    filenames,
			PkgObj:     pkgObj,
		},
	}
	return BuildPackage(pkg)
}

func Install(pkgPath string) error {
	buildPkg, err := BuildContext.Import(pkgPath, "", 0)
	if err != nil {
		return err
	}
	pkg := &Package{Package: buildPkg}
	if pkg.IsCommand() {
		pkg.PkgObj = pkg.BinDir + "/" + path.Base(pkg.ImportPath) + ".js"
	}
	InstallMode = true
	return BuildPackage(pkg)
}

func BuildPackage(pkg *Package) error {
	if pkg.ImportPath == "unsafe" {
		TypesConfig.Packages["unsafe"] = types.Unsafe
		return nil
	}

	TypesConfig.Import = func(imports map[string]*types.Package, path string) (*types.Package, error) {
		if _, found := Packages[path]; found {
			return imports[path], nil
		}

		otherPkg, err := BuildContext.Import(path, pkg.Dir, build.AllowBinary)
		if err != nil {
			return nil, err
		}
		pkg := &Package{Package: otherPkg}
		Packages[path] = pkg
		if err := BuildPackage(pkg); err != nil {
			return nil, err
		}

		return imports[path], nil
	}

	if InstallMode {
		if fileInfo, err := os.Stat(os.Args[0]); err == nil { // gopherjs itself
			pkg.SrcModTime = fileInfo.ModTime()
		}

		for _, importedPkgPath := range pkg.Imports {
			_, err := TypesConfig.Import(TypesConfig.Packages, importedPkgPath)
			if err != nil {
				return err
			}
			impModeTime := Packages[importedPkgPath].SrcModTime
			if impModeTime.After(pkg.SrcModTime) {
				pkg.SrcModTime = impModeTime
			}
		}

		for _, name := range pkg.GoFiles {
			fileInfo, err := os.Stat(pkg.Dir + "/" + name)
			if err != nil {
				return err
			}
			if fileInfo.ModTime().After(pkg.SrcModTime) {
				pkg.SrcModTime = fileInfo.ModTime()
			}
		}

		pkgObjFileInfo, err := os.Stat(pkg.PkgObj)
		if err == nil && !pkg.SrcModTime.After(pkgObjFileInfo.ModTime()) {
			// package object is up to date, load from disk if library
			if pkg.IsCommand() {
				return nil
			}

			objFile, err := os.Open(pkg.PkgObj)
			if err != nil {
				return err
			}
			defer objFile.Close()

			pkg.JavaScriptCode, _, err = translator.ReadArchive(TypesConfig.Packages, pkg.PkgObj, pkg.ImportPath, objFile)
			if err != nil {
				return err
			}

			return nil
		}
	}

	files := make([]*ast.File, 0)
	var errList translator.ErrorList
	for _, name := range pkg.GoFiles {
		if !path.IsAbs(name) {
			name = path.Join(pkg.Dir, name)
		}
		r, err := os.Open(name)
		if err != nil {
			return err
		}
		file, err := parser.ParseFile(FileSet, name, r, 0)
		r.Close()
		if err != nil {
			if list, isList := err.(scanner.ErrorList); isList {
				for _, entry := range list {
					errList = append(errList, entry)
				}
				continue
			}
			errList = append(errList, err)
			continue
		}
		files = append(files, file)
	}
	if errList != nil {
		return errList
	}

	var err error
	pkg.JavaScriptCode, err = translator.TranslatePackage(pkg.ImportPath, files, FileSet, TypesConfig)
	if err != nil {
		return err
	}

	if !pkg.IsCommand() {
		if InstallMode {
			if err := os.MkdirAll(path.Dir(pkg.PkgObj), 0777); err != nil {
				return err
			}
			file, err := os.Create(pkg.PkgObj)
			if err != nil {
				return err
			}
			defer file.Close()
			translator.WriteArchive(pkg.JavaScriptCode, TypesConfig.Packages[pkg.ImportPath], file)
		}
		return nil
	}

	webMode := false
	webModeConst := TypesConfig.Packages[pkg.ImportPath].Scope().Lookup("gopherjsWebMode")
	if webModeConst != nil {
		webMode = exact.BoolVal(webModeConst.(*types.Const).Val())
	}

	if err := os.MkdirAll(path.Dir(pkg.PkgObj), 0777); err != nil {
		return err
	}
	var perm os.FileMode = 0666
	if !webMode {
		perm = 0777
	}
	file, err := os.OpenFile(pkg.PkgObj, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	defer file.Close()

	if !webMode {
		fmt.Fprintln(file, "#!/usr/bin/env node")
	}
	fmt.Fprintln(file, `"use strict";`)
	fmt.Fprintf(file, "var Go$webMode = %t;\n", webMode)
	file.WriteString(strings.TrimSpace(translator.Prelude))
	file.WriteString("\n")

	Packages[pkg.ImportPath] = pkg
	dependencies, err := translator.GetAllDependencies(pkg.ImportPath, TypesConfig)
	if err != nil {
		return err
	}

	for _, dep := range dependencies {
		file.WriteString("Go$packages[\"" + dep.Path() + "\"] = (function() {\n")
		file.Write(Packages[dep.Path()].JavaScriptCode)
		file.WriteString("})();\n")
	}

	translator.WriteInterfaces(dependencies, file, false)

	for _, dep := range dependencies {
		file.WriteString("Go$packages[\"" + dep.Path() + "\"].init();\n")
	}
	file.WriteString("Go$packages[\"" + pkg.ImportPath + "\"].main();\n")

	return nil
}
<|endoftext|>


<commit_before>package discordgo

import (
	"fmt"
	"strings"
)

// A User stores all data for an individual Discord user.
type User struct {
	ID            string `json:"id"`
	Email         string `json:"email"`
	Username      string `json:"username"`
	Avatar        string `json:"avatar"`
	Discriminator string `json:"discriminator"`
	Token         string `json:"token"`
	Verified      bool   `json:"verified"`
	MFAEnabled    bool   `json:"mfa_enabled"`
	Bot           bool   `json:"bot"`
}

// String returns a unique identifier of the form username#discriminator
func (u *User) String() string {
	return fmt.Sprintf("%s#%s", u.Username, u.Discriminator)
}

// Mention return a string which mentions the user
func (u *User) Mention() string {
	return fmt.Sprintf("<@%s>", u.ID)
}

// AvatarURL returns a URL to the user's avatar.
//    size:    The size of the user's avatar as a power of two
//             if size is an empty string, no size parameter will
//             be added to the URL.
func (u *User) AvatarURL(size string) string {
	var URL string
	if strings.HasPrefix(u.Avatar, "a_") {
		URL = EndpointUserAvatarAnimated(u.ID, u.Avatar)
	} else {
		URL = EndpointUserAvatar(u.ID, u.Avatar)
	}

	if size != "" {
		return URL + "?size=" + size
	}
	return URL
}
<commit_msg>gofmt :)<commit_after>package discordgo

import (
	"fmt"
	"strings"
)

// A User stores all data for an individual Discord user.
type User struct {
	ID            string `json:"id"`
	Email         string `json:"email"`
	Username      string `json:"username"`
	Avatar        string `json:"avatar"`
	Discriminator string `json:"discriminator"`
	Token         string `json:"token"`
	Verified      bool   `json:"verified"`
	MFAEnabled    bool   `json:"mfa_enabled"`
	Bot           bool   `json:"bot"`
}

// String returns a unique identifier of the form username#discriminator
func (u *User) String() string {
	return fmt.Sprintf("%s#%s", u.Username, u.Discriminator)
}

// Mention return a string which mentions the user
func (u *User) Mention() string {
	return fmt.Sprintf("<@%s>", u.ID)
}

// AvatarURL returns a URL to the user's avatar.
//    size:    The size of the user's avatar as a power of two
//             if size is an empty string, no size parameter will
//             be added to the URL.
func (u *User) AvatarURL(size string) string {
	var URL string
	if strings.HasPrefix(u.Avatar, "a_") {
		URL = EndpointUserAvatarAnimated(u.ID, u.Avatar)
	} else {
		URL = EndpointUserAvatar(u.ID, u.Avatar)
	}

	if size != "" {
		return URL + "?size=" + size
	}
	return URL
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// Runs a command in dir.
// The name and args are as in exec.Command.
// Stdout, stderr, and the environment are inherited
// from the current process.
func runIn(dir, name string, args ...string) error {
	_, err := runInWithOutput(dir, name, args...)
	return err
}

func runInWithOutput(dir, name string, args ...string) (string, error) {
	c := exec.Command(name, args...)
	c.Dir = dir
	o, err := c.CombinedOutput()

	if debug {
		fmt.Printf("execute: %+v\n", c)
		fmt.Printf(" output: %s\n", string(o))
	}

	return string(o), err
}

// driveLetterToUpper converts Windows path's drive letters to uppercase. This
// is needed when comparing 2 paths with different drive letter case.
func driveLetterToUpper(path string) string {
	if runtime.GOOS != "windows" || path == "" {
		return path
	}

	p := path

	// If path's drive letter is lowercase, change it to uppercase.
	if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
		p = string(p[0]+'A'-'a') + p[1:]
	}

	return p
}

// clean the path and ensure that a drive letter is upper case (if it exists).
func cleanPath(path string) string {
	return driveLetterToUpper(filepath.Clean(path))
}

// deal with case insensitive filesystems and other weirdness
func pathEqual(a, b string) bool {
	a = cleanPath(a)
	b = cleanPath(b)
	return strings.EqualFold(a, b)
}
<commit_msg>Added symlink evaluating to pathEqual<commit_after>package main

import (
	"fmt"
	"log"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
)

// Runs a command in dir.
// The name and args are as in exec.Command.
// Stdout, stderr, and the environment are inherited
// from the current process.
func runIn(dir, name string, args ...string) error {
	_, err := runInWithOutput(dir, name, args...)
	return err
}

func runInWithOutput(dir, name string, args ...string) (string, error) {
	c := exec.Command(name, args...)
	c.Dir = dir
	o, err := c.CombinedOutput()

	if debug {
		fmt.Printf("execute: %+v\n", c)
		fmt.Printf(" output: %s\n", string(o))
	}

	return string(o), err
}

// driveLetterToUpper converts Windows path's drive letters to uppercase. This
// is needed when comparing 2 paths with different drive letter case.
func driveLetterToUpper(path string) string {
	if runtime.GOOS != "windows" || path == "" {
		return path
	}

	p := path

	// If path's drive letter is lowercase, change it to uppercase.
	if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
		p = string(p[0]+'A'-'a') + p[1:]
	}

	return p
}

// clean the path and ensure that a drive letter is upper case (if it exists).
func cleanPath(path string) string {
	return driveLetterToUpper(filepath.Clean(path))
}

// deal with case insensitive filesystems and other weirdness
func pathEqual(a, b string) bool {
	a = cleanPath(a)
	b = cleanPath(b)

	var err error
	a, err = filepath.EvalSymlinks(a)
	if err != nil {
		log.Printf("failed to evaluate symlink: %s: %v", a, err)
		return false
	}
	b, err = filepath.EvalSymlinks(b)
	if err != nil {
		log.Printf("failed to evaluate symlink: %s: %v", b, err)
		return false
	}

	return strings.EqualFold(a, b)
}
<|endoftext|>