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

// Package query implements encoding of structs into URL query parameters.
//
// As a simple example:
//
// 	type Options struct {
// 		Query   string `url:"q"`
// 		ShowAll bool   `url:"all"`
// 		Page    int    `url:"page"`
// 	}
//
// 	opt := Options{ "foo", true, 2 }
// 	v, _ := query.Values(opt)
// 	fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
//
// The exact mapping between Go values and url.Values is described in the
// documentation for the Values() function.
package query

import (
	"bytes"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)

var timeType = reflect.TypeOf(time.Time{})

var encoderType = reflect.TypeOf(new(Encoder)).Elem()

// Encoder is an interface implemented by any type that wishes to encode
// itself into URL values in a non-standard way.
type Encoder interface {
	EncodeValues(key string, v *url.Values) error
}

// Values returns the url.Values encoding of v.
//
// Values expects to be passed a struct, and traverses it recursively using the
// following encoding rules.
//
// Each exported struct field is encoded as a URL parameter unless
//
//	- the field's tag is "-", or
//	- the field is empty and its tag specifies the "omitempty" option
//
// The empty values are false, 0, any nil pointer or interface value, any array
// slice, map, or string of length zero, and any type (such as time.Time) that
// returns true for IsZero().
//
// The URL parameter name defaults to the struct field name but can be
// specified in the struct field's tag value.  The "url" key in the struct
// field's tag value is the key name, followed by an optional comma and
// options.  For example:
//
// 	// Field is ignored by this package.
// 	Field int `url:"-"`
//
// 	// Field appears as URL parameter "myName".
// 	Field int `url:"myName"`
//
// 	// Field appears as URL parameter "myName" and the field is omitted if
// 	// its value is empty
// 	Field int `url:"myName,omitempty"`
//
// 	// Field appears as URL parameter "Field" (the default), but the field
// 	// is skipped if empty.  Note the leading comma.
// 	Field int `url:",omitempty"`
//
// For encoding individual field values, the following type-dependent rules
// apply:
//
// Boolean values default to encoding as the strings "true" or "false".
// Including the "int" option signals that the field should be encoded as the
// strings "1" or "0".
//
// time.Time values default to encoding as RFC3339 timestamps.  Including the
// "unix" option signals that the field should be encoded as a Unix time (see
// time.Unix()).  The "unixmilli" and "unixnano" options will encode the number
// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see
// time.UnixNano()).  Including the "layout" struct tag (separate from the
// "url" tag) will use the value of the "layout" tag as a layout passed to
// time.Format.  For example:
//
// 	// Encode a time.Time as YYYY-MM-DD
// 	Field time.Time `layout:"2006-01-02"`
//
// Slice and Array values default to encoding as multiple URL values of the
// same name.  Including the "comma" option signals that the field should be
// encoded as a single comma-delimited value.  Including the "space" option
// similarly encodes the value as a single space-delimited string. Including
// the "semicolon" option will encode the value as a semicolon-delimited string.
// Including the "brackets" option signals that the multiple URL values should
// have "[]" appended to the value name. "numbered" will append a number to
// the end of each incidence of the value name, example:
// name0=value0&name1=value1, etc.  Including the "del" struct tag (separate
// from the "url" tag) will use the value of the "del" tag as the delimiter.
// For example:
//
// 	// Encode a slice of bools as ints ("1" for true, "0" for false),
// 	// separated by exclamation points "!".
// 	Field []bool `url:",int" del:"!"`
//
// Anonymous struct fields are usually encoded as if their inner exported
// fields were fields in the outer struct, subject to the standard Go
// visibility rules.  An anonymous struct field with a name given in its URL
// tag is treated as having that name, rather than being anonymous.
//
// Non-nil pointer values are encoded as the value pointed to.
//
// Nested structs are encoded including parent fields in value names for
// scoping. e.g:
//
// 	"user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
//
// All other values are encoded using their default string representation.
//
// Multiple fields that encode to the same URL parameter name will be included
// as multiple URL values of the same name.
func Values(v interface{}) (url.Values, error) {
	values := make(url.Values)
	val := reflect.ValueOf(v)
	for val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return values, nil
		}
		val = val.Elem()
	}

	if v == nil {
		return values, nil
	}

	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
	}

	err := reflectValue(values, val, "")
	return values, err
}

// reflectValue populates the values parameter from the struct fields in val.
// Embedded structs are followed recursively (using the rules defined in the
// Values function documentation) breadth-first.
func reflectValue(values url.Values, val reflect.Value, scope string) error {
	var embedded []reflect.Value

	typ := val.Type()
	for i := 0; i < typ.NumField(); i++ {
		sf := typ.Field(i)
		if sf.PkgPath != "" && !sf.Anonymous { // unexported
			continue
		}

		sv := val.Field(i)
		tag := sf.Tag.Get("url")
		if tag == "-" {
			continue
		}
		name, opts := parseTag(tag)

		if name == "" {
			if sf.Anonymous {
				v := reflect.Indirect(sv)
				if v.IsValid() && v.Kind() == reflect.Struct {
					// save embedded struct for later processing
					embedded = append(embedded, v)
					continue
				}
			}

			name = sf.Name
		}

		if scope != "" {
			name = scope + "[" + name + "]"
		}

		if opts.Contains("omitempty") && isEmptyValue(sv) {
			continue
		}

		if sv.Type().Implements(encoderType) {
			// if sv is a nil pointer and the custom encoder is defined on a non-pointer
			// method receiver, set sv to the zero value of the underlying type
			if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) {
				sv = reflect.New(sv.Type().Elem())
			}

			m := sv.Interface().(Encoder)
			if err := m.EncodeValues(name, &values); err != nil {
				return err
			}
			continue
		}

		// recursively dereference pointers. break on nil pointers
		for sv.Kind() == reflect.Ptr {
			if sv.IsNil() {
				break
			}
			sv = sv.Elem()
		}

		if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
			var del string
			if opts.Contains("comma") {
				del = ","
			} else if opts.Contains("space") {
				del = " "
			} else if opts.Contains("semicolon") {
				del = ";"
			} else if opts.Contains("brackets") {
				name = name + "[]"
			} else {
				del = sf.Tag.Get("del")
			}

			if del != "" {
				s := new(bytes.Buffer)
				first := true
				for i := 0; i < sv.Len(); i++ {
					if first {
						first = false
					} else {
						s.WriteString(del)
					}
					s.WriteString(valueString(sv.Index(i), opts, sf))
				}
				values.Add(name, s.String())
			} else {
				for i := 0; i < sv.Len(); i++ {
					k := name
					if opts.Contains("numbered") {
						k = fmt.Sprintf("%s%d", name, i)
					}
					values.Add(k, valueString(sv.Index(i), opts, sf))
				}
			}
			continue
		}

		if sv.Type() == timeType {
			values.Add(name, valueString(sv, opts, sf))
			continue
		}

		if sv.Kind() == reflect.Struct {
			if err := reflectValue(values, sv, name); err != nil {
				return err
			}
			continue
		}

		values.Add(name, valueString(sv, opts, sf))
	}

	for _, f := range embedded {
		if err := reflectValue(values, f, scope); err != nil {
			return err
		}
	}

	return nil
}

// valueString returns the string representation of a value.
func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string {
	for v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return ""
		}
		v = v.Elem()
	}

	if v.Kind() == reflect.Bool && opts.Contains("int") {
		if v.Bool() {
			return "1"
		}
		return "0"
	}

	if v.Type() == timeType {
		t := v.Interface().(time.Time)
		if opts.Contains("unix") {
			return strconv.FormatInt(t.Unix(), 10)
		}
		if opts.Contains("unixmilli") {
			return strconv.FormatInt((t.UnixNano() / 1e6), 10)
		}
		if opts.Contains("unixnano") {
			return strconv.FormatInt(t.UnixNano(), 10)
		}
		if layout := sf.Tag.Get("layout"); layout != "" {
			return t.Format(layout)
		}
		return t.Format(time.RFC3339)
	}

	return fmt.Sprint(v.Interface())
}

// isEmptyValue checks if a value should be considered empty for the purposes
// of omitting fields with the "omitempty" option.
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}

	type zeroable interface {
		IsZero() bool
	}

	if z, ok := v.Interface().(zeroable); ok {
		return z.IsZero()
	}

	return false
}

// tagOptions is the string following a comma in a struct field's "url" tag, or
// the empty string. It does not include the leading comma.
type tagOptions []string

// parseTag splits a struct field's url tag into its name and comma-separated
// options.
func parseTag(tag string) (string, tagOptions) {
	s := strings.Split(tag, ",")
	return s[0], s[1:]
}

// Contains checks whether the tagOptions contains the specified option.
func (o tagOptions) Contains(option string) bool {
	for _, s := range o {
		if s == option {
			return true
		}
	}
	return false
}
<commit_msg>docs: clarify behavior of nested structs<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package query implements encoding of structs into URL query parameters.
//
// As a simple example:
//
// 	type Options struct {
// 		Query   string `url:"q"`
// 		ShowAll bool   `url:"all"`
// 		Page    int    `url:"page"`
// 	}
//
// 	opt := Options{ "foo", true, 2 }
// 	v, _ := query.Values(opt)
// 	fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
//
// The exact mapping between Go values and url.Values is described in the
// documentation for the Values() function.
package query

import (
	"bytes"
	"fmt"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"time"
)

var timeType = reflect.TypeOf(time.Time{})

var encoderType = reflect.TypeOf(new(Encoder)).Elem()

// Encoder is an interface implemented by any type that wishes to encode
// itself into URL values in a non-standard way.
type Encoder interface {
	EncodeValues(key string, v *url.Values) error
}

