<commit_before>// +build !windows

package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/deis/deis/deisctl/backend/fleet"
	"github.com/deis/deis/deisctl/client"
	"github.com/deis/deis/pkg/prettyprint"
	"github.com/deis/deis/version"

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

// main exits with the return value of Command(os.Args[1:]), deferring all logic to
// a func we can test.
func main() {
	os.Exit(Command(nil))
}

// Command executes the given deisctl command line.
func Command(argv []string) int {
	deisctlMotd := prettyprint.DeisIfy("Deis Control Utility")
	usage := deisctlMotd + `
Usage: deisctl [options] <command> [<args>...]

Commands, use "deisctl help <command>" to learn more:
  install           install components, or the entire platform
  uninstall         uninstall components
  list              list installed components
  start             start components
  stop              stop components
  restart           stop, then start components
  scale             grow or shrink the number of routers, registries or store gateways
  journal           print the log output of a component
  config            set platform or component values
  refresh-units     refresh unit files from GitHub
  ssh               open an interacive shell on a machine in the cluster
  help              show the help screen for a command

Options:
  -h --help                   show this help screen
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --known-hosts-file=<path>   where to store remote fingerprints [default: ~/.ssh/known_hosts]
  --request-timeout=<secs>    seconds before a request is considered failed [default: 10.0]
  --ssh-timeout=<secs>        seconds before SSH connection is considered failed [default: 10.0]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             SSH tunnel for communication with fleet and etcd [default: ]
  --version                   print the version of deisctl
`
	// pre-parse command-line arguments
	argv, helpFlag := parseArgs(argv)
	// give docopt an optional final false arg so it doesn't call os.Exit()
	args, err := docopt.Parse(usage, argv, false, version.Version, true, false)

	if err != nil && err.Error() != "" {
		fmt.Println(err)
		return 1
	}

	if len(args) == 0 {
		return 0
	}

	command := args["<command>"]
	setTunnel := true
	// "--help" and "refresh-units" doesn't need SSH tunneling
	if helpFlag || command == "refresh-units" {
		setTunnel = false
	}
	setGlobalFlags(args, setTunnel)
	// clean up the args so subcommands don't need to reparse them
	argv = removeGlobalArgs(argv)
	// construct a client
	c, err := client.NewClient("fleet")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}
	// Dispatch the command, passing the argv through so subcommands can
	// re-parse it according to their usage strings.
	switch command {
	case "list":
		err = c.List(argv)
	case "scale":
		err = c.Scale(argv)
	case "start":
		err = c.Start(argv)
	case "restart":
		err = c.Restart(argv)
	case "stop":
		err = c.Stop(argv)
	case "status":
		err = c.Status(argv)
	case "journal":
		err = c.Journal(argv)
	case "install":
		err = c.Install(argv)
	case "uninstall":
		err = c.Uninstall(argv)
	case "config":
		err = c.Config(argv)
	case "refresh-units":
		err = c.RefreshUnits(argv)
	case "ssh":
		err = c.SSH(argv)
	case "dock":
		err = c.Dock(argv)
	case "help":
		fmt.Print(usage)
		return 0
	default:
		fmt.Println(`Found no matching command, try "deisctl help"
Usage: deisctl <command> [<args>...] [options]`)
		return 1
	}
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}
	return 0
}

// isGlobalArg returns true if a string looks like it is a global deisctl option flag,
// such as "--tunnel".
func isGlobalArg(arg string) bool {
	prefixes := []string{
		"--endpoint=",
		"--etcd-key-prefix=",
		"--etcd-keyfile=",
		"--etcd-certfile=",
		"--etcd-cafile=",
		// "--experimental-api=",
		"--known-hosts-file=",
		"--request-timeout=",
		"--ssh-timeout=",
		"--strict-host-key-checking=",
		"--tunnel=",
	}
	for _, p := range prefixes {
		if strings.HasPrefix(arg, p) {
			return true
		}
	}
	return false
}

// parseArgs returns the provided args with "--help" as the last arg if need be,
// and a boolean to indicate whether help was requested.
func parseArgs(argv []string) ([]string, bool) {
	if argv == nil {
		argv = os.Args[1:]
	}

	if len(argv) == 1 {
		// rearrange "deisctl --help" as "deisctl help"
		if argv[0] == "--help" || argv[0] == "-h" {
			argv[0] = "help"
		}
	}

	if len(argv) >= 2 {
		// rearrange "deisctl help <command>" as "deisctl <command> --help"
		if argv[0] == "help" || argv[0] == "--help" || argv[0] == "-h" {
			argv = append(argv[1:], "--help")
		}
	}

	helpFlag := false
	for _, a := range argv {
		if a == "help" || a == "--help" || a == "-h" {
			helpFlag = true
			break
		}
	}

	return argv, helpFlag
}

// removeGlobalArgs returns the given args without any global option flags, to make
// re-parsing by subcommands easier.
func removeGlobalArgs(argv []string) []string {
	var v []string
	for _, a := range argv {
		if !isGlobalArg(a) {
			v = append(v, a)
		}
	}
	return v
}

// setGlobalFlags sets fleet provider options based on deisctl global flags.
func setGlobalFlags(args map[string]interface{}, setTunnel bool) {
	fleet.Flags.Endpoint = args["--endpoint"].(string)
	fleet.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	fleet.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	fleet.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	fleet.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//fleet.Flags.UseAPI = args["--experimental-api"].(bool)
	fleet.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	fleet.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	fleet.Flags.RequestTimeout = timeout
	sshTimeout, _ := strconv.ParseFloat(args["--ssh-timeout"].(string), 64)
	fleet.Flags.SSHTimeout = sshTimeout
	if setTunnel == true {
		tunnel := args["--tunnel"].(string)
		if tunnel != "" {
			fleet.Flags.Tunnel = tunnel
		} else {
			fleet.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
		}
	}
}
<commit_msg>fix(deisctl): add dock to the list of commands<commit_after>// +build !windows

package main

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/deis/deis/deisctl/backend/fleet"
	"github.com/deis/deis/deisctl/client"
	"github.com/deis/deis/pkg/prettyprint"
	"github.com/deis/deis/version"

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

// main exits with the return value of Command(os.Args[1:]), deferring all logic to
// a func we can test.
func main() {
	os.Exit(Command(nil))
}

// Command executes the given deisctl command line.
func Command(argv []string) int {
	deisctlMotd := prettyprint.DeisIfy("Deis Control Utility")
	usage := deisctlMotd + `
Usage: deisctl [options] <command> [<args>...]

Commands, use "deisctl help <command>" to learn more:
  install           install components, or the entire platform
  uninstall         uninstall components
  list              list installed components
  start             start components
  stop              stop components
  restart           stop, then start components
  scale             grow or shrink the number of routers, registries or store gateways
  journal           print the log output of a component
  config            set platform or component values
  refresh-units     refresh unit files from GitHub
  ssh               open an interactive shell on a machine in the cluster
  dock              open an interactive shell on a container in the cluster
  help              show the help screen for a command

Options:
  -h --help                   show this help screen
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --known-hosts-file=<path>   where to store remote fingerprints [default: ~/.ssh/known_hosts]
  --request-timeout=<secs>    seconds before a request is considered failed [default: 10.0]
  --ssh-timeout=<secs>        seconds before SSH connection is considered failed [default: 10.0]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             SSH tunnel for communication with fleet and etcd [default: ]
  --version                   print the version of deisctl
`
	// pre-parse command-line arguments
	argv, helpFlag := parseArgs(argv)
	// give docopt an optional final false arg so it doesn't call os.Exit()
	args, err := docopt.Parse(usage, argv, false, version.Version, true, false)

	if err != nil && err.Error() != "" {
		fmt.Println(err)
		return 1
	}

	if len(args) == 0 {
		return 0
	}

	command := args["<command>"]
	setTunnel := true
	// "--help" and "refresh-units" doesn't need SSH tunneling
	if helpFlag || command == "refresh-units" {
		setTunnel = false
	}
	setGlobalFlags(args, setTunnel)
	// clean up the args so subcommands don't need to reparse them
	argv = removeGlobalArgs(argv)
	// construct a client
	c, err := client.NewClient("fleet")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}
	// Dispatch the command, passing the argv through so subcommands can
	// re-parse it according to their usage strings.
	switch command {
	case "list":
		err = c.List(argv)
	case "scale":
		err = c.Scale(argv)
	case "start":
		err = c.Start(argv)
	case "restart":
		err = c.Restart(argv)
	case "stop":
		err = c.Stop(argv)
	case "status":
		err = c.Status(argv)
	case "journal":
		err = c.Journal(argv)
	case "install":
		err = c.Install(argv)
	case "uninstall":
		err = c.Uninstall(argv)
	case "config":
		err = c.Config(argv)
	case "refresh-units":
		err = c.RefreshUnits(argv)
	case "ssh":
		err = c.SSH(argv)
	case "dock":
		err = c.Dock(argv)
	case "help":
		fmt.Print(usage)
		return 0
	default:
		fmt.Println(`Found no matching command, try "deisctl help"
Usage: deisctl <command> [<args>...] [options]`)
		return 1
	}
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}
	return 0
}

