<commit_before>// Copyright 2011 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.

// TODO: Dashboard upload

package main

import (
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

var cmdGet = &Command{
	UsageLine: "get [-d] [-fix] [-t] [-u] [build flags] [packages]",
	Short:     "download and install packages and dependencies",
	Long: `
Get downloads and installs the packages named by the import paths,
along with their dependencies.

The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.

The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.

The -t flag instructs get to also download the packages required to build
the tests for the specified packages.

The -u flag instructs get to use the network to update the named packages
and their dependencies.  By default, get uses the network to check out
missing packages but does not use it to look for updates to existing packages.

Get also accepts all the flags in the 'go build' and 'go install' commands,
to control the installation. See 'go help build'.

When checking out or updating a package, get looks for a branch or tag
that matches the locally installed version of Go. The most important
rule is that if the local installation is running version "go1", get
searches for a branch or tag named "go1". If no such version exists it
retrieves the most recent version of the package.

For more about specifying packages, see 'go help packages'.

For more about how 'go get' finds source code to
download, see 'go help importpath'.

See also: go build, go install, go clean.
	`,
}

var getD = cmdGet.Flag.Bool("d", false, "")
var getT = cmdGet.Flag.Bool("t", false, "")
var getU = cmdGet.Flag.Bool("u", false, "")
var getFix = cmdGet.Flag.Bool("fix", false, "")

func init() {
	addBuildFlags(cmdGet)
	cmdGet.Run = runGet // break init loop
}

func runGet(cmd *Command, args []string) {
	// Phase 1.  Download/update.
	var stk importStack
	for _, arg := range downloadPaths(args) {
		download(arg, &stk, *getT)
	}
	exitIfErrors()

	// Phase 2. Rescan packages and reevaluate args list.

	// Code we downloaded and all code that depends on it
	// needs to be evicted from the package cache so that
	// the information will be recomputed.  Instead of keeping
	// track of the reverse dependency information, evict
	// everything.
	for name := range packageCache {
		delete(packageCache, name)
	}

	args = importPaths(args)

	// Phase 3.  Install.
	if *getD {
		// Download only.
		// Check delayed until now so that importPaths
		// has a chance to print errors.
		return
	}

	runInstall(cmd, args)
}

// downloadPaths prepares the list of paths to pass to download.
// It expands ... patterns that can be expanded.  If there is no match
// for a particular pattern, downloadPaths leaves it in the result list,
// in the hope that we can figure out the repository from the
// initial ...-free prefix.
func downloadPaths(args []string) []string {
	args = importPathsNoDotExpansion(args)
	var out []string
	for _, a := range args {
		if strings.Contains(a, "...") {
			var expand []string
			// Use matchPackagesInFS to avoid printing
			// warnings.  They will be printed by the
			// eventual call to importPaths instead.
			if build.IsLocalImport(a) {
				expand = matchPackagesInFS(a)
			} else {
				expand = matchPackages(a)
			}
			if len(expand) > 0 {
				out = append(out, expand...)
				continue
			}
		}
		out = append(out, a)
	}
	return out
}

// downloadCache records the import paths we have already
// considered during the download, to avoid duplicate work when
// there is more than one dependency sequence leading to
// a particular package.
var downloadCache = map[string]bool{}

// downloadRootCache records the version control repository
// root directories we have already considered during the download.
// For example, all the packages in the code.google.com/p/codesearch repo
// share the same root (the directory for that path), and we only need
// to run the hg commands to consider each repository once.
var downloadRootCache = map[string]bool{}

// download runs the download half of the get command
// for the package named by the argument.
func download(arg string, stk *importStack, getTestDeps bool) {
	p := loadPackage(arg, stk)
	if p.Error != nil {
		errorf("%s", p.Error)
		return
	}

	// There's nothing to do if this is a package in the standard library.
	if p.Standard {
		return
	}

	// Only process each package once.
	if downloadCache[arg] {
		return
	}
	downloadCache[arg] = true

	pkgs := []*Package{p}
	wildcardOkay := len(*stk) == 0
	isWildcard := false

	// Download if the package is missing, or update if we're using -u.
	if p.Dir == "" || *getU {
		// The actual download.
		stk.push(p.ImportPath)
		err := downloadPackage(p)
		if err != nil {
			errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
			stk.pop()
			return
		}

		args := []string{arg}
		// If the argument has a wildcard in it, re-evaluate the wildcard.
		// We delay this until after reloadPackage so that the old entry
		// for p has been replaced in the package cache.
		if wildcardOkay && strings.Contains(arg, "...") {
			if build.IsLocalImport(arg) {
				args = matchPackagesInFS(arg)
			} else {
				args = matchPackages(arg)
			}
			isWildcard = true
		}

		// Clear all relevant package cache entries before
		// doing any new loads.
		for _, arg := range args {
			p := packageCache[arg]
			if p != nil {
				delete(packageCache, p.Dir)
				delete(packageCache, p.ImportPath)
			}
		}

		pkgs = pkgs[:0]
		for _, arg := range args {
			stk.push(arg)
			p := loadPackage(arg, stk)
			stk.pop()
			if p.Error != nil {
				errorf("%s", p.Error)
				continue
			}
			pkgs = append(pkgs, p)
		}
	}

	// Process package, which might now be multiple packages
	// due to wildcard expansion.
	for _, p := range pkgs {
		if *getFix {
			run(stringList(tool("fix"), relPaths(p.allgofiles)))

			// The imports might have changed, so reload again.
			p = reloadPackage(arg, stk)
			if p.Error != nil {
				errorf("%s", p.Error)
				return
			}
		}

		if isWildcard {
			// Report both the real package and the
			// wildcard in any error message.
			stk.push(p.ImportPath)
		}

		// Process dependencies, now that we know what they are.
		for _, dep := range p.deps {
			// Don't get test dependencies recursively.
			download(dep.ImportPath, stk, false)
		}
		if getTestDeps {
			// Process test dependencies when -t is specified.
			// (Don't get test dependencies for test dependencies.)
			for _, path := range p.TestImports {
				download(path, stk, false)
			}
			for _, path := range p.XTestImports {
				download(path, stk, false)
			}
		}

		if isWildcard {
			stk.pop()
		}
	}
}

// downloadPackage runs the create or download command
// to make the first copy of or update a copy of the given package.
func downloadPackage(p *Package) error {
	var (
		vcs            *vcsCmd
		repo, rootPath string
		err            error
	)
	if p.build.SrcRoot != "" {
		// Directory exists.  Look for checkout along path to src.
		vcs, rootPath, err = vcsForDir(p)
		if err != nil {
			return err
		}
		repo = "<local>" // should be unused; make distinctive
	} else {
		// Analyze the import path to determine the version control system,
		// repository, and the import path for the root of the repository.
		rr, err := repoRootForImportPath(p.ImportPath)
		if err != nil {
			return err
		}
		vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
	}

	if p.build.SrcRoot == "" {
		// Package not found.  Put in first directory of $GOPATH.
		list := filepath.SplitList(buildContext.GOPATH)
		if len(list) == 0 {
			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
		}
		// Guard against people setting GOPATH=$GOROOT.
		if list[0] == goroot {
			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath")
		}
		p.build.SrcRoot = filepath.Join(list[0], "src")
		p.build.PkgRoot = filepath.Join(list[0], "pkg")
	}
	root := filepath.Join(p.build.SrcRoot, rootPath)
	// If we've considered this repository already, don't do it again.
	if downloadRootCache[root] {
		return nil
	}
	downloadRootCache[root] = true

	if buildV {
		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
	}

	// Check that this is an appropriate place for the repo to be checked out.
	// The target directory must either not exist or have a repo checked out already.
	meta := filepath.Join(root, "."+vcs.cmd)
	st, err := os.Stat(meta)
	if err == nil && !st.IsDir() {
		return fmt.Errorf("%s exists but is not a directory", meta)
	}
	if err != nil {
		// Metadata directory does not exist.  Prepare to checkout new copy.
		// Some version control tools require the target directory not to exist.
		// We require that too, just to avoid stepping on existing work.
		if _, err := os.Stat(root); err == nil {
			return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
		}
		// Some version control tools require the parent of the target to exist.
		parent, _ := filepath.Split(root)
		if err = os.MkdirAll(parent, 0777); err != nil {
			return err
		}
		if err = vcs.create(root, repo); err != nil {
			return err
		}
	} else {
		// Metadata directory does exist; download incremental updates.
		if err = vcs.download(root); err != nil {
			return err
		}
	}

	if buildN {
		// Do not show tag sync in -n; it's noise more than anything,
		// and since we're not running commands, no tag will be found.
		// But avoid printing nothing.
		fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
		return nil
	}

	// Select and sync to appropriate version of the repository.
	tags, err := vcs.tags(root)
	if err != nil {
		return err
	}
	vers := runtime.Version()
	if i := strings.Index(vers, " "); i >= 0 {
		vers = vers[:i]
	}
	if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
		return err
	}

	return nil
}