// Values returns the url.Values encoding of v.
//
// Values expects to be passed a struct, and traverses it recursively using the
// following encoding rules.
//
// Each exported struct field is encoded as a URL parameter unless
//
//	- the field's tag is "-", or
//	- the field is empty and its tag specifies the "omitempty" option
//
// The empty values are false, 0, any nil pointer or interface value, any array
// slice, map, or string of length zero, and any type (such as time.Time) that
// returns true for IsZero().
//
// The URL parameter name defaults to the struct field name but can be
// specified in the struct field's tag value.  The "url" key in the struct
// field's tag value is the key name, followed by an optional comma and
// options.  For example:
//
// 	// Field is ignored by this package.
// 	Field int `url:"-"`
//
// 	// Field appears as URL parameter "myName".
// 	Field int `url:"myName"`
//
// 	// Field appears as URL parameter "myName" and the field is omitted if
// 	// its value is empty
// 	Field int `url:"myName,omitempty"`
//
// 	// Field appears as URL parameter "Field" (the default), but the field
// 	// is skipped if empty.  Note the leading comma.
// 	Field int `url:",omitempty"`
//
// For encoding individual field values, the following type-dependent rules
// apply:
//
// Boolean values default to encoding as the strings "true" or "false".
// Including the "int" option signals that the field should be encoded as the
// strings "1" or "0".
//
// time.Time values default to encoding as RFC3339 timestamps.  Including the
// "unix" option signals that the field should be encoded as a Unix time (see
// time.Unix()).  The "unixmilli" and "unixnano" options will encode the number
// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see
// time.UnixNano()).  Including the "layout" struct tag (separate from the
// "url" tag) will use the value of the "layout" tag as a layout passed to
// time.Format.  For example:
//
// 	// Encode a time.Time as YYYY-MM-DD
// 	Field time.Time `layout:"2006-01-02"`
//
// Slice and Array values default to encoding as multiple URL values of the
// same name.  Including the "comma" option signals that the field should be
// encoded as a single comma-delimited value.  Including the "space" option
// similarly encodes the value as a single space-delimited string. Including
// the "semicolon" option will encode the value as a semicolon-delimited string.
// Including the "brackets" option signals that the multiple URL values should
// have "[]" appended to the value name. "numbered" will append a number to
// the end of each incidence of the value name, example:
// name0=value0&name1=value1, etc.  Including the "del" struct tag (separate
// from the "url" tag) will use the value of the "del" tag as the delimiter.
// For example:
//
// 	// Encode a slice of bools as ints ("1" for true, "0" for false),
// 	// separated by exclamation points "!".
// 	Field []bool `url:",int" del:"!"`
//
// Anonymous struct fields are usually encoded as if their inner exported
// fields were fields in the outer struct, subject to the standard Go
// visibility rules.  An anonymous struct field with a name given in its URL
// tag is treated as having that name, rather than being anonymous.
//
// Non-nil pointer values are encoded as the value pointed to.
//
// Nested structs have their fields processed recursively and are encoded
// including parent fields in value names for scoping. For example,
//
// 	"user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
//
// All other values are encoded using their default string representation.
//
// Multiple fields that encode to the same URL parameter name will be included
// as multiple URL values of the same name.
func Values(v interface{}) (url.Values, error) {
	values := make(url.Values)
	val := reflect.ValueOf(v)
	for val.Kind() == reflect.Ptr {
		if val.IsNil() {
			return values, nil
		}
		val = val.Elem()
	}

	if v == nil {
		return values, nil
	}

	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
	}

	err := reflectValue(values, val, "")
	return values, err
}

// reflectValue populates the values parameter from the struct fields in val.
// Embedded structs are followed recursively (using the rules defined in the
// Values function documentation) breadth-first.
func reflectValue(values url.Values, val reflect.Value, scope string) error {
	var embedded []reflect.Value

	typ := val.Type()
	for i := 0; i < typ.NumField(); i++ {
		sf := typ.Field(i)
		if sf.PkgPath != "" && !sf.Anonymous { // unexported
			continue
		}

		sv := val.Field(i)
		tag := sf.Tag.Get("url")
		if tag == "-" {
			continue
		}
		name, opts := parseTag(tag)

		if name == "" {
			if sf.Anonymous {
				v := reflect.Indirect(sv)
				if v.IsValid() && v.Kind() == reflect.Struct {
					// save embedded struct for later processing
					embedded = append(embedded, v)
					continue
				}
			}

			name = sf.Name
		}

		if scope != "" {
			name = scope + "[" + name + "]"
		}

		if opts.Contains("omitempty") && isEmptyValue(sv) {
			continue
		}

		if sv.Type().Implements(encoderType) {
			// if sv is a nil pointer and the custom encoder is defined on a non-pointer
			// method receiver, set sv to the zero value of the underlying type
			if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) {
				sv = reflect.New(sv.Type().Elem())
			}

			m := sv.Interface().(Encoder)
			if err := m.EncodeValues(name, &values); err != nil {
				return err
			}
			continue
		}

		// recursively dereference pointers. break on nil pointers
		for sv.Kind() == reflect.Ptr {
			if sv.IsNil() {
				break
			}
			sv = sv.Elem()
		}

		if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
			var del string
			if opts.Contains("comma") {
				del = ","
			} else if opts.Contains("space") {
				del = " "
			} else if opts.Contains("semicolon") {
				del = ";"
			} else if opts.Contains("brackets") {
				name = name + "[]"
			} else {
				del = sf.Tag.Get("del")
			}

			if del != "" {
				s := new(bytes.Buffer)
				first := true
				for i := 0; i < sv.Len(); i++ {
					if first {
						first = false
					} else {
						s.WriteString(del)
					}
					s.WriteString(valueString(sv.Index(i), opts, sf))
				}
				values.Add(name, s.String())
			} else {
				for i := 0; i < sv.Len(); i++ {
					k := name
					if opts.Contains("numbered") {
						k = fmt.Sprintf("%s%d", name, i)
					}
					values.Add(k, valueString(sv.Index(i), opts, sf))
				}
			}
			continue
		}

		if sv.Type() == timeType {
			values.Add(name, valueString(sv, opts, sf))
			continue
		}

		if sv.Kind() == reflect.Struct {
			if err := reflectValue(values, sv, name); err != nil {
				return err
			}
			continue
		}

		values.Add(name, valueString(sv, opts, sf))
	}

	for _, f := range embedded {
		if err := reflectValue(values, f, scope); err != nil {
			return err
		}
	}

	return nil
}

// valueString returns the string representation of a value.
func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string {
	for v.Kind() == reflect.Ptr {
		if v.IsNil() {
			return ""
		}
		v = v.Elem()
	}

	if v.Kind() == reflect.Bool && opts.Contains("int") {
		if v.Bool() {
			return "1"
		}
		return "0"
	}

	if v.Type() == timeType {
		t := v.Interface().(time.Time)
		if opts.Contains("unix") {
			return strconv.FormatInt(t.Unix(), 10)
		}
		if opts.Contains("unixmilli") {
			return strconv.FormatInt((t.UnixNano() / 1e6), 10)
		}
		if opts.Contains("unixnano") {
			return strconv.FormatInt(t.UnixNano(), 10)
		}
		if layout := sf.Tag.Get("layout"); layout != "" {
			return t.Format(layout)
		}
		return t.Format(time.RFC3339)
	}

	return fmt.Sprint(v.Interface())
}

// isEmptyValue checks if a value should be considered empty for the purposes
// of omitting fields with the "omitempty" option.
func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}

	type zeroable interface {
		IsZero() bool
	}

	if z, ok := v.Interface().(zeroable); ok {
		return z.IsZero()
	}

	return false
}

// tagOptions is the string following a comma in a struct field's "url" tag, or
// the empty string. It does not include the leading comma.
type tagOptions []string

// parseTag splits a struct field's url tag into its name and comma-separated
// options.
func parseTag(tag string) (string, tagOptions) {
	s := strings.Split(tag, ",")
	return s[0], s[1:]
}