// isGlobalArg returns true if a string looks like it is a global deisctl option flag,
// such as "--tunnel".
func isGlobalArg(arg string) bool {
	prefixes := []string{
		"--endpoint=",
		"--etcd-key-prefix=",
		"--etcd-keyfile=",
		"--etcd-certfile=",
		"--etcd-cafile=",
		// "--experimental-api=",
		"--known-hosts-file=",
		"--request-timeout=",
		"--ssh-timeout=",
		"--strict-host-key-checking=",
		"--tunnel=",
	}
	for _, p := range prefixes {
		if strings.HasPrefix(arg, p) {
			return true
		}
	}
	return false
}

// parseArgs returns the provided args with "--help" as the last arg if need be,
// and a boolean to indicate whether help was requested.
func parseArgs(argv []string) ([]string, bool) {
	if argv == nil {
		argv = os.Args[1:]
	}

	if len(argv) == 1 {
		// rearrange "deisctl --help" as "deisctl help"
		if argv[0] == "--help" || argv[0] == "-h" {
			argv[0] = "help"
		}
	}

	if len(argv) >= 2 {
		// rearrange "deisctl help <command>" as "deisctl <command> --help"
		if argv[0] == "help" || argv[0] == "--help" || argv[0] == "-h" {
			argv = append(argv[1:], "--help")
		}
	}

	helpFlag := false
	for _, a := range argv {
		if a == "help" || a == "--help" || a == "-h" {
			helpFlag = true
			break
		}
	}

	return argv, helpFlag
}

// removeGlobalArgs returns the given args without any global option flags, to make
// re-parsing by subcommands easier.
func removeGlobalArgs(argv []string) []string {
	var v []string
	for _, a := range argv {
		if !isGlobalArg(a) {
			v = append(v, a)
		}
	}
	return v
}

// setGlobalFlags sets fleet provider options based on deisctl global flags.
func setGlobalFlags(args map[string]interface{}, setTunnel bool) {
	fleet.Flags.Endpoint = args["--endpoint"].(string)
	fleet.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	fleet.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	fleet.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	fleet.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//fleet.Flags.UseAPI = args["--experimental-api"].(bool)
	fleet.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	fleet.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	fleet.Flags.RequestTimeout = timeout
	sshTimeout, _ := strconv.ParseFloat(args["--ssh-timeout"].(string), 64)
	fleet.Flags.SSHTimeout = sshTimeout
	if setTunnel == true {
		tunnel := args["--tunnel"].(string)
		if tunnel != "" {
			fleet.Flags.Tunnel = tunnel
		} else {
			fleet.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"errors"
	"fmt"
	"io"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type object struct {
	// A storage.Object representing metadata for this object. Never changes.
	metadata *storage.Object

	// The contents of the object. These never change.
	contents string
}

// A slice of objects compared by name.
type objectSlice []object

func (s objectSlice) Len() int           { return len(s) }
func (s objectSlice) Less(i, j int) bool { return s[i].metadata.Name < s[j].metadata.Name }
func (s objectSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// Return the smallest i such that s[i].metadata.Name >= name, or len(s) if
// there is no such i.
func (s objectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].metadata.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].metadata.Name == name, or len(s) if
// there is no such i.
func (s objectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].metadata.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].metadata.Name and
// !strings.HasPrefix(s[i].metadata.Name, prefix).
func (s objectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects objectSlice // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.metadata.Name < objB.metadata.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.metadata.Name,
					objB.metadata.Name))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o object = b.objects[i]
		name := o.metadata.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.Index(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, save as an object result.
		listing.Results = append(listing.Results, o.metadata)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].metadata.Name
		}
	}

	return
}

func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	return nil, errors.New("TODO: Implement NewReader.")
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (gcs.ObjectWriter, error) {
	// Check that the object name is legal.
	name := attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	return newObjectWriter(b, attrs), nil
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object not found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents string) (o object) {
	// Set up metadata.
	// TODO(jacobsa): Other fields.
	o.metadata = &storage.Object{
		Bucket:   b.Name(),
		Name:     attrs.Name,
		Owner:    "user-fake",
		Size:     int64(len(contents)),
		Metadata: attrs.Metadata,
	}

	// Set up contents.
	o.contents = contents

	return
}