// goTag matches go release tags such as go1 and go1.2.3.
// The numbers involved must be small (at most 4 digits),
// have no unnecessary leading zeros, and the version cannot
// end in .0 - it is go1, not go1.0 or go1.0.0.
var goTag = regexp.MustCompile(
	`^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
)

// selectTag returns the closest matching tag for a given version.
// Closest means the latest one that is not after the current release.
// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
//
// NOTE(rsc): Eventually we will need to decide on some logic here.
// For now, there is only "go1".  This matches the docs in go help get.
func selectTag(goVersion string, tags []string) (match string) {
	for _, t := range tags {
		if t == "go1" {
			return "go1"
		}
	}
	return ""

	/*
		if goTag.MatchString(goVersion) {
			v := goVersion
			for _, t := range tags {
				if !goTag.MatchString(t) {
					continue
				}
				if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
					match = t
				}
			}
		}

		return match
	*/
}

// cmpGoVersion returns -1, 0, +1 reporting whether
// x < y, x == y, or x > y.
func cmpGoVersion(x, y string) int {
	// Malformed strings compare less than well-formed strings.
	if !goTag.MatchString(x) {
		return -1
	}
	if !goTag.MatchString(y) {
		return +1
	}

	// Compare numbers in sequence.
	xx := strings.Split(x[len("go"):], ".")
	yy := strings.Split(y[len("go"):], ".")

	for i := 0; i < len(xx) && i < len(yy); i++ {
		// The Atoi are guaranteed to succeed
		// because the versions match goTag.
		xi, _ := strconv.Atoi(xx[i])
		yi, _ := strconv.Atoi(yy[i])
		if xi < yi {
			return -1
		} else if xi > yi {
			return +1
		}
	}

	if len(xx) < len(yy) {
		return -1
	}
	if len(xx) > len(yy) {
		return +1
	}
	return 0
}
<commit_msg>undo CL 87300043 / 1dc800571456<commit_after>// Copyright 2011 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.

// TODO: Dashboard upload

package main

import (
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
)

var cmdGet = &Command{
	UsageLine: "get [-d] [-fix] [-t] [-u] [build flags] [packages]",
	Short:     "download and install packages and dependencies",
	Long: `
Get downloads and installs the packages named by the import paths,
along with their dependencies.

The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.

The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.

The -t flag instructs get to also download the packages required to build
the tests for the specified packages.

The -u flag instructs get to use the network to update the named packages
and their dependencies.  By default, get uses the network to check out
missing packages but does not use it to look for updates to existing packages.

Get also accepts all the flags in the 'go build' and 'go install' commands,
to control the installation. See 'go help build'.

When checking out or updating a package, get looks for a branch or tag
that matches the locally installed version of Go. The most important
rule is that if the local installation is running version "go1", get
searches for a branch or tag named "go1". If no such version exists it
retrieves the most recent version of the package.

For more about specifying packages, see 'go help packages'.

For more about how 'go get' finds source code to
download, see 'go help importpath'.

See also: go build, go install, go clean.
	`,
}

var getD = cmdGet.Flag.Bool("d", false, "")
var getT = cmdGet.Flag.Bool("t", false, "")
var getU = cmdGet.Flag.Bool("u", false, "")
var getFix = cmdGet.Flag.Bool("fix", false, "")

func init() {
	addBuildFlags(cmdGet)
	cmdGet.Run = runGet // break init loop
}

func runGet(cmd *Command, args []string) {
	// Phase 1.  Download/update.
	var stk importStack
	for _, arg := range downloadPaths(args) {
		download(arg, &stk, *getT)
	}
	exitIfErrors()

	// Phase 2. Rescan packages and reevaluate args list.

	// Code we downloaded and all code that depends on it
	// needs to be evicted from the package cache so that
	// the information will be recomputed.  Instead of keeping
	// track of the reverse dependency information, evict
	// everything.
	for name := range packageCache {
		delete(packageCache, name)
	}

	args = importPaths(args)

	// Phase 3.  Install.
	if *getD {
		// Download only.
		// Check delayed until now so that importPaths
		// has a chance to print errors.
		return
	}

	runInstall(cmd, args)
}

// downloadPaths prepares the list of paths to pass to download.
// It expands ... patterns that can be expanded.  If there is no match
// for a particular pattern, downloadPaths leaves it in the result list,
// in the hope that we can figure out the repository from the
// initial ...-free prefix.
func downloadPaths(args []string) []string {
	args = importPathsNoDotExpansion(args)
	var out []string
	for _, a := range args {
		if strings.Contains(a, "...") {
			var expand []string
			// Use matchPackagesInFS to avoid printing
			// warnings.  They will be printed by the
			// eventual call to importPaths instead.
			if build.IsLocalImport(a) {
				expand = matchPackagesInFS(a)
			} else {
				expand = matchPackages(a)
			}
			if len(expand) > 0 {
				out = append(out, expand...)
				continue
			}
		}
		out = append(out, a)
	}
	return out
}

// downloadCache records the import paths we have already
// considered during the download, to avoid duplicate work when
// there is more than one dependency sequence leading to
// a particular package.
var downloadCache = map[string]bool{}

// downloadRootCache records the version control repository
// root directories we have already considered during the download.
// For example, all the packages in the code.google.com/p/codesearch repo
// share the same root (the directory for that path), and we only need
// to run the hg commands to consider each repository once.
var downloadRootCache = map[string]bool{}

// download runs the download half of the get command
// for the package named by the argument.
func download(arg string, stk *importStack, getTestDeps bool) {
	p := loadPackage(arg, stk)

	// There's nothing to do if this is a package in the standard library.
	if p.Standard {
		return
	}

	// Only process each package once.
	if downloadCache[arg] {
		return
	}
	downloadCache[arg] = true

	pkgs := []*Package{p}
	wildcardOkay := len(*stk) == 0
	isWildcard := false

	// Download if the package is missing, or update if we're using -u.
	if p.Dir == "" || *getU {
		// The actual download.
		stk.push(p.ImportPath)
		err := downloadPackage(p)
		if err != nil {
			errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
			stk.pop()
			return
		}

		args := []string{arg}
		// If the argument has a wildcard in it, re-evaluate the wildcard.
		// We delay this until after reloadPackage so that the old entry
		// for p has been replaced in the package cache.
		if wildcardOkay && strings.Contains(arg, "...") {
			if build.IsLocalImport(arg) {
				args = matchPackagesInFS(arg)
			} else {
				args = matchPackages(arg)
			}
			isWildcard = true
		}

		// Clear all relevant package cache entries before
		// doing any new loads.
		for _, arg := range args {
			p := packageCache[arg]
			if p != nil {
				delete(packageCache, p.Dir)
				delete(packageCache, p.ImportPath)
			}
		}

		pkgs = pkgs[:0]
		for _, arg := range args {
			stk.push(arg)
			p := loadPackage(arg, stk)
			stk.pop()
			if p.Error != nil {
				errorf("%s", p.Error)
				continue
			}
			pkgs = append(pkgs, p)
		}
	}

	// Process package, which might now be multiple packages
	// due to wildcard expansion.
	for _, p := range pkgs {
		if *getFix {
			run(stringList(tool("fix"), relPaths(p.allgofiles)))

			// The imports might have changed, so reload again.
			p = reloadPackage(arg, stk)
			if p.Error != nil {
				errorf("%s", p.Error)
				return
			}
		}

		if isWildcard {
			// Report both the real package and the
			// wildcard in any error message.
			stk.push(p.ImportPath)
		}

		// Process dependencies, now that we know what they are.
		for _, dep := range p.deps {
			// Don't get test dependencies recursively.
			download(dep.ImportPath, stk, false)
		}
		if getTestDeps {
			// Process test dependencies when -t is specified.
			// (Don't get test dependencies for test dependencies.)
			for _, path := range p.TestImports {
				download(path, stk, false)
			}
			for _, path := range p.XTestImports {
				download(path, stk, false)
			}
		}

		if isWildcard {
			stk.pop()
		}
	}
}

// downloadPackage runs the create or download command
// to make the first copy of or update a copy of the given package.
func downloadPackage(p *Package) error {
	var (
		vcs            *vcsCmd
		repo, rootPath string
		err            error
	)
	if p.build.SrcRoot != "" {
		// Directory exists.  Look for checkout along path to src.
		vcs, rootPath, err = vcsForDir(p)
		if err != nil {
			return err
		}
		repo = "<local>" // should be unused; make distinctive
	} else {
		// Analyze the import path to determine the version control system,
		// repository, and the import path for the root of the repository.
		rr, err := repoRootForImportPath(p.ImportPath)
		if err != nil {
			return err
		}
		vcs, repo, rootPath = rr.vcs, rr.repo, rr.root
	}

	if p.build.SrcRoot == "" {
		// Package not found.  Put in first directory of $GOPATH.
		list := filepath.SplitList(buildContext.GOPATH)
		if len(list) == 0 {
			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath")
		}
		// Guard against people setting GOPATH=$GOROOT.
		if list[0] == goroot {
			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath")
		}
		p.build.SrcRoot = filepath.Join(list[0], "src")
		p.build.PkgRoot = filepath.Join(list[0], "pkg")
	}
	root := filepath.Join(p.build.SrcRoot, rootPath)
	// If we've considered this repository already, don't do it again.
	if downloadRootCache[root] {
		return nil
	}
	downloadRootCache[root] = true

	if buildV {
		fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
	}

	// Check that this is an appropriate place for the repo to be checked out.
	// The target directory must either not exist or have a repo checked out already.
	meta := filepath.Join(root, "."+vcs.cmd)
	st, err := os.Stat(meta)
	if err == nil && !st.IsDir() {
		return fmt.Errorf("%s exists but is not a directory", meta)
	}
	if err != nil {
		// Metadata directory does not exist.  Prepare to checkout new copy.
		// Some version control tools require the target directory not to exist.
		// We require that too, just to avoid stepping on existing work.
		if _, err := os.Stat(root); err == nil {
			return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
		}
		// Some version control tools require the parent of the target to exist.
		parent, _ := filepath.Split(root)
		if err = os.MkdirAll(parent, 0777); err != nil {
			return err
		}
		if err = vcs.create(root, repo); err != nil {
			return err
		}
	} else {
		// Metadata directory does exist; download incremental updates.
		if err = vcs.download(root); err != nil {
			return err
		}
	}

	if buildN {
		// Do not show tag sync in -n; it's noise more than anything,
		// and since we're not running commands, no tag will be found.
		// But avoid printing nothing.
		fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd)
		return nil
	}

	// Select and sync to appropriate version of the repository.
	tags, err := vcs.tags(root)
	if err != nil {
		return err
	}
	vers := runtime.Version()
	if i := strings.Index(vers, " "); i >= 0 {
		vers = vers[:i]
	}
	if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil {
		return err
	}

	return nil
}

// goTag matches go release tags such as go1 and go1.2.3.
// The numbers involved must be small (at most 4 digits),
// have no unnecessary leading zeros, and the version cannot
// end in .0 - it is go1, not go1.0 or go1.0.0.
var goTag = regexp.MustCompile(
	`^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
)

// selectTag returns the closest matching tag for a given version.
// Closest means the latest one that is not after the current release.
// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
//
// NOTE(rsc): Eventually we will need to decide on some logic here.
// For now, there is only "go1".  This matches the docs in go help get.
func selectTag(goVersion string, tags []string) (match string) {
	for _, t := range tags {
		if t == "go1" {
			return "go1"
		}
	}
	return ""

	/*
		if goTag.MatchString(goVersion) {
			v := goVersion
			for _, t := range tags {
				if !goTag.MatchString(t) {
					continue
				}
				if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
					match = t
				}
			}
		}

		return match
	*/
}

// cmpGoVersion returns -1, 0, +1 reporting whether
// x < y, x == y, or x > y.
func cmpGoVersion(x, y string) int {
	// Malformed strings compare less than well-formed strings.
	if !goTag.MatchString(x) {
		return -1
	}
	if !goTag.MatchString(y) {
		return +1
	}

	// Compare numbers in sequence.
	xx := strings.Split(x[len("go"):], ".")
	yy := strings.Split(y[len("go"):], ".")

	for i := 0; i < len(xx) && i < len(yy); i++ {
		// The Atoi are guaranteed to succeed
		// because the versions match goTag.
		xi, _ := strconv.Atoi(xx[i])
		yi, _ := strconv.Atoi(yy[i])
		if xi < yi {
			return -1
		} else if xi > yi {
			return +1
		}
	}

	if len(xx) < len(yy) {
		return -1
	}
	if len(xx) > len(yy) {
		return +1
	}
	return 0
}
<|endoftext|>


<commit_before>package ishell

import "strings"

type iCompleter struct {
	cmd *Cmd
}

func (ic iCompleter) Do(line []rune, pos int) (newLine [][]rune, length int) {
	words := strings.Fields(string(line))
	var cWords []string
	prefix := ""
	if len(words) > 0 && line[pos-1] != ' ' {
		prefix = words[len(words)-1]
		cWords = ic.getWords(words[:len(words)-1])
	} else {
		cWords = ic.getWords(words)
	}

	var suggestions [][]rune
	for _, w := range cWords {
		if strings.HasPrefix(w, prefix) {
			suggestions = append(suggestions, []rune(strings.TrimPrefix(w, prefix)))
		}
	}
	return suggestions, len(prefix)
}

func (ic iCompleter) getWords(w []string) (s []string) {
	cmd, args := ic.cmd.FindCmd(w)
	if cmd == nil {
		cmd, args = ic.cmd, w
	}
	if cmd.Completer != nil {
		return cmd.Completer(args)
	}
	for k := range cmd.children {
		s = append(s, k)
	}
	return
}
<commit_msg>Add space on tab with no suggestion<commit_after>package ishell