// Contains checks whether the tagOptions contains the specified option.
func (o tagOptions) Contains(option string) bool {
	for _, s := range o {
		if s == option {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
    "github.com/coreos/go-etcd/etcd"
    "github.com/miekg/dns"
    "net"
    "strings"
    "bytes"
    "time"
)

type Resolver struct {
    etcd        *etcd.Client
    dns         *dns.Client
    rTimeout   time.Duration
}

func (r *Resolver) Lookup(req *dns.Msg, nameservers []string) (msg *dns.Msg) {
    q := req.Question[0]

    msg = new(dns.Msg)
    msg.SetReply(req)

    if q.Qclass == dns.ClassINET {

        // A records
        if q.Qtype == dns.TypeA || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupA(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // AAAA records
        if q.Qtype == dns.TypeAAAA || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupAAAA(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // TXT records
        if q.Qtype == dns.TypeTXT || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupTXT(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // CNAME records
        if q.Qtype == dns.TypeCNAME || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupCNAME(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // NS records
        if q.Qtype == dns.TypeNS || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupNS(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }
    }

    if len(msg.Answer) == 0 {
        c := make(chan *dns.Msg)
        for _, nameserver := range nameservers {
            go r.LookupNameserver(c, req, nameserver)
        }

        timeout := time.After(r.rTimeout)
        select {
        case result := <-c:
            return result
        case <-timeout:
            return
        }
    }

    return
}

func (r *Resolver) LookupNameserver(c chan *dns.Msg, req *dns.Msg, ns string) {
    msg, _, err := r.dns.Exchange(req, ns)
    if err != nil {
        return
    }
    c <- msg
}

func (r *Resolver) LookupA(name string, class uint16) (answers []*dns.A) {
    answers = make([]*dns.A, 0)

    key := nameToKey(name, "/.A")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    ip := net.ParseIP(node.Value)
    if ip == nil {
        logger.Fatalf("Failed to parse IP value '%s'", node.Value)
    }

    answers = make([]*dns.A, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeA, Ttl: 0}
    answers[0] = &dns.A{*rr_header, ip}

    return
}

func (r *Resolver) LookupAAAA(name string, class uint16) (answers []*dns.AAAA) {
    answers = make([]*dns.AAAA, 0)

    key := nameToKey(name, "/.AAAA")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    ip := net.ParseIP(node.Value)
    if ip == nil {
        logger.Fatalf("Failed to parse IP value '%s'", node.Value)
    }

    answers = make([]*dns.AAAA, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeAAAA, Ttl: 0}
    answers[0] = &dns.AAAA{*rr_header, ip}

    return
}

func (r *Resolver) LookupTXT(name string, class uint16) (answers []*dns.TXT) {
    answers = make([]*dns.TXT, 0)

    key := nameToKey(name, "/.TXT")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.TXT, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeTXT, Ttl: 0}
    answers[0] = &dns.TXT{*rr_header, []string{node.Value}}

    return
}

func (r *Resolver) LookupCNAME(name string, class uint16) (answers []*dns.CNAME) {
    answers = make([]*dns.CNAME, 0)

    key := nameToKey(name, "/.CNAME")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.CNAME, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeCNAME, Ttl: 0}
    answers[0] = &dns.CNAME{*rr_header, node.Value}

    return
}

func (r *Resolver) LookupNS(name string, class uint16) (answers []*dns.NS) {
    answers = make([]*dns.NS, 0)

    key := nameToKey(name, "/.NS")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.NS, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeNS, Ttl: 0}
    answers[0] = &dns.NS{*rr_header, node.Value}

    return
}

func nameToKey(name string, suffix string) string {
    segments := strings.Split(name, ".")

    var keyBuffer bytes.Buffer
    for i := len(segments) - 1; i >= 0; i-- {
        if len(segments[i]) > 0 {
            keyBuffer.WriteString("/")
            keyBuffer.WriteString(segments[i])
        }
    }

    keyBuffer.WriteString(suffix)
    return keyBuffer.String()
}
<commit_msg>Initial trial  (A records only) of supporting 'directories' of keys in etcd, returning multiple RRs for all the keys found in the directory.<commit_after>package main

import (
    "github.com/coreos/go-etcd/etcd"
    "github.com/miekg/dns"
    "net"
    "strings"
    "bytes"
    "time"
)

type Resolver struct {
    etcd        *etcd.Client
    dns         *dns.Client
    rTimeout   time.Duration
}

func (r *Resolver) Lookup(req *dns.Msg, nameservers []string) (msg *dns.Msg) {
    q := req.Question[0]

    msg = new(dns.Msg)
    msg.SetReply(req)

    if q.Qclass == dns.ClassINET {

        // A records
        if q.Qtype == dns.TypeA || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupA(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // AAAA records
        if q.Qtype == dns.TypeAAAA || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupAAAA(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // TXT records
        if q.Qtype == dns.TypeTXT || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupTXT(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // CNAME records
        if q.Qtype == dns.TypeCNAME || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupCNAME(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }

        // NS records
        if q.Qtype == dns.TypeNS || q.Qtype == dns.TypeANY {
            for _, a := range r.LookupNS(q.Name, q.Qclass) {
                msg.Answer = append(msg.Answer, a)
            }
        }
    }

    if len(msg.Answer) == 0 {
        c := make(chan *dns.Msg)
        for _, nameserver := range nameservers {
            go r.LookupNameserver(c, req, nameserver)
        }

        timeout := time.After(r.rTimeout)
        select {
        case result := <-c:
            return result
        case <-timeout:
            return
        }
    }

    return
}

func (r *Resolver) LookupNameserver(c chan *dns.Msg, req *dns.Msg, ns string) {
    msg, _, err := r.dns.Exchange(req, ns)
    if err != nil {
        return
    }
    c <- msg
}

func (r *Resolver) LookupA(name string, class uint16) (answers []*dns.A) {
    answers = make([]*dns.A, 0)

    key := nameToKey(name, "/.A")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    var nodes []*etcd.Node

    if response.Node.Dir == true {

        nodes = make([]*etcd.Node, len(response.Node.Nodes))
        for i := 0; i < len(response.Node.Nodes); i++ {
            nodes[i] = &response.Node.Nodes[i]
        }

    } else {

        nodes = make([]*etcd.Node, 1)
        nodes[0] = response.Node

    }

    answers = make([]*dns.A, len(nodes))

    for i := 0; i < len(nodes); i++ {

        node := nodes[i]
        ip := net.ParseIP(node.Value)
        if ip == nil {
            logger.Fatalf("Failed to parse IP value '%s'", node.Value)
        }

        rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeA, Ttl: 0}
        answers[i] = &dns.A{*rr_header, ip}
    }

    return
}

func (r *Resolver) LookupAAAA(name string, class uint16) (answers []*dns.AAAA) {
    answers = make([]*dns.AAAA, 0)

    key := nameToKey(name, "/.AAAA")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    ip := net.ParseIP(node.Value)
    if ip == nil {
        logger.Fatalf("Failed to parse IP value '%s'", node.Value)
    }

    answers = make([]*dns.AAAA, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeAAAA, Ttl: 0}
    answers[0] = &dns.AAAA{*rr_header, ip}

    return
}

func (r *Resolver) LookupTXT(name string, class uint16) (answers []*dns.TXT) {
    answers = make([]*dns.TXT, 0)

    key := nameToKey(name, "/.TXT")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.TXT, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeTXT, Ttl: 0}
    answers[0] = &dns.TXT{*rr_header, []string{node.Value}}

    return
}

func (r *Resolver) LookupCNAME(name string, class uint16) (answers []*dns.CNAME) {
    answers = make([]*dns.CNAME, 0)

    key := nameToKey(name, "/.CNAME")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.CNAME, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeCNAME, Ttl: 0}
    answers[0] = &dns.CNAME{*rr_header, node.Value}

    return
}

func (r *Resolver) LookupNS(name string, class uint16) (answers []*dns.NS) {
    answers = make([]*dns.NS, 0)

    key := nameToKey(name, "/.NS")
    response, err := r.etcd.Get(key, false, false)
    if err != nil {
        logger.Printf("Error with etcd: %s", err)
        return
    }

    node := response.Node

    answers = make([]*dns.NS, 1)
    rr_header := &dns.RR_Header{Name: name, Class: class, Rrtype: dns.TypeNS, Ttl: 0}
    answers[0] = &dns.NS{*rr_header, node.Value}

    return
}

func nameToKey(name string, suffix string) string {
    segments := strings.Split(name, ".")

    var keyBuffer bytes.Buffer
    for i := len(segments) - 1; i >= 0; i-- {
        if len(segments[i]) > 0 {
            keyBuffer.WriteString("/")
            keyBuffer.WriteString(segments[i])
        }
    }

    keyBuffer.WriteString(suffix)
    return keyBuffer.String()
}
<|endoftext|>


<commit_before>package goalfred

import (
	"encoding/json"
	"fmt"
	"os"
)

// Arguments just wrappes the call to os.Args for better readability
func Arguments() []string {
	return os.Args[1:]
}

// NormalizedArguments re-normalizes the user arguments provided via Alfred.
// This isn't necessary for every workflow, specifically only when you're working with special characters.
// For more info on this topic, please refer to this thread: http://www.alfredforum.com/topic/2015-encoding-issue/
func NormalizedArguments() (normalizedArgs []string, err error) {
	for _, e := range Arguments() {
		var normalizedElement string
		normalizedElement, err = Normalize(e)
		normalizedArgs = append(normalizedArgs, normalizedElement)
	}
	return
}

// Response is the top level domain object.
// Create a new instance by calling NewResponse()
// Add items by calling AddItem on the response object
type Response struct {
	Items []Item `json:"items"`
}

// NewResponse initializes a new instance of Response
func NewResponse() *Response {
	r := new(Response)
	r.Items = []Item{}
	return r
}

// Print should be called last to output the result of the workflow to stdout.
func (r *Response) Print() {
	bytes, _ := json.Marshal(r)
	fmt.Println(string(bytes))
}

// AddItem adds a new Item to the response.
// The order in Alfred will be in the order how you add them.
func (r *Response) AddItem(item AlfredItem) *Response {
	i := item.Item()
	r.Items = append(r.Items, *i)
	return r
}
<commit_msg>Immediately return on error in NormalizedArgs<commit_after>package goalfred

import (
	"encoding/json"
	"fmt"
	"os"
)

// Arguments just wrappes the call to os.Args for better readability
func Arguments() []string {
	return os.Args[1:]
}

// NormalizedArguments re-normalizes the user arguments provided via Alfred.
// This isn't necessary for every workflow, specifically only when you're working with special characters.
// For more info on this topic, please refer to this thread: http://www.alfredforum.com/topic/2015-encoding-issue/
func NormalizedArguments() (normalizedArgs []string, err error) {
	for _, e := range Arguments() {
		var normalizedElement string
		normalizedElement, err = Normalize(e)
		if err != nil {
			return
		}
		normalizedArgs = append(normalizedArgs, normalizedElement)
	}
	return
}

// Response is the top level domain object.
// Create a new instance by calling NewResponse()
// Add items by calling AddItem on the response object
type Response struct {
	Items []Item `json:"items"`
}

// NewResponse initializes a new instance of Response
func NewResponse() *Response {
	r := new(Response)
	r.Items = []Item{}
	return r
}

// Print should be called last to output the result of the workflow to stdout.
func (r *Response) Print() {
	bytes, _ := json.Marshal(r)
	fmt.Println(string(bytes))
}

// AddItem adds a new Item to the response.
// The order in Alfred will be in the order how you add them.
func (r *Response) AddItem(item AlfredItem) *Response {
	i := item.Item()
	r.Items = append(r.Items, *i)
	return r
}
<|endoftext|>


<commit_before>package vkutil

import (
	"encoding/json"
	"fmt"
)

type Response int

const (
	RESPONSE_IDS Response = iota
)

type ResponseIds struct {
	Resp IdsResp `json:"response"`
	ResponseError
}

type ResponseError struct {
	Error Err `json:"error"`
}

type Err struct {
	Code       int    `json:"error_code"`
	Msg        string `json:"error_msg"`
	CaptchaSid string `json:"captcha_sid"`
	CaptchaImg string `json:"captcha_img"`
}

type IdsResp struct {
	Count int   `json:"count"`
	Items []int `json:"items"`
}

/* likes */
type ResponseLikes struct {
}

type ResponsePosts struct {
	Response RespPosts `json:"response"`
	ResponseError
}

type RespPosts struct {
	Count int     `json:"count"`
	Items []*Post `json:"items"`
}

type Comment struct {
	Id             int          `json:"id"`
	FromId         int          `json:"from_id"`
	Date           EpochTime    `json:"date"`
	Text           string       `json:"text"`
	ReplyToUser    int          `json:"reply_to_user"`
	ReplyToComment int          `json:"reply_to_comment"`
	Attachments    []Attachment `json:"attachments"`
}

type RespComments struct {
	Items []Comment `json:"items"`
	Count int       `json:"count"`
}

type ResponseComments struct {
	Response RespComments `json:"response"`
	ResponseError
}

type ResponseCommentsList struct {
	Response []*Comment `json:"response"`
	ResponseError
}

type ResponseInt struct {
	Response int `json:"response"`
	ResponseError
}

/* messages */

type ResponseMessages struct {
	Response RespMessages `json:"response"`
	ResponseError
}

//todo create RespCount struct
type RespMessages struct {
	Count int       `json:"count"`
	Items []Message `json:"items"`
}

type RespFriendsGetMutual struct {
	Id            int   `json:"id"`
	CommonFriends []int `json:"common_friends"`
	CommonCount   int   `json:"common_count"`
}

type ResponseFriendsGetMutual struct {
	Response []RespFriendsGetMutual `json:"response"`
	ResponseError
}

type RespUnreadMessages struct {
	Count         int      `json:"count"`
	UnreadDialogs int      `json:"unread_dialogs"`
	Items         []Dialog `json:"items"`
}

type Dialog struct {
	Unread  int     `json:"unread"`
	Message Message `json:"message"`
}

type Message struct {
	Id        int       `json:"id"`
	Date      EpochTime `json:"date"`
	Out       int       `json:"out"`
	UserId    int       `json:"user_id"`
	ReadState int       `json:"read_state"`
	Title     string    `json:"title"`
	Body      string    `json:"body"`
}

type RespUserWithCount struct {
	Count int    `json:"count"`
	Items []User `json:"items"`
}

type ResponseUserWithCount struct {
	Response RespUserWithCount `json:"response"`
	ResponseError
}

type RespPhotos struct {
	Count int     `json:"count"`
	Items []Photo `json:"items"`
}

type ResponsePhotos struct {
	Response RespPhotos `json:"response"`
	ResponseError
}

type City struct {
	Id     int    `json:"id"`
	Title  string `json:"title"`
	Area   string `json:"area,omitempty"`
	Region string `json:"region"`
}

type ResponseCities struct {
	Response struct {
		Count int    `json:"count"`
		Items []City `json:"items"`
	} `json:"response"`
	ResponseError
}

func ParseIdsResponse(data []byte) (count int, ids []int, err error) {
	var r ResponseIds
	err = json.Unmarshal(data, &r)
	if err != nil {
		return 0, []int{}, err
	}
	return r.Resp.Count, r.Resp.Items, nil
}

func ParseIntResponse(data []byte) (int, error) {
	var r ResponseInt
	e := json.Unmarshal(data, &r)
	if e != nil {
		return 0, e
	}
	if r.Error.Code != 0 {
		return 0, fmt.Errorf("%s", r.Error.Msg)
	}
	return r.Response, nil
}

func ParseUsersResponse(data []byte) (users []User, err error) {
	var r ResponseUsers
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []User{}, err
	}
	return r.Response, nil
}

func ParseDialogsResponse(data []byte) (ms []Dialog, err error) {
	var r struct {
		RespUnreadMessages `json:"response"`
		ResponseError
	}
	err = json.Unmarshal(data, &r)
	if err != nil {
		return
	}
	return r.RespUnreadMessages.Items, nil
}

func ParseMessagesResponse(data []byte) (ms []Message, err error) {
	var r ResponseMessages
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []Message{}, err
	}
	return r.Response.Items, nil
}

func ParseUnreadMessagesResponse(data []byte) (ms []Dialog, err error) {
	var r struct {
		RespUnreadMessages `json:"response"`
		ResponseError
	}
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []Dialog{}, err
	}
	return r.RespUnreadMessages.Items, nil
}