// Add a record for an object with the given attributes and contents, then
// return the minted metadata.
//
// LOCKS_EXCLUDED(b.mu)
func (b *bucket) addObject(
	attrs *storage.ObjectAttrs,
	contents string) *storage.Object {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Create an object record from the given attributes.
	var o object = b.mintObject(attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	return o.metadata
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<commit_msg>Implemented NewReader.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsfake

import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"sort"
	"strings"
	"unicode/utf8"

	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/gcloud/syncutil"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

// Create an in-memory bucket with the given name and empty contents.
func NewFakeBucket(name string) gcs.Bucket {
	b := &bucket{name: name}
	b.mu = syncutil.NewInvariantMutex(func() { b.checkInvariants() })
	return b
}

type object struct {
	// A storage.Object representing metadata for this object. Never changes.
	metadata *storage.Object

	// The contents of the object. These never change.
	contents string
}

// A slice of objects compared by name.
type objectSlice []object

func (s objectSlice) Len() int           { return len(s) }
func (s objectSlice) Less(i, j int) bool { return s[i].metadata.Name < s[j].metadata.Name }
func (s objectSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

// Return the smallest i such that s[i].metadata.Name >= name, or len(s) if
// there is no such i.
func (s objectSlice) lowerBound(name string) int {
	pred := func(i int) bool {
		return s[i].metadata.Name >= name
	}

	return sort.Search(len(s), pred)
}

// Return the smallest i such that s[i].metadata.Name == name, or len(s) if
// there is no such i.
func (s objectSlice) find(name string) int {
	lb := s.lowerBound(name)
	if lb < len(s) && s[lb].metadata.Name == name {
		return lb
	}

	return len(s)
}

// Return the smallest string that is lexicographically larger than prefix and
// does not have prefix as a prefix. For the sole case where this is not
// possible (all strings consisting solely of 0xff bytes, including the empty
// string), return the empty string.
func prefixSuccessor(prefix string) string {
	// Attempt to increment the last byte. If that is a 0xff byte, erase it and
	// recurse. If we hit an empty string, then we know our task is impossible.
	limit := []byte(prefix)
	for len(limit) > 0 {
		b := limit[len(limit)-1]
		if b != 0xff {
			limit[len(limit)-1]++
			break
		}

		limit = limit[:len(limit)-1]
	}

	return string(limit)
}

// Return the smallest i such that prefix < s[i].metadata.Name and
// !strings.HasPrefix(s[i].metadata.Name, prefix).
func (s objectSlice) prefixUpperBound(prefix string) int {
	successor := prefixSuccessor(prefix)
	if successor == "" {
		return len(s)
	}

	return s.lowerBound(successor)
}

type bucket struct {
	name string
	mu   syncutil.InvariantMutex

	// The set of extant objects.
	//
	// INVARIANT: Strictly increasing.
	objects objectSlice // GUARDED_BY(mu)
}

// SHARED_LOCKS_REQUIRED(b.mu)
func (b *bucket) checkInvariants() {
	// Make sure 'objects' is strictly increasing.
	for i := 1; i < len(b.objects); i++ {
		objA := b.objects[i-1]
		objB := b.objects[i]
		if !(objA.metadata.Name < objB.metadata.Name) {
			panic(
				fmt.Sprintf(
					"Object names are not strictly increasing: %v vs. %v",
					objA.metadata.Name,
					objB.metadata.Name))
		}
	}
}

func (b *bucket) Name() string {
	return b.name
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) ListObjects(
	ctx context.Context,
	query *storage.Query) (listing *storage.Objects, err error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// Set up the result object.
	listing = new(storage.Objects)

	// Handle nil queries.
	if query == nil {
		query = &storage.Query{}
	}

	// Handle defaults.
	maxResults := query.MaxResults
	if maxResults == 0 {
		maxResults = 1000
	}

	// Find where in the space of object names to start.
	nameStart := query.Prefix
	if query.Cursor != "" && query.Cursor > nameStart {
		nameStart = query.Cursor
	}

	// Find the range of indexes within the array to scan.
	indexStart := b.objects.lowerBound(nameStart)
	prefixLimit := b.objects.prefixUpperBound(query.Prefix)
	indexLimit := minInt(indexStart+maxResults, prefixLimit)

	// Scan the array.
	var lastResultWasPrefix bool
	for i := indexStart; i < indexLimit; i++ {
		var o object = b.objects[i]
		name := o.metadata.Name

		// Search for a delimiter if necessary.
		if query.Delimiter != "" {
			// Search only in the part after the prefix.
			nameMinusQueryPrefix := name[len(query.Prefix):]

			delimiterIndex := strings.Index(nameMinusQueryPrefix, query.Delimiter)
			if delimiterIndex >= 0 {
				resultPrefixLimit := delimiterIndex

				// Transform to an index within name.
				resultPrefixLimit += len(query.Prefix)

				// Include the delimiter in the result.
				resultPrefixLimit += len(query.Delimiter)

				// Save the result, but only if it's not a duplicate.
				resultPrefix := name[:resultPrefixLimit]
				if len(listing.Prefixes) == 0 ||
					listing.Prefixes[len(listing.Prefixes)-1] != resultPrefix {
					listing.Prefixes = append(listing.Prefixes, resultPrefix)
				}

				lastResultWasPrefix = true
				continue
			}
		}

		lastResultWasPrefix = false

		// Otherwise, save as an object result.
		listing.Results = append(listing.Results, o.metadata)
	}

	// Set up a cursor for where to start the next scan if we didn't exhaust the
	// results.
	if indexLimit < prefixLimit {
		listing.Next = &storage.Query{}
		*listing.Next = *query

		// Ion is if the final object we visited was returned as an element in
		// listing.Prefixes, we want to skip all other objects that would result in
		// the same so we don't return duplicate elements in listing.Prefixes
		// accross requests.
		if lastResultWasPrefix {
			lastResultPrefix := listing.Prefixes[len(listing.Prefixes)-1]
			listing.Next.Cursor = prefixSuccessor(lastResultPrefix)

			// Check an assumption: prefixSuccessor cannot result in the empty string
			// above because object names must be non-empty UTF-8 strings, and there
			// is no valid non-empty UTF-8 string that consists of entirely 0xff
			// bytes.
			if listing.Next.Cursor == "" {
				err = errors.New("Unexpected empty string from prefixSuccessor")
				return
			}
		} else {
			// Otherwise, we'll start scanning at the next object.
			listing.Next.Cursor = b.objects[indexLimit].metadata.Name
		}
	}

	return
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) NewReader(
	ctx context.Context,
	objectName string) (io.ReadCloser, error) {
	b.mu.RLock()
	defer b.mu.RUnlock()

	index := b.objects.find(objectName)
	if index == len(b.objects) {
		return nil, errors.New("Object not found.")
	}

	return ioutil.NopCloser(strings.NewReader(b.objects[index].contents)), nil
}

func (b *bucket) NewWriter(
	ctx context.Context,
	attrs *storage.ObjectAttrs) (gcs.ObjectWriter, error) {
	// Check that the object name is legal.
	name := attrs.Name
	if len(name) == 0 || len(name) > 1024 {
		return nil, errors.New("Invalid object name: length must be in [1, 1024]")
	}

	if !utf8.ValidString(name) {
		return nil, errors.New("Invalid object name: not valid UTF-8")
	}

	for _, r := range name {
		if r == 0x0a || r == 0x0d {
			return nil, errors.New("Invalid object name: must not contain CR or LF")
		}
	}

	return newObjectWriter(b, attrs), nil
}

// LOCKS_EXCLUDED(b.mu)
func (b *bucket) DeleteObject(
	ctx context.Context,
	name string) error {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Do we possess the object with the given name?
	index := b.objects.find(name)
	if index == len(b.objects) {
		return errors.New("Object not found.")
	}

	// Remove the object.
	b.objects = append(b.objects[:index], b.objects[index+1:]...)

	return nil
}

// Create an object struct for the given attributes and contents.
//
// EXCLUSIVE_LOCKS_REQUIRED(b.mu)
func (b *bucket) mintObject(
	attrs *storage.ObjectAttrs,
	contents string) (o object) {
	// Set up metadata.
	// TODO(jacobsa): Other fields.
	o.metadata = &storage.Object{
		Bucket:   b.Name(),
		Name:     attrs.Name,
		Owner:    "user-fake",
		Size:     int64(len(contents)),
		Metadata: attrs.Metadata,
	}

	// Set up contents.
	o.contents = contents

	return
}

// Add a record for an object with the given attributes and contents, then
// return the minted metadata.
//
// LOCKS_EXCLUDED(b.mu)
func (b *bucket) addObject(
	attrs *storage.ObjectAttrs,
	contents string) *storage.Object {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Create an object record from the given attributes.
	var o object = b.mintObject(attrs, contents)

	// Replace an entry in or add an entry to our list of objects.
	existingIndex := b.objects.find(attrs.Name)
	if existingIndex < len(b.objects) {
		b.objects[existingIndex] = o
	} else {
		b.objects = append(b.objects, o)
		sort.Sort(b.objects)
	}

	return o.metadata
}

func minInt(a, b int) int {
	if a < b {
		return a
	}

	return b
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}

	return b
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"errors"
	"net/url"
	"net/http"
	"io/ioutil"
	"strings"
)

func getVideoInfo(videoId string) (string, error) {
	url := "http://youtube.com/get_video_info?video_id=" + videoId
	log("Requesting url: %s", url)
	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("An error occured while requesting the video information: '%s'", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return "", fmt.Errorf("An error occured while requesting the video information: non 200 status code received: '%s'", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("An error occured while reading the video information: '%s'", err)
	}
	log("Got %d bytes answer", len(body))
	return string(body), nil
}

func ensureFields(source url.Values, fields []string) (err error) {
	for _, field := range fields {
		if _, exists := source[field]; !exists {
			return fmt.Errorf("Field '%s' is missing in url.Values source", field)
		}
	}
	return nil
}

func decodeVideoInfo(response string) (streams streamList, err error) {
	// decode

	answer, err := url.ParseQuery(response)
	if err != nil {
		err = fmt.Errorf("parsing the server's answer: '%s'", err)
		return
	}

	// check the status

	err = ensureFields(answer, []string{"status", "url_encoded_fmt_stream_map", "title", "author"})
	if err != nil {
		err = fmt.Errorf("Missing fields in the server's answer: '%s'", err)
		return
	}

	status := answer["status"]
	if status[0] == "fail" {
		reason, ok := answer["reason"]
		if ok {
			err = fmt.Errorf("'fail' response status found in the server's answer, reason: '%s'", reason[0])
		} else {
			err = errors.New(fmt.Sprint("'fail' response status found in the server's answer, no reason given"))
		}
		return
	}
	if status[0] != "ok" {
		err = fmt.Errorf("non-success response status found in the server's answer (status: '%s')", status)
		return
	}

	log("Server answered with a success code")

	/*
	for k, v := range answer {
		log("%s: %#v", k, v)
	}
	*/

	// read the streams map

	stream_map := answer["url_encoded_fmt_stream_map"]

	// read each stream

	streams_list := strings.Split(stream_map[0], ",")

	log("Found %d streams in answer", len(streams_list))

	for stream_pos, stream_raw := range streams_list {
		stream_qry, err := url.ParseQuery(stream_raw)
		if err != nil {
			log(fmt.Sprintf("An error occured while decoding one of the video's stream's information: stream %d: %s\n", stream_pos, err))
			continue
		}
		err = ensureFields(stream_qry, []string{"quality", "type", "url", "sig"})
		if err != nil {
			log(fmt.Sprintf("Missing fields in one of the video's stream's information: stream %d: %s\n", stream_pos, err))
			continue
		}
		/* dumps the raw streams
		log(fmt.Sprintf("%v\n", stream_qry))
		*/
		stream := stream{
			"quality": stream_qry["quality"][0],
			"type": stream_qry["type"][0],
			"url": stream_qry["url"][0],
			"sig": stream_qry["sig"][0],
			"title": answer["title"][0],
			"author": answer["author"][0],
		}
		streams = append(streams, stream)

		quality := stream.Quality()
		if quality == QUALITY_UNKNOWN {
			log("Found unknown quality '%s'", stream["quality"])
		}

		format := stream.Format()
		if format == FORMAT_UNKNOWN {
			log("Found unknown format '%s'", stream["type"])
		}

		log("Stream found: quality '%s', format '%s'", quality, format)
	}

	log("Successfully decoded %d streams", len(streams))

	return
}
<commit_msg>Handle sig being optionnal in stream<commit_after>package main

import (
	"fmt"
	"errors"
	"net/url"
	"net/http"
	"io/ioutil"
	"strings"
)

func getVideoInfo(videoId string) (string, error) {
	url := "http://youtube.com/get_video_info?video_id=" + videoId
	log("Requesting url: %s", url)
	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("An error occured while requesting the video information: '%s'", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return "", fmt.Errorf("An error occured while requesting the video information: non 200 status code received: '%s'", err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("An error occured while reading the video information: '%s'", err)
	}
	log("Got %d bytes answer", len(body))
	return string(body), nil
}

func ensureFields(source url.Values, fields []string) (err error) {
	for _, field := range fields {
		if _, exists := source[field]; !exists {
			return fmt.Errorf("Field '%s' is missing in url.Values source", field)
		}
	}
	return nil
}

func decodeVideoInfo(response string) (streams streamList, err error) {
	// decode

	answer, err := url.ParseQuery(response)
	if err != nil {
		err = fmt.Errorf("parsing the server's answer: '%s'", err)
		return
	}

	// check the status

	err = ensureFields(answer, []string{"status", "url_encoded_fmt_stream_map", "title", "author"})
	if err != nil {
		err = fmt.Errorf("Missing fields in the server's answer: '%s'", err)
		return
	}

	status := answer["status"]
	if status[0] == "fail" {
		reason, ok := answer["reason"]
		if ok {
			err = fmt.Errorf("'fail' response status found in the server's answer, reason: '%s'", reason[0])
		} else {
			err = errors.New(fmt.Sprint("'fail' response status found in the server's answer, no reason given"))
		}
		return
	}
	if status[0] != "ok" {
		err = fmt.Errorf("non-success response status found in the server's answer (status: '%s')", status)
		return
	}

	log("Server answered with a success code")

	/*
	for k, v := range answer {
		log("%s: %#v", k, v)
	}
	*/

	// read the streams map

	stream_map := answer["url_encoded_fmt_stream_map"]

	// read each stream

	streams_list := strings.Split(stream_map[0], ",")

	log("Found %d streams in answer", len(streams_list))

	for stream_pos, stream_raw := range streams_list {
		stream_qry, err := url.ParseQuery(stream_raw)
		if err != nil {
			log(fmt.Sprintf("An error occured while decoding one of the video's stream's information: stream %d: %s\n", stream_pos, err))
			continue
		}
		err = ensureFields(stream_qry, []string{"quality", "type", "url"})
		if err != nil {
			log(fmt.Sprintf("Missing fields in one of the video's stream's information: stream %d: %s\n", stream_pos, err))
			continue
		}
		/* dumps the raw streams
		log(fmt.Sprintf("%v\n", stream_qry))
		*/
		stream := stream{
			"quality": stream_qry["quality"][0],
			"type": stream_qry["type"][0],
			"url": stream_qry["url"][0],
			"sig": "",
			"title": answer["title"][0],
			"author": answer["author"][0],
		}

		if sig, exists := stream_qry["sig"]; exists {
			stream["sig"] = sig[0]
		}

		streams = append(streams, stream)

		quality := stream.Quality()
		if quality == QUALITY_UNKNOWN {
			log("Found unknown quality '%s'", stream["quality"])
		}

		format := stream.Format()
		if format == FORMAT_UNKNOWN {
			log("Found unknown format '%s'", stream["type"])
		}

		log("Stream found: quality '%s', format '%s'", quality, format)
	}

	log("Successfully decoded %d streams", len(streams))

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Christian Saide <Supernomad>
// Licensed under the MPL-2.0, for details see https://github.com/Supernomad/protond/blob/master/LICENSE

package worker
<commit_msg>Added some docs the worker module doc.go<commit_after>// Copyright (c) 2017 Christian Saide <Supernomad>
// Licensed under the MPL-2.0, for details see https://github.com/Supernomad/protond/blob/master/LICENSE

/*
Package worker contains the structs, and logic that form the basis of protonds worker subsystem.

Protond currently implements a single worker type, that is responsible for ingesting events from an arbitrary set of user defined input plugins, processing those events with an arbitrary set of filter plugins, and pushing those filtered events to an arbitrary set of output plugins.
*/
package worker
<|endoftext|>


<commit_before>package kloud

import (
	"errors"
	"fmt"
	"koding/kites/kloud/contexthelper/session"

	"golang.org/x/net/context"

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/service/ec2"
	"github.com/koding/kite"
)

type AuthenticateRequest struct {
	// PublicKeys contains publicKeys to be authenticated
	PublicKeys []string `json:"publicKeys"`
}

func (k *Kloud) Authenticate(r *kite.Request) (interface{}, error) {
	if r.Args == nil {
		return nil, NewError(ErrNoArguments)
	}

	var args *TerraformBootstrapRequest
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	if len(args.PublicKeys) == 0 {
		return nil, errors.New("publicKeys are not passed")
	}

	ctx := k.ContextCreator(context.Background())
	sess, ok := session.FromContext(ctx)
	if !ok {
		return nil, errors.New("session context is not passed")
	}

	creds, err := fetchCredentials(r.Username, sess.DB, args.PublicKeys)
	if err != nil {
		return nil, err
	}

	for _, cred := range creds.Creds {
		// We are going to support more providers in the future, for now only allow aws
		if cred.Provider != "aws" {
			return nil, fmt.Errorf("Bootstrap is only supported for 'aws' provider. Got: '%s'", cred.Provider)
		}

		accessKey := cred.Data["access_key"]
		secretKey := cred.Data["secret_key"]
		authRegion := "us-east-1"

		svc := ec2.New(&aws.Config{
			Credentials: aws.Creds(accessKey, secretKey, ""),
			Region:      authRegion,
		})

		// We do request to fetch and describe all supported regions. This
		// doesn't create any resources but validates the request itself before
		// we can make a request. Also because of having dryrun enabled, we'll
		// get no response (less network io). An error means no validation.
		_, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{})
		if err != nil {
			return nil, err // not authenticated
		}
	}

	return true, nil
}
<commit_msg>kloud/authenticate: fix comment [ci skip]<commit_after>package kloud

import (
	"errors"
	"fmt"
	"koding/kites/kloud/contexthelper/session"

	"golang.org/x/net/context"

	"github.com/awslabs/aws-sdk-go/aws"
	"github.com/awslabs/aws-sdk-go/service/ec2"
	"github.com/koding/kite"
)

type AuthenticateRequest struct {
	// PublicKeys contains publicKeys to be authenticated
	PublicKeys []string `json:"publicKeys"`
}

func (k *Kloud) Authenticate(r *kite.Request) (interface{}, error) {
	if r.Args == nil {
		return nil, NewError(ErrNoArguments)
	}

	var args *TerraformBootstrapRequest
	if err := r.Args.One().Unmarshal(&args); err != nil {
		return nil, err
	}

	if len(args.PublicKeys) == 0 {
		return nil, errors.New("publicKeys are not passed")
	}

	ctx := k.ContextCreator(context.Background())
	sess, ok := session.FromContext(ctx)
	if !ok {
		return nil, errors.New("session context is not passed")
	}

	creds, err := fetchCredentials(r.Username, sess.DB, args.PublicKeys)
	if err != nil {
		return nil, err
	}

	for _, cred := range creds.Creds {
		// We are going to support more providers in the future, for now only allow aws
		if cred.Provider != "aws" {
			return nil, fmt.Errorf("Bootstrap is only supported for 'aws' provider. Got: '%s'", cred.Provider)
		}

		accessKey := cred.Data["access_key"]
		secretKey := cred.Data["secret_key"]
		authRegion := "us-east-1"

		svc := ec2.New(&aws.Config{
			Credentials: aws.Creds(accessKey, secretKey, ""),
			Region:      authRegion,
		})

		// We do request to fetch and describe all supported regions. This
		// doesn't create any resources but validates the request itself before
		// we can make a request. An error means no validation.
		_, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{})
		if err != nil {
			return nil, err // not authenticated
		}
	}

	return true, nil
}
<|endoftext|>


<commit_before>// Copyright 2017 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 ghutil_test

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"

	"github.com/google/code-review-bot/ghutil"
	"github.com/google/go-github/github"
)

type MockGitHubClient struct {
	Organizations *ghutil.MockOrganizationsService
	PullRequests  *ghutil.MockPullRequestsService
	Issues        *ghutil.MockIssuesService
	Repositories  *ghutil.MockRepositoriesService
}

func NewMockGitHubClient(ghc *ghutil.GitHubClient, ctrl *gomock.Controller) *MockGitHubClient {
	mockGhc := &MockGitHubClient{
		Organizations: ghutil.NewMockOrganizationsService(ctrl),
		PullRequests:  ghutil.NewMockPullRequestsService(ctrl),
		Issues:        ghutil.NewMockIssuesService(ctrl),
		Repositories:  ghutil.NewMockRepositoriesService(ctrl),
	}

	// Patch the original GitHubClient with our mock services.
	ghc.Organizations = mockGhc.Organizations
	ghc.PullRequests = mockGhc.PullRequests
	ghc.Issues = mockGhc.Issues
	ghc.Repositories = mockGhc.Repositories

	return mockGhc
}

// Common parameters used across most, if not all, tests.
var (
	ctrl    *gomock.Controller
	ghc     *ghutil.GitHubClient
	mockGhc *MockGitHubClient

	noLabel *github.Label = nil
)

const (
	orgName   = "org"
	repoName  = "repo"
)

func setUp(t *testing.T) {
	ctrl = gomock.NewController(t)
	ghc = &ghutil.GitHubClient{}
	mockGhc = NewMockGitHubClient(ghc, ctrl)
}

func tearDown(t *testing.T) {
	ctrl.Finish()
}

func TestGetAllRepos_OrgAndRepo(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	repo := github.Repository{}

	mockGhc.Repositories.EXPECT().Get(orgName, repoName).Return(&repo, nil, nil)

	repos := ghc.GetAllRepos(context.Background(), orgName, repoName)
	if len(repos) != 1 {
		t.Logf("repos is not of length 1: %v", repos)
		t.Fail()
	}
}

func TestGetAllRepos_OrgOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	expectedRepos := []*github.Repository{
		{},
		{},
	}

	mockGhc.Repositories.EXPECT().List(orgName, nil).Return(expectedRepos, nil, nil)

	actualRepos := ghc.GetAllRepos(context.Background(), orgName, "")
	if len(expectedRepos) != len(actualRepos) {
		t.Logf("Expected repos: %v, actual repos: %v", expectedRepos, actualRepos)
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_NoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasYesOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&label, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasNoOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&label, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_YesAndNoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	labelYes := github.Label{}
	labelNo := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&labelYes, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&labelNo, nil, nil)

	if !ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned true")
		t.Fail()
	}
}
<commit_msg>Underscore unused parameter<commit_after>// Copyright 2017 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 ghutil_test

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"

	"github.com/google/code-review-bot/ghutil"
	"github.com/google/go-github/github"
)