import "strings"

type iCompleter struct {
	cmd *Cmd
}

func (ic iCompleter) Do(line []rune, pos int) (newLine [][]rune, length int) {
	words := strings.Fields(string(line))
	var cWords []string
	prefix := ""
	if len(words) > 0 && line[pos-1] != ' ' {
		prefix = words[len(words)-1]
		cWords = ic.getWords(words[:len(words)-1])
	} else {
		cWords = ic.getWords(words)
	}

	var suggestions [][]rune
	for _, w := range cWords {
		if strings.HasPrefix(w, prefix) {
			suggestions = append(suggestions, []rune(strings.TrimPrefix(w, prefix)))
		}
	}
	if len(suggestions) == 1 && prefix != "" && string(suggestions[0]) == "" {
		suggestions = [][]rune{[]rune(" ")}
	}
	return suggestions, len(prefix)
}

func (ic iCompleter) getWords(w []string) (s []string) {
	cmd, args := ic.cmd.FindCmd(w)
	if cmd == nil {
		cmd, args = ic.cmd, w
	}
	if cmd.Completer != nil {
		return cmd.Completer(args)
	}
	for k := range cmd.children {
		s = append(s, k)
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2014 Richard Lehane. 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 siegfried describes the layout of the Siegfried signature file.
// This signature file contains the siegfried object that performs identification
package siegfried

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"

	"github.com/richardlehane/siegfried/config"
	"github.com/richardlehane/siegfried/pkg/core"
	"github.com/richardlehane/siegfried/pkg/core/bytematcher"
	"github.com/richardlehane/siegfried/pkg/core/containermatcher"
	"github.com/richardlehane/siegfried/pkg/core/extensionmatcher"
	"github.com/richardlehane/siegfried/pkg/core/siegreader"
	"github.com/richardlehane/siegfried/pkg/pronom"
)

type Siegfried struct {
	C  time.Time    // signature create time
	em core.Matcher // extensionmatcher
	cm core.Matcher // containermatcher
	bm core.Matcher // bytematcher
	// mutatable fields follow
	ids    []core.Identifier // at present only one identifier (the PRONOM identifier) is used, but can add other identifiers e.g. for FILE sigs
	buffer *siegreader.Buffer
}

func New() *Siegfried {
	s := &Siegfried{}
	s.C = time.Now()
	s.em = extensionmatcher.New()
	s.cm = containermatcher.New()
	s.bm = bytematcher.New()
	s.buffer = siegreader.New()
	return s
}

func (s *Siegfried) String() string {
	str := "IDENTIFIERS\n"
	for _, i := range s.ids {
		str += i.String()
	}
	str += "\nEXTENSION MATCHER\n"
	str += s.em.String()
	str += "\nCONTAINER MATCHER\n"
	str += s.cm.String()
	str += "\nBYTE MATCHER\n"
	str += s.bm.String()
	return str
}

func (s *Siegfried) InspectTTI(tti int) string {
	bm := s.bm.(*bytematcher.Matcher)
	idxs := bm.InspectTTI(tti)
	if idxs == nil {
		return "No test tree at this index"
	}
	res := make([]string, len(idxs))
	for i, v := range idxs {
		for _, id := range s.ids {
			ok, str := id.Recognise(core.ByteMatcher, v)
			if ok {
				res[i] = str
				break
			}
		}
	}
	return "Test tree indexes match:\n" + strings.Join(res, "\n")
}

func (s *Siegfried) Add(i core.Identifier) error {
	switch i := i.(type) {
	default:
		return fmt.Errorf("Siegfried: unknown identifier type %T", i)
	case *pronom.Identifier:
		if err := i.Add(s.em); err != nil {
			return err
		}
		if err := i.Add(s.cm); err != nil {
			return err
		}
		if err := i.Add(s.bm); err != nil {
			return err
		}
		s.ids = append(s.ids, i)
	}
	return nil
}

func (s *Siegfried) Yaml() string {
	version := config.Version()
	str := fmt.Sprintf(
		"---\nsiegfried   : %d.%d.%d\nscandate    : %v\nsignature   : %s\ncreated     : %v\nidentifiers : \n",
		version[0], version[1], version[2],
		time.Now().Format(time.RFC3339),
		config.SignatureBase(),
		s.C.Format(time.RFC3339))
	for _, id := range s.ids {
		str += id.Yaml()
	}
	return str
}

func (s *Siegfried) Update(t string) bool {
	tm, err := time.Parse(time.RFC3339, t)
	if err != nil {
		return false
	}
	return tm.After(s.C)
}

type Header struct {
	SSize int                // sigversion
	BSize int                // bytematcher
	CSize int                // container
	ESize int                // extension matcher
	Ids   []IdentifierHeader // size and types of identifiers
}

type IdentifierHeader struct {
	Typ identifierType
	Sz  int
}

type identifierType int

// Register additional identifier types here
const (
	Pronom identifierType = iota
)

func identifierSz(ids []IdentifierHeader) int {
	var sz int
	for _, v := range ids {
		sz += v.Sz
	}
	return sz
}

func (s *Siegfried) Save(path string) error {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(s)
	if err != nil {
		return err
	}
	ssz := buf.Len()
	bsz, err := s.bm.Save(buf)
	if err != nil {
		return err
	}
	csz, err := s.cm.Save(buf)
	if err != nil {
		return err
	}
	esz, err := s.em.Save(buf)
	if err != nil {
		return err
	}
	ids := make([]IdentifierHeader, len(s.ids))
	for i, v := range s.ids {
		sz, err := v.Save(buf)
		if err != nil {
			return err
		}
		// add any additional identifiers to this type switch
		switch t := v.(type) {
		default:
			return fmt.Errorf("Siegfried: unexpected type for an identifier %T", t)
		case *pronom.Identifier:
			ids[i].Typ = Pronom
		}
		ids[i].Sz = sz
	}
	hbuf := new(bytes.Buffer)
	henc := gob.NewEncoder(hbuf)
	err = henc.Encode(Header{ssz, bsz, csz, esz, ids})
	f, err := os.Create(path)
	defer f.Close()
	if err != nil {
		return err
	}
	_, err = f.Write(hbuf.Bytes())
	if err != nil {
		return err
	}
	_, err = f.Write(buf.Bytes())
	if err != nil {
		return err
	}
	return nil
}

func Load(path string) (*Siegfried, error) {
	c, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error opening signature file; got %s\nTry running `sf -update`", err)
	}
	buf := bytes.NewBuffer(c)
	dec := gob.NewDecoder(buf)
	var h Header
	err = dec.Decode(&h)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error reading signature file; got %s\nTry running `sf -update`", err)
	}
	iSize := identifierSz(h.Ids)
	sstart := len(c) - h.SSize - h.BSize - h.CSize - h.ESize - iSize
	bstart := len(c) - h.ESize - h.CSize - h.BSize - iSize
	cstart := len(c) - h.ESize - h.CSize - iSize
	estart := len(c) - h.ESize - iSize
	istart := len(c) - iSize
	sbuf := bytes.NewBuffer(c[sstart : sstart+h.SSize])
	bbuf := bytes.NewBuffer(c[bstart : bstart+h.BSize])
	cbuf := bytes.NewBuffer(c[cstart : cstart+h.CSize])
	ebuf := bytes.NewBuffer(c[estart : estart+h.ESize])
	sdec := gob.NewDecoder(sbuf)
	var s Siegfried
	err = sdec.Decode(&s)
	if err != nil {
		return nil, err
	}
	bm, err := bytematcher.Load(bbuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading bytematcher; got %s", err)
	}
	cm, err := containermatcher.Load(cbuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading containermatcher; got %s", err)
	}
	em, err := extensionmatcher.Load(ebuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading extensionmatcher; got %s", err)
	}
	s.bm = bm
	s.cm = cm
	s.em = em
	s.ids = make([]core.Identifier, len(h.Ids))
	for i, v := range h.Ids {
		ibuf := bytes.NewBuffer(c[istart : istart+v.Sz])
		var id core.Identifier
		var err error
		switch v.Typ {
		default:
			return nil, fmt.Errorf("Siegfried: loading, unknown identifier type %d", v.Typ)
		case Pronom:
			id, err = pronom.Load(ibuf)
			if err != nil {
				return nil, fmt.Errorf("Siegfried: loading PRONOM identifier; got %s", err)
			}
		}
		s.ids[i] = id
		istart += v.Sz
	}
	s.buffer = siegreader.New()
	return &s, nil
}

func (s *Siegfried) Identify(n string, r io.Reader) (chan core.Identification, error) {
	err := s.buffer.SetSource(r)
	if err != nil && err != io.EOF {
		return nil, fmt.Errorf("Siegfried: error reading input, got %v", err)
	}
	res := make(chan core.Identification)
	recs := make([]core.Recorder, len(s.ids))
	for i, v := range s.ids {
		recs[i] = v.Recorder()
	}
	// Extension Matcher
	if len(n) > 0 {
		ems := s.em.Identify(n, nil)
		for v := range ems {
			for _, rec := range recs {
				if rec.Record(core.ExtensionMatcher, v) {
					break
				}
			}
		}
	}

	// Container Matcher
	if s.cm != nil {
		cms := s.cm.Identify(n, s.buffer)
		for v := range cms {
			for _, rec := range recs {
				if rec.Record(core.ContainerMatcher, v) {
					break
				}
			}
		}
	}
	satisfied := true
	for _, rec := range recs {
		if !rec.Satisfied() {
			satisfied = false
		}
	}
	// Byte Matcher
	if !satisfied {
		ids := s.bm.Identify("", s.buffer)
		for v := range ids {
			for _, rec := range recs {
				if rec.Record(core.ByteMatcher, v) {
					break
				}
			}
		}
	}
	go func() {
		for _, rec := range recs {
			rec.Report(res)
		}
		close(res)
	}()
	return res, nil
}
<commit_msg>siegfried doco<commit_after>// Copyright 2014 Richard Lehane. 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 siegfried identifies file formats
//
// Example:
//   s, _ := siegfried.Load("pronom.gob")
//	 f, _ := os.Open("file")
//	 defer f.Close()
//	 c, err := s.Identify("filename", f)
//	 if err != nil {
//	   return nil, fmt.Errorf("failed to identify %v, got: %v", "filename", err)
//	 }
//	 for id := range c {
//	   fmt.Print(id.Yaml())
//	 }
package siegfried

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"time"

	"github.com/richardlehane/siegfried/config"
	"github.com/richardlehane/siegfried/pkg/core"
	"github.com/richardlehane/siegfried/pkg/core/bytematcher"
	"github.com/richardlehane/siegfried/pkg/core/containermatcher"
	"github.com/richardlehane/siegfried/pkg/core/extensionmatcher"
	"github.com/richardlehane/siegfried/pkg/core/siegreader"
	"github.com/richardlehane/siegfried/pkg/pronom"
)

type Siegfried struct {
	C  time.Time    // signature create time
	em core.Matcher // extensionmatcher
	cm core.Matcher // containermatcher
	bm core.Matcher // bytematcher
	// mutatable fields follow
	ids    []core.Identifier // at present only one identifier (the PRONOM identifier) is used, but can add other identifiers e.g. for FILE sigs
	buffer *siegreader.Buffer
}