func ParseResponseUserWithCount(data []byte) (users []User, cnt int, e error) {
	var r ResponseUserWithCount
	e = json.Unmarshal(data, &r)
	return r.Response.Items, r.Response.Count, e
}

type OutRequestDeletedResponse struct {
	OutRequestDeleted `json:"response"`
	ResponseError     `json:"error"`
}

type OutRequestDeleted struct {
	Success           int `json:"success"`
	OutRequestDeleted int `json:"out_request_deleted"`
}
<commit_msg>add chat_id to message<commit_after>package vkutil

import (
	"encoding/json"
	"fmt"
)

type Response int

const (
	RESPONSE_IDS Response = iota
)

type ResponseIds struct {
	Resp IdsResp `json:"response"`
	ResponseError
}

type ResponseError struct {
	Error Err `json:"error"`
}

type Err struct {
	Code       int    `json:"error_code"`
	Msg        string `json:"error_msg"`
	CaptchaSid string `json:"captcha_sid"`
	CaptchaImg string `json:"captcha_img"`
}

type IdsResp struct {
	Count int   `json:"count"`
	Items []int `json:"items"`
}

/* likes */
type ResponseLikes struct {
}

type ResponsePosts struct {
	Response RespPosts `json:"response"`
	ResponseError
}

type RespPosts struct {
	Count int     `json:"count"`
	Items []*Post `json:"items"`
}

type Comment struct {
	Id             int          `json:"id"`
	FromId         int          `json:"from_id"`
	Date           EpochTime    `json:"date"`
	Text           string       `json:"text"`
	ReplyToUser    int          `json:"reply_to_user"`
	ReplyToComment int          `json:"reply_to_comment"`
	Attachments    []Attachment `json:"attachments"`
}

type RespComments struct {
	Items []Comment `json:"items"`
	Count int       `json:"count"`
}

type ResponseComments struct {
	Response RespComments `json:"response"`
	ResponseError
}

type ResponseCommentsList struct {
	Response []*Comment `json:"response"`
	ResponseError
}

type ResponseInt struct {
	Response int `json:"response"`
	ResponseError
}

/* messages */

type ResponseMessages struct {
	Response RespMessages `json:"response"`
	ResponseError
}

//todo create RespCount struct
type RespMessages struct {
	Count int       `json:"count"`
	Items []Message `json:"items"`
}

type RespFriendsGetMutual struct {
	Id            int   `json:"id"`
	CommonFriends []int `json:"common_friends"`
	CommonCount   int   `json:"common_count"`
}

type ResponseFriendsGetMutual struct {
	Response []RespFriendsGetMutual `json:"response"`
	ResponseError
}

type RespUnreadMessages struct {
	Count         int      `json:"count"`
	UnreadDialogs int      `json:"unread_dialogs"`
	Items         []Dialog `json:"items"`
}

type Dialog struct {
	Unread  int     `json:"unread"`
	Message Message `json:"message"`
}

type Message struct {
	Id        int       `json:"id"`
	ChatID    int       `json:"chat_id"`
	Date      EpochTime `json:"date"`
	Out       int       `json:"out"`
	UserId    int       `json:"user_id"`
	ReadState int       `json:"read_state"`
	Title     string    `json:"title"`
	Body      string    `json:"body"`
}

type RespUserWithCount struct {
	Count int    `json:"count"`
	Items []User `json:"items"`
}

type ResponseUserWithCount struct {
	Response RespUserWithCount `json:"response"`
	ResponseError
}

type RespPhotos struct {
	Count int     `json:"count"`
	Items []Photo `json:"items"`
}

type ResponsePhotos struct {
	Response RespPhotos `json:"response"`
	ResponseError
}

type City struct {
	Id     int    `json:"id"`
	Title  string `json:"title"`
	Area   string `json:"area,omitempty"`
	Region string `json:"region"`
}

type ResponseCities struct {
	Response struct {
		Count int    `json:"count"`
		Items []City `json:"items"`
	} `json:"response"`
	ResponseError
}

func ParseIdsResponse(data []byte) (count int, ids []int, err error) {
	var r ResponseIds
	err = json.Unmarshal(data, &r)
	if err != nil {
		return 0, []int{}, err
	}
	return r.Resp.Count, r.Resp.Items, nil
}

func ParseIntResponse(data []byte) (int, error) {
	var r ResponseInt
	e := json.Unmarshal(data, &r)
	if e != nil {
		return 0, e
	}
	if r.Error.Code != 0 {
		return 0, fmt.Errorf("%s", r.Error.Msg)
	}
	return r.Response, nil
}

func ParseUsersResponse(data []byte) (users []User, err error) {
	var r ResponseUsers
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []User{}, err
	}
	return r.Response, nil
}

func ParseDialogsResponse(data []byte) (ms []Dialog, err error) {
	var r struct {
		RespUnreadMessages `json:"response"`
		ResponseError
	}
	err = json.Unmarshal(data, &r)
	if err != nil {
		return
	}
	return r.RespUnreadMessages.Items, nil
}

func ParseMessagesResponse(data []byte) (ms []Message, err error) {
	var r ResponseMessages
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []Message{}, err
	}
	return r.Response.Items, nil
}

func ParseUnreadMessagesResponse(data []byte) (ms []Dialog, err error) {
	var r struct {
		RespUnreadMessages `json:"response"`
		ResponseError
	}
	err = json.Unmarshal(data, &r)
	if err != nil {
		return []Dialog{}, err
	}
	return r.RespUnreadMessages.Items, nil
}

func ParseResponseUserWithCount(data []byte) (users []User, cnt int, e error) {
	var r ResponseUserWithCount
	e = json.Unmarshal(data, &r)
	return r.Response.Items, r.Response.Count, e
}

type OutRequestDeletedResponse struct {
	OutRequestDeleted `json:"response"`
	ResponseError     `json:"error"`
}

type OutRequestDeleted struct {
	Success           int `json:"success"`
	OutRequestDeleted int `json:"out_request_deleted"`
}
<|endoftext|>


<commit_before>package instrumentation

import (
	"github.com/porthos-rpc/porthos-go"
)

type TxResponse struct {
	Transaction
	porthos.Response
}

func (r *TxResponse) JSON(statusCode int16, body interface{}) {
	defer r.StartSegment("Response time").End()
	r.Response.JSON(statusCode, body)
}

func (r *TxResponse) Raw(statusCode int16, contentType string, body []byte) {
	defer r.StartSegment("Response time").End()
	r.Response.Raw(statusCode, contentType, body)
}

func (r *TxResponse) Empty(statusCode int16) {
	defer r.StartSegment("Response time").End()
	r.Response.Empty(statusCode)
}
<commit_msg>StatusCode as int32<commit_after>package instrumentation

import (
	"github.com/porthos-rpc/porthos-go"
)

type TxResponse struct {
	Transaction
	porthos.Response
}

func (r *TxResponse) JSON(statusCode int32, body interface{}) {
	defer r.StartSegment("Response time").End()
	r.Response.JSON(statusCode, body)
}

func (r *TxResponse) Raw(statusCode int32, contentType string, body []byte) {
	defer r.StartSegment("Response time").End()
	r.Response.Raw(statusCode, contentType, body)
}

func (r *TxResponse) Empty(statusCode int32) {
	defer r.StartSegment("Response time").End()
	r.Response.Empty(statusCode)
}
<|endoftext|>


<commit_before>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build linux
// +build amd64 arm64 ppc64el

package kvm

import (
	"os/exec"
	"os/user"
	"strconv"
	"syscall"

	"github.com/juju/errors"
)

// run the command as user libvirt-qemu and return the combined output.
func runAsLibvirt(command string, args ...string) (string, error) {
	uid, gid, err := getUserUIDGID(libvirtUser)
	if err != nil {
		return "", errors.Trace(err)
	}

	logger.Debugf("running: %s %v", command, args)
	logger.Debugf("running as uid: %d, gid: %d\n", uid, gid)

	cmd := exec.Command(command, args...)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{
		Uid: uint32(uid),
		Gid: uint32(gid),
	}

	out, err := cmd.CombinedOutput()
	output := string(out)
	logger.Debugf("output: %v", output)

	return output, err

}

// getUserUIDGID returns integervals for uid and gid for the user. It returns
// -1 when there's an error so no one accidently thinks 0 is the appropriate
// uid/gid when there's an error.
func getUserUIDGID(name string) (int, int, error) {
	u, err := user.Lookup(libvirtUser)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	uid, err := strconv.ParseUint(u.Uid, 10, 32)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	gid, err := strconv.ParseUint(u.Gid, 10, 32)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	return int(uid), int(gid), nil
}
<commit_msg>fix the build tag to use ppc64le not ppc64el<commit_after>// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build linux
// +build amd64 arm64 ppc64le

package kvm

import (
	"os/exec"
	"os/user"
	"strconv"
	"syscall"

	"github.com/juju/errors"
)

// run the command as user libvirt-qemu and return the combined output.
func runAsLibvirt(command string, args ...string) (string, error) {
	uid, gid, err := getUserUIDGID(libvirtUser)
	if err != nil {
		return "", errors.Trace(err)
	}

	logger.Debugf("running: %s %v", command, args)
	logger.Debugf("running as uid: %d, gid: %d\n", uid, gid)

	cmd := exec.Command(command, args...)
	cmd.SysProcAttr = &syscall.SysProcAttr{}
	cmd.SysProcAttr.Credential = &syscall.Credential{
		Uid: uint32(uid),
		Gid: uint32(gid),
	}

	out, err := cmd.CombinedOutput()
	output := string(out)
	logger.Debugf("output: %v", output)

	return output, err

}

// getUserUIDGID returns integervals for uid and gid for the user. It returns
// -1 when there's an error so no one accidently thinks 0 is the appropriate
// uid/gid when there's an error.
func getUserUIDGID(name string) (int, int, error) {
	u, err := user.Lookup(libvirtUser)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	uid, err := strconv.ParseUint(u.Uid, 10, 32)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	gid, err := strconv.ParseUint(u.Gid, 10, 32)
	if err != nil {
		return -1, -1, errors.Trace(err)
	}
	return int(uid), int(gid), nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ant0ine/go-json-rest/rest"
	"github.com/gorilla/mux"
	"github.com/imheresamir/picast"
	"io/ioutil"
	"log"
	"net/http"
)

type MyCorsMiddleware struct{}