type MockGitHubClient struct {
	Organizations *ghutil.MockOrganizationsService
	PullRequests  *ghutil.MockPullRequestsService
	Issues        *ghutil.MockIssuesService
	Repositories  *ghutil.MockRepositoriesService
}

func NewMockGitHubClient(ghc *ghutil.GitHubClient, ctrl *gomock.Controller) *MockGitHubClient {
	mockGhc := &MockGitHubClient{
		Organizations: ghutil.NewMockOrganizationsService(ctrl),
		PullRequests:  ghutil.NewMockPullRequestsService(ctrl),
		Issues:        ghutil.NewMockIssuesService(ctrl),
		Repositories:  ghutil.NewMockRepositoriesService(ctrl),
	}

	// Patch the original GitHubClient with our mock services.
	ghc.Organizations = mockGhc.Organizations
	ghc.PullRequests = mockGhc.PullRequests
	ghc.Issues = mockGhc.Issues
	ghc.Repositories = mockGhc.Repositories

	return mockGhc
}

// Common parameters used across most, if not all, tests.
var (
	ctrl    *gomock.Controller
	ghc     *ghutil.GitHubClient
	mockGhc *MockGitHubClient

	noLabel *github.Label = nil
)

const (
	orgName   = "org"
	repoName  = "repo"
)