func New() *Siegfried {
	s := &Siegfried{}
	s.C = time.Now()
	s.em = extensionmatcher.New()
	s.cm = containermatcher.New()
	s.bm = bytematcher.New()
	s.buffer = siegreader.New()
	return s
}

func (s *Siegfried) String() string {
	str := "IDENTIFIERS\n"
	for _, i := range s.ids {
		str += i.String()
	}
	str += "\nEXTENSION MATCHER\n"
	str += s.em.String()
	str += "\nCONTAINER MATCHER\n"
	str += s.cm.String()
	str += "\nBYTE MATCHER\n"
	str += s.bm.String()
	return str
}

func (s *Siegfried) InspectTTI(tti int) string {
	bm := s.bm.(*bytematcher.Matcher)
	idxs := bm.InspectTTI(tti)
	if idxs == nil {
		return "No test tree at this index"
	}
	res := make([]string, len(idxs))
	for i, v := range idxs {
		for _, id := range s.ids {
			ok, str := id.Recognise(core.ByteMatcher, v)
			if ok {
				res[i] = str
				break
			}
		}
	}
	return "Test tree indexes match:\n" + strings.Join(res, "\n")
}

func (s *Siegfried) Add(i core.Identifier) error {
	switch i := i.(type) {
	default:
		return fmt.Errorf("Siegfried: unknown identifier type %T", i)
	case *pronom.Identifier:
		if err := i.Add(s.em); err != nil {
			return err
		}
		if err := i.Add(s.cm); err != nil {
			return err
		}
		if err := i.Add(s.bm); err != nil {
			return err
		}
		s.ids = append(s.ids, i)
	}
	return nil
}

func (s *Siegfried) Yaml() string {
	version := config.Version()
	str := fmt.Sprintf(
		"---\nsiegfried   : %d.%d.%d\nscandate    : %v\nsignature   : %s\ncreated     : %v\nidentifiers : \n",
		version[0], version[1], version[2],
		time.Now().Format(time.RFC3339),
		config.SignatureBase(),
		s.C.Format(time.RFC3339))
	for _, id := range s.ids {
		str += id.Yaml()
	}
	return str
}

func (s *Siegfried) Update(t string) bool {
	tm, err := time.Parse(time.RFC3339, t)
	if err != nil {
		return false
	}
	return tm.After(s.C)
}

type Header struct {
	SSize int                // sigversion
	BSize int                // bytematcher
	CSize int                // container
	ESize int                // extension matcher
	Ids   []IdentifierHeader // size and types of identifiers
}

type IdentifierHeader struct {
	Typ identifierType
	Sz  int
}

type identifierType int

// Register additional identifier types here
const (
	Pronom identifierType = iota
)

func identifierSz(ids []IdentifierHeader) int {
	var sz int
	for _, v := range ids {
		sz += v.Sz
	}
	return sz
}

func (s *Siegfried) Save(path string) error {
	buf := new(bytes.Buffer)
	enc := gob.NewEncoder(buf)
	err := enc.Encode(s)
	if err != nil {
		return err
	}
	ssz := buf.Len()
	bsz, err := s.bm.Save(buf)
	if err != nil {
		return err
	}
	csz, err := s.cm.Save(buf)
	if err != nil {
		return err
	}
	esz, err := s.em.Save(buf)
	if err != nil {
		return err
	}
	ids := make([]IdentifierHeader, len(s.ids))
	for i, v := range s.ids {
		sz, err := v.Save(buf)
		if err != nil {
			return err
		}
		// add any additional identifiers to this type switch
		switch t := v.(type) {
		default:
			return fmt.Errorf("Siegfried: unexpected type for an identifier %T", t)
		case *pronom.Identifier:
			ids[i].Typ = Pronom
		}
		ids[i].Sz = sz
	}
	hbuf := new(bytes.Buffer)
	henc := gob.NewEncoder(hbuf)
	err = henc.Encode(Header{ssz, bsz, csz, esz, ids})
	f, err := os.Create(path)
	defer f.Close()
	if err != nil {
		return err
	}
	_, err = f.Write(hbuf.Bytes())
	if err != nil {
		return err
	}
	_, err = f.Write(buf.Bytes())
	if err != nil {
		return err
	}
	return nil
}

func Load(path string) (*Siegfried, error) {
	c, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error opening signature file; got %s\nTry running `sf -update`", err)
	}
	buf := bytes.NewBuffer(c)
	dec := gob.NewDecoder(buf)
	var h Header
	err = dec.Decode(&h)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error reading signature file; got %s\nTry running `sf -update`", err)
	}
	iSize := identifierSz(h.Ids)
	sstart := len(c) - h.SSize - h.BSize - h.CSize - h.ESize - iSize
	bstart := len(c) - h.ESize - h.CSize - h.BSize - iSize
	cstart := len(c) - h.ESize - h.CSize - iSize
	estart := len(c) - h.ESize - iSize
	istart := len(c) - iSize
	sbuf := bytes.NewBuffer(c[sstart : sstart+h.SSize])
	bbuf := bytes.NewBuffer(c[bstart : bstart+h.BSize])
	cbuf := bytes.NewBuffer(c[cstart : cstart+h.CSize])
	ebuf := bytes.NewBuffer(c[estart : estart+h.ESize])
	sdec := gob.NewDecoder(sbuf)
	var s Siegfried
	err = sdec.Decode(&s)
	if err != nil {
		return nil, err
	}
	bm, err := bytematcher.Load(bbuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading bytematcher; got %s", err)
	}
	cm, err := containermatcher.Load(cbuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading containermatcher; got %s", err)
	}
	em, err := extensionmatcher.Load(ebuf)
	if err != nil {
		return nil, fmt.Errorf("Siegfried: error loading extensionmatcher; got %s", err)
	}
	s.bm = bm
	s.cm = cm
	s.em = em
	s.ids = make([]core.Identifier, len(h.Ids))
	for i, v := range h.Ids {
		ibuf := bytes.NewBuffer(c[istart : istart+v.Sz])
		var id core.Identifier
		var err error
		switch v.Typ {
		default:
			return nil, fmt.Errorf("Siegfried: loading, unknown identifier type %d", v.Typ)
		case Pronom:
			id, err = pronom.Load(ibuf)
			if err != nil {
				return nil, fmt.Errorf("Siegfried: loading PRONOM identifier; got %s", err)
			}
		}
		s.ids[i] = id
		istart += v.Sz
	}
	s.buffer = siegreader.New()
	return &s, nil
}

func (s *Siegfried) Identify(n string, r io.Reader) (chan core.Identification, error) {
	err := s.buffer.SetSource(r)
	if err != nil && err != io.EOF {
		return nil, fmt.Errorf("Siegfried: error reading input, got %v", err)
	}
	res := make(chan core.Identification)
	recs := make([]core.Recorder, len(s.ids))
	for i, v := range s.ids {
		recs[i] = v.Recorder()
	}
	// Extension Matcher
	if len(n) > 0 {
		ems := s.em.Identify(n, nil)
		for v := range ems {
			for _, rec := range recs {
				if rec.Record(core.ExtensionMatcher, v) {
					break
				}
			}
		}
	}

	// Container Matcher
	if s.cm != nil {
		cms := s.cm.Identify(n, s.buffer)
		for v := range cms {
			for _, rec := range recs {
				if rec.Record(core.ContainerMatcher, v) {
					break
				}
			}
		}
	}
	satisfied := true
	for _, rec := range recs {
		if !rec.Satisfied() {
			satisfied = false
		}
	}
	// Byte Matcher
	if !satisfied {
		ids := s.bm.Identify("", s.buffer)
		for v := range ids {
			for _, rec := range recs {
				if rec.Record(core.ByteMatcher, v) {
					break
				}
			}
		}
	}
	go func() {
		for _, rec := range recs {
			rec.Report(res)
		}
		close(res)
	}()
	return res, nil
}
<|endoftext|>


<commit_before>package rabbit

import (
	"os"
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"github.com/streadway/amqp"
)

var (
	RabbitURL string
	Exchange  string
)

func init() {
	RabbitURL = os.Getenv("RABBIT_URL")
	if RabbitURL == "" {
		RabbitURL = "amqp://localhost:5672"
		log.Infof("Setting RABBIT_URL to default value %s", RabbitURL)
	}
	log.Infof("Set RABBIT_URL to %s", RabbitURL)
	Exchange = os.Getenv("RABBIT_EXCHANGE")
	if Exchange == "" {
		Exchange = "typhon"
		log.Infof("Setting RABBIT_EXCHANGE to default value %s", Exchange)
	}
	log.Infof("Set RABBIT_EXCHANGE to %s", Exchange)
}

func NewRabbitConnection() *RabbitConnection {
	return &RabbitConnection{
		notify:    make(chan bool, 1),
		closeChan: make(chan struct{}),
	}
}

type RabbitConnection struct {
	Connection      *amqp.Connection
	Channel         *RabbitChannel
	ExchangeChannel *RabbitChannel
	notify          chan bool

	mtx       sync.Mutex
	closeChan chan struct{}
	closed    bool
}

func (r *RabbitConnection) Init() chan bool {
	go r.Connect(r.notify)
	return r.notify
}

func (r *RabbitConnection) Connect(connected chan bool) {
	for {
		if err := r.tryToConnect(); err != nil {
			time.Sleep(1 * time.Second)
			continue
		}
		connected <- true
		notifyClose := make(chan *amqp.Error)
		r.Connection.NotifyClose(notifyClose)

		// Block until we get disconnected, or shut down
		select {
		case <-notifyClose:
			// Spin around and reconnect
		case <-r.closeChan:
			// Shut down connection
			if err := r.Connection.Close(); err != nil {
				log.Errorf("Failed to close AMQP connection: %v", err)
			}
			return
		}
	}
}

func (r *RabbitConnection) Close() {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	if r.closed {
		return
	}

	close(r.closeChan)
	r.closed = true
}

func (r *RabbitConnection) tryToConnect() error {
	var err error
	r.Connection, err = amqp.Dial(RabbitURL)
	if err != nil {
		log.Errorf("[Rabbit] Failed to establish connection with RabbitMQ: %s", RabbitURL)
		return err
	}
	r.Channel, err = NewRabbitChannel(r.Connection)
	if err != nil {
		log.Error("[Rabbit] Failed to create Bunny Channel")
		return err
	}
	r.Channel.DeclareExchange(Exchange)
	r.ExchangeChannel, err = NewRabbitChannel(r.Connection)
	if err != nil {
		log.Error("[Rabbit] Failed to create default Channel")
		return err
	}
	log.Info("[Rabbit] Connected to RabbitMQ")
	return nil
}

func (r *RabbitConnection) Consume(serverName string) (<-chan amqp.Delivery, error) {
	consumerChannel, err := NewRabbitChannel(r.Connection)
	if err != nil {
		log.Errorf("[Rabbit] Failed to create new channel")
		log.Error(err.Error())
	}
	err = consumerChannel.DeclareQueue(serverName)
	if err != nil {
		log.Errorf("[Rabbit] Failed to declare queue %s", serverName)
		log.Error(err.Error())
	}
	err = consumerChannel.BindQueue(serverName, Exchange)
	if err != nil {
		log.Errorf("[Rabbit] Failed to bind %s to %s exchange", serverName, Exchange)
	}
	return consumerChannel.ConsumeQueue(serverName)
}