func (mw *MyCorsMiddleware) MiddlewareFunc(handler rest.HandlerFunc) rest.HandlerFunc {
	return func(writer rest.ResponseWriter, request *rest.Request) {

		corsInfo := request.GetCorsInfo()

		// Be nice with non CORS requests, continue
		// Alternatively, you may also chose to only allow CORS requests, and return an error.
		if !corsInfo.IsCors {
			// continure, execute the wrapped middleware
			handler(writer, request)
			return
		}

		// Validate the Origin
		// More sophisticated validations can be implemented, regexps, DB lookups, ...
		/*if corsInfo.Origin != "http://my.other.host" {
			rest.Error(writer, "Invalid Origin", http.StatusForbidden)
			return
		}*/

		if corsInfo.IsPreflight {
			// check the request methods
			allowedMethods := map[string]bool{
				"GET":  true,
				"POST": true,
				"PUT":  true,
				// don't allow DELETE, for instance
			}
			if !allowedMethods[corsInfo.AccessControlRequestMethod] {
				rest.Error(writer, "Invalid Preflight Request", http.StatusForbidden)
				return
			}
			// check the request headers
			allowedHeaders := map[string]bool{
				"Accept":       true,
				"Content-Type": true,
			}
			for _, requestedHeader := range corsInfo.AccessControlRequestHeaders {
				if !allowedHeaders[requestedHeader] {
					rest.Error(writer, "Invalid Preflight Request", http.StatusForbidden)
					return
				}
			}

			for allowedMethod, _ := range allowedMethods {
				writer.Header().Add("Access-Control-Allow-Methods", allowedMethod)
			}
			for allowedHeader, _ := range allowedHeaders {
				writer.Header().Add("Access-Control-Allow-Headers", allowedHeader)
			}
			writer.Header().Set("Access-Control-Allow-Origin", corsInfo.Origin)
			writer.Header().Set("Access-Control-Allow-Credentials", "true")
			writer.Header().Set("Access-Control-Max-Age", "3600")
			writer.WriteHeader(http.StatusOK)
			return
		} else {
			writer.Header().Set("Access-Control-Expose-Headers", "X-Powered-By")
			writer.Header().Set("Access-Control-Allow-Origin", corsInfo.Origin)
			writer.Header().Set("Access-Control-Allow-Credentials", "true")
			// continure, execute the wrapped middleware
			handler(writer, request)
			return
		}
	}
}

func main() {

	mainMedia := picast.Media{Metadata: &picast.PlaylistEntry{}}
	api := picast.Api{CurrentMedia: &mainMedia}
	api.InitDB()

	fileserverPort := "8080"

	log.Println("Server Started.")

	// REST handler

	handler := rest.ResourceHandler{
		PreRoutingMiddlewares: []rest.Middleware{
			&MyCorsMiddleware{},
		},
	}
	handler.SetRoutes(
		&rest.Route{"GET", "/api/entries", api.GetAllEntries},
		&rest.Route{"GET", "/api/entries/:id", api.GetEntry},
		&rest.Route{"POST", "/api/entries", api.PostEntry},
		&rest.Route{"DELETE", "/api/entries/:id", api.DeleteEntry},

		&rest.Route{"POST", "/api/playall", api.PlayAll},
		&rest.Route{"POST", "/api/prev", api.Prev},
		&rest.Route{"POST", "/api/next", api.Next},

		&rest.Route{"POST", "/media/play", mainMedia.Play},
		&rest.Route{"POST", "/media/pause", mainMedia.TogglePause},
		&rest.Route{"POST", "/media/stop", mainMedia.Stop},
	)

	go http.ListenAndServe(":8082", &handler)

	// HTTP handler

	// Write server configuration to js file that will be referenced by webapp
	ip, err := externalIP()
	if err != nil {
		log.Println(err)
	}

	serverConfigjs := "define(function(require, exports, module) {" + "\n\tmodule.exports = ['" + ip + "'];" + "\n});"

	err = ioutil.WriteFile("static/src/serverConfig.js", []byte(serverConfigjs), 0644)
	if err != nil {
		log.Panicln(err)
	}

	r := mux.NewRouter()

	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))

	http.Handle("/", r)
	log.Panic(http.ListenAndServe(":"+fileserverPort, nil))
}
<commit_msg>Added support for Server Sent Events, allowing the server to push status updates to client webapps<commit_after>package main

import (
	"github.com/ant0ine/go-json-rest/rest"
	"github.com/antage/eventsource"
	"github.com/gorilla/mux"
	"github.com/imheresamir/picast"
	"io/ioutil"
	"log"
	"net/http"
	//"strconv"
	"time"
)

const (
	fileserverPort = "8080"
	ssePort        = "8081"
	restPort       = "8082"
)

type MyCorsMiddleware struct{}

func (mw *MyCorsMiddleware) MiddlewareFunc(handler rest.HandlerFunc) rest.HandlerFunc {
	return func(writer rest.ResponseWriter, request *rest.Request) {

		corsInfo := request.GetCorsInfo()

		// Be nice with non CORS requests, continue
		// Alternatively, you may also chose to only allow CORS requests, and return an error.
		if !corsInfo.IsCors {
			// continure, execute the wrapped middleware
			handler(writer, request)
			return
		}

		// Validate the Origin
		// More sophisticated validations can be implemented, regexps, DB lookups, ...
		/*myIp, _ := externalIP()
		if corsInfo.Origin != myIp+":"+fileserverPort && corsInfo.Origin != "raspberrypi.local:"+fileserverPort {
			rest.Error(writer, "Invalid Origin", http.StatusForbidden)
			return
		}*/

		if corsInfo.IsPreflight {
			// check the request methods
			allowedMethods := map[string]bool{
				"GET":  true,
				"POST": true,
				// don't allow DELETE, for instance
			}
			if !allowedMethods[corsInfo.AccessControlRequestMethod] {
				rest.Error(writer, "Invalid Preflight Request", http.StatusForbidden)
				return
			}
			// check the request headers
			allowedHeaders := map[string]bool{
				"Accept":       true,
				"Content-Type": true,
			}
			for _, requestedHeader := range corsInfo.AccessControlRequestHeaders {
				if !allowedHeaders[requestedHeader] {
					rest.Error(writer, "Invalid Preflight Request", http.StatusForbidden)
					return
				}
			}

			for allowedMethod, _ := range allowedMethods {
				writer.Header().Add("Access-Control-Allow-Methods", allowedMethod)
			}
			for allowedHeader, _ := range allowedHeaders {
				writer.Header().Add("Access-Control-Allow-Headers", allowedHeader)
			}
			writer.Header().Set("Access-Control-Allow-Origin", corsInfo.Origin)
			writer.Header().Set("Access-Control-Allow-Credentials", "true")
			writer.Header().Set("Access-Control-Max-Age", "3600")
			writer.WriteHeader(http.StatusOK)
			return
		} else {
			writer.Header().Set("Access-Control-Expose-Headers", "X-Powered-By")
			writer.Header().Set("Access-Control-Allow-Origin", corsInfo.Origin)
			writer.Header().Set("Access-Control-Allow-Credentials", "true")
			// continure, execute the wrapped middleware
			handler(writer, request)
			return
		}
	}
}