func setUp(t *testing.T) {
	ctrl = gomock.NewController(t)
	ghc = &ghutil.GitHubClient{}
	mockGhc = NewMockGitHubClient(ghc, ctrl)
}

func tearDown(_ *testing.T) {
	ctrl.Finish()
}

func TestGetAllRepos_OrgAndRepo(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	repo := github.Repository{}

	mockGhc.Repositories.EXPECT().Get(orgName, repoName).Return(&repo, nil, nil)

	repos := ghc.GetAllRepos(context.Background(), orgName, repoName)
	if len(repos) != 1 {
		t.Logf("repos is not of length 1: %v", repos)
		t.Fail()
	}
}

func TestGetAllRepos_OrgOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	expectedRepos := []*github.Repository{
		{},
		{},
	}

	mockGhc.Repositories.EXPECT().List(orgName, nil).Return(expectedRepos, nil, nil)

	actualRepos := ghc.GetAllRepos(context.Background(), orgName, "")
	if len(expectedRepos) != len(actualRepos) {
		t.Logf("Expected repos: %v, actual repos: %v", expectedRepos, actualRepos)
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_NoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasYesOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&label, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(noLabel, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_HasNoOnly(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	label := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(noLabel, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&label, nil, nil)

	if ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned false")
		t.Fail()
	}
}

func TestVerifyRepoHasClaLabels_YesAndNoLabels(t *testing.T) {
	setUp(t)
	defer tearDown(t)

	labelYes := github.Label{}
	labelNo := github.Label{}

	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaYes).Return(&labelYes, nil, nil)
	mockGhc.Issues.EXPECT().GetLabel(orgName, repoName, ghutil.LabelClaNo).Return(&labelNo, nil, nil)

	if !ghc.VerifyRepoHasClaLabels(context.Background(), orgName, repoName) {
		t.Log("Should have returned true")
		t.Fail()
	}
}
<|endoftext|>


<commit_before>package gitManip

import (
	"fmt"

	"github.com/fatih/color"

	git "gopkg.in/libgit2/git2go.v24"
)

/*GitObject contains informations about the current git repository
 *
 *The structure is:
 *  accessible:
 *		Is the repository still exists in the hard drive?
 *	path:
 *		The path file.
 *	repository:
 *		The object repository.
 */
type GitObject struct {
	accessible error
	path       string
	repository git.Repository
}

/*New is a constructor for GitObject
 *
 * It neeeds:
 *	path:
 *		The path of the current repository.
 */
func New(path string) *GitObject {
	r, err := git.OpenRepository(path)
	return &GitObject{accessible: err, path: path, repository: *r}
}

func (g *GitObject) isAccessible() bool {
	return g.accessible == nil
}

/*Status prints the current status of the repository, accessible via the structure path field.
 *This method works only if the repository is accessible.
 */
func (g *GitObject) Status() {
	if g.isAccessible() {
		fmt.Printf("The status of %s is: %s\n", g.path, g.repository.State())
	}
}

/*List lists the path and the accessibility of a list of git repositories
 */
func List(repositories *[]GitObject) {
	for _, object := range *repositories {
		fmt.Printf("* %s ", object.path)
		if object.isAccessible() {
			fmt.Println(color.GreenString(" [accessible]"))
		} else {
			fmt.Println(color.RedString(" [not accessible]"))
		}
	}
}
<commit_msg>Add new maps, new methods and a new path to print out modified files<commit_after>package gitManip

import (
	"fmt"

	"github.com/fatih/color"

	git "gopkg.in/libgit2/git2go.v24"
)

/*Map to match the RepositoryState enum type with a string
 */
var repositoryStateToString = map[git.RepositoryState]string{
	git.RepositoryStateNone:                 "None",
	git.RepositoryStateMerge:                "Merge",
	git.RepositoryStateRevert:               "Revert",
	git.RepositoryStateCherrypick:           "Cherrypick",
	git.RepositoryStateBisect:               "Bisect",
	git.RepositoryStateRebase:               "Rebase",
	git.RepositoryStateRebaseInteractive:    "Rebase Interactive",
	git.RepositoryStateRebaseMerge:          "Rebase Merge",
	git.RepositoryStateApplyMailbox:         "Apply Mailbox",
	git.RepositoryStateApplyMailboxOrRebase: "Apply Mailbox or Rebase",
}

var fileStateToString = map[git.Status]string{
	// git.StatusCurrent:         "Current",
	git.StatusIndexNew: "You forgot to commit a new file!",
	// git.StatusIndexModified:   "You forgot to commit a modified file!",
	// git.StatusIndexDeleted:    "You forgot to commit that you deleted a file!",
	// git.StatusIndexRenamed:    "You forgot to commit the renaming of a file!",
	// git.StatusIndexTypeChange: "You forget to commit a type change!",
	git.StatusIgnored:      "Ignored",
	git.StatusConflicted:   "Conflicted",
	git.StatusWtNew:        "New file in your working tree!",
	git.StatusWtModified:   "Modified file in your working tree!",
	git.StatusWtDeleted:    "Deleted file in your working tree!",
	git.StatusWtTypeChange: "Type change detected in your working tree!",
	git.StatusWtRenamed:    "Renamed file in your working tree!",
}

/*Global variable to set the StatusOption parameter, in order to list each file status
 */
var statusOption = git.StatusOptions{
	Show:     git.StatusShowIndexAndWorkdir,
	Flags:    git.StatusOptIncludeUntracked,
	Pathspec: []string{},
}

/*GitObject contains informations about the current git repository
 *
 *The structure is:
 *  accessible:
 *		Is the repository still exists in the hard drive?
 *	path:
 *		The path file.
 *	repository:
 *		The object repository.
 */
type GitObject struct {
	accessible error
	path       string
	repository git.Repository
}

/*New is a constructor for GitObject
 *
 * It neeeds:
 *	path:
 *		The path of the current repository.
 */
func New(path string) *GitObject {
	r, err := git.OpenRepository(path)
	return &GitObject{accessible: err, path: path, repository: *r}
}

/*isAccesible returns the information that is the current git repository is existing or not.
 *This method returns a boolean value: true if the git repository is still accesible (still exists), or false if not.
 */
func (g *GitObject) isAccessible() bool {
	return g.accessible == nil
}

/*Status prints the current status of the repository, accessible via the structure path field.
 *This method works only if the repository is accessible.
 */
func (g *GitObject) Status() {
	if g.isAccessible() {
		g.getUntrackedFiles()
		// g.getDiffWithWT()
	}
}

// func (g *GitObject) getDiffWithWT() {
// 	currentIndex, err := git.OpenIndex(path.Join(g.path, ".git/"))
// 	if err != nil {
// 		fmt.Println("Error using last index: %s", err)
// 	}
// 	diff, err := g.repository.DiffIndexToWorkdir(*currentIndex)
// }

func (g *GitObject) getUntrackedFiles() {
	fmt.Printf("[%s]...", g.path)
	if untrackedFields, err := g.repository.StatusList(&statusOption); err == nil {
		count, _ := untrackedFields.EntryCount()
		if count == 0 {
			fmt.Println(color.GreenString("\tOK!"))
			return
		}
		fmt.Printf(color.RedString("\t%d untracked files!\n", count))
		for i := 0; i < count; i++ {
			statusEntry, _ := untrackedFields.ByIndex(i)
			fmt.Printf("\t%s\n", fileStateToString[statusEntry.Status])
		}
	}
}

/*List lists the path and the accessibility of a list of git repositories
 */
func List(repositories *[]GitObject) {
	for _, object := range *repositories {
		fmt.Printf("* %s ", object.path)
		if object.isAccessible() {
			fmt.Println(color.GreenString(" [accessible]"))
		} else {
			fmt.Println(color.RedString(" [not accessible]"))
		}
	}
}
<|endoftext|>


<commit_before>package gokeepasslib

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"regexp"

	"github.com/aead/argon2"
)

// DBCredentials holds the key used to lock and unlock the database
type DBCredentials struct {
	Passphrase []byte //Passphrase if using one, stored in sha256 hash
	Key        []byte //Contents of the keyfile if using one, stored in sha256 hash
	Windows    []byte //Whatever is returned from windows user account auth, stored in sha256 hash
}

func (c *DBCredentials) buildCompositeKey() ([]byte, error) {
	hash := sha256.New()
	if c.Passphrase != nil { //If the hashed password is provided
		_, err := hash.Write(c.Passphrase)
		if err != nil {
			return nil, err
		}
	}
	if c.Key != nil { //If the hashed keyfile is provided
		_, err := hash.Write(c.Key)
		if err != nil {
			return nil, err
		}
	}
	if c.Windows != nil { //If the hashed password is provided
		_, err := hash.Write(c.Windows)
		if err != nil {
			return nil, err
		}
	}
	return hash.Sum(nil), nil
}