func (r *RabbitConnection) Publish(exchange, routingKey string, msg amqp.Publishing) error {
	return r.ExchangeChannel.Publish(exchange, routingKey, msg)
}
<commit_msg>Add connected flag on rabbit connection to track if connected<commit_after>package rabbit

import (
	"os"
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"github.com/streadway/amqp"
)

var (
	RabbitURL string
	Exchange  string
)

func init() {
	RabbitURL = os.Getenv("RABBIT_URL")
	if RabbitURL == "" {
		RabbitURL = "amqp://localhost:5672"
		log.Infof("Setting RABBIT_URL to default value %s", RabbitURL)
	}
	log.Infof("Set RABBIT_URL to %s", RabbitURL)
	Exchange = os.Getenv("RABBIT_EXCHANGE")
	if Exchange == "" {
		Exchange = "typhon"
		log.Infof("Setting RABBIT_EXCHANGE to default value %s", Exchange)
	}
	log.Infof("Set RABBIT_EXCHANGE to %s", Exchange)
}

func NewRabbitConnection() *RabbitConnection {
	return &RabbitConnection{
		notify:    make(chan bool, 1),
		closeChan: make(chan struct{}),
	}
}

type RabbitConnection struct {
	Connection      *amqp.Connection
	Channel         *RabbitChannel
	ExchangeChannel *RabbitChannel
	notify          chan bool

	connected bool

	mtx       sync.Mutex
	closeChan chan struct{}
	closed    bool
}

func (r *RabbitConnection) Init() chan bool {
	go r.Connect(r.notify)
	return r.notify
}

func (r *RabbitConnection) Connect(connected chan bool) {
	for {
		if err := r.tryToConnect(); err != nil {
			time.Sleep(1 * time.Second)
			continue
		}
		connected <- true
		r.connected = true
		notifyClose := make(chan *amqp.Error)
		r.Connection.NotifyClose(notifyClose)

		// Block until we get disconnected, or shut down
		select {
		case <-notifyClose:
			// Spin around and reconnect
			r.connected = false
			log.Debugf("[Rabbit] AMQP connection closed (notifyClose): %s", err.Error())
		case <-r.closeChan:
			// Shut down connection
			if err := r.Connection.Close(); err != nil {
				log.Errorf("Failed to close AMQP connection: %v", err)
			}
			r.connected = false
			return
		}
	}
}

func (r *RabbitConnection) IsConnected() bool {
	return r.connected
}

func (r *RabbitConnection) Close() {
	r.mtx.Lock()
	defer r.mtx.Unlock()

	if r.closed {
		return
	}

	close(r.closeChan)
	r.closed = true
}

func (r *RabbitConnection) tryToConnect() error {
	var err error
	r.Connection, err = amqp.Dial(RabbitURL)
	if err != nil {
		log.Errorf("[Rabbit] Failed to establish connection with RabbitMQ: %s", RabbitURL)
		return err
	}
	r.Channel, err = NewRabbitChannel(r.Connection)
	if err != nil {
		log.Error("[Rabbit] Failed to create Bunny Channel")
		return err
	}
	r.Channel.DeclareExchange(Exchange)
	r.ExchangeChannel, err = NewRabbitChannel(r.Connection)
	if err != nil {
		log.Error("[Rabbit] Failed to create default Channel")
		return err
	}
	log.Info("[Rabbit] Connected to RabbitMQ")
	return nil
}

func (r *RabbitConnection) Consume(serverName string) (<-chan amqp.Delivery, error) {
	consumerChannel, err := NewRabbitChannel(r.Connection)
	if err != nil {
		log.Errorf("[Rabbit] Failed to create new channel")
		log.Error(err.Error())
	}
	err = consumerChannel.DeclareQueue(serverName)
	if err != nil {
		log.Errorf("[Rabbit] Failed to declare queue %s", serverName)
		log.Error(err.Error())
	}
	err = consumerChannel.BindQueue(serverName, Exchange)
	if err != nil {
		log.Errorf("[Rabbit] Failed to bind %s to %s exchange", serverName, Exchange)
	}
	return consumerChannel.ConsumeQueue(serverName)
}

func (r *RabbitConnection) Publish(exchange, routingKey string, msg amqp.Publishing) error {
	return r.ExchangeChannel.Publish(exchange, routingKey, msg)
}
<|endoftext|>


<commit_before>package utils

import (
	"syscall"
)

type Utsname syscall.Utsname

func uname() (*Utsname, error) {
	uts := &syscall.Utsname{}

	if err := syscall.Uname(uts); err != nil {
		return nil, err
	}
	return uts, nil
}
<commit_msg>fix compilation on linux<commit_after>package utils

import (
	"syscall"
)

type Utsname syscall.Utsname

func uname() (*syscall.Utsname, error) {
	uts := &syscall.Utsname{}

	if err := syscall.Uname(uts); err != nil {
		return nil, err
	}
	return uts, nil
}
<|endoftext|>


<commit_before>package configmanager

import (
	"fmt"
)

var (
	// ErrParsed is an error that the config has been parsed.
	ErrParsed = fmt.Errorf("the config manager has been parsed")

	// ErrNotParsed is an error that the config has not been parsed.
	ErrNotParsed = fmt.Errorf("the config manager has not been parsed")
)

// Opt stands for an opt value.
type Opt interface {
	GetName() string
	GetShort() string
	GetHelp() string
	GetDefault() interface{}
	IsRequired() bool
	Parse(string) (interface{}, error)
}

// ConfigManager is used to manage the configuration parsers.
type ConfigManager struct {
	Args []string

	parsed  bool
	cli     CliParser
	parsers []Parser
	opts    []Opt
	cliopts []Opt
	config  map[string]interface{}
}

// NewConfigManager returns a new ConfigMangaer.
func NewConfigManager(cli CliParser) *ConfigManager {
	return &ConfigManager{
		cli:     cli,
		parsers: make([]Parser, 0, 2),
		opts:    make([]Opt, 0),
		cliopts: make([]Opt, 0),
		config:  make(map[string]interface{}),
	}
}

// Parse parses the option, including CLI, the config file, or others.
func (c *ConfigManager) Parse(arguments []string) (err error) {
	if c.parsed {
		return ErrParsed
	}
	c.parsed = true

	// Register the CLI option into the CLI parser.
	c.cli.Register(c.cliopts)

	// Register the option into the other parsers.
	for _, p := range c.parsers {
		p.Register(c.opts)
	}

	// Parse the CLI arguments.
	if err = c.parseCli(arguments); err != nil {
		return
	}

	// Parse the other options by other parsers.
	for _, parser := range c.parsers {
		args, err := c.getValuesByKeys(parser.Name(), parser.GetKeys())
		if err != nil {
			return err
		}

		opts, err := parser.Parse(args)
		if err != nil {
			return err
		}

		for _, opt := range c.opts {
			if value, ok := opts[opt.GetName()]; ok {
				v, err := opt.Parse(value)
				if err != nil {
					return err
				}
				c.config[opt.GetName()] = v
			} else if _default := opt.GetDefault(); _default != nil {
				c.config[opt.GetName()] = _default
			} else if opt.IsRequired() {
				return fmt.Errorf("the option '%s' has no value", opt.GetName())
			}
		}
	}

	return
}

func (c *ConfigManager) getValuesByKeys(name string, keys map[string]bool) (args map[string]string, err error) {
	if len(keys) == 0 {
		return
	}

	args = make(map[string]string, len(keys))
	for key, required := range keys {
		v, ok := c.config[key]
		if !ok {
			if !required {
				continue
			}
			err = fmt.Errorf("the option '%s' is missing, which is reqired by the parser '%s'", key, name)
			return
		}
		s, ok := v.(string)
		if !ok {
			err = fmt.Errorf("the type of the option '%s' is not string", key)
			return
		}
		args[key] = s
	}

	return
}

func (c *ConfigManager) parseCli(arguments []string) (err error) {
	opts, args, err := c.cli.Parse(arguments)
	if err != nil {
		return
	}

	// Parse the values of all the options
	for _, opt := range c.cliopts {
		if value, ok := opts[opt.GetName()]; ok {
			v, err := opt.Parse(value)
			if err != nil {
				return err
			}
			c.config[opt.GetName()] = v
		} else if _default := opt.GetDefault(); _default != nil {
			c.config[opt.GetName()] = _default
		} else if opt.IsRequired() {
			return fmt.Errorf("the option '%s' has no value", opt.GetName())
		}
	}

	c.Args = args
	return
}

// Parsed returns true if has been parsed, or false.
func (c *ConfigManager) Parsed() bool {
	return c.parsed
}

// AddParser adds a named parser.
//
// It will panic if the parser has been added.
func (c *ConfigManager) AddParser(parser Parser) *ConfigManager {
	if c.parsed {
		panic(ErrParsed)
	}

	name := parser.Name()
	for _, p := range c.parsers {
		if p.Name() == name {
			panic(fmt.Errorf("the parser '%s' has been added", name))
		}
	}

	c.parsers = append(c.parsers, parser)
	return c
}

// RegisterCliOpt registers a CLI option, the type of which is string, also
// registers it by RegisterOpt.
//
// It will panic if the option has been registered or is nil.
func (c *ConfigManager) RegisterCliOpt(opt Opt) {
	if c.parsed {
		panic(ErrParsed)
	}
	c.RegisterOpt(opt)

	name := opt.GetName()
	for _, _opt := range c.cliopts {
		if _opt.GetName() == name {
			panic(fmt.Errorf("the option '%s' has been registered", name))
		}
	}

	c.cliopts = append(c.cliopts, opt)
}

// RegisterCliOpts registers lots of options once.
func (c *ConfigManager) RegisterCliOpts(opts []Opt) {
	for _, opt := range opts {
		c.RegisterCliOpt(opt)
	}
}

// RegisterOpt registers a option, the type of which is string.
//
// It will panic if the option has been registered or is nil.
func (c *ConfigManager) RegisterOpt(opt Opt) {
	if c.parsed {
		panic(ErrParsed)
	}

	name := opt.GetName()
	for _, _opt := range c.opts {
		if _opt.GetName() == name {
			panic(fmt.Errorf("the option '%s' has been registered", name))
		}
	}

	c.opts = append(c.opts, opt)
}

// RegisterOpts registers lots of options once.
func (c *ConfigManager) RegisterOpts(opts []Opt) {
	for _, opt := range opts {
		c.RegisterOpt(opt)
	}
}

// Value returns the option value named name.
//
// If no the option, return nil.
func (c *ConfigManager) Value(name string) interface{} {
	if !c.parsed {
		panic(ErrNotParsed)
	}
	return c.config[name]
}

// StringE returns the option value, the type of which is string.
//
// Return an error if no the option or the type of the option isn't string.
func (c *ConfigManager) StringE(name string) (string, error) {
	if !c.parsed {
		return "", ErrNotParsed
	}

	if opt := c.Value(name); opt != nil {
		if v, ok := opt.(string); ok {
			return v, nil
		}
		return "", fmt.Errorf("the type of the option '%s' is not string", name)
	}
	return "", fmt.Errorf("no option '%s'", name)
}

// StringD is the same as StringE, but returns the default if there is an error.
func (c *ConfigManager) StringD(name, _default string) string {
	if value, err := c.StringE(name); err == nil {
		return value
	}
	return _default
}

// String is the same as StringE, but panic if there is an error.
func (c *ConfigManager) String(name string) string {
	value, err := c.StringE(name)
	if err != nil {
		panic(err)
	}
	return value
}