func main() {

	mainMedia := picast.Media{Metadata: &picast.PlaylistEntry{}}
	api := picast.Api{CurrentMedia: &mainMedia}
	api.InitDB()

	log.Println("Server Started.")

	// REST handler

	handler := rest.ResourceHandler{
		PreRoutingMiddlewares: []rest.Middleware{
			&MyCorsMiddleware{},
		},
	}
	handler.SetRoutes(
		&rest.Route{"GET", "/api/entries", api.GetAllEntries},
		&rest.Route{"GET", "/api/entries/:id", api.GetEntry},
		&rest.Route{"POST", "/api/entries", api.PostEntry},
		&rest.Route{"DELETE", "/api/entries/:id", api.DeleteEntry},

		&rest.Route{"POST", "/api/playall", api.PlayAll},
		&rest.Route{"POST", "/api/prev", api.Prev},
		&rest.Route{"POST", "/api/next", api.Next},

		&rest.Route{"POST", "/media/play", mainMedia.Play},
		&rest.Route{"GET", "/media/pause", mainMedia.TogglePause},
		&rest.Route{"GET", "/media/stop", mainMedia.Stop},
		&rest.Route{"GET", "/media/status", mainMedia.Status},
	)

	go http.ListenAndServe(":"+restPort, &handler)

	// Server Sent Events Handler

	es := eventsource.New(
		eventsource.DefaultSettings(),
		func(req *http.Request) [][]byte {
			return [][]byte{
				[]byte("Access-Control-Allow-Origin: *"),
			}
		},
	)
	//defer es.Close()
	http.Handle("/events", es)
	go func() {
		currentState := 0

		for {
			if mainMedia.Player != nil && currentState != mainMedia.Player.StatusCode() {
				switch mainMedia.Player.StatusCode() {
				case 0:
					es.SendEventMessage("stopped", "playerStateChanged", "")
				case 2:
					es.SendEventMessage("paused", "playerStateChanged", "")
				case 3:
					es.SendEventMessage("playing", "playerStateChanged", "")
				}

				log.Println("Server Event Sent.")

				currentState = mainMedia.Player.StatusCode()
			}

			time.Sleep(1 * time.Second)

		}
	}()
	go http.ListenAndServe(":"+ssePort, nil)

	// HTTP handler

	// Write server configuration to js file that will be referenced by webapp
	ip, err := externalIP()
	if err != nil {
		log.Println(err)
	}

	serverConfigjs := "define(function(require, exports, module) {" + "\n\tmodule.exports = ['" + ip + "'];" + "\n});"

	err = ioutil.WriteFile("static/src/serverConfig.js", []byte(serverConfigjs), 0644)
	if err != nil {
		log.Panicln(err)
	}

	r := mux.NewRouter()

	r.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/")))

	http.Handle("/", r)
	log.Panic(http.ListenAndServe(":"+fileserverPort, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os/exec"
	"strings"
)

func mainHandler(w http.ResponseWriter, r *http.Request) {

	path := strings.TrimSpace(r.URL.Path)

	//Cut off the leading and trailing forward slashes, if they exist.
	//This cuts off the leading forward slash.
	if strings.HasPrefix(path, "/") {
		path = path[1:]
	}
	//This cuts off the trailing forward slash.
	if strings.HasSuffix(path, "/") {
		cut_off_last_char_len := len(path) - 1
		path = path[:cut_off_last_char_len]
	}

	if len(path) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// We need to isolate the individual components of the path.
	components := strings.Split(path, "/")

	salt_node := fmt.Sprintf("G@node_type:%s", components[0])

	cmdName := "salt"
	cmdArgs := []string{"-C", salt_node, "state.highstate"}

	out, err := exec.Command(cmdName, cmdArgs...).Output()
	if err != nil {
		fmt.Fprintf(w, "There was an error running git rev-parse command: %s", err)
		return
	}

	fmt.Fprintf(w, string(out))
	return
}
<commit_msg>	modified:   mainHandler.go<commit_after>package main

import (
	"fmt"
	"net/http"
	"os/exec"
	"strings"
)

func mainHandler(w http.ResponseWriter, r *http.Request) {

	path := strings.TrimSpace(r.URL.Path)

	//Cut off the leading and trailing forward slashes, if they exist.
	//This cuts off the leading forward slash.
	if strings.HasPrefix(path, "/") {
		path = path[1:]
	}
	//This cuts off the trailing forward slash.
	if strings.HasSuffix(path, "/") {
		cut_off_last_char_len := len(path) - 1
		path = path[:cut_off_last_char_len]
	}

	if len(path) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// We need to isolate the individual components of the path.
	components := strings.Split(path, "/")

	salt_node := fmt.Sprintf("G@node_type:%s", components[0])

	cmdName := "salt"
	cmdArgs := []string{"-C", salt_node, "state.highstate"}

	out, err := exec.Command(cmdName, cmdArgs...).Output()
	if err != nil {
		fmt.Fprintf(w, "There was an error running command: %s", err)
		return
	}

	fmt.Fprintf(w, string(out))
	return
}
<|endoftext|>


<commit_before>package libct

import "testing"
import "syscall"
import "os"

func TestSpawnExecv(t *testing.T) {
	s := &Session{}

	err := s.OpenLocal()
	if err != nil {
		t.Fatal(err)
	}

	p, err := s.ProcessCreateDesc()
	if err != nil {
		t.Fatal(err)
	}

	ct, err := s.ContainerCreate("test")
	if err != nil {
		t.Fatal(err)
	}

	ct.SetNsMask(syscall.CLONE_NEWNS | syscall.CLONE_NEWPID)

	err = ct.SpawnExecve(p, "true",
		[]string{"true"},
		[]string{"PATH=/bin:/usr/bin"})
	if err != nil {
		t.Fatal(err)
	}
	ct.Wait()
}

func TestSpawnExecvStdout(t *testing.T) {
	s := &Session{}

	err := s.OpenLocal()
	if err != nil {
		t.Fatal(err)
	}

	p, err := s.ProcessCreateDesc()
	if err != nil {
		t.Fatal(err)
	}

	pr, pw, err := os.Pipe()
	ir, iw, err := os.Pipe()
	er, ew, err := os.Pipe()
	tr, tw, err := os.Pipe()

	p.Stdout = pw
	p.Stdin = ir
	p.Stderr = ew
	p.ExtraFiles = append(p.ExtraFiles, tr)

	ct, err := s.ContainerCreate("test")
	if err != nil {
		t.Fatal(err)
	}

	err = ct.SpawnExecve(p, "bash",
		[]string{"sh", "-c", "echo ok; cat; cat <&3 >&2"},
		[]string{"PATH=/bin:/usr/bin"})
	if err != nil {
		t.Fatal(err)
	}
	pw.Close()
	ir.Close()
	tr.Close()
	ew.Close()

	iw.WriteString("iok")
	iw.Close()
	tw.WriteString("good")
	tw.Close()

	data := make([]byte, 100)
	count, err := pr.Read(data)
	if count != 3 {
		t.Fatal(err)
	}
	count, err = pr.Read(data)
	if count != 3 {
		t.Fatal(err)
	}
	count, err = er.Read(data)
	if count != 4 {
		t.Fatal(count, string(data), data)
	}
	ct.Wait()
}
<commit_msg>go/test: fix race<commit_after>package libct

import "testing"
import "syscall"
import "os"

func TestSpawnExecv(t *testing.T) {
	s := &Session{}

	err := s.OpenLocal()
	if err != nil {
		t.Fatal(err)
	}

	p, err := s.ProcessCreateDesc()
	if err != nil {
		t.Fatal(err)
	}

	ct, err := s.ContainerCreate("test")
	if err != nil {
		t.Fatal(err)
	}

	ct.SetNsMask(syscall.CLONE_NEWNS | syscall.CLONE_NEWPID)

	err = ct.SpawnExecve(p, "true",
		[]string{"true"},
		[]string{"PATH=/bin:/usr/bin"})
	if err != nil {
		t.Fatal(err)
	}
	ct.Wait()
}

func TestSpawnExecvStdout(t *testing.T) {
	s := &Session{}

	err := s.OpenLocal()
	if err != nil {
		t.Fatal(err)
	}

	p, err := s.ProcessCreateDesc()
	if err != nil {
		t.Fatal(err)
	}

	pr, pw, err := os.Pipe()
	ir, iw, err := os.Pipe()
	er, ew, err := os.Pipe()
	tr, tw, err := os.Pipe()

	p.Stdout = pw
	p.Stdin = ir
	p.Stderr = ew
	p.ExtraFiles = append(p.ExtraFiles, tr)

	ct, err := s.ContainerCreate("test")
	if err != nil {
		t.Fatal(err)
	}

	if err = ct.AddController(CTL_CPU); err != nil {
		t.Fatal(err);
	}

	err = ct.SpawnExecve(p, "sh",
		[]string{"sh", "-c", "echo ok; cat; cat <&3 >&2"},
		[]string{"PATH=/bin:/usr/bin"})
	defer ct.Wait()
	pw.Close()
	ir.Close()
	tr.Close()
	ew.Close()
	defer pr.Close()
	defer iw.Close()
	defer tw.Close()
	defer er.Close()

	if err != nil {
		t.Fatal(err)
	}

	procs, err := ct.Processes()
	if err != nil {
		t.Fatal(err)
	}

	if len(procs) > 2 {
		t.Fatal(procs)
	}

	iw.WriteString("iok")
	iw.Close()
	tw.WriteString("good")
	tw.Close()

	ct.Wait()

	data := make([]byte, 100)
	count, err := pr.Read(data)
	if count != 6 {
		t.Fatal(count, string(data), data)
	}
	count, err = er.Read(data)
	if count != 4 {
		t.Fatal(count, string(data), data)
	}
}
<|endoftext|>


<commit_before>package teams

import (
	"fmt"
	"sort"

	"golang.org/x/net/context"

	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
)

type statusList struct {
	Teams  []keybase1.MemberInfo `json:"teams"`
	Status libkb.AppStatus       `json:"status"`
}

func (r *statusList) GetAppStatus() *libkb.AppStatus {
	return &r.Status
}

func getTeamsListFromServer(ctx context.Context, g *libkb.GlobalContext, uid keybase1.UID, all bool) ([]keybase1.MemberInfo, error) {
	var endpoint string
	if all {
		endpoint = "team/teammates_for_user"
	} else {
		endpoint = "team/for_user"
	}
	a := libkb.NewAPIArg(endpoint)
	if uid.Exists() {
		a.Args = libkb.HTTPArgs{
			"uid": libkb.S{Val: uid.String()},
		}
	}
	a.NetContext = ctx
	a.SessionType = libkb.APISessionTypeREQUIRED
	var list statusList
	if err := g.API.GetDecode(a, &list); err != nil {
		return nil, err
	}
	return list.Teams, nil
}

func List(ctx context.Context, g *libkb.GlobalContext, arg keybase1.TeamListArg) (*keybase1.AnnotatedTeamList, error) {
	var uid keybase1.UID
	if arg.UserAssertion != "" {
		res := g.Resolver.ResolveFullExpression(ctx, arg.UserAssertion)
		if res.GetError() != nil {
			return nil, res.GetError()
		}
		uid = res.GetUID()
	}

	meUID := g.ActiveDevice.UID()

	teams, err := getTeamsListFromServer(ctx, g, uid, arg.All)
	if err != nil {
		return nil, err
	}

	teamNames := make(map[string]bool)
	upakLoader := g.GetUPAKLoader()
	annotatedTeams := make([]keybase1.AnnotatedMemberInfo, len(teams))
	administeredTeams := make(map[string]bool)
	for idx, memberInfo := range teams {
		teamNames[memberInfo.FqName] = true
		if memberInfo.UserID == meUID && (memberInfo.Role.IsAdminOrAbove() || (memberInfo.Implicit != nil && memberInfo.Implicit.Role.IsAdminOrAbove())) {
			administeredTeams[memberInfo.FqName] = true
		}

		memberuid := memberInfo.UserID
		username, err := upakLoader.LookupUsername(context.Background(), memberuid)
		if err != nil {
			return nil, err
		}
		fullName, err := engine.GetFullName(context.Background(), g, memberuid)
		if err != nil {
			return nil, err
		}
		annotatedTeams[idx] = keybase1.AnnotatedMemberInfo{
			TeamID:   memberInfo.TeamID,
			FqName:   memberInfo.FqName,
			UserID:   memberInfo.UserID,
			Role:     memberInfo.Role,
			Implicit: memberInfo.Implicit,
			Username: username.String(),
			FullName: fullName,
		}
	}

	annotatedInvites := make(map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite)
	for teamName := range teamNames {
		_, ok := administeredTeams[teamName]
		if ok {
			t, err := GetForTeamManagementByStringName(ctx, g, teamName, true)
			if err != nil {
				g.Log.Warning("Error while getting team (%s): %v", teamName, err)
				continue
			}
			teamAnnotatedInvites, err := AnnotateInvites(ctx, g, t.chain().inner.ActiveInvites, teamName)
			if err != nil {
				return nil, err
			}
			for teamInviteID, annotatedTeamInvite := range teamAnnotatedInvites {
				annotatedInvites[teamInviteID] = annotatedTeamInvite
			}
		}
	}

	tl := keybase1.AnnotatedTeamList{
		Teams: annotatedTeams,
		AnnotatedActiveInvites: annotatedInvites,
	}

	return &tl, nil
}

func AnnotateInvites(ctx context.Context, g *libkb.GlobalContext, invites map[keybase1.TeamInviteID]keybase1.TeamInvite, teamName string) (map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite, error) {

	annotatedInvites := make(map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite, len(invites))
	upakLoader := g.GetUPAKLoader()
	for id, invite := range invites {
		username, err := upakLoader.LookupUsername(context.Background(), invite.Inviter.Uid)
		if err != nil {
			return annotatedInvites, err
		}

		name := invite.Name
		category, err := invite.Type.C()
		if err != nil {
			return nil, err
		}
		if category == keybase1.TeamInviteCategory_KEYBASE {
			// "keybase" invites (i.e. pukless users) have uid for name
			uid, err := keybase1.UIDFromString(string(invite.Name))
			if err != nil {
				return nil, err
			}
			normalized, err := upakLoader.LookupUsername(context.Background(), uid)
			if err != nil {
				return nil, err
			}
			name = keybase1.TeamInviteName(normalized.String())
		}
		annotatedInvites[id] = keybase1.AnnotatedTeamInvite{
			Role:            invite.Role,
			Id:              invite.Id,
			Type:            invite.Type,
			Name:            name,
			InviterUsername: username.String(),
			TeamName:        teamName,
		}
	}
	return annotatedInvites, nil
}

func TeamTree(ctx context.Context, g *libkb.GlobalContext, arg keybase1.TeamTreeArg) (res keybase1.TeamTreeResult, err error) {
	if !arg.Name.IsRootTeam() {
		return res, fmt.Errorf("cannot get tree of non-root team")
	}

	serverList, err := getTeamsListFromServer(ctx, g, "", false)
	if err != nil {
		return res, err
	}

	// Map from team name (string) to entry
	entryMap := make(map[string]keybase1.TeamTreeEntry)

	// The server might have omitted some teams, oh well.
	// Trusts the server for role.
	// Load the teams by ID to make sure they are valid and get the validated names.
	for _, info := range serverList {
		serverName, err := info.TeamName()
		if err != nil {
			return res, err
		}
		if !serverName.RootAncestorName().Eq(arg.Name) {
			// Skip those not in this tree.
			continue
		}
		team, err := Load(ctx, g, keybase1.LoadTeamArg{
			ID:          info.TeamID,
			ForceRepoll: true,
		})
		if err != nil {
			return res, err
		}
		var admin bool // true if an admin or implicit admin
		if info.Role.IsAdminOrAbove() {
			admin = true
		}
		if info.Implicit != nil && info.Implicit.Role.IsAdminOrAbove() {
			admin = true
		}
		entryMap[team.Name().String()] = keybase1.TeamTreeEntry{
			Name:  team.Name(),
			Admin: admin,
		}
	}

	// Add all parent names (recursively)
	// So that if only A.B.C is in the list, we add A.B and A as well.
	// Adding map entries while iterating is safe.
	// "If map entries are created during iteration, that entry may be produced during the iteration or may be skipped."
	for _, entry := range entryMap {
		name := entry.Name.DeepCopy()
		for name.Depth() > 0 {
			_, ok := entryMap[name.String()]
			if !ok {
				entryMap[name.String()] = keybase1.TeamTreeEntry{
					Name:  name,
					Admin: false,
				}
			}
			name, err = name.Parent()
			if err != nil {
				break
			}
		}
	}

	for _, entry := range entryMap {
		res.Entries = append(res.Entries, entry)
	}

	if len(res.Entries) == 0 {
		return res, fmt.Errorf("team not found: %v", arg.Name)
	}

	// Order into a tree order. Which happens to be alphabetical ordering.
	// Example: [a, a.b, a.b.c, a.b.d, a.e.f, a.e.g]
	sort.Slice(res.Entries, func(i, j int) bool {
		return res.Entries[i].Name.String() < res.Entries[j].Name.String()
	})

	return res, nil
}
<commit_msg>Use UserVersion<commit_after>package teams

import (
	"fmt"
	"sort"

	"golang.org/x/net/context"

	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
)

type statusList struct {
	Teams  []keybase1.MemberInfo `json:"teams"`
	Status libkb.AppStatus       `json:"status"`
}

func (r *statusList) GetAppStatus() *libkb.AppStatus {
	return &r.Status
}

func getTeamsListFromServer(ctx context.Context, g *libkb.GlobalContext, uid keybase1.UID, all bool) ([]keybase1.MemberInfo, error) {
	var endpoint string
	if all {
		endpoint = "team/teammates_for_user"
	} else {
		endpoint = "team/for_user"
	}
	a := libkb.NewAPIArg(endpoint)
	if uid.Exists() {
		a.Args = libkb.HTTPArgs{
			"uid": libkb.S{Val: uid.String()},
		}
	}
	a.NetContext = ctx
	a.SessionType = libkb.APISessionTypeREQUIRED
	var list statusList
	if err := g.API.GetDecode(a, &list); err != nil {
		return nil, err
	}
	return list.Teams, nil
}

func List(ctx context.Context, g *libkb.GlobalContext, arg keybase1.TeamListArg) (*keybase1.AnnotatedTeamList, error) {
	var uid keybase1.UID
	if arg.UserAssertion != "" {
		res := g.Resolver.ResolveFullExpression(ctx, arg.UserAssertion)
		if res.GetError() != nil {
			return nil, res.GetError()
		}
		uid = res.GetUID()
	}

	meUID := g.ActiveDevice.UID()

	teams, err := getTeamsListFromServer(ctx, g, uid, arg.All)
	if err != nil {
		return nil, err
	}

	teamNames := make(map[string]bool)
	upakLoader := g.GetUPAKLoader()
	annotatedTeams := make([]keybase1.AnnotatedMemberInfo, len(teams))
	administeredTeams := make(map[string]bool)
	for idx, memberInfo := range teams {
		teamNames[memberInfo.FqName] = true
		if memberInfo.UserID == meUID && (memberInfo.Role.IsAdminOrAbove() || (memberInfo.Implicit != nil && memberInfo.Implicit.Role.IsAdminOrAbove())) {
			administeredTeams[memberInfo.FqName] = true
		}

		memberuid := memberInfo.UserID
		username, err := upakLoader.LookupUsername(context.Background(), memberuid)
		if err != nil {
			return nil, err
		}
		fullName, err := engine.GetFullName(context.Background(), g, memberuid)
		if err != nil {
			return nil, err
		}
		annotatedTeams[idx] = keybase1.AnnotatedMemberInfo{
			TeamID:   memberInfo.TeamID,
			FqName:   memberInfo.FqName,
			UserID:   memberInfo.UserID,
			Role:     memberInfo.Role,
			Implicit: memberInfo.Implicit,
			Username: username.String(),
			FullName: fullName,
		}
	}

	annotatedInvites := make(map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite)
	for teamName := range teamNames {
		_, ok := administeredTeams[teamName]
		if ok {
			t, err := GetForTeamManagementByStringName(ctx, g, teamName, true)
			if err != nil {
				g.Log.Warning("Error while getting team (%s): %v", teamName, err)
				continue
			}
			teamAnnotatedInvites, err := AnnotateInvites(ctx, g, t.chain().inner.ActiveInvites, teamName)
			if err != nil {
				return nil, err
			}
			for teamInviteID, annotatedTeamInvite := range teamAnnotatedInvites {
				annotatedInvites[teamInviteID] = annotatedTeamInvite
			}
		}
	}

	tl := keybase1.AnnotatedTeamList{
		Teams: annotatedTeams,
		AnnotatedActiveInvites: annotatedInvites,
	}

	return &tl, nil
}

func AnnotateInvites(ctx context.Context, g *libkb.GlobalContext, invites map[keybase1.TeamInviteID]keybase1.TeamInvite, teamName string) (map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite, error) {

	annotatedInvites := make(map[keybase1.TeamInviteID]keybase1.AnnotatedTeamInvite, len(invites))
	upakLoader := g.GetUPAKLoader()
	for id, invite := range invites {
		username, err := upakLoader.LookupUsername(context.Background(), invite.Inviter.Uid)
		if err != nil {
			return annotatedInvites, err
		}

		name := invite.Name
		category, err := invite.Type.C()
		if err != nil {
			return nil, err
		}
		if category == keybase1.TeamInviteCategory_KEYBASE {
			// "keybase" invites (i.e. pukless users) have user version for name
			uv, err := ParseUserVersion(string(invite.Name))
			if err != nil {
				return nil, err
			}
			normalized, err := upakLoader.LookupUsername(context.Background(), uv.Uid)
			if err != nil {
				return nil, err
			}
			name = keybase1.TeamInviteName(normalized.String())
		}
		annotatedInvites[id] = keybase1.AnnotatedTeamInvite{
			Role:            invite.Role,
			Id:              invite.Id,
			Type:            invite.Type,
			Name:            name,
			InviterUsername: username.String(),
			TeamName:        teamName,
		}
	}
	return annotatedInvites, nil
}

func TeamTree(ctx context.Context, g *libkb.GlobalContext, arg keybase1.TeamTreeArg) (res keybase1.TeamTreeResult, err error) {
	if !arg.Name.IsRootTeam() {
		return res, fmt.Errorf("cannot get tree of non-root team")
	}

	serverList, err := getTeamsListFromServer(ctx, g, "", false)
	if err != nil {
		return res, err
	}

	// Map from team name (string) to entry
	entryMap := make(map[string]keybase1.TeamTreeEntry)

	// The server might have omitted some teams, oh well.
	// Trusts the server for role.
	// Load the teams by ID to make sure they are valid and get the validated names.
	for _, info := range serverList {
		serverName, err := info.TeamName()
		if err != nil {
			return res, err
		}
		if !serverName.RootAncestorName().Eq(arg.Name) {
			// Skip those not in this tree.
			continue
		}
		team, err := Load(ctx, g, keybase1.LoadTeamArg{
			ID:          info.TeamID,
			ForceRepoll: true,
		})
		if err != nil {
			return res, err
		}
		var admin bool // true if an admin or implicit admin
		if info.Role.IsAdminOrAbove() {
			admin = true
		}
		if info.Implicit != nil && info.Implicit.Role.IsAdminOrAbove() {
			admin = true
		}
		entryMap[team.Name().String()] = keybase1.TeamTreeEntry{
			Name:  team.Name(),
			Admin: admin,
		}
	}

	// Add all parent names (recursively)
	// So that if only A.B.C is in the list, we add A.B and A as well.
	// Adding map entries while iterating is safe.
	// "If map entries are created during iteration, that entry may be produced during the iteration or may be skipped."
	for _, entry := range entryMap {
		name := entry.Name.DeepCopy()
		for name.Depth() > 0 {
			_, ok := entryMap[name.String()]
			if !ok {
				entryMap[name.String()] = keybase1.TeamTreeEntry{
					Name:  name,
					Admin: false,
				}
			}
			name, err = name.Parent()
			if err != nil {
				break
			}
		}
	}

	for _, entry := range entryMap {
		res.Entries = append(res.Entries, entry)
	}

	if len(res.Entries) == 0 {
		return res, fmt.Errorf("team not found: %v", arg.Name)
	}

	// Order into a tree order. Which happens to be alphabetical ordering.
	// Example: [a, a.b, a.b.c, a.b.d, a.e.f, a.e.g]
	sort.Slice(res.Entries, func(i, j int) bool {
		return res.Entries[i].Name.String() < res.Entries[j].Name.String()
	})

	return res, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 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 or at
// https://developers.google.com/open-source/licenses/bsd.

// golint lints the Go source files named on its command line.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/golang/lint"
)

var minConfidence = flag.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it")

func main() {
	flag.Parse()

	// TODO(dsymonds): Support linting of stdin.
	for _, filename := range flag.Args() {
		lintFile(filename)
	}
}

func lintFile(filename string) {
	src, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Printf("Failed reading file: %v", err)
		return
	}

	l := new(lint.Linter)
	ps, err := l.Lint(filename, src)
	if err != nil {
		log.Printf("Failed parsing file: %v", err)
		return
	}
	for _, p := range ps {
		if p.Confidence >= *minConfidence {
			fmt.Printf("%s:%v: %s\n", filename, p.Position, p.Text)
		}
	}
}
<commit_msg>Include filename in reading/parsing errors.<commit_after>// Copyright (c) 2013 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 or at
// https://developers.google.com/open-source/licenses/bsd.

// golint lints the Go source files named on its command line.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/golang/lint"
)