func (c *DBCredentials) buildTransformedKey(db *Database) ([]byte, error) {
	transformedKey, err := c.buildCompositeKey()
	if err != nil {
		return nil, err
	}

	if db.Header.IsKdbx4() {
		if reflect.DeepEqual(db.Header.FileHeaders.KdfParameters.UUID, KdfArgon2) {
			// Argon 2
			transformedKey = argon2.Key2d(
				[]byte(transformedKey),                                  // Master key
				db.Header.FileHeaders.KdfParameters.Salt[:],             // Salt
				uint32(db.Header.FileHeaders.KdfParameters.Iterations),  // Time cost
				uint32(db.Header.FileHeaders.KdfParameters.Memory)/1024, // Memory cost
				uint8(db.Header.FileHeaders.KdfParameters.Parallelism),  // Parallelism
				32, // Hash length
			)
		} else {
			// AES
			key, err := cryptAesKey(
				transformedKey,
				db.Header.FileHeaders.KdfParameters.Salt[:],
				db.Header.FileHeaders.KdfParameters.Rounds,
			)
			if err != nil {
				return nil, err
			}
			transformedKey = key[:]
		}
	} else {
		// AES
		key, err := cryptAesKey(
			transformedKey,
			db.Header.FileHeaders.TransformSeed,
			db.Header.FileHeaders.TransformRounds,
		)
		if err != nil {
			return nil, err
		}
		transformedKey = key[:]
	}
	return transformedKey, nil
}

func buildMasterKey(db *Database, transformedKey []byte) []byte {
	masterKey := sha256.New()
	masterKey.Write(db.Header.FileHeaders.MasterSeed)
	masterKey.Write(transformedKey)
	return masterKey.Sum(nil)
}

func buildHmacKey(db *Database, transformedKey []byte) []byte {
	masterKey := sha512.New()
	masterKey.Write(db.Header.FileHeaders.MasterSeed)
	masterKey.Write(transformedKey)
	masterKey.Write([]byte{0x01})
	hmacKey := sha512.New()
	hmacKey.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
	hmacKey.Write(masterKey.Sum(nil))
	return hmacKey.Sum(nil)
}

func cryptAesKey(masterKey []byte, seed []byte, rounds uint64) ([]byte, error) {
	block, err := aes.NewCipher(seed)
	if err != nil {
		return nil, err
	}

	// http://crypto.stackexchange.com/questions/21048/
	for i := uint64(0); i < rounds; i++ {
		result := make([]byte, 16)
		crypter := cipher.NewCBCEncrypter(block, result)
		crypter.CryptBlocks(masterKey[:16], masterKey[:16])
		crypter = cipher.NewCBCEncrypter(block, result)
		crypter.CryptBlocks(masterKey[16:], masterKey[16:])
	}

	hash := sha256.Sum256(masterKey)
	return hash[:], nil
}

// Build a new DBCredentials from a Password string
func NewPasswordCredentials(password string) *DBCredentials {
	hashedpw := sha256.Sum256([]byte(password))
	return &DBCredentials{Passphrase: hashedpw[:]}
}

// Return the hashed key from a key file at the path specified by location, parsing xml if needed
func ParseKeyFile(location string) ([]byte, error) {
	r, err := regexp.Compile("<Data>(.+)<\\/Data>")
	if err != nil {
		return nil, err
	}
	file, err := os.Open(location)
	if err != nil {
		return nil, err
	}
	var data []byte
	if data, err = ioutil.ReadAll(file); err != nil {
		return nil, err
	}
	if r.Match(data) { //If keyfile is in xml form, extract key data
		base := r.FindSubmatch(data)[1]
		data = make([]byte, base64.StdEncoding.DecodedLen(len(base)))
		if _, err := base64.StdEncoding.Decode(data, base); err != nil {
			return nil, err
		}
	}
	// Slice necessary due to padding at the end of the hash
	return data[:32], nil
}

// Build a new DBCredentials from a key file at the path specified by location
func NewKeyCredentials(location string) (*DBCredentials, error) {
	key, err := ParseKeyFile(location)
	if err != nil {
		return nil, err
	}

	return &DBCredentials{Key: key}, nil
}

// Build a new DBCredentials from a password and the key file at the path specified by location
func NewPasswordAndKeyCredentials(password, location string) (*DBCredentials, error) {
	key, err := ParseKeyFile(location)
	if err != nil {
		return nil, err
	}

	hashedpw := sha256.Sum256([]byte(password))

	return &DBCredentials{
		Passphrase: hashedpw[:],
		Key:        key,
	}, nil
}

func (c *DBCredentials) String() string {
	return fmt.Sprintf(
		"Hashed Passphrase: %x\nHashed Key: %x\nHashed Windows Auth: %x",
		c.Passphrase,
		c.Key,
		c.Windows,
	)
}
<commit_msg>Improved docs and golint fixes<commit_after>package gokeepasslib

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"regexp"

	"github.com/aead/argon2"
)

// DBCredentials holds the key used to lock and unlock the database
type DBCredentials struct {
	Passphrase []byte //Passphrase if using one, stored in sha256 hash
	Key        []byte //Contents of the keyfile if using one, stored in sha256 hash
	Windows    []byte //Whatever is returned from windows user account auth, stored in sha256 hash
}

func (c *DBCredentials) buildCompositeKey() ([]byte, error) {
	hash := sha256.New()
	if c.Passphrase != nil { //If the hashed password is provided
		_, err := hash.Write(c.Passphrase)
		if err != nil {
			return nil, err
		}
	}
	if c.Key != nil { //If the hashed keyfile is provided
		_, err := hash.Write(c.Key)
		if err != nil {
			return nil, err
		}
	}
	if c.Windows != nil { //If the hashed password is provided
		_, err := hash.Write(c.Windows)
		if err != nil {
			return nil, err
		}
	}
	return hash.Sum(nil), nil
}

func (c *DBCredentials) buildTransformedKey(db *Database) ([]byte, error) {
	transformedKey, err := c.buildCompositeKey()
	if err != nil {
		return nil, err
	}

	if db.Header.IsKdbx4() {
		if reflect.DeepEqual(db.Header.FileHeaders.KdfParameters.UUID, KdfArgon2) {
			// Argon 2
			transformedKey = argon2.Key2d(
				transformedKey, // Master key
				db.Header.FileHeaders.KdfParameters.Salt[:],             // Salt
				uint32(db.Header.FileHeaders.KdfParameters.Iterations),  // Time cost
				uint32(db.Header.FileHeaders.KdfParameters.Memory)/1024, // Memory cost
				uint8(db.Header.FileHeaders.KdfParameters.Parallelism),  // Parallelism
				32, // Hash length
			)
		} else {
			// AES
			key, err := cryptAesKey(
				transformedKey,
				db.Header.FileHeaders.KdfParameters.Salt[:],
				db.Header.FileHeaders.KdfParameters.Rounds,
			)
			if err != nil {
				return nil, err
			}
			transformedKey = key[:]
		}
	} else {
		// AES
		key, err := cryptAesKey(
			transformedKey,
			db.Header.FileHeaders.TransformSeed,
			db.Header.FileHeaders.TransformRounds,
		)
		if err != nil {
			return nil, err
		}
		transformedKey = key[:]
	}
	return transformedKey, nil
}

func buildMasterKey(db *Database, transformedKey []byte) []byte {
	masterKey := sha256.New()
	masterKey.Write(db.Header.FileHeaders.MasterSeed)
	masterKey.Write(transformedKey)
	return masterKey.Sum(nil)
}