// IntE returns the option value, the type of which is int.
//
// Return an error if no the option or the type of the option isn't int.
func (c *ConfigManager) IntE(name string) (int, error) {
	if !c.parsed {
		return 0, ErrNotParsed
	}

	if opt := c.Value(name); opt != nil {
		if v, ok := opt.(int); ok {
			return v, nil
		}
		return 0, fmt.Errorf("the type of the option '%s' is not int", name)
	}
	return 0, fmt.Errorf("no option '%s'", name)
}

// IntD is the same as IntE, but returns the default if there is an error.
func (c *ConfigManager) IntD(name string, _default int) int {
	if value, err := c.IntE(name); err == nil {
		return value
	}
	return _default
}

// Int is the same as IntE, but panic if there is an error.
func (c *ConfigManager) Int(name string) int {
	value, err := c.IntE(name)
	if err != nil {
		panic(err)
	}
	return value
}
<commit_msg>Fix a bug.<commit_after>package configmanager

import (
	"fmt"
)

var (
	// ErrParsed is an error that the config has been parsed.
	ErrParsed = fmt.Errorf("the config manager has been parsed")

	// ErrNotParsed is an error that the config has not been parsed.
	ErrNotParsed = fmt.Errorf("the config manager has not been parsed")
)

// Opt stands for an opt value.
type Opt interface {
	GetName() string
	GetShort() string
	GetHelp() string
	GetDefault() interface{}
	IsRequired() bool
	Parse(string) (interface{}, error)
}

// ConfigManager is used to manage the configuration parsers.
type ConfigManager struct {
	Args []string

	parsed  bool
	cli     CliParser
	parsers []Parser
	opts    []Opt
	cliopts []Opt
	config  map[string]interface{}
}

// NewConfigManager returns a new ConfigMangaer.
func NewConfigManager(cli CliParser) *ConfigManager {
	return &ConfigManager{
		cli:     cli,
		parsers: make([]Parser, 0, 2),
		opts:    make([]Opt, 0),
		cliopts: make([]Opt, 0),
		config:  make(map[string]interface{}),
	}
}

// Parse parses the option, including CLI, the config file, or others.
func (c *ConfigManager) Parse(arguments []string) (err error) {
	if c.parsed {
		return ErrParsed
	}
	c.parsed = true

	// Register the CLI option into the CLI parser.
	c.cli.Register(c.cliopts)

	// Register the option into the other parsers.
	for _, p := range c.parsers {
		p.Register(c.opts)
	}

	// Parse the CLI arguments.
	if err = c.parseCli(arguments); err != nil {
		return
	}

	// Parse the other options by other parsers.
	for _, parser := range c.parsers {
		args, err := c.getValuesByKeys(parser.Name(), parser.GetKeys())
		if err != nil {
			return err
		}

		opts, err := parser.Parse(args)
		if err != nil {
			return err
		}

		for _, opt := range c.opts {
			if value, ok := opts[opt.GetName()]; ok {
				v, err := opt.Parse(value)
				if err != nil {
					return err
				}
				c.config[opt.GetName()] = v
			} else if _default := opt.GetDefault(); _default != nil {
				c.config[opt.GetName()] = _default
			}
		}
	}

	// Check whether some required options neither have the value nor the default value.
	for _, opt := range c.cliopts {
		if _, ok := c.config[opt.GetName()]; !ok && opt.IsRequired() {
			return fmt.Errorf("the option '%s' is required, but has no value", opt.GetName())
		}
	}
	for _, opt := range c.opts {
		if _, ok := c.config[opt.GetName()]; !ok && opt.IsRequired() {
			return fmt.Errorf("the option '%s' is required, but has no value", opt.GetName())
		}
	}

	return
}

func (c *ConfigManager) getValuesByKeys(name string, keys map[string]bool) (args map[string]string, err error) {
	if len(keys) == 0 {
		return
	}

	args = make(map[string]string, len(keys))
	for key, required := range keys {
		v, ok := c.config[key]
		if !ok {
			if !required {
				continue
			}
			err = fmt.Errorf("the option '%s' is missing, which is reqired by the parser '%s'", key, name)
			return
		}
		s, ok := v.(string)
		if !ok {
			err = fmt.Errorf("the type of the option '%s' is not string", key)
			return
		}
		args[key] = s
	}

	return
}

func (c *ConfigManager) parseCli(arguments []string) (err error) {
	opts, args, err := c.cli.Parse(arguments)
	if err != nil {
		return
	}

	// Parse the values of all the options
	for _, opt := range c.cliopts {
		if value, ok := opts[opt.GetName()]; ok {
			v, err := opt.Parse(value)
			if err != nil {
				return err
			}
			c.config[opt.GetName()] = v
		} else if _default := opt.GetDefault(); _default != nil {
			c.config[opt.GetName()] = _default
		}
	}

	c.Args = args
	return
}

// Parsed returns true if has been parsed, or false.
func (c *ConfigManager) Parsed() bool {
	return c.parsed
}

// AddParser adds a named parser.
//
// It will panic if the parser has been added.
func (c *ConfigManager) AddParser(parser Parser) *ConfigManager {
	if c.parsed {
		panic(ErrParsed)
	}

	name := parser.Name()
	for _, p := range c.parsers {
		if p.Name() == name {
			panic(fmt.Errorf("the parser '%s' has been added", name))
		}
	}

	c.parsers = append(c.parsers, parser)
	return c
}

// RegisterCliOpt registers a CLI option, the type of which is string, also
// registers it by RegisterOpt.
//
// It will panic if the option has been registered or is nil.
func (c *ConfigManager) RegisterCliOpt(opt Opt) {
	if c.parsed {
		panic(ErrParsed)
	}
	c.RegisterOpt(opt)

	name := opt.GetName()
	for _, _opt := range c.cliopts {
		if _opt.GetName() == name {
			panic(fmt.Errorf("the option '%s' has been registered", name))
		}
	}

	c.cliopts = append(c.cliopts, opt)
}

// RegisterCliOpts registers lots of options once.
func (c *ConfigManager) RegisterCliOpts(opts []Opt) {
	for _, opt := range opts {
		c.RegisterCliOpt(opt)
	}
}

// RegisterOpt registers a option, the type of which is string.
//
// It will panic if the option has been registered or is nil.
func (c *ConfigManager) RegisterOpt(opt Opt) {
	if c.parsed {
		panic(ErrParsed)
	}

	name := opt.GetName()
	for _, _opt := range c.opts {
		if _opt.GetName() == name {
			panic(fmt.Errorf("the option '%s' has been registered", name))
		}
	}

	c.opts = append(c.opts, opt)
}

// RegisterOpts registers lots of options once.
func (c *ConfigManager) RegisterOpts(opts []Opt) {
	for _, opt := range opts {
		c.RegisterOpt(opt)
	}
}

// Value returns the option value named name.
//
// If no the option, return nil.
func (c *ConfigManager) Value(name string) interface{} {
	if !c.parsed {
		panic(ErrNotParsed)
	}
	return c.config[name]
}

// StringE returns the option value, the type of which is string.
//
// Return an error if no the option or the type of the option isn't string.
func (c *ConfigManager) StringE(name string) (string, error) {
	if !c.parsed {
		return "", ErrNotParsed
	}

	if opt := c.Value(name); opt != nil {
		if v, ok := opt.(string); ok {
			return v, nil
		}
		return "", fmt.Errorf("the type of the option '%s' is not string", name)
	}
	return "", fmt.Errorf("no option '%s'", name)
}

// StringD is the same as StringE, but returns the default if there is an error.
func (c *ConfigManager) StringD(name, _default string) string {
	if value, err := c.StringE(name); err == nil {
		return value
	}
	return _default
}

// String is the same as StringE, but panic if there is an error.
func (c *ConfigManager) String(name string) string {
	value, err := c.StringE(name)
	if err != nil {
		panic(err)
	}
	return value
}

// IntE returns the option value, the type of which is int.
//
// Return an error if no the option or the type of the option isn't int.
func (c *ConfigManager) IntE(name string) (int, error) {
	if !c.parsed {
		return 0, ErrNotParsed
	}

	if opt := c.Value(name); opt != nil {
		if v, ok := opt.(int); ok {
			return v, nil
		}
		return 0, fmt.Errorf("the type of the option '%s' is not int", name)
	}
	return 0, fmt.Errorf("no option '%s'", name)
}

// IntD is the same as IntE, but returns the default if there is an error.
func (c *ConfigManager) IntD(name string, _default int) int {
	if value, err := c.IntE(name); err == nil {
		return value
	}
	return _default
}

// Int is the same as IntE, but panic if there is an error.
func (c *ConfigManager) Int(name string) int {
	value, err := c.IntE(name)
	if err != nil {
		panic(err)
	}
	return value
}
<|endoftext|>


<commit_before>package tuple

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

type convTestInput struct {
	ValueDesc string
	Value     Value
	Expected  interface{}
}

func TestToBool(t *testing.T) {
	toFun := ToBool
	funcName := "ToBool"

	testCases := map[string]([]convTestInput){
		"Null": []convTestInput{
			convTestInput{"Null", Null{}, false},
		},
		"Bool": []convTestInput{
			convTestInput{"true", Bool(true), true},
			convTestInput{"false", Bool(false), false},
		},
		"Int": []convTestInput{
			convTestInput{"positive", Int(2), true},
			convTestInput{"negative", Int(-2), true},
			convTestInput{"zero", Int(0), false},
		},
		"Float": []convTestInput{
			convTestInput{"positive", Float(3.14), true},
			convTestInput{"negative", Float(-3.14), true},
			convTestInput{"zero", Float(0.0), false},
		},
		"String": []convTestInput{
			convTestInput{"empty", String(""), false},
			convTestInput{"non-empty", String("hoge"), true},
		},
		"Blob": []convTestInput{
			convTestInput{"empty", Blob(""), false},
			convTestInput{"non-empty", Blob("hoge"), true},
		},
		"Timestamp": []convTestInput{
			convTestInput{"zero", Timestamp(time.Time{}), false},
			convTestInput{"now", Timestamp(time.Now()), true},
		},
		"Array": []convTestInput{
			convTestInput{"empty", Array{}, false},
			convTestInput{"non-empty", Array{Int(2), String("foo")}, true},
		},
		"Map": []convTestInput{
			convTestInput{"empty", Map{}, false},
			convTestInput{"non-empty", Map{"a": Int(2), "b": String("foo")}, true},
		},
	}

	for valType, cases := range testCases {
		cases := cases
		Convey(fmt.Sprintf("Given a %s value", valType), t, func() {
			for _, testCase := range cases {
				tc := testCase
				Convey(fmt.Sprintf("When it is %s", tc.ValueDesc), func() {
					inVal := tc.Value
					exp := tc.Expected
					Convey(fmt.Sprintf("Then %s returns %v", funcName, exp), func() {
						val, err := toFun(inVal)
						So(err, ShouldBeNil)
						So(val, ShouldEqual, exp)
					})
				})
			}
		})
	}
}