var minConfidence = flag.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it")

func main() {
	flag.Parse()

	// TODO(dsymonds): Support linting of stdin.
	for _, filename := range flag.Args() {
		lintFile(filename)
	}
}

func lintFile(filename string) {
	src, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Printf("Failed reading %v: %v", filename, err)
		return
	}

	l := new(lint.Linter)
	ps, err := l.Lint(filename, src)
	if err != nil {
		log.Printf("Failed parsing %v: %v", filename, err)
		return
	}
	for _, p := range ps {
		if p.Confidence >= *minConfidence {
			fmt.Printf("%s:%v: %s\n", filename, p.Position, p.Text)
		}
	}
}
<|endoftext|>


<commit_before>package main

/*

This file holds a direct copy of the import path matching code of
https://code.google.com/p/go/source/browse/src/cmd/go/main.go. It can be
replaced when https://code.google.com/p/go/issues/detail?id=8768 is resolved.

*/

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

var buildContext = build.Default

var (
	goroot       = filepath.Clean(runtime.GOROOT())
	gorootSrcPkg = filepath.Join(goroot, "src/pkg")
)

// importPathsNoDotExpansion returns the import paths to use for the given
// command line, but it does no ... expansion.
func importPathsNoDotExpansion(args []string) []string {
	if len(args) == 0 {
		return []string{"."}
	}
	var out []string
	for _, a := range args {
		// Arguments are supposed to be import paths, but
		// as a courtesy to Windows developers, rewrite \ to /
		// in command-line arguments.  Handles .\... and so on.
		if filepath.Separator == '\\' {
			a = strings.Replace(a, `\`, `/`, -1)
		}

		// Put argument in canonical form, but preserve leading ./.
		if strings.HasPrefix(a, "./") {
			a = "./" + path.Clean(a)
			if a == "./." {
				a = "."
			}
		} else {
			a = path.Clean(a)
		}
		if a == "all" || a == "std" {
			out = append(out, allPackages(a)...)
			continue
		}
		out = append(out, a)
	}
	return out
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	args = importPathsNoDotExpansion(args)
	var out []string
	for _, a := range args {
		if strings.Contains(a, "...") {
			if build.IsLocalImport(a) {
				out = append(out, allPackagesInFS(a)...)
			} else {
				out = append(out, allPackages(a)...)
			}
			continue
		}
		out = append(out, a)
	}
	return out
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	// Special case: foo/... matches foo too.
	if strings.HasSuffix(re, `/.*`) {
		re = re[:len(re)-len(`/.*`)] + `(/.*)?`
	}
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}

// hasPathPrefix reports whether the path s begins with the
// elements in prefix.
func hasPathPrefix(s, prefix string) bool {
	switch {
	default:
		return false
	case len(s) == len(prefix):
		return s == prefix
	case len(s) > len(prefix):
		if prefix != "" && prefix[len(prefix)-1] == '/' {
			return strings.HasPrefix(s, prefix)
		}
		return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
	}
}

// treeCanMatchPattern(pattern)(name) reports whether
// name or children of name can possibly match pattern.
// Pattern is the same limited glob accepted by matchPattern.
func treeCanMatchPattern(pattern string) func(name string) bool {
	wildCard := false
	if i := strings.Index(pattern, "..."); i >= 0 {
		wildCard = true
		pattern = pattern[:i]
	}
	return func(name string) bool {
		return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
			wildCard && strings.HasPrefix(name, pattern)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
func allPackages(pattern string) []string {
	pkgs := matchPackages(pattern)
	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

func matchPackages(pattern string) []string {
	match := func(string) bool { return true }
	treeCanMatch := func(string) bool { return true }
	if pattern != "all" && pattern != "std" {
		match = matchPattern(pattern)
		treeCanMatch = treeCanMatchPattern(pattern)
	}

	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	if !buildContext.CgoEnabled {
		have["runtime/cgo"] = true // ignore during walk
	}
	var pkgs []string

	// Commands
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == cmd {
			return nil
		}
		name := path[len(cmd):]
		if !treeCanMatch(name) {
			return filepath.SkipDir
		}
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if have[name] {
			return nil
		}
		have[name] = true
		if !match(name) {
			return nil
		}
		_, err = buildContext.ImportDir(path, 0)
		if err != nil {
			if _, noGo := err.(*build.NoGoError); !noGo {
				log.Print(err)
			}
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})

	for _, src := range buildContext.SrcDirs() {
		if pattern == "std" && src != gorootSrcPkg {
			continue
		}
		src = filepath.Clean(src) + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() || path == src {
				return nil
			}

			// Avoid .foo, _foo, and testdata directory trees.
			_, elem := filepath.Split(path)
			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if pattern == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if !treeCanMatch(name) {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}
			have[name] = true
			if !match(name) {
				return nil
			}
			_, err = buildContext.ImportDir(path, 0)
			if err != nil {
				if _, noGo := err.(*build.NoGoError); noGo {
					return nil
				}
			}
			pkgs = append(pkgs, name)
			return nil
		})
	}
	return pkgs
}

// allPackagesInFS is like allPackages but is passed a pattern
// beginning ./ or ../, meaning it should scan the tree rooted
// at the given directory.  There are ... in the pattern too.
func allPackagesInFS(pattern string) []string {
	pkgs := matchPackagesInFS(pattern)
	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

func matchPackagesInFS(pattern string) []string {
	// Find directory to begin the scan.
	// Could be smarter but this one optimization
	// is enough for now, since ... is usually at the
	// end of a path.
	i := strings.Index(pattern, "...")
	dir, _ := path.Split(pattern[:i])

	// pattern begins with ./ or ../.
	// path.Clean will discard the ./ but not the ../.
	// We need to preserve the ./ for pattern matching
	// and in the returned import paths.
	prefix := ""
	if strings.HasPrefix(pattern, "./") {
		prefix = "./"
	}
	match := matchPattern(pattern)

	var pkgs []string
	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() {
			return nil
		}
		if path == dir {
			// filepath.Walk starts at dir and recurses. For the recursive case,
			// the path is the result of filepath.Join, which calls filepath.Clean.
			// The initial case is not Cleaned, though, so we do this explicitly.
			//
			// This converts a path like "./io/" to "io". Without this step, running
			// "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
			// package, because prepending the prefix "./" to the unclean path would
			// result in "././io", and match("././io") returns false.
			path = filepath.Clean(path)
		}

		// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
		_, elem := filepath.Split(path)
		dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
		if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
			return filepath.SkipDir
		}

		name := prefix + filepath.ToSlash(path)
		if !match(name) {
			return nil
		}
		if _, err = build.ImportDir(path, 0); err != nil {
			if _, noGo := err.(*build.NoGoError); !noGo {
				log.Print(err)
			}
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})
	return pkgs
}
<commit_msg>Update obsolete code.google.com references.<commit_after>package main

/*

This file holds a direct copy of the import path matching code of
https://github.com/golang/go/blob/master/src/cmd/go/main.go. It can be
replaced when https://golang.org/issue/8768 is resolved.

*/

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

var buildContext = build.Default

var (
	goroot       = filepath.Clean(runtime.GOROOT())
	gorootSrcPkg = filepath.Join(goroot, "src/pkg")
)

// importPathsNoDotExpansion returns the import paths to use for the given
// command line, but it does no ... expansion.
func importPathsNoDotExpansion(args []string) []string {
	if len(args) == 0 {
		return []string{"."}
	}
	var out []string
	for _, a := range args {
		// Arguments are supposed to be import paths, but
		// as a courtesy to Windows developers, rewrite \ to /
		// in command-line arguments.  Handles .\... and so on.
		if filepath.Separator == '\\' {
			a = strings.Replace(a, `\`, `/`, -1)
		}

		// Put argument in canonical form, but preserve leading ./.
		if strings.HasPrefix(a, "./") {
			a = "./" + path.Clean(a)
			if a == "./." {
				a = "."
			}
		} else {
			a = path.Clean(a)
		}
		if a == "all" || a == "std" {
			out = append(out, allPackages(a)...)
			continue
		}
		out = append(out, a)
	}
	return out
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	args = importPathsNoDotExpansion(args)
	var out []string
	for _, a := range args {
		if strings.Contains(a, "...") {
			if build.IsLocalImport(a) {
				out = append(out, allPackagesInFS(a)...)
			} else {
				out = append(out, allPackages(a)...)
			}
			continue
		}
		out = append(out, a)
	}
	return out
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	// Special case: foo/... matches foo too.
	if strings.HasSuffix(re, `/.*`) {
		re = re[:len(re)-len(`/.*`)] + `(/.*)?`
	}
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}

// hasPathPrefix reports whether the path s begins with the
// elements in prefix.
func hasPathPrefix(s, prefix string) bool {
	switch {
	default:
		return false
	case len(s) == len(prefix):
		return s == prefix
	case len(s) > len(prefix):
		if prefix != "" && prefix[len(prefix)-1] == '/' {
			return strings.HasPrefix(s, prefix)
		}
		return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
	}
}

// treeCanMatchPattern(pattern)(name) reports whether
// name or children of name can possibly match pattern.
// Pattern is the same limited glob accepted by matchPattern.
func treeCanMatchPattern(pattern string) func(name string) bool {
	wildCard := false
	if i := strings.Index(pattern, "..."); i >= 0 {
		wildCard = true
		pattern = pattern[:i]
	}
	return func(name string) bool {
		return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
			wildCard && strings.HasPrefix(name, pattern)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
func allPackages(pattern string) []string {
	pkgs := matchPackages(pattern)
	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

func matchPackages(pattern string) []string {
	match := func(string) bool { return true }
	treeCanMatch := func(string) bool { return true }
	if pattern != "all" && pattern != "std" {
		match = matchPattern(pattern)
		treeCanMatch = treeCanMatchPattern(pattern)
	}

	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	if !buildContext.CgoEnabled {
		have["runtime/cgo"] = true // ignore during walk
	}
	var pkgs []string

	// Commands
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == cmd {
			return nil
		}
		name := path[len(cmd):]
		if !treeCanMatch(name) {
			return filepath.SkipDir
		}
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if have[name] {
			return nil
		}
		have[name] = true
		if !match(name) {
			return nil
		}
		_, err = buildContext.ImportDir(path, 0)
		if err != nil {
			if _, noGo := err.(*build.NoGoError); !noGo {
				log.Print(err)
			}
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})

	for _, src := range buildContext.SrcDirs() {
		if pattern == "std" && src != gorootSrcPkg {
			continue
		}
		src = filepath.Clean(src) + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() || path == src {
				return nil
			}

			// Avoid .foo, _foo, and testdata directory trees.
			_, elem := filepath.Split(path)
			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if pattern == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if !treeCanMatch(name) {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}
			have[name] = true
			if !match(name) {
				return nil
			}
			_, err = buildContext.ImportDir(path, 0)
			if err != nil {
				if _, noGo := err.(*build.NoGoError); noGo {
					return nil
				}
			}
			pkgs = append(pkgs, name)
			return nil
		})
	}
	return pkgs
}

// allPackagesInFS is like allPackages but is passed a pattern
// beginning ./ or ../, meaning it should scan the tree rooted
// at the given directory.  There are ... in the pattern too.
func allPackagesInFS(pattern string) []string {
	pkgs := matchPackagesInFS(pattern)
	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

func matchPackagesInFS(pattern string) []string {
	// Find directory to begin the scan.
	// Could be smarter but this one optimization
	// is enough for now, since ... is usually at the
	// end of a path.
	i := strings.Index(pattern, "...")
	dir, _ := path.Split(pattern[:i])

	// pattern begins with ./ or ../.
	// path.Clean will discard the ./ but not the ../.
	// We need to preserve the ./ for pattern matching
	// and in the returned import paths.
	prefix := ""
	if strings.HasPrefix(pattern, "./") {
		prefix = "./"
	}
	match := matchPattern(pattern)

	var pkgs []string
	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() {
			return nil
		}
		if path == dir {
			// filepath.Walk starts at dir and recurses. For the recursive case,
			// the path is the result of filepath.Join, which calls filepath.Clean.
			// The initial case is not Cleaned, though, so we do this explicitly.
			//
			// This converts a path like "./io/" to "io". Without this step, running
			// "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
			// package, because prepending the prefix "./" to the unclean path would
			// result in "././io", and match("././io") returns false.
			path = filepath.Clean(path)
		}

		// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
		_, elem := filepath.Split(path)
		dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
		if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
			return filepath.SkipDir
		}

		name := prefix + filepath.ToSlash(path)
		if !match(name) {
			return nil
		}
		if _, err = build.ImportDir(path, 0); err != nil {
			if _, noGo := err.(*build.NoGoError); !noGo {
				log.Print(err)
			}
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})
	return pkgs
}
<|endoftext|>