func buildHmacKey(db *Database, transformedKey []byte) []byte {
	masterKey := sha512.New()
	masterKey.Write(db.Header.FileHeaders.MasterSeed)
	masterKey.Write(transformedKey)
	masterKey.Write([]byte{0x01})
	hmacKey := sha512.New()
	hmacKey.Write([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
	hmacKey.Write(masterKey.Sum(nil))
	return hmacKey.Sum(nil)
}

func cryptAesKey(masterKey []byte, seed []byte, rounds uint64) ([]byte, error) {
	block, err := aes.NewCipher(seed)
	if err != nil {
		return nil, err
	}

	// http://crypto.stackexchange.com/questions/21048/
	for i := uint64(0); i < rounds; i++ {
		result := make([]byte, 16)
		crypter := cipher.NewCBCEncrypter(block, result)
		crypter.CryptBlocks(masterKey[:16], masterKey[:16])
		crypter = cipher.NewCBCEncrypter(block, result)
		crypter.CryptBlocks(masterKey[16:], masterKey[16:])
	}

	hash := sha256.Sum256(masterKey)
	return hash[:], nil
}

// NewPasswordCredentials builds a new DBCredentials from a Password string
func NewPasswordCredentials(password string) *DBCredentials {
	hashedpw := sha256.Sum256([]byte(password))
	return &DBCredentials{Passphrase: hashedpw[:]}
}

// ParseKeyFile returns the hashed key from a key file at the path specified by location, parsing xml if needed
func ParseKeyFile(location string) ([]byte, error) {
	r, err := regexp.Compile(`<Data>(.+)</Data>`)
	if err != nil {
		return nil, err
	}
	file, err := os.Open(location)
	if err != nil {
		return nil, err
	}
	var data []byte
	if data, err = ioutil.ReadAll(file); err != nil {
		return nil, err
	}
	if r.Match(data) { //If keyfile is in xml form, extract key data
		base := r.FindSubmatch(data)[1]
		data = make([]byte, base64.StdEncoding.DecodedLen(len(base)))
		if _, err := base64.StdEncoding.Decode(data, base); err != nil {
			return nil, err
		}
	}
	// Slice necessary due to padding at the end of the hash
	return data[:32], nil
}

// NewKeyCredentials builds a new DBCredentials from a key file at the path specified by location
func NewKeyCredentials(location string) (*DBCredentials, error) {
	key, err := ParseKeyFile(location)
	if err != nil {
		return nil, err
	}

	return &DBCredentials{Key: key}, nil
}

// NewPasswordAndKeyCredentials builds a new DBCredentials from a password and the key file at the path specified by location
func NewPasswordAndKeyCredentials(password, location string) (*DBCredentials, error) {
	key, err := ParseKeyFile(location)
	if err != nil {
		return nil, err
	}

	hashedpw := sha256.Sum256([]byte(password))

	return &DBCredentials{
		Passphrase: hashedpw[:],
		Key:        key,
	}, nil
}

func (c *DBCredentials) String() string {
	return fmt.Sprintf(
		"Hashed Passphrase: %x\nHashed Key: %x\nHashed Windows Auth: %x",
		c.Passphrase,
		c.Key,
		c.Windows,
	)
}
<|endoftext|>


<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.

// Plan 9 system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.

package syscall

import "unsafe"

const ImplementsGetwd = true

// ErrorString implements Error's String method by returning itself.
type ErrorString string

func (e ErrorString) Error() string { return string(e) }

// NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) error { return ErrorString(s) }

var (
	Stdin  = 0
	Stdout = 1
	Stderr = 2

	EAFNOSUPPORT = NewError("address family not supported by protocol")
	EISDIR       = NewError("file is a directory")
)

// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)

func atoi(b []byte) (n uint) {
	n = 0
	for i := 0; i < len(b); i++ {
		n = n*10 + uint(b[i]-'0')
	}
	return
}

func cstring(s []byte) string {
	for i := range s {
		if s[i] == 0 {
			return string(s[0:i])
		}
	}
	return string(s)
}

func errstr() string {
	var buf [ERRMAX]byte

	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)

	buf[len(buf)-1] = 0
	return cstring(buf[:])
}

func Getpagesize() int { return 4096 }

//sys	exits(msg *byte)
func Exits(msg *string) {
	if msg == nil {
		exits(nil)
	}

	exits(StringBytePtr(*msg))
}

func Exit(code int) {
	if code == 0 {
		Exits(nil)
	}

	msg := itoa(code)
	Exits(&msg)
}

func readnum(path string) (uint, error) {
	var b [12]byte

	fd, e := Open(path, O_RDONLY)
	if e != nil {
		return 0, e
	}
	defer Close(fd)

	n, e := Pread(fd, b[:], 0)

	if e != nil {
		return 0, e
	}

	m := 0
	for ; m < n && b[m] == ' '; m++ {
	}

	return atoi(b[m : n-1]), nil
}

func Getpid() (pid int) {
	n, _ := readnum("#c/pid")
	return int(n)
}

func Getppid() (ppid int) {
	n, _ := readnum("#c/ppid")
	return int(n)
}

func Read(fd int, p []byte) (n int, err error) {
	return Pread(fd, p, -1)
}

func Write(fd int, p []byte) (n int, err error) {
	return Pwrite(fd, p, -1)
}

func Getwd() (wd string, err error) {
	fd, e := Open(".", O_RDONLY)

	if e != nil {
		return "", e
	}
	defer Close(fd)

	return Fd2path(fd)
}

//sys	fd2path(fd int, buf []byte) (err error)
func Fd2path(fd int) (path string, err error) {
	var buf [512]byte

	e := fd2path(fd, buf[:])
	if e != nil {
		return "", e
	}
	return cstring(buf[:]), nil
}

//sys	pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return NewError("bad arg in system call")
	}
	var pp [2]_C_int
	err = pipe(&pp)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)

func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
	newoffset, e := seek(0, fd, offset, whence)

	if newoffset == -1 {
		err = NewError(e)
	}
	return
}

func Mkdir(path string, mode uint32) (err error) {
	fd, err := Create(path, O_RDONLY, DMDIR|mode)

	if fd != -1 {
		Close(fd)
	}

	return
}

type Waitmsg struct {
	Pid  int
	Time [3]uint32
	Msg  string
}

func (w Waitmsg) Exited() bool   { return true }
func (w Waitmsg) Signaled() bool { return false }

func (w Waitmsg) ExitStatus() int {
	if len(w.Msg) == 0 {
		// a normal exit returns no message
		return 0
	}
	return 1
}

//sys	await(s []byte) (n int, err error)
func Await(w *Waitmsg) (err error) {
	var buf [512]byte
	var f [5][]byte

	n, err := await(buf[:])

	if err != nil || w == nil {
		return
	}

	nf := 0
	p := 0
	for i := 0; i < n && nf < len(f)-1; i++ {
		if buf[i] == ' ' {
			f[nf] = buf[p:i]
			p = i + 1
			nf++
		}
	}
	f[nf] = buf[p:]
	nf++

	if nf != len(f) {
		return NewError("invalid wait message")
	}
	w.Pid = int(atoi(f[0]))
	w.Time[0] = uint32(atoi(f[1]))
	w.Time[1] = uint32(atoi(f[2]))
	w.Time[2] = uint32(atoi(f[3]))
	w.Msg = cstring(f[4])
	if w.Msg == "''" {
		// await() returns '' for no error
		w.Msg = ""
	}
	return
}

func Unmount(name, old string) (err error) {
	oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))

	var r0 uintptr
	var e ErrorString

	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
	if name == "" {
		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
	} else {
		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
	}

	if int(r0) == -1 {
		err = e
	}
	return
}

func Fchdir(fd int) (err error) {
	path, err := Fd2path(fd)

	if err != nil {
		return
	}

	return Chdir(path)
}

type Timeval struct {
	Sec  int32
	Usec int32
}

func NsecToTimeval(nsec int64) (tv Timeval) {
	nsec += 999 // round up to microsecond
	tv.Usec = int32(nsec % 1e9 / 1e3)
	tv.Sec = int32(nsec / 1e9)
	return
}

func DecodeBintime(b []byte) (nsec int64, err error) {
	if len(b) != 8 {
		return -1, NewError("bad /dev/bintime format")
	}
	nsec = int64(b[0])<<56 |
		int64(b[1])<<48 |
		int64(b[2])<<40 |
		int64(b[3])<<32 |
		int64(b[4])<<24 |
		int64(b[5])<<16 |
		int64(b[6])<<8 |
		int64(b[7])
	return
}

func Gettimeofday(tv *Timeval) (err error) {
	// TODO(paulzhol):
	// avoid reopening a file descriptor for /dev/bintime on each call,
	// use lower-level calls to avoid allocation.

	var b [8]byte
	var nsec int64

	fd, e := Open("/dev/bintime", O_RDONLY)
	if e != nil {
		return e
	}
	defer Close(fd)

	if _, e = Pread(fd, b[:], 0); e != nil {
		return e
	}

	if nsec, e = DecodeBintime(b[:]); e != nil {
		return e
	}
	*tv = NsecToTimeval(nsec)

	return e
}

func Getegid() (egid int) { return -1 }
func Geteuid() (euid int) { return -1 }
func Getgid() (gid int)   { return -1 }
func Getuid() (uid int)   { return -1 }

func Getgroups() (gids []int, err error) {
	return make([]int, 0), nil
}

//sys	Dup(oldfd int, newfd int) (fd int, err error)
//sys	Open(path string, mode int) (fd int, err error)
//sys	Create(path string, mode int, perm uint32) (fd int, err error)
//sys	Remove(path string) (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys	Close(fd int) (err error)
//sys	Chdir(path string) (err error)
//sys	Bind(name string, old string, flag int) (err error)
//sys	Mount(fd int, afd int, old string, flag int, aname string) (err error)
//sys	Stat(path string, edir []byte) (n int, err error)
//sys	Fstat(fd int, edir []byte) (n int, err error)
//sys	Wstat(path string, edir []byte) (err error)
//sys	Fwstat(fd int, edir []byte) (err error)
<commit_msg>syscall: fix plan9 build<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.

// Plan 9 system calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates system call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.

package syscall

import "unsafe"

const ImplementsGetwd = true

// ErrorString implements Error's String method by returning itself.
type ErrorString string

func (e ErrorString) Error() string { return string(e) }

// NewError converts s to an ErrorString, which satisfies the Error interface.
func NewError(s string) error { return ErrorString(s) }

var (
	Stdin  = 0
	Stdout = 1
	Stderr = 2

	EAFNOSUPPORT = NewError("address family not supported by protocol")
	EISDIR       = NewError("file is a directory")
)

// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool

func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err ErrorString)
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorString)
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)

func atoi(b []byte) (n uint) {
	n = 0
	for i := 0; i < len(b); i++ {
		n = n*10 + uint(b[i]-'0')
	}
	return
}

func cstring(s []byte) string {
	for i := range s {
		if s[i] == 0 {
			return string(s[0:i])
		}
	}
	return string(s)
}

func errstr() string {
	var buf [ERRMAX]byte

	RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)

	buf[len(buf)-1] = 0
	return cstring(buf[:])
}

func Getpagesize() int { return 4096 }