func TestToInt(t *testing.T) {
	toFun := ToInt
	funcName := "ToInt"

	now := time.Now()

	testCases := map[string]([]convTestInput){
		"Null": []convTestInput{
			convTestInput{"Null", Null{}, int64(0)},
		},
		"Bool": []convTestInput{
			convTestInput{"true", Bool(true), int64(1)},
			convTestInput{"false", Bool(false), int64(0)},
		},
		"Int": []convTestInput{
			convTestInput{"positive", Int(2), int64(2)},
			convTestInput{"negative", Int(-2), int64(-2)},
			convTestInput{"zero", Int(0), int64(0)},
		},
		"Float": []convTestInput{
			// normal conversion
			convTestInput{"positive", Float(3.14), int64(3)},
			convTestInput{"negative", Float(-3.14), int64(-3)},
			convTestInput{"zero", Float(0.0), int64(0)},
			// we truncate and don't round
			convTestInput{"positive (> x.5)", Float(2.71), int64(2)},
			convTestInput{"negative (< x.5)", Float(-2.71), int64(-2)},
			// we cannot convert all numbers
			convTestInput{"maximal positive", Float(math.MaxFloat64), nil},
			convTestInput{"maximal negative", Float(-math.MaxFloat64), nil},
		},
		"String": []convTestInput{
			convTestInput{"empty", String(""), nil},
			convTestInput{"non-empty", String("hoge"), nil},
		},
		"Blob": []convTestInput{
			convTestInput{"empty", Blob(""), nil},
			convTestInput{"non-empty", Blob("hoge"), nil},
		},
		"Timestamp": []convTestInput{
			// The zero value for a time.Time is *not* the timestamp
			// that has unix time zero!
			convTestInput{"zero", Timestamp(time.Time{}), int64(-62135596800)},
			convTestInput{"now", Timestamp(now), now.Unix()},
		},
		"Array": []convTestInput{
			convTestInput{"empty", Array{}, nil},
			convTestInput{"non-empty", Array{Int(2), String("foo")}, nil},
		},
		"Map": []convTestInput{
			convTestInput{"empty", Map{}, nil},
			convTestInput{"non-empty", Map{"a": Int(2), "b": String("foo")}, nil},
		},
	}

	for valType, cases := range testCases {
		cases := cases
		Convey(fmt.Sprintf("Given a %s value", valType), t, func() {
			for _, testCase := range cases {
				tc := testCase
				Convey(fmt.Sprintf("When it is %s", tc.ValueDesc), func() {
					inVal := tc.Value
					exp := tc.Expected
					if exp == nil {
						Convey(fmt.Sprintf("Then %s returns an error", funcName), func() {
							_, err := toFun(inVal)
							So(err, ShouldNotBeNil)
						})
					} else {
						Convey(fmt.Sprintf("Then %s returns %v", funcName, exp), func() {
							val, err := toFun(inVal)
							So(err, ShouldBeNil)
							So(val, ShouldEqual, exp)
						})
					}
				})
			}
		})
	}
}
<commit_msg>refactor result checking into a function of its own<commit_after>package tuple

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

type convTestInput struct {
	ValueDesc string
	Value     Value
	Expected  interface{}
}

func TestToBool(t *testing.T) {
	testCases := map[string]([]convTestInput){
		"Null": []convTestInput{
			convTestInput{"Null", Null{}, false},
		},
		"Bool": []convTestInput{
			convTestInput{"true", Bool(true), true},
			convTestInput{"false", Bool(false), false},
		},
		"Int": []convTestInput{
			convTestInput{"positive", Int(2), true},
			convTestInput{"negative", Int(-2), true},
			convTestInput{"zero", Int(0), false},
		},
		"Float": []convTestInput{
			convTestInput{"positive", Float(3.14), true},
			convTestInput{"negative", Float(-3.14), true},
			convTestInput{"zero", Float(0.0), false},
		},
		"String": []convTestInput{
			convTestInput{"empty", String(""), false},
			convTestInput{"non-empty", String("hoge"), true},
		},
		"Blob": []convTestInput{
			convTestInput{"empty", Blob(""), false},
			convTestInput{"non-empty", Blob("hoge"), true},
		},
		"Timestamp": []convTestInput{
			convTestInput{"zero", Timestamp(time.Time{}), false},
			convTestInput{"now", Timestamp(time.Now()), true},
		},
		"Array": []convTestInput{
			convTestInput{"empty", Array{}, false},
			convTestInput{"non-empty", Array{Int(2), String("foo")}, true},
		},
		"Map": []convTestInput{
			convTestInput{"empty", Map{}, false},
			convTestInput{"non-empty", Map{"a": Int(2), "b": String("foo")}, true},
		},
	}

	toFun := func(v Value) (interface{}, error) {
		val, err := ToBool(v)
		return val, err
	}
	runConversionTestCases(t, toFun, "ToBool", testCases)
}

func TestToInt(t *testing.T) {
	now := time.Now()

	testCases := map[string]([]convTestInput){
		"Null": []convTestInput{
			convTestInput{"Null", Null{}, int64(0)},
		},
		"Bool": []convTestInput{
			convTestInput{"true", Bool(true), int64(1)},
			convTestInput{"false", Bool(false), int64(0)},
		},
		"Int": []convTestInput{
			convTestInput{"positive", Int(2), int64(2)},
			convTestInput{"negative", Int(-2), int64(-2)},
			convTestInput{"zero", Int(0), int64(0)},
		},
		"Float": []convTestInput{
			// normal conversion
			convTestInput{"positive", Float(3.14), int64(3)},
			convTestInput{"negative", Float(-3.14), int64(-3)},
			convTestInput{"zero", Float(0.0), int64(0)},
			// we truncate and don't round
			convTestInput{"positive (> x.5)", Float(2.71), int64(2)},
			convTestInput{"negative (< x.5)", Float(-2.71), int64(-2)},
			// we cannot convert all numbers
			convTestInput{"maximal positive", Float(math.MaxFloat64), nil},
			convTestInput{"maximal negative", Float(-math.MaxFloat64), nil},
		},
		"String": []convTestInput{
			convTestInput{"empty", String(""), nil},
			convTestInput{"non-empty", String("hoge"), nil},
		},
		"Blob": []convTestInput{
			convTestInput{"empty", Blob(""), nil},
			convTestInput{"non-empty", Blob("hoge"), nil},
		},
		"Timestamp": []convTestInput{
			// The zero value for a time.Time is *not* the timestamp
			// that has unix time zero!
			convTestInput{"zero", Timestamp(time.Time{}), int64(-62135596800)},
			convTestInput{"now", Timestamp(now), now.Unix()},
		},
		"Array": []convTestInput{
			convTestInput{"empty", Array{}, nil},
			convTestInput{"non-empty", Array{Int(2), String("foo")}, nil},
		},
		"Map": []convTestInput{
			convTestInput{"empty", Map{}, nil},
			convTestInput{"non-empty", Map{"a": Int(2), "b": String("foo")}, nil},
		},
	}

	toFun := func(v Value) (interface{}, error) {
		val, err := ToInt(v)
		return val, err
	}
	runConversionTestCases(t, toFun, "ToInt", testCases)
}

func runConversionTestCases(t *testing.T,
	toFun func(v Value) (interface{}, error),
	funcName string,
	testCases map[string][]convTestInput) {
	for valType, cases := range testCases {
		cases := cases
		Convey(fmt.Sprintf("Given a %s value", valType), t, func() {
			for _, testCase := range cases {
				tc := testCase
				Convey(fmt.Sprintf("When it is %s", tc.ValueDesc), func() {
					inVal := tc.Value
					exp := tc.Expected
					if exp == nil {
						Convey(fmt.Sprintf("Then %s returns an error", funcName), func() {
							_, err := toFun(inVal)
							So(err, ShouldNotBeNil)
						})
					} else {
						Convey(fmt.Sprintf("Then %s returns %v", funcName, exp), func() {
							val, err := toFun(inVal)
							So(err, ShouldBeNil)
							So(val, ShouldEqual, exp)
						})
					}
				})
			}
		})
	}
}
<|endoftext|>


<commit_before>package db_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Regions", func() {
	Describe("Get", func() {
		It("should get region by name", func(done Done) {
			defer close(done)
			region, err := regionsCollection.Get("Tartu")
			Expect(err).NotTo(HaveOccurred())
			Expect(region.Name).To(Equal("Tartu"))
			Expect(region.Location).To(Equal("Europe/Tallinn"))
		})

		It("should get region by name", func(done Done) {
			defer close(done)
			region, err := regionsCollection.Get("London")
			Expect(err).NotTo(HaveOccurred())
			Expect(region.Name).To(Equal("London"))
			Expect(region.Location).To(Equal("Europe/London"))
		})
	})
})
<commit_msg>add test for when region not found in DB<commit_after>package db_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"gopkg.in/mgo.v2"
)