//sys	exits(msg *byte)
func Exits(msg *string) {
	if msg == nil {
		exits(nil)
	}

	exits(StringBytePtr(*msg))
}

func Exit(code int) {
	if code == 0 {
		Exits(nil)
	}

	msg := itoa(code)
	Exits(&msg)
}

func readnum(path string) (uint, error) {
	var b [12]byte

	fd, e := Open(path, O_RDONLY)
	if e != nil {
		return 0, e
	}
	defer Close(fd)

	n, e := Pread(fd, b[:], 0)

	if e != nil {
		return 0, e
	}

	m := 0
	for ; m < n && b[m] == ' '; m++ {
	}

	return atoi(b[m : n-1]), nil
}

func Getpid() (pid int) {
	n, _ := readnum("#c/pid")
	return int(n)
}

func Getppid() (ppid int) {
	n, _ := readnum("#c/ppid")
	return int(n)
}

func Read(fd int, p []byte) (n int, err error) {
	return Pread(fd, p, -1)
}

func Write(fd int, p []byte) (n int, err error) {
	return Pwrite(fd, p, -1)
}

func Getwd() (wd string, err error) {
	fd, e := Open(".", O_RDONLY)

	if e != nil {
		return "", e
	}
	defer Close(fd)

	return Fd2path(fd)
}

//sys	fd2path(fd int, buf []byte) (err error)
func Fd2path(fd int) (path string, err error) {
	var buf [512]byte

	e := fd2path(fd, buf[:])
	if e != nil {
		return "", e
	}
	return cstring(buf[:]), nil
}

//sys	pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return NewError("bad arg in system call")
	}
	var pp [2]_C_int
	err = pipe(&pp)
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

// Underlying system call writes to newoffset via pointer.
// Implemented in assembly to avoid allocation.
func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string)

func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
	newoffset, e := seek(0, fd, offset, whence)

	if newoffset == -1 {
		err = NewError(e)
	}
	return
}

func Mkdir(path string, mode uint32) (err error) {
	fd, err := Create(path, O_RDONLY, DMDIR|mode)

	if fd != -1 {
		Close(fd)
	}

	return
}

type Waitmsg struct {
	Pid  int
	Time [3]uint32
	Msg  string
}

func (w Waitmsg) Exited() bool   { return true }
func (w Waitmsg) Signaled() bool { return false }

func (w Waitmsg) ExitStatus() int {
	if len(w.Msg) == 0 {
		// a normal exit returns no message
		return 0
	}
	return 1
}

//sys	await(s []byte) (n int, err error)
func Await(w *Waitmsg) (err error) {
	var buf [512]byte
	var f [5][]byte

	n, err := await(buf[:])

	if err != nil || w == nil {
		return
	}

	nf := 0
	p := 0
	for i := 0; i < n && nf < len(f)-1; i++ {
		if buf[i] == ' ' {
			f[nf] = buf[p:i]
			p = i + 1
			nf++
		}
	}
	f[nf] = buf[p:]
	nf++

	if nf != len(f) {
		return NewError("invalid wait message")
	}
	w.Pid = int(atoi(f[0]))
	w.Time[0] = uint32(atoi(f[1]))
	w.Time[1] = uint32(atoi(f[2]))
	w.Time[2] = uint32(atoi(f[3]))
	w.Msg = cstring(f[4])
	if w.Msg == "''" {
		// await() returns '' for no error
		w.Msg = ""
	}
	return
}

func Unmount(name, old string) (err error) {
	oldp := uintptr(unsafe.Pointer(StringBytePtr(old)))

	var r0 uintptr
	var e ErrorString

	// bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted.
	if name == "" {
		r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldp, 0)
	} else {
		r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(StringBytePtr(name))), oldp, 0)
	}

	if int(r0) == -1 {
		err = e
	}
	return
}

func Fchdir(fd int) (err error) {
	path, err := Fd2path(fd)

	if err != nil {
		return
	}

	return Chdir(path)
}

type Timespec struct {
	Sec  int32
	Nsec int32
}

type Timeval struct {
	Sec  int32
	Usec int32
}

func NsecToTimeval(nsec int64) (tv Timeval) {
	nsec += 999 // round up to microsecond
	tv.Usec = int32(nsec % 1e9 / 1e3)
	tv.Sec = int32(nsec / 1e9)
	return
}

func DecodeBintime(b []byte) (nsec int64, err error) {
	if len(b) != 8 {
		return -1, NewError("bad /dev/bintime format")
	}
	nsec = int64(b[0])<<56 |
		int64(b[1])<<48 |
		int64(b[2])<<40 |
		int64(b[3])<<32 |
		int64(b[4])<<24 |
		int64(b[5])<<16 |
		int64(b[6])<<8 |
		int64(b[7])
	return
}

func Gettimeofday(tv *Timeval) (err error) {
	// TODO(paulzhol):
	// avoid reopening a file descriptor for /dev/bintime on each call,
	// use lower-level calls to avoid allocation.

	var b [8]byte
	var nsec int64

	fd, e := Open("/dev/bintime", O_RDONLY)
	if e != nil {
		return e
	}
	defer Close(fd)

	if _, e = Pread(fd, b[:], 0); e != nil {
		return e
	}

	if nsec, e = DecodeBintime(b[:]); e != nil {
		return e
	}
	*tv = NsecToTimeval(nsec)

	return e
}

func Getegid() (egid int) { return -1 }
func Geteuid() (euid int) { return -1 }
func Getgid() (gid int)   { return -1 }
func Getuid() (uid int)   { return -1 }

func Getgroups() (gids []int, err error) {
	return make([]int, 0), nil
}

//sys	Dup(oldfd int, newfd int) (fd int, err error)
//sys	Open(path string, mode int) (fd int, err error)
//sys	Create(path string, mode int, perm uint32) (fd int, err error)
//sys	Remove(path string) (err error)
//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
//sys	Close(fd int) (err error)
//sys	Chdir(path string) (err error)
//sys	Bind(name string, old string, flag int) (err error)
//sys	Mount(fd int, afd int, old string, flag int, aname string) (err error)
//sys	Stat(path string, edir []byte) (n int, err error)
//sys	Fstat(fd int, edir []byte) (n int, err error)
//sys	Wstat(path string, edir []byte) (err error)
//sys	Fwstat(fd int, edir []byte) (err error)
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Cavium
//
// SPDX-License-Identifier: Apache-2.0
//

package distro

import (
	"strconv"

	"github.com/drasko/edgex-export"
	MQTT "github.com/eclipse/paho.mqtt.golang"
	"go.uber.org/zap"
)

type mqttSender struct {
	client MQTT.Client
	topic  string
}

const clientID = "edgex"
const topic = "EdgeX"

func NewMqttSender(addr export.Addressable) Sender {
	opts := MQTT.NewClientOptions()
	// CHN: Should be added protocol from Addressable instead of include it the address param.
	// CHN: We will maintain this behaviour for compatibility with Java
	broker := addr.Address + ":" + strconv.Itoa(addr.Port)
	opts.AddBroker(broker)
	opts.SetClientID(clientID)
	opts.SetUsername(addr.User)
	opts.SetPassword(addr.Password)

	sender := mqttSender{
		client: MQTT.NewClient(opts),
		topic:  addr.Topic,
	}

	if token := sender.client.Connect(); token.Wait() && token.Error() != nil {
		panic(token.Error())
	}
	logger.Info("Sample Publisher Started")

	return sender
}

func (sender mqttSender) Send(data []byte) {
	token := sender.client.Publish(sender.topic, 0, false, data)
	// FIXME: could be removed? set of tokens?
	token.Wait()
	logger.Debug("Sent data: ", zap.ByteString("data", data))
}
<commit_msg>Do not connect to the mqtt server when creating sender<commit_after>//
// Copyright (c) 2017 Cavium
//
// SPDX-License-Identifier: Apache-2.0
//

package distro

import (
	"strconv"

	"github.com/drasko/edgex-export"
	MQTT "github.com/eclipse/paho.mqtt.golang"
	"go.uber.org/zap"
)

type mqttSender struct {
	client MQTT.Client
	topic  string
}

const clientID = "edgex"
const topic = "EdgeX"

func NewMqttSender(addr export.Addressable) Sender {
	opts := MQTT.NewClientOptions()
	// CHN: Should be added protocol from Addressable instead of include it the address param.
	// CHN: We will maintain this behaviour for compatibility with Java
	broker := addr.Address + ":" + strconv.Itoa(addr.Port)
	opts.AddBroker(broker)
	opts.SetClientID(clientID)
	opts.SetUsername(addr.User)
	opts.SetPassword(addr.Password)
	opts.SetAutoReconnect(false)

	sender := mqttSender{
		client: MQTT.NewClient(opts),
		topic:  addr.Topic,
	}

	return sender
}

func (sender mqttSender) Send(data []byte) {
	if !sender.client.IsConnected() {
		logger.Info("Connecting to mqtt server")
		if token := sender.client.Connect(); token.Wait() && token.Error() != nil {
			logger.Warn("Could not connect to mqtt server, drop event")
			return
		}
	}

	token := sender.client.Publish(sender.topic, 0, false, data)
	// FIXME: could be removed? set of tokens?
	token.Wait()
	if token.Error() != nil {
		logger.Warn("mqtt error: ", zap.Error(token.Error()))
	} else {
		logger.Debug("Sent data: ", zap.ByteString("data", data))
	}
}
<|endoftext|>