var _ = Describe("Regions", func() {
	Describe("Get", func() {
		It("should get region by name", func(done Done) {
			defer close(done)
			region, err := regionsCollection.Get("Tartu")
			Expect(err).NotTo(HaveOccurred())
			Expect(region.Name).To(Equal("Tartu"))
			Expect(region.Location).To(Equal("Europe/Tallinn"))
		})

		It("should get region by name", func(done Done) {
			defer close(done)
			region, err := regionsCollection.Get("London")
			Expect(err).NotTo(HaveOccurred())
			Expect(region.Name).To(Equal("London"))
			Expect(region.Location).To(Equal("Europe/London"))
		})

		It("should return nothing if doesn't exist", func(done Done) {
			defer close(done)
			_, err := regionsCollection.Get("blablabla")
			Expect(err).To(Equal(mgo.ErrNotFound))
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"github.com/flynn/go-shlex"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os/exec"
)

// Handle requests received through a channel
func handleRequest(channel ssh.Channel, req *ssh.Request) {
	ok := true
	s, _ := shlex.Split(string(req.Payload[4:]))

	// We only do scp, so ignore everything after a ";" or "&&"
	commandStop := len(s)
	for i := 1; i < len(s); i++ {
		if s[i] == ";" || s[i] == "&&" {
			commandStop = i
		}
	}

	// Ignore everything that's not scp
	if s[0] != "scp" {
		ok = false
		req.Reply(ok, []byte("Only scp is supported"))
		channel.Write([]byte("Only scp is supported\n"))
		channel.Close()
		return
	}

	cmd := exec.Command(s[0], s[1:commandStop]...)

	cerr, _ := cmd.StderrPipe()
	go io.Copy(channel, cerr)
	cout, _ := cmd.StdoutPipe()
	go io.Copy(channel, cout)
	cin, _ := cmd.StdinPipe()
	go io.Copy(cin, channel)

	log.Printf("Starting command")
	cmd.Start()

	log.Printf("Waiting")
	err := cmd.Wait()
	log.Printf("Waited")

	channel.Close()
	if err != nil {
		log.Printf("Error when running command (%s)", err)
	}
	log.Printf("session closed")
	fmt.Println(ok)
	req.Reply(ok, nil)
}

func handleNewChannel(newChannel ssh.NewChannel) {
	fmt.Println("Channel type is ", newChannel.ChannelType())
	// Channels have a type, depending on the application level
	// protocol intended. In the case of a shell, the type is
	// "session" and ServerShell may be used to present a simple
	// terminal interface.
	// TODO: Is there any other channel type we want to accept?
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		panic("could not accept channel.")
	}

	// We just handle "exec" requests
	for req := range requests {
		// scp does an exec, so that's all we care about
		switch req.Type {
		case "exec":
			go handleRequest(channel, req)
		default:
			ok := false
			fmt.Println(req.Type, string(req.Payload))
			req.Reply(ok, nil)
		}
	}
}

// Handle new connections
func handleConn(nConn net.Conn, config *ssh.ServerConfig) {
	// Before use, a handshake must be performed on the incoming
	// net.Conn.
	_, chans, _, err := ssh.NewServerConn(nConn, config)
	if err != nil {
		// If the key changes this is considered a handshake failure
		log.Println("failed to handshake")
	}

	// Service the incoming Channel channel.
	for newChannel := range chans {
		go handleNewChannel(newChannel)
	}
}

func passwordAuth(conn ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
	// TODO: Everything!!
	// Should use constant-time compare (or better, salt+hash) in
	// a production setting.
	if conn.User() == "testuser" && string(pass) == "tiger" {
		return nil, nil
	}
	return nil, fmt.Errorf("password rejected for %q", conn.User())
}

func keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	// TODO: Improve log message
	log.Println(conn.RemoteAddr(), "authenticating with", key.Type())
	// TODO: Actually do authentication here
	return nil, fmt.Errorf("key rejected for %q", conn.User())
}

func main() {
	// An SSH server is represented by a ServerConfig, which holds
	// certificate details and handles authentication of ServerConns.
	config := &ssh.ServerConfig{
		PasswordCallback:  passwordAuth,
		PublicKeyCallback: keyAuth,
	}

	// TODO: Tidy up a bit, allow to specify keys on startup
	privateBytes, err := ioutil.ReadFile("id_rsa")
	var private ssh.Signer
	if err != nil {
		fmt.Println("Failed to load private key, generating one")
		key, _ := rsa.GenerateKey(rand.Reader, 2048)
		private, _ = ssh.NewSignerFromKey(key)
	} else {
		private, err = ssh.ParsePrivateKey(privateBytes)
		if err != nil {
			panic("Failed to parse private key")
		}
	}

	config.AddHostKey(private)

	// Once a ServerConfig has been configured, connections can be
	// accepted.
	listener, err := net.Listen("tcp", "0.0.0.0:2222")
	if err != nil {
		panic("failed to listen for connection")
	}

	for {
		nConn, err := listener.Accept()
		if err != nil {
			panic("failed to accept incoming connection")
		}
		go handleConn(nConn, config)
	}
}
<commit_msg>Return exit status to client<commit_after>package main

import (
	"crypto/rand"
	"crypto/rsa"
	"encoding/binary"
	"fmt"
	"github.com/flynn/go-shlex"
	"golang.org/x/crypto/ssh"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os/exec"
)

// Handle requests received through a channel
func handleRequest(channel ssh.Channel, req *ssh.Request) {
	ok := true
	s, _ := shlex.Split(string(req.Payload[4:]))

	// We only do scp, so ignore everything after a ";" or "&&"
	commandStop := len(s)
	for i := 1; i < len(s); i++ {
		if s[i] == ";" || s[i] == "&&" {
			commandStop = i
		}
	}

	// Ignore everything that's not scp
	if s[0] != "scp" {
		ok = false
		req.Reply(ok, []byte("Only scp is supported"))
		channel.Write([]byte("Only scp is supported\n"))
		channel.Close()
		return
	}

	cmd := exec.Command(s[0], s[1:commandStop]...)

	cerr, _ := cmd.StderrPipe()
	cout, _ := cmd.StdoutPipe()
	cin, _ := cmd.StdinPipe()

	go io.Copy(channel.Stderr(), cerr)
	go io.Copy(channel, cout)
	go io.Copy(cin, channel)

	log.Printf("Starting command")
	cmd.Start()

	log.Printf("Waiting")
	var exitStatus uint64 = 0
	err := cmd.Wait()
	if err != nil {
		log.Printf("Error when running command (%s)", err)
		// TODO: Get the actual exit status and store it here
		exitStatus = 1
	}

	log.Printf("Waited")

	exitStatusBuffer := make([]byte, 4)
	binary.PutUvarint(exitStatusBuffer, uint64(exitStatus))
	_, err = channel.SendRequest("exit-status", false, exitStatusBuffer)
	if err != nil {
		log.Println("Failed to forward exit-status to client:", err)
	}

	channel.Close()
	log.Printf("session closed")
	fmt.Println(ok)
	req.Reply(ok, nil)
}

func handleNewChannel(newChannel ssh.NewChannel) {
	fmt.Println("Channel type is ", newChannel.ChannelType())
	// Channels have a type, depending on the application level
	// protocol intended. In the case of a shell, the type is
	// "session" and ServerShell may be used to present a simple
	// terminal interface.
	// TODO: Is there any other channel type we want to accept?
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		// TODO: Don't panic here, just clean up and log error
		panic("could not accept channel.")
	}

	// We just handle "exec" requests
	for req := range requests {
		// scp does an exec, so that's all we care about
		switch req.Type {
		case "exec":
			go handleRequest(channel, req)
		case "shell":
			channel.Write([]byte("Opening a shell is not supported by the server\n"))
			req.Reply(false, nil)
		case "env":
			// Ignore these
			req.Reply(true, nil)
		default:
			log.Println("__", req.Type, "__", string(req.Payload))
			req.Reply(true, nil)
		}
	}
}

// Handle new connections
func handleConn(nConn net.Conn, config *ssh.ServerConfig) {
	// Before use, a handshake must be performed on the incoming
	// net.Conn.
	_, chans, _, err := ssh.NewServerConn(nConn, config)
	if err != nil {
		// If the key changes this is considered a handshake failure
		log.Println("failed to handshake")
	}

	// Service the incoming Channel channel.
	for newChannel := range chans {
		go handleNewChannel(newChannel)
	}
}

func passwordAuth(conn ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
	// TODO: Everything!!
	// Should use constant-time compare (or better, salt+hash) in
	// a production setting.
	if conn.User() == "testuser" && string(pass) == "" {
		return nil, nil
	}
	return nil, fmt.Errorf("password rejected for %q", conn.User())
}

func keyAuth(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
	// TODO: Improve log message
	log.Println(conn.RemoteAddr(), "authenticating with", key.Type())
	// TODO: Actually do authentication here
	return nil, fmt.Errorf("key rejected for %q", conn.User())
}

func main() {
	// An SSH server is represented by a ServerConfig, which holds
	// certificate details and handles authentication of ServerConns.
	config := &ssh.ServerConfig{
		PasswordCallback:  passwordAuth,
		PublicKeyCallback: keyAuth,
	}

	// TODO: Tidy up a bit, allow to specify keys on startup
	privateBytes, err := ioutil.ReadFile("id_rsa")
	var private ssh.Signer
	if err != nil {
		fmt.Println("Failed to load private key, generating one")
		key, _ := rsa.GenerateKey(rand.Reader, 2048)
		private, _ = ssh.NewSignerFromKey(key)
	} else {
		private, err = ssh.ParsePrivateKey(privateBytes)
		if err != nil {
			panic("Failed to parse private key")
		}
	}

	config.AddHostKey(private)

	// Once a ServerConfig has been configured, connections can be
	// accepted.
	listener, err := net.Listen("tcp", "0.0.0.0:2222")
	if err != nil {
		panic("failed to listen for connection")
	}

	for {
		nConn, err := listener.Accept()
		if err != nil {
			panic("failed to accept incoming connection")
		}
		go handleConn(nConn, config)
	}
}
<|endoftext|>


<commit_before>package simplessh

import (
	"code.google.com/p/go.crypto/ssh"
	"github.com/pkg/sftp"

	"io"
	"io/ioutil"
	"os"
)

type Client struct {
	SSHClient *ssh.Client
}

func ConnectWithPassword(host, user, pass string) (*Client, error) {
	authMethod := ssh.Password(pass)

	return connect(user, host, authMethod)
}

func ConnectWithPrivateKey(host, user, privKeyPath string) (*Client, error) {
	privKey, err := ioutil.ReadFile(privKeyPath)
	if err != nil {
		return nil, err
	}

	signer, err := ssh.ParsePrivateKey(privKey)
	if err != nil {
		return nil, err
	}

	authMethod := ssh.PublicKeys(signer)

	return connect(user, host, authMethod)
}

func connect(user, host string, authMethod ssh.AuthMethod) (*Client, error) {
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{authMethod},
	}

	client, err := ssh.Dial("tcp", host, config)
	if err != nil {
		return nil, err
	}

	c := &Client{SSHClient: client}
	return c, nil
}

func (c *Client) Exec(cmd string) ([]byte, error) {
	session, err := c.SSHClient.NewSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()

	return session.CombinedOutput(cmd)
}

func (c *Client) Download(remote, local string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()

	remoteFile, err := client.Open(remote)
	if err != nil {
		return err
	}
	defer remoteFile.Close()

	localFile, err := os.Create(local)
	if err != nil {
		return err
	}
	defer localFile.Close()

	_, err = io.Copy(localFile, remoteFile)
	return err
}

func (c *Client) Upload(local, remote string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()

	localFile, err := os.Open(local)
	if err != nil {
		return err
	}
	defer localFile.Close()

	remoteFile, err := client.Create(remote)
	if err != nil {
		return err
	}

	_, err = io.Copy(remoteFile, localFile)
	return err
}
<commit_msg>Add port number to host if it doesn't already contain it.<commit_after>package simplessh

import (
	"code.google.com/p/go.crypto/ssh"
	"github.com/pkg/sftp"

	"io"
	"io/ioutil"
	"net"
	"os"
)

type Client struct {
	SSHClient *ssh.Client
}

func ConnectWithPassword(host, user, pass string) (*Client, error) {
	authMethod := ssh.Password(pass)

	return connect(user, host, authMethod)
}

func ConnectWithPrivateKey(host, user, privKeyPath string) (*Client, error) {
	privKey, err := ioutil.ReadFile(privKeyPath)
	if err != nil {
		return nil, err
	}

	signer, err := ssh.ParsePrivateKey(privKey)
	if err != nil {
		return nil, err
	}

	authMethod := ssh.PublicKeys(signer)

	return connect(user, host, authMethod)
}

func connect(user, host string, authMethod ssh.AuthMethod) (*Client, error) {
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{authMethod},
	}

	host = addPortToHost(host)

	client, err := ssh.Dial("tcp", host, config)
	if err != nil {
		return nil, err
	}

	c := &Client{SSHClient: client}
	return c, nil
}

func (c *Client) Exec(cmd string) ([]byte, error) {
	session, err := c.SSHClient.NewSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()

	return session.CombinedOutput(cmd)
}

func (c *Client) Download(remote, local string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()

	remoteFile, err := client.Open(remote)
	if err != nil {
		return err
	}
	defer remoteFile.Close()

	localFile, err := os.Create(local)
	if err != nil {
		return err
	}
	defer localFile.Close()

	_, err = io.Copy(localFile, remoteFile)
	return err
}

func (c *Client) Upload(local, remote string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()

	localFile, err := os.Open(local)
	if err != nil {
		return err
	}
	defer localFile.Close()

	remoteFile, err := client.Create(remote)
	if err != nil {
		return err
	}

	_, err = io.Copy(remoteFile, localFile)
	return err
}

func addPortToHost(host string) string {
	_, _, err := net.SplitHostPort(host)

	// We got an error so blindly try to add a port number
	if err != nil {
		return net.JoinHostPort(host, "22")
	}

	return host
}
<|endoftext|>