<commit_before>// Copyright 2017 the u-root 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 testutil

import (
	"io/ioutil"
	"os/exec"
	"path/filepath"
	"testing"
)

// CompileInTempDir creates a temp directory and compiles the main package of
// the current directory. Remember to delete the directory after the test:
//     defer os.RemoveAll(tmpDir)
func CompileInTempDir(t *testing.T) (tmpDir string, execPath string) {
	// Create temp directory
	tmpDir, err := ioutil.TempDir("", "Test")
	if err != nil {
		t.Fatal("TempDir failed: ", err)
	}

	// Compile the program
	execPath = filepath.Join(tmpDir, "exec")
	out, err := exec.Command("go", "build", "-o", execPath).CombinedOutput()
	if err != nil {
		t.Fatalf("Failed to build: %v\n%s", err, string(out))
	}
	return
}
<commit_msg>Override execPath with the EXECPATH env variable<commit_after>// Copyright 2017 the u-root 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 testutil

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

// CompileInTempDir creates a temp directory and compiles the main package of
// the current directory. Remember to delete the directory after the test:
//
//     defer os.RemoveAll(tmpDir)
//
// The environment variable EXECPATH overrides execPath.
func CompileInTempDir(t testing.TB) (tmpDir string, execPath string) {
	// Create temp directory
	tmpDir, err := ioutil.TempDir("", "Test")
	if err != nil {
		t.Fatal("TempDir failed: ", err)
	}

	// Skip compilation if EXECPATH is set.
	execPath = os.Getenv("EXECPATH")
	if execPath != "" {
		return
	}

	// Compile the program
	execPath = filepath.Join(tmpDir, "exec")
	out, err := exec.Command("go", "build", "-o", execPath).CombinedOutput()
	if err != nil {
		t.Fatalf("Failed to build: %v\n%s", err, string(out))
	}
	return
}
<|endoftext|>


<commit_before>package validate

import (
	"fmt"
	"net"
	"regexp"
	"strconv"
	"strings"

	"github.com/lxc/lxd/shared/units"
)

// stringInSlice checks whether the supplied string is present in the supplied slice.
func stringInSlice(key string, list []string) bool {
	for _, entry := range list {
		if entry == key {
			return true
		}
	}
	return false
}

// Required returns function that runs one or more validators, all must pass without error.
func Required(validators ...func(value string) error) func(value string) error {
	return func(value string) error {
		for _, validator := range validators {
			err := validator(value)
			if err != nil {
				return err
			}
		}

		return nil
	}
}

// Optional wraps Required() function to make it return nil if value is empty string.
func Optional(validators ...func(value string) error) func(value string) error {
	return func(value string) error {
		if value == "" {
			return nil
		}

		return Required(validators...)(value)
	}
}

// IsInt64 validates whether the string can be converted to an int64.
func IsInt64(value string) error {
	_, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q", value)
	}

	return nil
}

// IsUint8 validates whether the string can be converted to an uint8.
func IsUint8(value string) error {
	_, err := strconv.ParseUint(value, 10, 8)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q. Must be between 0 and 255", value)
	}

	return nil
}

// IsUint32 validates whether the string can be converted to an uint32.
func IsUint32(value string) error {
	_, err := strconv.ParseUint(value, 10, 32)
	if err != nil {
		return fmt.Errorf("Invalid value for uint32 %q: %v", value, err)
	}

	return nil
}

// IsPriority validates priority number.
func IsPriority(value string) error {
	valueInt, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q", value)
	}

	if valueInt < 0 || valueInt > 10 {
		return fmt.Errorf("Invalid value for a limit %q. Must be between 0 and 10", value)
	}

	return nil
}

// IsBool validates if string can be understood as a bool.
func IsBool(value string) error {
	if !stringInSlice(strings.ToLower(value), []string{"true", "false", "yes", "no", "1", "0", "on", "off"}) {
		return fmt.Errorf("Invalid value for a boolean %q", value)
	}

	return nil
}

// IsOneOf checks whether the string is present in the supplied slice of strings.
func IsOneOf(value string, valid []string) error {
	if value == "" {
		return nil
	}

	if !stringInSlice(value, valid) {
		return fmt.Errorf("Invalid value %q (not one of %s)", value, valid)
	}

	return nil
}

// IsAny accepts all strings as valid.
func IsAny(value string) error {
	return nil
}

// IsNotEmpty requires a non-empty string.
func IsNotEmpty(value string) error {
	if value == "" {
		return fmt.Errorf("Required value")
	}

	return nil
}

// IsSize checks if string is valid size according to units.ParseByteSizeString.
func IsSize(value string) error {
	_, err := units.ParseByteSizeString(value)
	if err != nil {
		return err
	}

	return nil
}

// IsDeviceID validates string is four lowercase hex characters suitable as Vendor or Device ID.
func IsDeviceID(value string) error {
	regexHexLc, err := regexp.Compile("^[0-9a-f]+$")
	if err != nil {
		return err
	}

	if len(value) != 4 || !regexHexLc.MatchString(value) {
		return fmt.Errorf("Invalid value, must be four lower case hex characters")
	}

	return nil
}

// IsNetworkMAC validates an Ethernet MAC address. e.g. "00:00:5e:00:53:01".
func IsNetworkMAC(value string) error {
	_, err := net.ParseMAC(value)

	// Check is valid Ethernet MAC length and delimiter.
	if err != nil || len(value) != 17 || strings.ContainsAny(value, "-.") {
		return fmt.Errorf("Invalid MAC address, must be 6 bytes of hex separated by colons")
	}

	return nil
}

// IsNetworkAddress validates an IP (v4 or v6) address string. If string is empty, returns valid.
func IsNetworkAddress(value string) error {
	ip := net.ParseIP(value)
	if ip == nil {
		return fmt.Errorf("Not an IP address %q", value)
	}

	return nil
}

// IsNetworkV4 validates an IPv4 CIDR string. If string is empty, returns valid.
func IsNetworkV4(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 network %q", value)
	}

	if ip.String() != subnet.IP.String() {
		return fmt.Errorf("Not an IPv4 network address %q", value)
	}

	return nil
}

// IsNetworkAddressV4 validates an IPv4 addresss string. If string is empty, returns valid.
func IsNetworkAddressV4(value string) error {
	ip := net.ParseIP(value)
	if ip == nil || ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 address %q", value)
	}

	return nil
}

// IsNetworkAddressCIDRV4 validates an IPv4 addresss string in CIDR format. If string is empty, returns valid.
func IsNetworkAddressCIDRV4(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 address %q", value)
	}

	if ip.String() == subnet.IP.String() {
		return fmt.Errorf("Not a usable IPv4 address %q", value)
	}

	return nil
}

// IsNetworkAddressV4List validates a comma delimited list of IPv4 addresses.
func IsNetworkAddressV4List(value string) error {
	for _, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		err := IsNetworkAddressV4(v)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkV4List validates a comma delimited list of IPv4 CIDR strings.
func IsNetworkV4List(value string) error {
	for _, network := range strings.Split(value, ",") {
		network = strings.TrimSpace(network)
		err := IsNetworkV4(network)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkV6 validates an IPv6 CIDR string. If string is empty, returns valid.
func IsNetworkV6(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip == nil || ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 network %q", value)
	}

	if ip.String() != subnet.IP.String() {
		return fmt.Errorf("Not an IPv6 network address %q", value)
	}

	return nil
}

// IsNetworkAddressV6 validates an IPv6 addresss string. If string is empty, returns valid.
func IsNetworkAddressV6(value string) error {
	ip := net.ParseIP(value)
	if ip == nil || ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 address %q", value)
	}

	return nil
}

// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format. If string is empty, returns valid.
func IsNetworkAddressCIDRV6(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 address %q", value)
	}

	if ip.String() == subnet.IP.String() {
		return fmt.Errorf("Not a usable IPv6 address %q", value)
	}

	return nil
}

// IsNetworkAddressV6List validates a comma delimited list of IPv6 addresses.
func IsNetworkAddressV6List(value string) error {
	for _, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		err := IsNetworkAddressV6(v)
		if err != nil {
			return err
		}
	}
	return nil
}

// IsNetworkV6List validates a comma delimited list of IPv6 CIDR strings.
func IsNetworkV6List(value string) error {
	for _, network := range strings.Split(value, ",") {
		network = strings.TrimSpace(network)
		err := IsNetworkV6(network)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV4 validates an IPv4 range in the format "start-end".
func IsNetworkRangeV4(value string) error {
	ips := strings.SplitN(value, "-", 2)
	if len(ips) != 2 {
		return fmt.Errorf("IP range must contain start and end IP addresses")
	}

	for _, ip := range ips {
		err := IsNetworkAddressV4(ip)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV4List validates a comma delimited list of IPv4 ranges.
func IsNetworkRangeV4List(value string) error {
	for _, ipRange := range strings.Split(value, ",") {
		err := IsNetworkRangeV4(strings.TrimSpace(ipRange))
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV6 validates an IPv6 range in the format "start-end".
func IsNetworkRangeV6(value string) error {
	ips := strings.SplitN(value, "-", 2)
	if len(ips) != 2 {
		return fmt.Errorf("IP range must contain start and end IP addresses")
	}

	for _, ip := range ips {
		err := IsNetworkAddressV6(ip)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV6List validates a comma delimited list of IPv6 ranges.
func IsNetworkRangeV6List(value string) error {
	for _, ipRange := range strings.Split(value, ",") {
		err := IsNetworkRangeV6(strings.TrimSpace(ipRange))
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkVLAN validates a VLAN ID.
func IsNetworkVLAN(value string) error {
	vlanID, err := strconv.Atoi(value)
	if err != nil {
		return fmt.Errorf("Invalid VLAN ID %q", value)
	}

	if vlanID < 0 || vlanID > 4094 {
		return fmt.Errorf("Out of VLAN ID range (0-4094) %q", value)
	}

	return nil
}

// IsNetworkMTU validates MTU number >= 1280 and <= 16384.
// Anything below 68 and the kernel doesn't allow IPv4, anything below 1280 and the kernel doesn't allow IPv6.
// So require an IPv6-compatible MTU as the low value and cap at the max ethernet jumbo frame size.
func IsNetworkMTU(value string) error {
	mtu, err := strconv.ParseUint(value, 10, 32)
	if err != nil {
		return fmt.Errorf("Invalid MTU %q", value)
	}

	if mtu < 1280 || mtu > 16384 {
		return fmt.Errorf("Out of MTU range (1280-16384) %q", value)
	}

	return nil
}

// IsURLSegmentSafe validates whether value can be used in a URL segment.
func IsURLSegmentSafe(value string) error {
	for _, char := range []string{"/", "?", "&", "+"} {
		if strings.Contains(value, char) {
			return fmt.Errorf("Cannot contain %q", char)
		}
	}

	return nil
}
<commit_msg>shared/validate: Adds IsNetworkAddressList function<commit_after>package validate

import (
	"fmt"
	"net"
	"regexp"
	"strconv"
	"strings"

	"github.com/lxc/lxd/shared/units"
)

// stringInSlice checks whether the supplied string is present in the supplied slice.
func stringInSlice(key string, list []string) bool {
	for _, entry := range list {
		if entry == key {
			return true
		}
	}
	return false
}

// Required returns function that runs one or more validators, all must pass without error.
func Required(validators ...func(value string) error) func(value string) error {
	return func(value string) error {
		for _, validator := range validators {
			err := validator(value)
			if err != nil {
				return err
			}
		}

		return nil
	}
}

// Optional wraps Required() function to make it return nil if value is empty string.
func Optional(validators ...func(value string) error) func(value string) error {
	return func(value string) error {
		if value == "" {
			return nil
		}

		return Required(validators...)(value)
	}
}

// IsInt64 validates whether the string can be converted to an int64.
func IsInt64(value string) error {
	_, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q", value)
	}

	return nil
}

// IsUint8 validates whether the string can be converted to an uint8.
func IsUint8(value string) error {
	_, err := strconv.ParseUint(value, 10, 8)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q. Must be between 0 and 255", value)
	}

	return nil
}

// IsUint32 validates whether the string can be converted to an uint32.
func IsUint32(value string) error {
	_, err := strconv.ParseUint(value, 10, 32)
	if err != nil {
		return fmt.Errorf("Invalid value for uint32 %q: %v", value, err)
	}

	return nil
}

// IsPriority validates priority number.
func IsPriority(value string) error {
	valueInt, err := strconv.ParseInt(value, 10, 64)
	if err != nil {
		return fmt.Errorf("Invalid value for an integer %q", value)
	}

	if valueInt < 0 || valueInt > 10 {
		return fmt.Errorf("Invalid value for a limit %q. Must be between 0 and 10", value)
	}

	return nil
}

// IsBool validates if string can be understood as a bool.
func IsBool(value string) error {
	if !stringInSlice(strings.ToLower(value), []string{"true", "false", "yes", "no", "1", "0", "on", "off"}) {
		return fmt.Errorf("Invalid value for a boolean %q", value)
	}

	return nil
}

// IsOneOf checks whether the string is present in the supplied slice of strings.
func IsOneOf(value string, valid []string) error {
	if value == "" {
		return nil
	}

	if !stringInSlice(value, valid) {
		return fmt.Errorf("Invalid value %q (not one of %s)", value, valid)
	}

	return nil
}

// IsAny accepts all strings as valid.
func IsAny(value string) error {
	return nil
}

// IsNotEmpty requires a non-empty string.
func IsNotEmpty(value string) error {
	if value == "" {
		return fmt.Errorf("Required value")
	}

	return nil
}

// IsSize checks if string is valid size according to units.ParseByteSizeString.
func IsSize(value string) error {
	_, err := units.ParseByteSizeString(value)
	if err != nil {
		return err
	}

	return nil
}

// IsDeviceID validates string is four lowercase hex characters suitable as Vendor or Device ID.
func IsDeviceID(value string) error {
	regexHexLc, err := regexp.Compile("^[0-9a-f]+$")
	if err != nil {
		return err
	}

	if len(value) != 4 || !regexHexLc.MatchString(value) {
		return fmt.Errorf("Invalid value, must be four lower case hex characters")
	}

	return nil
}

// IsNetworkMAC validates an Ethernet MAC address. e.g. "00:00:5e:00:53:01".
func IsNetworkMAC(value string) error {
	_, err := net.ParseMAC(value)

	// Check is valid Ethernet MAC length and delimiter.
	if err != nil || len(value) != 17 || strings.ContainsAny(value, "-.") {
		return fmt.Errorf("Invalid MAC address, must be 6 bytes of hex separated by colons")
	}

	return nil
}

// IsNetworkAddress validates an IP (v4 or v6) address string. If string is empty, returns valid.
func IsNetworkAddress(value string) error {
	ip := net.ParseIP(value)
	if ip == nil {
		return fmt.Errorf("Not an IP address %q", value)
	}

	return nil
}

// IsNetworkAddressList validates a comma delimited list of IPv4 or IPv6 addresses.
func IsNetworkAddressList(value string) error {
	for _, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		err := IsNetworkAddress(v)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkV4 validates an IPv4 CIDR string. If string is empty, returns valid.
func IsNetworkV4(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 network %q", value)
	}

	if ip.String() != subnet.IP.String() {
		return fmt.Errorf("Not an IPv4 network address %q", value)
	}

	return nil
}

// IsNetworkAddressV4 validates an IPv4 addresss string. If string is empty, returns valid.
func IsNetworkAddressV4(value string) error {
	ip := net.ParseIP(value)
	if ip == nil || ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 address %q", value)
	}

	return nil
}

// IsNetworkAddressCIDRV4 validates an IPv4 addresss string in CIDR format. If string is empty, returns valid.
func IsNetworkAddressCIDRV4(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() == nil {
		return fmt.Errorf("Not an IPv4 address %q", value)
	}

	if ip.String() == subnet.IP.String() {
		return fmt.Errorf("Not a usable IPv4 address %q", value)
	}

	return nil
}

// IsNetworkAddressV4List validates a comma delimited list of IPv4 addresses.
func IsNetworkAddressV4List(value string) error {
	for _, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		err := IsNetworkAddressV4(v)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkV4List validates a comma delimited list of IPv4 CIDR strings.
func IsNetworkV4List(value string) error {
	for _, network := range strings.Split(value, ",") {
		network = strings.TrimSpace(network)
		err := IsNetworkV4(network)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkV6 validates an IPv6 CIDR string. If string is empty, returns valid.
func IsNetworkV6(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip == nil || ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 network %q", value)
	}

	if ip.String() != subnet.IP.String() {
		return fmt.Errorf("Not an IPv6 network address %q", value)
	}

	return nil
}

// IsNetworkAddressV6 validates an IPv6 addresss string. If string is empty, returns valid.
func IsNetworkAddressV6(value string) error {
	ip := net.ParseIP(value)
	if ip == nil || ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 address %q", value)
	}

	return nil
}

// IsNetworkAddressCIDRV6 validates an IPv6 addresss string in CIDR format. If string is empty, returns valid.
func IsNetworkAddressCIDRV6(value string) error {
	ip, subnet, err := net.ParseCIDR(value)
	if err != nil {
		return err
	}

	if ip.To4() != nil {
		return fmt.Errorf("Not an IPv6 address %q", value)
	}

	if ip.String() == subnet.IP.String() {
		return fmt.Errorf("Not a usable IPv6 address %q", value)
	}

	return nil
}

// IsNetworkAddressV6List validates a comma delimited list of IPv6 addresses.
func IsNetworkAddressV6List(value string) error {
	for _, v := range strings.Split(value, ",") {
		v = strings.TrimSpace(v)
		err := IsNetworkAddressV6(v)
		if err != nil {
			return err
		}
	}
	return nil
}

// IsNetworkV6List validates a comma delimited list of IPv6 CIDR strings.
func IsNetworkV6List(value string) error {
	for _, network := range strings.Split(value, ",") {
		network = strings.TrimSpace(network)
		err := IsNetworkV6(network)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV4 validates an IPv4 range in the format "start-end".
func IsNetworkRangeV4(value string) error {
	ips := strings.SplitN(value, "-", 2)
	if len(ips) != 2 {
		return fmt.Errorf("IP range must contain start and end IP addresses")
	}

	for _, ip := range ips {
		err := IsNetworkAddressV4(ip)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV4List validates a comma delimited list of IPv4 ranges.
func IsNetworkRangeV4List(value string) error {
	for _, ipRange := range strings.Split(value, ",") {
		err := IsNetworkRangeV4(strings.TrimSpace(ipRange))
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV6 validates an IPv6 range in the format "start-end".
func IsNetworkRangeV6(value string) error {
	ips := strings.SplitN(value, "-", 2)
	if len(ips) != 2 {
		return fmt.Errorf("IP range must contain start and end IP addresses")
	}

	for _, ip := range ips {
		err := IsNetworkAddressV6(ip)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkRangeV6List validates a comma delimited list of IPv6 ranges.
func IsNetworkRangeV6List(value string) error {
	for _, ipRange := range strings.Split(value, ",") {
		err := IsNetworkRangeV6(strings.TrimSpace(ipRange))
		if err != nil {
			return err
		}
	}

	return nil
}

// IsNetworkVLAN validates a VLAN ID.
func IsNetworkVLAN(value string) error {
	vlanID, err := strconv.Atoi(value)
	if err != nil {
		return fmt.Errorf("Invalid VLAN ID %q", value)
	}

	if vlanID < 0 || vlanID > 4094 {
		return fmt.Errorf("Out of VLAN ID range (0-4094) %q", value)
	}

	return nil
}

// IsNetworkMTU validates MTU number >= 1280 and <= 16384.
// Anything below 68 and the kernel doesn't allow IPv4, anything below 1280 and the kernel doesn't allow IPv6.
// So require an IPv6-compatible MTU as the low value and cap at the max ethernet jumbo frame size.
func IsNetworkMTU(value string) error {
	mtu, err := strconv.ParseUint(value, 10, 32)
	if err != nil {
		return fmt.Errorf("Invalid MTU %q", value)
	}

	if mtu < 1280 || mtu > 16384 {
		return fmt.Errorf("Out of MTU range (1280-16384) %q", value)
	}

	return nil
}

// IsURLSegmentSafe validates whether value can be used in a URL segment.
func IsURLSegmentSafe(value string) error {
	for _, char := range []string{"/", "?", "&", "+"} {
		if strings.Contains(value, char) {
			return fmt.Errorf("Cannot contain %q", char)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package frontend

import (
	"bytes"
	"database/sql"
	"fmt"
	"html/template"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/kvu787/goschedule/goschedule/shared"
	"github.com/kvu787/goschedule/lib"
)

var appDb *sql.DB
var switchDatabase *sql.DB
var conn string

func Serve(connString string, switchDb *sql.DB, local bool, frontendRoot string, port int) error {
	conn = connString
	switchDatabase = switchDb
	if err := os.Chdir(os.ExpandEnv(frontendRoot)); err != nil {
		return err
	}
	if local {
		http.HandleFunc("/", router)
		if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
			return err
		}
	} else {
		listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
		if err != nil {
			return err
		}
		http.HandleFunc("/", router)
		if err := fcgi.Serve(listener, nil); err != nil {
			return err
		}
	}
	return nil
}

var routing = [][]interface{}{
	{"/", indexHandler},
	{"/search", searchHandler},
	{"/schedule", deptsHandler},
	{"/schedule/:dept", classesHandler},
	{"/schedule/:dept/:class", sectsHandler},
	{"/assets/:type/:file", assetHandler},
}

type routeHandler func(http.ResponseWriter, *http.Request, map[string]string)

func router(w http.ResponseWriter, r *http.Request) {
	// determine application db
	appNum, err := shared.GetSwitch(switchDatabase)
	if err != nil {
		panic(fmt.Sprintf("Failed to query switch database for app db number in frontend.router: %v", err))
	}
	if appNum == 1 {
		appNum = 2
	} else {
		appNum = 1
	}
	appDb, err = sql.Open("postgres", fmt.Sprintf(conn, appNum))
	if err != nil {
		panic(err)
	}
	// process request
	path := r.URL.Path
	var matched bool
	for _, tuple := range routing {
		handler := tuple[1].(func(http.ResponseWriter, *http.Request, map[string]string))
		if ro := route(tuple[0].(string)); ro.match(path) {
			handler(w, r, ro.parse(path))
			matched = true
		}
	}
	if !matched {
		fmt.Fprintf(w, "No route matched for:\n%q", r.URL.Path)
	}
}

func searchHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
	search := strings.TrimSpace(r.FormValue("search"))
	depts, err := searchDepts(search)
	if err != nil {
		panic(err)
	}
	classes, err := searchClasses(search)
	if err != nil {
		panic(err)
	}

	var htmlBuffer = &bytes.Buffer{}
	viewBag := map[string]interface{}{
		"depts":   depts,
		"classes": classes,
		"query":   search,
	}
	searchTemplate, err := ioutil.ReadFile("templates/search.html")
	if err != nil {
		panic(err)
	}
	if err := template.Must(template.New("").Funcs(template.FuncMap{
		"upper":     strings.ToUpper,
		"boldWords": boldWords,
		"toHTML":    toHTML,
	}).Parse(string(searchTemplate))).Execute(htmlBuffer, viewBag); err != nil {
		panic(err)
	}
	htmlStr := htmlBuffer.String()
	htmlStr = strings.Replace(htmlStr, "\n", "", -1)

	t := template.Must(template.ParseFiles("templates/search.js"))
	// sort slice of college names
	t.ExecuteTemplate(w, "searchjs", template.HTML(htmlStr))
}

func toHTML(in string) template.HTML {
	return template.HTML(in)
}

func boldWords(search, in string) string {
	inSlice := strings.Split(strings.TrimSpace(in), " ")
	searchSlice := strings.Split(strings.TrimSpace(search), " ")
	for i := range inSlice {
		var outWord string
		var longestSearchTerm string
		for _, searchTerm := range searchSlice {
			if checkedWord := boldPrefix(inSlice[i], searchTerm); len(searchTerm) > len(longestSearchTerm) && len(checkedWord) > len(outWord) {
				longestSearchTerm = searchTerm
				outWord = checkedWord
			}
		}
		if len(outWord) > 0 {
			inSlice[i] = outWord
		}
	}
	return strings.Join(inSlice, " ")
}

func boldPrefix(word, searchTerm string) string {
	if strings.HasPrefix(strings.ToLower(word), strings.ToLower(searchTerm)) {
		word = word[:len(searchTerm)] + "" + word[len(searchTerm):]
		word = "" + word
		return word
	}
	return ""
}

func searchDepts(search string) ([]goschedule.Dept, error) {
	records, err := goschedule.Select(appDb, goschedule.Dept{},
		fmt.Sprintf("ORDER BY word_score('%s', name) + word_score('%s', abbreviation) DESC, letter_score('%s', name) + letter_score('%s', abbreviation) DESC LIMIT 5", search, search, search, search))
	if err != nil {
		return nil, err
	}
	var depts []goschedule.Dept
	for _, record := range records {
		depts = append(depts, record.(goschedule.Dept))
	}
	return depts, nil
}

func searchClasses(search string) ([]goschedule.Class, error) {
	records, err := goschedule.Select(appDb, goschedule.Class{}, fmt.Sprintf("ORDER BY word_score('%s', abbreviationcode) + word_score('%s', name) DESC, letter_score('%s', abbreviationcode) + letter_score('%s', name) DESC LIMIT 5", search, search))
	if err != nil {
		return nil, err
	}
	var classes []goschedule.Class
	for _, record := range records {
		classes = append(classes, record.(goschedule.Class))
	}
	return classes, nil
}

// CREDIT: http://stackoverflow.com/questions/11467731/is-it-possible-to-have-nested-templates-in-go-using-the-standard-library-googl
func indexHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	t := template.Must(template.ParseFiles(
		"templates/index.html",
		"templates/base.html",
	))
	t.ExecuteTemplate(w, "base", nil)
}

func deptsHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	var data = make(map[string][]goschedule.Dept)
	// get colleges
	collegeRecords, err := goschedule.Select(appDb, goschedule.College{}, "ORDER BY abbreviation")
	if err != nil {
		panic(err)
	}
	var collegeNames []string
	var collegesNamesToAbbreviations = make(map[string]string)
	for _, v := range collegeRecords {
		college := v.(goschedule.College)
		// create list of college names
		collegeNames = append(collegeNames, college.Name)
		// create map of college names to abbreviations
		collegesNamesToAbbreviations[college.Name] = college.Abbreviation
	}
	for _, collegeName := range collegeNames {
		// get depts
		deptRecords, err := goschedule.Select(appDb, goschedule.Dept{}, fmt.Sprintf("WHERE collegekey = '%s'", collegesNamesToAbbreviations[collegeName]))
		if err != nil {
			panic(err)
		}
		// create map of college names to depts
		for _, v := range deptRecords {
			data[collegeName] = append(data[collegeName], v.(goschedule.Dept))
		}
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"title": strings.Title,
		"upper": strings.ToUpper,
	}).ParseFiles(
		"templates/depts.html",
		"templates/base.html",
	))
	// sort slice of college names
	sort.Strings(collegeNames)
	viewBag := map[string]interface{}{
		"collegeNames":         collegeNames,
		"collegeAbbreviations": collegesNamesToAbbreviations,
		"collegesMap":          data,
	}
	t.ExecuteTemplate(w, "base", viewBag)
}

func classesHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	classRecords, err := goschedule.Select(appDb, goschedule.Class{}, fmt.Sprintf("WHERE deptkey = '%s' ORDER BY code", params["dept"]))
	if err != nil {
		panic(err)
	}
	var classes []goschedule.Class
	for _, v := range classRecords {
		classes = append(classes, v.(goschedule.Class))
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"title": strings.Title,
		"upper": strings.ToUpper,
	}).ParseFiles(
		"templates/classes.html",
		"templates/base.html",
	))
	viewBag := map[string]interface{}{
		"classes": classes,
		"dept":    params["dept"],
	}
	t.ExecuteTemplate(w, "base", viewBag)
}

func sectsHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	dept := strings.Split(strings.ToLower(r.URL.Path), "/")[2]
	class := strings.Split(strings.ToLower(r.URL.Path), "/")[3]
	sectRecords, err := goschedule.Select(appDb, goschedule.Sect{}, fmt.Sprintf("WHERE classkey = '%s' ORDER BY section", class))
	if err != nil {
		panic(err)
	}
	var sects []goschedule.Sect
	for _, v := range sectRecords {
		sects = append(sects, v.(goschedule.Sect))
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"upper": strings.ToUpper,
		"lower": strings.ToLower,
	}).ParseFiles(
		"templates/sects.html",
		"templates/base.html",
	))
	viewBag := make(map[string]interface{})
	viewBag["dept"] = dept
	viewBag["class"] = class
	viewBag["sects"] = sects
	t.ExecuteTemplate(w, "base", viewBag)
}

func assetHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	filePath := fmt.Sprintf("assets/%s/%s", params["type"], params["file"])
	staticFile, err := os.Open(filePath)
	if err != nil {
		fmt.Fprintf(w, "404, file not found error: %v", err.Error())
	} else {
		http.ServeContent(w, r, params["file"], time.Now(), staticFile)
	}
}
<commit_msg>bugfix: idle appdb connections causing scraper to crash<commit_after>package frontend

import (
	"bytes"
	"database/sql"
	"fmt"
	"html/template"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/kvu787/goschedule/goschedule/shared"
	"github.com/kvu787/goschedule/lib"
)

var appDb *sql.DB
var switchDatabase *sql.DB
var conn string

func Serve(connString string, switchDb *sql.DB, local bool, frontendRoot string, port int) error {
	conn = connString
	switchDatabase = switchDb
	if err := os.Chdir(os.ExpandEnv(frontendRoot)); err != nil {
		return err
	}
	if local {
		http.HandleFunc("/", router)
		if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil {
			return err
		}
	} else {
		listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
		if err != nil {
			return err
		}
		http.HandleFunc("/", router)
		if err := fcgi.Serve(listener, nil); err != nil {
			return err
		}
	}
	return nil
}

var routing = [][]interface{}{
	{"/", indexHandler},
	{"/search", searchHandler},
	{"/schedule", deptsHandler},
	{"/schedule/:dept", classesHandler},
	{"/schedule/:dept/:class", sectsHandler},
	{"/assets/:type/:file", assetHandler},
}

type routeHandler func(http.ResponseWriter, *http.Request, map[string]string)

func router(w http.ResponseWriter, r *http.Request) {
	// determine application db
	appNum, err := shared.GetSwitch(switchDatabase)
	if err != nil {
		panic(fmt.Sprintf("Failed to query switch database for app db number in frontend.router: %v", err))
	}
	if appNum == 1 {
		appNum = 2
	} else {
		appNum = 1
	}
	appDb, err = sql.Open("postgres", fmt.Sprintf(conn, appNum))
	if err != nil {
		panic(err)
	}
	defer appDb.Close()
	// process request
	path := r.URL.Path
	var matched bool
	for _, tuple := range routing {
		handler := tuple[1].(func(http.ResponseWriter, *http.Request, map[string]string))
		if ro := route(tuple[0].(string)); ro.match(path) {
			handler(w, r, ro.parse(path))
			matched = true
		}
	}
	if !matched {
		fmt.Fprintf(w, "No route matched for:\n%q", r.URL.Path)
	}
}

func searchHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	w.Header().Set("Content-Type", "text/javascript; charset=utf-8")
	search := strings.TrimSpace(r.FormValue("search"))
	depts, err := searchDepts(search)
	if err != nil {
		panic(err)
	}
	classes, err := searchClasses(search)
	if err != nil {
		panic(err)
	}

	var htmlBuffer = &bytes.Buffer{}
	viewBag := map[string]interface{}{
		"depts":   depts,
		"classes": classes,
		"query":   search,
	}
	searchTemplate, err := ioutil.ReadFile("templates/search.html")
	if err != nil {
		panic(err)
	}
	if err := template.Must(template.New("").Funcs(template.FuncMap{
		"upper":     strings.ToUpper,
		"boldWords": boldWords,
		"toHTML":    toHTML,
	}).Parse(string(searchTemplate))).Execute(htmlBuffer, viewBag); err != nil {
		panic(err)
	}
	htmlStr := htmlBuffer.String()
	htmlStr = strings.Replace(htmlStr, "\n", "", -1)

	t := template.Must(template.ParseFiles("templates/search.js"))
	// sort slice of college names
	t.ExecuteTemplate(w, "searchjs", template.HTML(htmlStr))
}

func toHTML(in string) template.HTML {
	return template.HTML(in)
}

func boldWords(search, in string) string {
	inSlice := strings.Split(strings.TrimSpace(in), " ")
	searchSlice := strings.Split(strings.TrimSpace(search), " ")
	for i := range inSlice {
		var outWord string
		var longestSearchTerm string
		for _, searchTerm := range searchSlice {
			if checkedWord := boldPrefix(inSlice[i], searchTerm); len(searchTerm) > len(longestSearchTerm) && len(checkedWord) > len(outWord) {
				longestSearchTerm = searchTerm
				outWord = checkedWord
			}
		}
		if len(outWord) > 0 {
			inSlice[i] = outWord
		}
	}
	return strings.Join(inSlice, " ")
}

func boldPrefix(word, searchTerm string) string {
	if strings.HasPrefix(strings.ToLower(word), strings.ToLower(searchTerm)) {
		word = word[:len(searchTerm)] + "" + word[len(searchTerm):]
		word = "" + word
		return word
	}
	return ""
}

func searchDepts(search string) ([]goschedule.Dept, error) {
	records, err := goschedule.Select(appDb, goschedule.Dept{},
		fmt.Sprintf("ORDER BY word_score('%s', name) + word_score('%s', abbreviation) DESC, letter_score('%s', name) + letter_score('%s', abbreviation) DESC LIMIT 5", search, search, search, search))
	if err != nil {
		return nil, err
	}
	var depts []goschedule.Dept
	for _, record := range records {
		depts = append(depts, record.(goschedule.Dept))
	}
	return depts, nil
}

func searchClasses(search string) ([]goschedule.Class, error) {
	records, err := goschedule.Select(appDb, goschedule.Class{}, fmt.Sprintf("ORDER BY word_score('%s', abbreviationcode) + word_score('%s', name) DESC, letter_score('%s', abbreviationcode) + letter_score('%s', name) DESC LIMIT 5", search, search))
	if err != nil {
		return nil, err
	}
	var classes []goschedule.Class
	for _, record := range records {
		classes = append(classes, record.(goschedule.Class))
	}
	return classes, nil
}

// CREDIT: http://stackoverflow.com/questions/11467731/is-it-possible-to-have-nested-templates-in-go-using-the-standard-library-googl
func indexHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	t := template.Must(template.ParseFiles(
		"templates/index.html",
		"templates/base.html",
	))
	t.ExecuteTemplate(w, "base", nil)
}

func deptsHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	var data = make(map[string][]goschedule.Dept)
	// get colleges
	collegeRecords, err := goschedule.Select(appDb, goschedule.College{}, "ORDER BY abbreviation")
	if err != nil {
		panic(err)
	}
	var collegeNames []string
	var collegesNamesToAbbreviations = make(map[string]string)
	for _, v := range collegeRecords {
		college := v.(goschedule.College)
		// create list of college names
		collegeNames = append(collegeNames, college.Name)
		// create map of college names to abbreviations
		collegesNamesToAbbreviations[college.Name] = college.Abbreviation
	}
	for _, collegeName := range collegeNames {
		// get depts
		deptRecords, err := goschedule.Select(appDb, goschedule.Dept{}, fmt.Sprintf("WHERE collegekey = '%s'", collegesNamesToAbbreviations[collegeName]))
		if err != nil {
			panic(err)
		}
		// create map of college names to depts
		for _, v := range deptRecords {
			data[collegeName] = append(data[collegeName], v.(goschedule.Dept))
		}
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"title": strings.Title,
		"upper": strings.ToUpper,
	}).ParseFiles(
		"templates/depts.html",
		"templates/base.html",
	))
	// sort slice of college names
	sort.Strings(collegeNames)
	viewBag := map[string]interface{}{
		"collegeNames":         collegeNames,
		"collegeAbbreviations": collegesNamesToAbbreviations,
		"collegesMap":          data,
	}
	t.ExecuteTemplate(w, "base", viewBag)
}

func classesHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	classRecords, err := goschedule.Select(appDb, goschedule.Class{}, fmt.Sprintf("WHERE deptkey = '%s' ORDER BY code", params["dept"]))
	if err != nil {
		panic(err)
	}
	var classes []goschedule.Class
	for _, v := range classRecords {
		classes = append(classes, v.(goschedule.Class))
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"title": strings.Title,
		"upper": strings.ToUpper,
	}).ParseFiles(
		"templates/classes.html",
		"templates/base.html",
	))
	viewBag := map[string]interface{}{
		"classes": classes,
		"dept":    params["dept"],
	}
	t.ExecuteTemplate(w, "base", viewBag)
}

func sectsHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	dept := strings.Split(strings.ToLower(r.URL.Path), "/")[2]
	class := strings.Split(strings.ToLower(r.URL.Path), "/")[3]
	sectRecords, err := goschedule.Select(appDb, goschedule.Sect{}, fmt.Sprintf("WHERE classkey = '%s' ORDER BY section", class))
	if err != nil {
		panic(err)
	}
	var sects []goschedule.Sect
	for _, v := range sectRecords {
		sects = append(sects, v.(goschedule.Sect))
	}
	t := template.Must(template.New("").Funcs(template.FuncMap{
		"upper": strings.ToUpper,
		"lower": strings.ToLower,
	}).ParseFiles(
		"templates/sects.html",
		"templates/base.html",
	))
	viewBag := make(map[string]interface{})
	viewBag["dept"] = dept
	viewBag["class"] = class
	viewBag["sects"] = sects
	t.ExecuteTemplate(w, "base", viewBag)
}

func assetHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
	filePath := fmt.Sprintf("assets/%s/%s", params["type"], params["file"])
	staticFile, err := os.Open(filePath)
	if err != nil {
		fmt.Fprintf(w, "404, file not found error: %v", err.Error())
	} else {
		http.ServeContent(w, r, params["file"], time.Now(), staticFile)
	}
}
<|endoftext|>


<commit_before>package version

import (
	"fmt"
	"runtime"
	"strings"

	"github.com/lxc/lxd/shared/osarch"
)

// UserAgent contains a string suitable as a user-agent
var UserAgent = getUserAgent(nil)

func getUserAgent(storageTokens []string) string {
	archID, err := osarch.ArchitectureId(runtime.GOARCH)
	if err != nil {
		panic(err)
	}

	arch, err := osarch.ArchitectureName(archID)
	if err != nil {
		panic(err)
	}

	osTokens := []string{strings.Title(runtime.GOOS), arch}
	osTokens = append(osTokens, getPlatformVersionStrings()...)

	agent := fmt.Sprintf("LXD %s", Version)
	if len(osTokens) > 0 {
		agent = fmt.Sprintf("%s (%s)", agent, strings.Join(osTokens, "; "))
	}

	if len(storageTokens) > 0 {
		agent = fmt.Sprintf("%s (%s)", agent, strings.Join(storageTokens, "; "))
	}

	return agent
}

// UserAgentStorageBackends updates the list of storage backends to include in the user-agent
func UserAgentStorageBackends(backends []string) {
	UserAgent = getUserAgent(backends)
}
<commit_msg>shared/version: Export features in agent<commit_after>package version

import (
	"fmt"
	"runtime"
	"strings"

	"github.com/lxc/lxd/shared/osarch"
)

// UserAgent contains a string suitable as a user-agent
var UserAgent = getUserAgent()
var userAgentStorageBackends []string
var userAgentFeatures []string

func getUserAgent() string {
	archID, err := osarch.ArchitectureId(runtime.GOARCH)
	if err != nil {
		panic(err)
	}

	arch, err := osarch.ArchitectureName(archID)
	if err != nil {
		panic(err)
	}

	osTokens := []string{strings.Title(runtime.GOOS), arch}
	osTokens = append(osTokens, getPlatformVersionStrings()...)

	// Initial version string
	agent := fmt.Sprintf("LXD %s", Version)

	// OS information
	agent = fmt.Sprintf("%s (%s)", agent, strings.Join(osTokens, "; "))

	// Storage information
	if len(userAgentStorageBackends) > 0 {
		agent = fmt.Sprintf("%s (%s)", agent, strings.Join(userAgentStorageBackends, "; "))
	}

	// Feature information
	if len(userAgentFeatures) > 0 {
		agent = fmt.Sprintf("%s (%s)", agent, strings.Join(userAgentFeatures, "; "))
	}

	return agent
}

// UserAgentStorageBackends updates the list of storage backends to include in the user-agent
func UserAgentStorageBackends(backends []string) {
	userAgentStorageBackends = backends
	UserAgent = getUserAgent()
}

// UserAgentFeatures updates the list of advertised features
func UserAgentFeatures(features []string) {
	userAgentFeatures = features
	UserAgent = getUserAgent()
}
<|endoftext|>


<commit_before>package kvnetfilter

import (
	"log"
	"os/exec"
	"strings"
	"syscall"
)

const (
	ip6tablesPath = "/usr/sbin/ip6tables"
	ipsetPath     = "/usr/sbin/ipset"
)

func checkTestError(err error) (bool, error) {
	switch {
	case err == nil:
		return true, nil
	case err.(*exec.ExitError).Sys().(syscall.WaitStatus).ExitStatus() == 1:
		return false, nil
	default:
		return false, err
	}
}

func iptablesRun(ipcmd string) error {
	args := strings.Fields(ipcmd)
	if firewalldRunning && !strings.HasPrefix(ipcmd, "-t") {
		Passthrough(args)
	} else {
		cmd := exec.Cmd{Path: ip6tablesPath, Args: append([]string{ip6tablesPath}, args...)}
		if err := cmd.Run(); err != nil {
			return err.(*exec.ExitError)
		}
	}
	return nil
}

func ipsetRun(ipcmd string) error {
	args := strings.Fields(ipcmd)
	cmd := exec.Cmd{Path: ipsetPath, Args: append([]string{ipsetPath}, args...)}
	if err := cmd.Run(); err != nil {
		return err.(*exec.ExitError)
	}
	return nil
}

func ipsetSrcDst(command string, set string, srcip string, dstip string, proto string, port string, timeout string) error {
	cmd := "-! " + command + " " + set + " " + srcip + "," + proto + ":" + port + "," + dstip
	if timeout != "" {
		cmd = cmd + " timeout " + timeout
	}

	log.Println("ipsetHost()", cmd)
	err := ipsetRun(cmd)
	if err != nil {
		return err
	}
	return nil
}

func iptablesInit(chain string, set string) error {
	exists, err := checkTestError(iptablesRun("-t filter -C " + chain + " -o docker0 -m set --match-set " + set + " dst,dst -j ACCEPT --wait"))
	if err != nil {
		return err
	}
	if !exists {
		iptablesRun("-A " + chain + " -o docker0 -m set --match-set " + set + " dst,dst -j ACCEPT --wait")
	}
	exists, err = checkTestError(iptablesRun("-t filter -C " + chain + " -o docker0 -j DROP --wait"))
	if err != nil {
		return err
	}
	if !exists {
		iptablesRun("-A " + chain + " -o docker0 -j DROP --wait")
	}

	return nil
}

func ipsetInit(set string) error {
	err := ipsetInitAndFlushWithHash(set, "ip,port,net")
	return err
}

func ipsetInitWithHash(set string, hash string) error {
	err := ipsetRun("-! create " + set + " hash:" + hash + " family inet6 counters timeout 0")
	if err != nil {
		log.Println("ipsetHost() could not create ipset: ", set)
		log.Println("Error: ", err)
		return err
	}
	return nil
}

func ipsetInitAndFlushWithHash(set string, hash string) error {
	err := ipsetInitWithHash(set, hash)
	if err != nil {
		return err
	}
	err = ipsetRun("-! flush " + set)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Fix set order<commit_after>package kvnetfilter

import (
	"log"
	"os/exec"
	"strings"
	"syscall"
)

const (
	ip6tablesPath = "/usr/sbin/ip6tables"
	ipsetPath     = "/usr/sbin/ipset"
)

func checkTestError(err error) (bool, error) {
	switch {
	case err == nil:
		return true, nil
	case err.(*exec.ExitError).Sys().(syscall.WaitStatus).ExitStatus() == 1:
		return false, nil
	default:
		return false, err
	}
}

func iptablesRun(ipcmd string) error {
	args := strings.Fields(ipcmd)
	if firewalldRunning && !strings.HasPrefix(ipcmd, "-t") {
		Passthrough(args)
	} else {
		cmd := exec.Cmd{Path: ip6tablesPath, Args: append([]string{ip6tablesPath}, args...)}
		if err := cmd.Run(); err != nil {
			return err.(*exec.ExitError)
		}
	}
	return nil
}

func ipsetRun(ipcmd string) error {
	args := strings.Fields(ipcmd)
	cmd := exec.Cmd{Path: ipsetPath, Args: append([]string{ipsetPath}, args...)}
	if err := cmd.Run(); err != nil {
		return err.(*exec.ExitError)
	}
	return nil
}

func ipsetSrcDst(command string, set string, srcip string, dstip string, proto string, port string, timeout string) error {
	cmd := "-! " + command + " " + set + " " + dstip + "," + proto + ":" + port + "," + srcip
	if timeout != "" {
		cmd = cmd + " timeout " + timeout
	}

	log.Println("ipsetHost()", cmd)
	err := ipsetRun(cmd)
	if err != nil {
		return err
	}
	return nil
}

func iptablesInit(chain string, set string) error {
	exists, err := checkTestError(iptablesRun("-t filter -C " + chain + " -o docker0 -m set --match-set " + set + " dst,dst,src -j ACCEPT --wait"))
	if err != nil {
		return err
	}
	if !exists {
		iptablesRun("-A " + chain + " -o docker0 -m set --match-set " + set + " dst,dst,src -j ACCEPT --wait")
	}
	exists, err = checkTestError(iptablesRun("-t filter -C " + chain + " -o docker0 -j DROP --wait"))
	if err != nil {
		return err
	}
	if !exists {
		iptablesRun("-A " + chain + " -o docker0 -j DROP --wait")
	}

	return nil
}

func ipsetInit(set string) error {
	err := ipsetInitAndFlushWithHash(set, "ip,port,net")
	return err
}

func ipsetInitWithHash(set string, hash string) error {
	err := ipsetRun("-! create " + set + " hash:" + hash + " family inet6 counters timeout 0")
	if err != nil {
		log.Println("ipsetHost() could not create ipset: ", set)
		log.Println("Error: ", err)
		return err
	}
	return nil
}

func ipsetInitAndFlushWithHash(set string, hash string) error {
	err := ipsetInitWithHash(set, hash)
	if err != nil {
		return err
	}
	err = ipsetRun("-! flush " + set)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/arschles/gbs/log"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/gorilla/mux"
)

const (
	defaultBuildImg = "quay.io/arschles/gbs-env:0.0.1"
)

func BuildURL() string {
	return fmt.Sprintf("/{%s}/{%s}/{%s}", site, org, repo)
}

type startBuildReq struct {
	BuildEnv string `json:"build_env"`
}

type startBuildResp struct {
	StatusURL string `json:"status_url"`
}

func Build(workdir string, dockerCl *docker.Client) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		flusher, ok := w.(http.Flusher)
		if !ok {
			httpErrf(w, http.StatusInternalServerError, "server doesn't support flushing output")
			return
		}

		site, ok := mux.Vars(r)[site]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing site in path")
			return
		}

		org, ok := mux.Vars(r)[org]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing org in path")
			return
		}

		repo, ok := mux.Vars(r)[repo]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing repo in path")
			return
		}

		buildImg := defaultBuildImg
		req := new(startBuildReq)
		if err := json.NewDecoder(r.Body).Decode(req); err == nil {
			buildImg = req.BuildEnv
		}
		defer r.Body.Close()

		containerOpts := createContainerOpts(buildImg, workdir, site, org, repo)
		container, err := dockerCl.CreateContainer(containerOpts)
		if err != nil {
			log.Errf("creating container [%s]", err)
			httpErrf(w, http.StatusInternalServerError, "error creating container [%s]", err)
			return
		}

		hostConfig := &docker.HostConfig{Binds: []string{fmt.Sprintf("%s:%s", workdir, absPwd)}}
		if err := dockerCl.StartContainer(container.ID, hostConfig); err != nil {
			log.Errf("starting container [%s]", err)
			httpErrf(w, http.StatusInternalServerError, "error starting container [%s]", err)
			return
		}

		attachOpts, outputReader := attachToContainerOpts(container.ID)
		errCh := make(chan error)
		go func() {
			if err := dockerCl.AttachToContainer(attachOpts); err != nil {
				errCh <- err
			}
		}()

		go func(reader io.Reader) {
			scanner := bufio.NewScanner(reader)
			for scanner.Scan() {
				fmt.Fprintf(w, "%s\n", scanner.Text())
				flusher.Flush()
			}
			if err := scanner.Err(); err != nil {
				fmt.Fprintf(w, "error with scanner in attached container [%s]\n", err)
			}
		}(outputReader)

		code, err := dockerCl.WaitContainer(container.ID)
		if err != nil {
			log.Errf("waiting for container %s [%s]", container.ID, err)
			return
		}
		w.Write([]byte(fmt.Sprintf("exited with error code %d\n", code)))
	})
}
<commit_msg>removing container<commit_after>package handlers

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/arschles/gbs/log"
	docker "github.com/fsouza/go-dockerclient"
	"github.com/gorilla/mux"
)

const (
	defaultBuildImg = "quay.io/arschles/gbs-env:0.0.1"
)

func BuildURL() string {
	return fmt.Sprintf("/{%s}/{%s}/{%s}", site, org, repo)
}

type startBuildReq struct {
	BuildEnv string `json:"build_env"`
}

type startBuildResp struct {
	StatusURL string `json:"status_url"`
}

func Build(workdir string, dockerCl *docker.Client) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		flusher, ok := w.(http.Flusher)
		if !ok {
			httpErrf(w, http.StatusInternalServerError, "server doesn't support flushing output")
			return
		}

		site, ok := mux.Vars(r)[site]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing site in path")
			return
		}

		org, ok := mux.Vars(r)[org]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing org in path")
			return
		}

		repo, ok := mux.Vars(r)[repo]
		if !ok {
			httpErrf(w, http.StatusBadRequest, "missing repo in path")
			return
		}

		buildImg := defaultBuildImg
		req := new(startBuildReq)
		if err := json.NewDecoder(r.Body).Decode(req); err == nil {
			buildImg = req.BuildEnv
		}
		defer r.Body.Close()

		containerOpts := createContainerOpts(buildImg, workdir, site, org, repo)
		container, err := dockerCl.CreateContainer(containerOpts)
		if err != nil {
			log.Errf("creating container [%s]", err)
			httpErrf(w, http.StatusInternalServerError, "error creating container [%s]", err)
			return
		}

		hostConfig := &docker.HostConfig{Binds: []string{fmt.Sprintf("%s:%s", workdir, absPwd)}}
		if err := dockerCl.StartContainer(container.ID, hostConfig); err != nil {
			log.Errf("starting container [%s]", err)
			httpErrf(w, http.StatusInternalServerError, "error starting container [%s]", err)
			return
		}

		attachOpts, outputReader := attachToContainerOpts(container.ID)
		errCh := make(chan error)
		go func() {
			if err := dockerCl.AttachToContainer(attachOpts); err != nil {
				errCh <- err
			}
		}()

		go func(reader io.Reader) {
			scanner := bufio.NewScanner(reader)
			for scanner.Scan() {
				fmt.Fprintf(w, "%s\n", scanner.Text())
				flusher.Flush()
			}
			if err := scanner.Err(); err != nil {
				fmt.Fprintf(w, "error with scanner in attached container [%s]\n", err)
			}
		}(outputReader)

		code, err := dockerCl.WaitContainer(container.ID)
		if err != nil {
			log.Errf("waiting for container %s [%s]", container.ID, err)
			return
		}
		w.Write([]byte(fmt.Sprintf("exited with error code %d\n", code)))

		removeOpts := docker.RemoveContainerOptions{
			ID:            container.ID,
			RemoveVolumes: true,
			Force:         true,
		}
		if err := dockerCl.RemoveContainer(removeOpts); err != nil {
			log.Errf("removing container %s [%s]", container.ID, err)
		}
	})
}
<|endoftext|>


<commit_before>package handlers

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

type counter interface {
	Count(packagePath string) (int, error)
}

type Lines struct {
	Counter counter
}

func (h *Lines) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	pkgPath := strings.TrimPrefix(req.URL.Path, "/lines/")
	lines, _ := h.Counter.Count(pkgPath)
	resp.Write([]byte(fmt.Sprintf(`{"lines": %d}`, lines)))
}
<commit_msg>passing unit test of lines handler errors<commit_after>package handlers

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

type counter interface {
	Count(packagePath string) (int, error)
}

type Lines struct {
	Counter counter
}

func (h *Lines) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	pkgPath := strings.TrimPrefix(req.URL.Path, "/lines/")
	lines, err := h.Counter.Count(pkgPath)
	if err != nil {
		resp.WriteHeader(500)
		resp.Write([]byte(fmt.Sprintf(`{"error": %q}`, err)))
		return
	}
	resp.Write([]byte(fmt.Sprintf(`{"lines": %d}`, lines)))
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

package hawk

import (
	"bytes"
	"encoding/hex"
	"net/http"
	"strings"
	"testing"
)

func Test_parseParameters(t *testing.T) {
	parameters, err := parseParameters(`id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="`)
	if err != nil {
		t.Error("Cannot parse Hawk parameters", err)
	}

	if parameters.Id != "dh37fgj492je" {
		t.Error("id mismatch")
	}

	if parameters.Timestamp != 1353832234 {
		t.Error("ts mismatch")
	}

	if parameters.Nonce != "j4h3g2" {
		t.Error("nonce mismatch")
	}

	if parameters.Ext != "some-app-ext-data" {
		t.Error("ext mismatch")
	}

	expectedHash, _ := hex.DecodeString("622f4b7c820546d0443edef83d599b4c5ff1540c0f9fbb9bd7978f2027e09ee6")
	if !bytes.Equal(parameters.Hash, expectedHash) {
		t.Error("mac mismatch")
	}

	expectedMac, _ := hex.DecodeString("6927b50c446666e465de9237ebff417599a712b4f0dec37338e01495f78a8d5c")
	if !bytes.Equal(parameters.Mac, expectedMac) {
		t.Error("mac mismatch")
	}
}

func Test_validateParameters(t *testing.T) {
}

func Test_getRequestHost(t *testing.T) {
	test := func(url string, expectedHost string, headers map[string]string) {
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			t.Error(err)
		}
		host := getRequestHost(request)
		if host != expectedHost {
			t.Errorf("Expected host %s for %s but got %s", expectedHost, url, host)
		}
	}
	test("http://localhost/foo", "localhost", nil)
	test("https://127.0.0.1/foo", "127.0.0.1", nil)
	test("http://localhost:8080/foo", "localhost", nil)
	test("https://127.0.0.1:8443/foo", "127.0.0.1", nil)
	// TODO: Add tests here that mimic a typical front proxy (X-Forwarded-Proto?)
	test("http://localhost/foo", "localhost", map[string]string{})
	test("https://127.0.0.1/foo", "127.0.0.1", map[string]string{})
	test("http://localhost:8080/foo", "localhost", map[string]string{})
	test("https://127.0.0.1:8443/foo", "127.0.0.1", map[string]string{})
}

func Test_getRequestPort(t *testing.T) {
	test := func(url string, expectedPort int) {
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			t.Error(err)
		}
		port := getRequestPort(request)
		if port != expectedPort {
			t.Errorf("Expected port %d for %s but got %d", expectedPort, url, port)
		}
	}
	test("http://localhost/foo", 80)
	test("https://localhost/foo", 443)
	test("http://localhost:8080/foo", 8080)
	test("https://localhost:8443/foo", 8443)
}

func Test_calculatePayloadHash(t *testing.T) {
	r, err := http.NewRequest("POST", "http://localhost", strings.NewReader("Thank you for flying Hawk"))
	if err != nil {
		t.Error(err)
	}
	r.Header.Add("Content-Type", "text/plain")
	hash, err := calculatePayloadHash(r)
	if err != nil {
		t.Error(err)
	}
	expectedHash, _ := hex.DecodeString("622f4b7c820546d0443edef83d599b4c5ff1540c0f9fbb9bd7978f2027e09ee6")
	if !bytes.Equal(hash, expectedHash) {
		t.Error("Hash mismatch")
	}
}
<commit_msg>Test for hawk.calculateRequestSignature<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

package hawk

import (
	"bytes"
	"encoding/base64"
	"encoding/hex"
	"net/http"
	"strings"
	"testing"
)

func Test_parseParameters(t *testing.T) {
	parameters, err := parseParameters(`id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="`)
	if err != nil {
		t.Error("Cannot parse Hawk parameters", err)
	}

	if parameters.Id != "dh37fgj492je" {
		t.Error("id mismatch")
	}

	if parameters.Timestamp != 1353832234 {
		t.Error("ts mismatch")
	}

	if parameters.Nonce != "j4h3g2" {
		t.Error("nonce mismatch")
	}

	if parameters.Ext != "some-app-ext-data" {
		t.Error("ext mismatch")
	}

	expectedHash, _ := hex.DecodeString("622f4b7c820546d0443edef83d599b4c5ff1540c0f9fbb9bd7978f2027e09ee6")
	if !bytes.Equal(parameters.Hash, expectedHash) {
		t.Error("mac mismatch")
	}

	expectedMac, _ := hex.DecodeString("6927b50c446666e465de9237ebff417599a712b4f0dec37338e01495f78a8d5c")
	if !bytes.Equal(parameters.Mac, expectedMac) {
		t.Error("mac mismatch")
	}
}

func Test_validateParameters(t *testing.T) {
}

func Test_getRequestHost(t *testing.T) {
	test := func(url string, expectedHost string, headers map[string]string) {
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			t.Error(err)
		}
		host := getRequestHost(request)
		if host != expectedHost {
			t.Errorf("Expected host %s for %s but got %s", expectedHost, url, host)
		}
	}
	test("http://localhost/foo", "localhost", nil)
	test("https://127.0.0.1/foo", "127.0.0.1", nil)
	test("http://localhost:8080/foo", "localhost", nil)
	test("https://127.0.0.1:8443/foo", "127.0.0.1", nil)
	// TODO: Add tests here that mimic a typical front proxy (X-Forwarded-Proto?)
	test("http://localhost/foo", "localhost", map[string]string{})
	test("https://127.0.0.1/foo", "127.0.0.1", map[string]string{})
	test("http://localhost:8080/foo", "localhost", map[string]string{})
	test("https://127.0.0.1:8443/foo", "127.0.0.1", map[string]string{})
}

func Test_getRequestPort(t *testing.T) {
	test := func(url string, expectedPort int) {
		request, err := http.NewRequest("GET", url, nil)
		if err != nil {
			t.Error(err)
		}
		port := getRequestPort(request)
		if port != expectedPort {
			t.Errorf("Expected port %d for %s but got %d", expectedPort, url, port)
		}
	}
	test("http://localhost/foo", 80)
	test("https://localhost/foo", 443)
	test("http://localhost:8080/foo", 8080)
	test("https://localhost:8443/foo", 8443)
}

func Test_calculatePayloadHash(t *testing.T) {
	r, err := http.NewRequest("POST", "http://localhost", strings.NewReader("Thank you for flying Hawk"))
	if err != nil {
		t.Error(err)
	}
	r.Header.Add("Content-Type", "text/plain")
	hash, err := calculatePayloadHash(r)
	if err != nil {
		t.Error(err)
	}
	expectedHash, _ := base64.StdEncoding.DecodeString("Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=")
	if !bytes.Equal(hash, expectedHash) {
		t.Error("Hash mismatch")
	}
}

func Test_calculateRequestSignature(t *testing.T) {
	r, err := http.NewRequest("GET", "http://example.com:8000/resource/1?b=1&a=2", nil)
	if err != nil {
		t.Error(err)
	}

	parameters := Parameters{
		Timestamp: 1353832234,
		Ext:       "some-app-ext-data",
		Nonce:     "j4h3g2",
		Hash:      nil,
		// TODO: Rest is not important for this test
	}

	credentials := Credentials{
		KeyIdentifier: "dh37fgj492je",
		Key:           []byte("werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn"),
		Algorithm:     "sha256",
	}

	mac, err := calculateRequestSignature(r, parameters, credentials)
	if err != nil {
		t.Error(err)
	}

	expectedMac, _ := base64.StdEncoding.DecodeString("6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=")
	if !bytes.Equal(mac, expectedMac) {
		t.Error("Mac mismatch")
	}
}
<|endoftext|>


<commit_before>package getter

import (
	"testing"
)

func TestGitDetector(t *testing.T) {
	cases := []struct {
		Input  string
		Output string
	}{
		{"git@github.com:hashicorp/foo.git", "git::ssh://git@github.com/hashicorp/foo.git"},
		{
			"git@github.com:hashicorp/foo.git//bar",
			"git::ssh://git@github.com/hashicorp/foo.git//bar",
		},
		{
			"git@github.com:hashicorp/foo.git?foo=bar",
			"git::ssh://git@github.com/hashicorp/foo.git?foo=bar",
		},
	}

	pwd := "/pwd"
	f := new(GitDetector)
	for i, tc := range cases {
		output, ok, err := f.Detect(tc.Input, pwd)
		if err != nil {
			t.Fatalf("err: %s", err)
		}
		if !ok {
			t.Fatal("not ok")
		}

		if output != tc.Output {
			t.Fatalf("%d: bad: %#v", i, output)
		}
	}
}
<commit_msg>Add tests (now passing) from #38<commit_after>package getter

import (
	"testing"
)

func TestGitDetector(t *testing.T) {
	cases := []struct {
		Input  string
		Output string
	}{
		{"git@github.com:hashicorp/foo.git", "git::ssh://git@github.com/hashicorp/foo.git"},
		{
			"git@github.com:org/project.git?ref=test-branch",
			"git::ssh://git@github.com/org/project.git?ref=test-branch",
		},
		{
			"git@github.com:hashicorp/foo.git//bar",
			"git::ssh://git@github.com/hashicorp/foo.git//bar",
		},
		{
			"git@github.com:hashicorp/foo.git?foo=bar",
			"git::ssh://git@github.com/hashicorp/foo.git?foo=bar",
		},
		{
			"git@github.xyz.com:org/project.git",
			"git::ssh://git@github.xyz.com/org/project.git",
		},
		{
			"git@github.xyz.com:org/project.git?ref=test-branch",
			"git::ssh://git@github.xyz.com/org/project.git?ref=test-branch",
		},
		{
			"git@github.xyz.com:org/project.git//module/a",
			"git::ssh://git@github.xyz.com/org/project.git//module/a",
		},
		{
			"git@github.xyz.com:org/project.git//module/a?ref=test-branch",
			"git::ssh://git@github.xyz.com/org/project.git//module/a?ref=test-branch",
		},
	}

	pwd := "/pwd"
	f := new(GitDetector)
	for i, tc := range cases {
		output, ok, err := f.Detect(tc.Input, pwd)
		if err != nil {
			t.Fatalf("err: %s", err)
		}
		if !ok {
			t.Fatal("not ok")
		}

		if output != tc.Output {
			t.Fatalf("%d: bad: %#v", i, output)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru 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 main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru"
	"launchpad.net/gnuflag"
	"os"
)

const (
	version = "0.5.2"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	return m
}

func main() {
	gnuflag.Parse(true)
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	args := gnuflag.Args()
	manager.Run(args)
}
<commit_msg>cmd/tsuru/developer: version 0.6<commit_after>// Copyright 2013 tsuru 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 main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru"
	"launchpad.net/gnuflag"
	"os"
)

const (
	version = "0.6"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	return m
}

func main() {
	gnuflag.Parse(true)
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	args := gnuflag.Args()
	manager.Run(args)
}
<|endoftext|>


<commit_before><commit_msg>Bubble up PostTask error without wrapping and losing type info.<commit_after><|endoftext|>


<commit_before><commit_msg>Create tests for engine.DotsMask<commit_after><|endoftext|>


<commit_before>// Copyright ©2015 The Gonum 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 gonum

import "gonum.org/v1/gonum/blas"

// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify
// a triangular portion with blas.Upper or blas.Lower, or can specify all of the
// elemest with blas.All.
//
// Dlacpy is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) {
	switch {
	case uplo != blas.Upper && uplo != blas.Lower && uplo != blas.All:
		panic(badUplo)
	case m < 0:
		panic(mLT0)
	case n < 0:
		panic(nLT0)
	case lda < max(1, n):
		panic(badLdA)
	case ldb < max(1, n):
		panic(badLdB)
	}

	if m == 0 || n == 0 {
		return
	}

	switch {
	case len(a) < (m-1)*lda+n:
		panic(shortA)
	case len(b) < (m-1)*ldb+n:
		panic(shortB)
	}

	switch uplo {
	case blas.Upper:
		for i := 0; i < m; i++ {
			for j := i; j < n; j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	case blas.Lower:
		for i := 0; i < m; i++ {
			for j := 0; j < min(i+1, n); j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	case blas.All:
		for i := 0; i < m; i++ {
			for j := 0; j < n; j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	}
}
<commit_msg>lapack/gonum: fix typo in comment for Dlacpy<commit_after>// Copyright ©2015 The Gonum 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 gonum

import "gonum.org/v1/gonum/blas"

// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify
// a triangular portion with blas.Upper or blas.Lower, or can specify all of the
// elements with blas.All.
//
// Dlacpy is an internal routine. It is exported for testing purposes.
func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) {
	switch {
	case uplo != blas.Upper && uplo != blas.Lower && uplo != blas.All:
		panic(badUplo)
	case m < 0:
		panic(mLT0)
	case n < 0:
		panic(nLT0)
	case lda < max(1, n):
		panic(badLdA)
	case ldb < max(1, n):
		panic(badLdB)
	}

	if m == 0 || n == 0 {
		return
	}

	switch {
	case len(a) < (m-1)*lda+n:
		panic(shortA)
	case len(b) < (m-1)*ldb+n:
		panic(shortB)
	}

	switch uplo {
	case blas.Upper:
		for i := 0; i < m; i++ {
			for j := i; j < n; j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	case blas.Lower:
		for i := 0; i < m; i++ {
			for j := 0; j < min(i+1, n); j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	case blas.All:
		for i := 0; i < m; i++ {
			for j := 0; j < n; j++ {
				b[i*ldb+j] = a[i*lda+j]
			}
		}
	}
}
<|endoftext|>


<commit_before>package helpers

import (
	"encoding/json"
	"os"
	"path/filepath"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/runner"
)

type Config struct {
	ApiEndpoint  string `json:"api"`
	SystemDomain string `json:"system_domain"`
	ClientSecret string `json:"client_secret"`
	AppsDomain   string `json:"apps_domain"`
	UseHttp      bool   `json:"use_http"`

	AdminUser     string `json:"admin_user"`
	AdminPassword string `json:"admin_password"`

	UseExistingUser      bool   `json:"use_existing_user"`
	ShouldKeepUser       bool   `json:"keep_user_at_suite_end"`
	ExistingUser         string `json:"existing_user"`
	ExistingUserPassword string `json:"existing_user_password"`

	ConfigurableTestPassword string `json:"test_password"`

	PersistentAppHost      string `json:"persistent_app_host"`
	PersistentAppSpace     string `json:"persistent_app_space"`
	PersistentAppOrg       string `json:"persistent_app_org"`
	PersistentAppQuotaName string `json:"persistent_app_quota_name"`

	SkipSSLValidation     bool   `json:"skip_ssl_validation"`
	SkipSSHHostValidation bool   `json:"skip_ssh_host_validation"`
	Backend               string `json:"backend"`
	IncludeRouteServices  bool   `json:"include_route_services"`
	IncludeDiegoDocker    bool   `json:"include_diego_docker"`
	IncludeTasks          bool   `json:"include_tasks"`

	ArtifactsDirectory string `json:"artifacts_directory"`

	DefaultTimeout     time.Duration `json:"default_timeout"`
	DetectTimeout      time.Duration `json:"detect_timeout"`
	CfPushTimeout      time.Duration `json:"cf_push_timeout"`
	LongCurlTimeout    time.Duration `json:"long_curl_timeout"`
	BrokerStartTimeout time.Duration `json:"broker_start_timeout"`

	TimeoutScale float64 `json:"timeout_scale"`

	SyslogDrainPort int    `json:"syslog_drain_port"`
	SyslogIpAddress string `json:"syslog_ip_address"`

	SecureAddress string `json:"secure_address"`

	DockerExecutable      string   `json:"docker_executable"`
	DockerParameters      []string `json:"docker_parameters"`
	DockerRegistryAddress string   `json:"docker_registry_address"`
	DockerPrivateImage    string   `json:"docker_private_image"`
	DockerUser            string   `json:"docker_user"`
	DockerPassword        string   `json:"docker_password"`
	DockerEmail           string   `json:"docker_email"`

	StaticFileBuildpackName string `json:"staticfile_buildpack_name"`
	JavaBuildpackName       string `json:"java_buildpack_name"`
	RubyBuildpackName       string `json:"ruby_buildpack_name"`
	NodejsBuildpackName     string `json:"nodejs_buildpack_name"`
	GoBuildpackName         string `json:"go_buildpack_name"`
	PythonBuildpackName     string `json:"python_buildpack_name"`
	PhpBuildpackName        string `json:"php_buildpack_name"`
	BinaryBuildpackName     string `json:"binary_buildpack_name"`
}

func (c Config) ScaledTimeout(timeout time.Duration) time.Duration {
	return time.Duration(float64(timeout) * c.TimeoutScale)
}

var loadedConfig *Config

func LoadConfig() Config {
	if loadedConfig == nil {
		loadedConfig = loadConfigJsonFromPath()
	}

	if loadedConfig.ApiEndpoint == "" {
		panic("missing configuration 'api'")
	}

	if loadedConfig.AdminUser == "" {
		panic("missing configuration 'admin_user'")
	}

	if loadedConfig.AdminPassword == "" {
		panic("missing configuration 'admin_password'")
	}

	if loadedConfig.TimeoutScale <= 0 {
		loadedConfig.TimeoutScale = 1.0
	}

	runner.SkipSSLValidation = loadedConfig.SkipSSLValidation

	return *loadedConfig
}

func (c Config) Protocol() string {
	if c.UseHttp {
		return "http://"
	} else {
		return "https://"
	}
}

func loadConfigJsonFromPath() *Config {
	var config *Config = &Config{
		PersistentAppHost:      "CATS-persistent-app",
		PersistentAppSpace:     "CATS-persistent-space",
		PersistentAppOrg:       "CATS-persistent-org",
		PersistentAppQuotaName: "CATS-persistent-quota",

		StaticFileBuildpackName: "staticfile_buildpack",
		JavaBuildpackName:       "java_buildpack",
		RubyBuildpackName:       "ruby_buildpack",
		NodejsBuildpackName:     "nodejs_buildpack",
		GoBuildpackName:         "go_buildpack",
		PythonBuildpackName:     "python_buildpack",
		PhpBuildpackName:        "php_buildpack",
		BinaryBuildpackName:     "binary_buildpack",

		ArtifactsDirectory: filepath.Join("..", "results"),
	}

	path := configPath()

	configFile, err := os.Open(path)
	if err != nil {
		panic(err)
	}

	decoder := json.NewDecoder(configFile)
	err = decoder.Decode(config)
	if err != nil {
		panic(err)
	}

	return config
}

func configPath() string {
	path := os.Getenv("CONFIG")
	if path == "" {
		panic("Must set $CONFIG to point to an integration config .json file.")
	}

	return path
}
<commit_msg>Revert "Add skip_ssh_host_validation option"<commit_after>package helpers

import (
	"encoding/json"
	"os"
	"path/filepath"
	"time"

	"github.com/cloudfoundry-incubator/cf-test-helpers/runner"
)

type Config struct {
	ApiEndpoint  string `json:"api"`
	SystemDomain string `json:"system_domain"`
	ClientSecret string `json:"client_secret"`
	AppsDomain   string `json:"apps_domain"`
	UseHttp      bool   `json:"use_http"`

	AdminUser     string `json:"admin_user"`
	AdminPassword string `json:"admin_password"`

	UseExistingUser      bool   `json:"use_existing_user"`
	ShouldKeepUser       bool   `json:"keep_user_at_suite_end"`
	ExistingUser         string `json:"existing_user"`
	ExistingUserPassword string `json:"existing_user_password"`

	ConfigurableTestPassword string `json:"test_password"`

	PersistentAppHost      string `json:"persistent_app_host"`
	PersistentAppSpace     string `json:"persistent_app_space"`
	PersistentAppOrg       string `json:"persistent_app_org"`
	PersistentAppQuotaName string `json:"persistent_app_quota_name"`

	SkipSSLValidation    bool   `json:"skip_ssl_validation"`
	Backend              string `json:"backend"`
	IncludeRouteServices bool   `json:"include_route_services"`
	IncludeDiegoDocker   bool   `json:"include_diego_docker"`
	IncludeTasks         bool   `json:"include_tasks"`

	ArtifactsDirectory string `json:"artifacts_directory"`

	DefaultTimeout     time.Duration `json:"default_timeout"`
	DetectTimeout      time.Duration `json:"detect_timeout"`
	CfPushTimeout      time.Duration `json:"cf_push_timeout"`
	LongCurlTimeout    time.Duration `json:"long_curl_timeout"`
	BrokerStartTimeout time.Duration `json:"broker_start_timeout"`

	TimeoutScale float64 `json:"timeout_scale"`

	SyslogDrainPort int    `json:"syslog_drain_port"`
	SyslogIpAddress string `json:"syslog_ip_address"`

	SecureAddress string `json:"secure_address"`

	DockerExecutable      string   `json:"docker_executable"`
	DockerParameters      []string `json:"docker_parameters"`
	DockerRegistryAddress string   `json:"docker_registry_address"`
	DockerPrivateImage    string   `json:"docker_private_image"`
	DockerUser            string   `json:"docker_user"`
	DockerPassword        string   `json:"docker_password"`
	DockerEmail           string   `json:"docker_email"`

	StaticFileBuildpackName string `json:"staticfile_buildpack_name"`
	JavaBuildpackName       string `json:"java_buildpack_name"`
	RubyBuildpackName       string `json:"ruby_buildpack_name"`
	NodejsBuildpackName     string `json:"nodejs_buildpack_name"`
	GoBuildpackName         string `json:"go_buildpack_name"`
	PythonBuildpackName     string `json:"python_buildpack_name"`
	PhpBuildpackName        string `json:"php_buildpack_name"`
	BinaryBuildpackName     string `json:"binary_buildpack_name"`
}

func (c Config) ScaledTimeout(timeout time.Duration) time.Duration {
	return time.Duration(float64(timeout) * c.TimeoutScale)
}

var loadedConfig *Config

func LoadConfig() Config {
	if loadedConfig == nil {
		loadedConfig = loadConfigJsonFromPath()
	}

	if loadedConfig.ApiEndpoint == "" {
		panic("missing configuration 'api'")
	}

	if loadedConfig.AdminUser == "" {
		panic("missing configuration 'admin_user'")
	}

	if loadedConfig.AdminPassword == "" {
		panic("missing configuration 'admin_password'")
	}

	if loadedConfig.TimeoutScale <= 0 {
		loadedConfig.TimeoutScale = 1.0
	}

	runner.SkipSSLValidation = loadedConfig.SkipSSLValidation

	return *loadedConfig
}

func (c Config) Protocol() string {
	if c.UseHttp {
		return "http://"
	} else {
		return "https://"
	}
}

func loadConfigJsonFromPath() *Config {
	var config *Config = &Config{
		PersistentAppHost:      "CATS-persistent-app",
		PersistentAppSpace:     "CATS-persistent-space",
		PersistentAppOrg:       "CATS-persistent-org",
		PersistentAppQuotaName: "CATS-persistent-quota",

		StaticFileBuildpackName: "staticfile_buildpack",
		JavaBuildpackName:       "java_buildpack",
		RubyBuildpackName:       "ruby_buildpack",
		NodejsBuildpackName:     "nodejs_buildpack",
		GoBuildpackName:         "go_buildpack",
		PythonBuildpackName:     "python_buildpack",
		PhpBuildpackName:        "php_buildpack",
		BinaryBuildpackName:     "binary_buildpack",

		ArtifactsDirectory: filepath.Join("..", "results"),
	}

	path := configPath()

	configFile, err := os.Open(path)
	if err != nil {
		panic(err)
	}

	decoder := json.NewDecoder(configFile)
	err = decoder.Decode(config)
	if err != nil {
		panic(err)
	}

	return config
}

func configPath() string {
	path := os.Getenv("CONFIG")
	if path == "" {
		panic("Must set $CONFIG to point to an integration config .json file.")
	}

	return path
}
<|endoftext|>


<commit_before>package triggers

type Donators struct{}

func (d *Donators) Triggers() []string {
    return []string{
        "donators",
        "donations",
        "donate",
        "supporters",
        "support",
        "patreon",
        "patreons",
        "credits",
    }
}

func (d *Donators) Response(trigger string, content string) string {
    return "<:robyulblush:327206930437373952> **These awesome people support me:**\nKakkela 💕\nSunny 💓\nsomicidal minaiac 💞\nOokami 🖤\nKeldra 💗\nTN 💝\nseulguille 💘\nSlenn 💜\nFugu ❣\nWoori 💞\nhikari 💙\nAshton 💖\nKay 💝\njamie 💓\nHomeboywill 💘\nThank you so much!\n_You want to be in this list? <https://www.patreon.com/sekl>!_"
}
<commit_msg>[donators] adds Rimbol!<commit_after>package triggers

type Donators struct{}

func (d *Donators) Triggers() []string {
    return []string{
        "donators",
        "donations",
        "donate",
        "supporters",
        "support",
        "patreon",
        "patreons",
        "credits",
    }
}

func (d *Donators) Response(trigger string, content string) string {
    return "<:robyulblush:327206930437373952> **These awesome people support me:**\nKakkela 💕\nSunny 💓\nsomicidal minaiac 💞\nOokami 🖤\nKeldra 💗\nTN 💝\nseulguille 💘\nSlenn 💜\nFugu ❣\nWoori 💞\nhikari 💙\nAshton 💖\nKay 💝\njamie 💓\nHomeboywill 💘\nRimbol 💕\nThank you so much!\n_You want to be in this list? <https://www.patreon.com/sekl>!_"
}
<|endoftext|>


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

// This file contains the code dealing with package directory trees.

package godoc

import (
	"bytes"
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	pathpkg "path"
	"strings"
)

// Conventional name for directories containing test data.
// Excluded from directory trees.
//
const testdataDirName = "testdata"

type Directory struct {
	Depth    int
	Path     string       // directory path; includes Name
	Name     string       // directory name
	HasPkg   bool         // true if the directory contains at least one package
	Synopsis string       // package documentation, if any
	Dirs     []*Directory // subdirectories
}

func isGoFile(fi os.FileInfo) bool {
	name := fi.Name()
	return !fi.IsDir() &&
		len(name) > 0 && name[0] != '.' && // ignore .files
		pathpkg.Ext(name) == ".go"
}

func isPkgFile(fi os.FileInfo) bool {
	return isGoFile(fi) &&
		!strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
}

func isPkgDir(fi os.FileInfo) bool {
	name := fi.Name()
	return fi.IsDir() && len(name) > 0 &&
		name[0] != '_' && name[0] != '.' // ignore _files and .files
}

type treeBuilder struct {
	c        *Corpus
	maxDepth int
}

func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth int) *Directory {
	if name == testdataDirName {
		return nil
	}

	if depth >= b.maxDepth {
		// return a dummy directory so that the parent directory
		// doesn't get discarded just because we reached the max
		// directory depth
		return &Directory{
			Depth: depth,
			Path:  path,
			Name:  name,
		}
	}

	list, _ := b.c.fs.ReadDir(path)

	// determine number of subdirectories and if there are package files
	ndirs := 0
	hasPkgFiles := false
	var synopses [3]string // prioritized package documentation (0 == highest priority)
	for _, d := range list {
		switch {
		case isPkgDir(d):
			ndirs++
		case isPkgFile(d):
			// looks like a package file, but may just be a file ending in ".go";
			// don't just count it yet (otherwise we may end up with hasPkgFiles even
			// though the directory doesn't contain any real package files - was bug)
			if synopses[0] == "" {
				// no "optimal" package synopsis yet; continue to collect synopses
				file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
					parser.ParseComments|parser.PackageClauseOnly)
				if err == nil {
					hasPkgFiles = true
					if file.Doc != nil {
						// prioritize documentation
						i := -1
						switch file.Name.Name {
						case name:
							i = 0 // normal case: directory name matches package name
						case "main":
							i = 1 // directory contains a main package
						default:
							i = 2 // none of the above
						}
						if 0 <= i && i < len(synopses) && synopses[i] == "" {
							synopses[i] = doc.Synopsis(file.Doc.Text())
						}
					}
				}
			}
		}
	}

	// create subdirectory tree
	var dirs []*Directory
	if ndirs > 0 {
		dirs = make([]*Directory, ndirs)
		i := 0
		for _, d := range list {
			if isPkgDir(d) {
				name := d.Name()
				dd := b.newDirTree(fset, pathpkg.Join(path, name), name, depth+1)
				if dd != nil {
					dirs[i] = dd
					i++
				}
			}
		}
		dirs = dirs[0:i]
	}

	// if there are no package files and no subdirectories
	// containing package files, ignore the directory
	if !hasPkgFiles && len(dirs) == 0 {
		return nil
	}

	// select the highest-priority synopsis for the directory entry, if any
	synopsis := ""
	for _, synopsis = range synopses {
		if synopsis != "" {
			break
		}
	}

	return &Directory{
		Depth:    depth,
		Path:     path,
		Name:     name,
		HasPkg:   hasPkgFiles,
		Synopsis: synopsis,
		Dirs:     dirs,
	}
}

// newDirectory creates a new package directory tree with at most maxDepth
// levels, anchored at root. The result tree is pruned such that it only
// contains directories that contain package files or that contain
// subdirectories containing package files (transitively). If a non-nil
// pathFilter is provided, directory paths additionally must be accepted
// by the filter (i.e., pathFilter(path) must be true). If a value >= 0 is
// provided for maxDepth, nodes at larger depths are pruned as well; they
// are assumed to contain package files even if their contents are not known
// (i.e., in this case the tree may contain directories w/o any package files).
//
func (c *Corpus) newDirectory(root string, maxDepth int) *Directory {
	// The root could be a symbolic link so use Stat not Lstat.
	d, err := c.fs.Stat(root)
	// If we fail here, report detailed error messages; otherwise
	// is is hard to see why a directory tree was not built.
	switch {
	case err != nil:
		log.Printf("newDirectory(%s): %s", root, err)
		return nil
	case !isPkgDir(d):
		log.Printf("newDirectory(%s): not a package directory", root)
		return nil
	}
	if maxDepth < 0 {
		maxDepth = 1e6 // "infinity"
	}
	b := treeBuilder{c, maxDepth}
	// the file set provided is only for local parsing, no position
	// information escapes and thus we don't need to save the set
	return b.newDirTree(token.NewFileSet(), root, d.Name(), 0)
}

func (dir *Directory) writeLeafs(buf *bytes.Buffer) {
	if dir != nil {
		if len(dir.Dirs) == 0 {
			buf.WriteString(dir.Path)
			buf.WriteByte('\n')
			return
		}

		for _, d := range dir.Dirs {
			d.writeLeafs(buf)
		}
	}
}

func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
	if dir != nil {
		if !skipRoot {
			c <- dir
		}
		for _, d := range dir.Dirs {
			d.walk(c, false)
		}
	}
}

func (dir *Directory) iter(skipRoot bool) <-chan *Directory {
	c := make(chan *Directory)
	go func() {
		dir.walk(c, skipRoot)
		close(c)
	}()
	return c
}

func (dir *Directory) lookupLocal(name string) *Directory {
	for _, d := range dir.Dirs {
		if d.Name == name {
			return d
		}
	}
	return nil
}

func splitPath(p string) []string {
	p = strings.TrimPrefix(p, "/")
	if p == "" {
		return nil
	}
	return strings.Split(p, "/")
}

// lookup looks for the *Directory for a given path, relative to dir.
func (dir *Directory) lookup(path string) *Directory {
	d := splitPath(dir.Path)
	p := splitPath(path)
	i := 0
	for i < len(d) {
		if i >= len(p) || d[i] != p[i] {
			return nil
		}
		i++
	}
	for dir != nil && i < len(p) {
		dir = dir.lookupLocal(p[i])
		i++
	}
	return dir
}

// DirEntry describes a directory entry. The Depth and Height values
// are useful for presenting an entry in an indented fashion.
//
type DirEntry struct {
	Depth    int    // >= 0
	Height   int    // = DirList.MaxHeight - Depth, > 0
	Path     string // directory path; includes Name, relative to DirList root
	Name     string // directory name
	HasPkg   bool   // true if the directory contains at least one package
	Synopsis string // package documentation, if any
}

type DirList struct {
	MaxHeight int // directory tree height, > 0
	List      []DirEntry
}

// listing creates a (linear) directory listing from a directory tree.
// If skipRoot is set, the root directory itself is excluded from the list.
//
func (root *Directory) listing(skipRoot bool) *DirList {
	if root == nil {
		return nil
	}

	// determine number of entries n and maximum height
	n := 0
	minDepth := 1 << 30 // infinity
	maxDepth := 0
	for d := range root.iter(skipRoot) {
		n++
		if minDepth > d.Depth {
			minDepth = d.Depth
		}
		if maxDepth < d.Depth {
			maxDepth = d.Depth
		}
	}
	maxHeight := maxDepth - minDepth + 1

	if n == 0 {
		return nil
	}

	// create list
	list := make([]DirEntry, n)
	i := 0
	for d := range root.iter(skipRoot) {
		p := &list[i]
		p.Depth = d.Depth - minDepth
		p.Height = maxHeight - p.Depth
		// the path is relative to root.Path - remove the root.Path
		// prefix (the prefix should always be present but avoid
		// crashes and check)
		path := strings.TrimPrefix(d.Path, root.Path)
		// remove leading separator if any - path must be relative
		path = strings.TrimPrefix(path, "/")
		p.Path = path
		p.Name = d.Name
		p.HasPkg = d.HasPkg
		p.Synopsis = d.Synopsis
		i++
	}

	return &DirList{maxHeight, list}
}
<commit_msg>godoc: parallelize corpus init<commit_after>// Copyright 2010 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.

// This file contains the code dealing with package directory trees.

package godoc

import (
	"bytes"
	"go/doc"
	"go/parser"
	"go/token"
	"log"
	"os"
	pathpkg "path"
	"strings"
)

// Conventional name for directories containing test data.
// Excluded from directory trees.
//
const testdataDirName = "testdata"

type Directory struct {
	Depth    int
	Path     string       // directory path; includes Name
	Name     string       // directory name
	HasPkg   bool         // true if the directory contains at least one package
	Synopsis string       // package documentation, if any
	Dirs     []*Directory // subdirectories
}

func isGoFile(fi os.FileInfo) bool {
	name := fi.Name()
	return !fi.IsDir() &&
		len(name) > 0 && name[0] != '.' && // ignore .files
		pathpkg.Ext(name) == ".go"
}

func isPkgFile(fi os.FileInfo) bool {
	return isGoFile(fi) &&
		!strings.HasSuffix(fi.Name(), "_test.go") // ignore test files
}

func isPkgDir(fi os.FileInfo) bool {
	name := fi.Name()
	return fi.IsDir() && len(name) > 0 &&
		name[0] != '_' && name[0] != '.' // ignore _files and .files
}

type treeBuilder struct {
	c        *Corpus
	maxDepth int
}

func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth int) *Directory {
	if name == testdataDirName {
		return nil
	}

	if depth >= b.maxDepth {
		// return a dummy directory so that the parent directory
		// doesn't get discarded just because we reached the max
		// directory depth
		return &Directory{
			Depth: depth,
			Path:  path,
			Name:  name,
		}
	}

	list, _ := b.c.fs.ReadDir(path)

	// determine number of subdirectories and if there are package files
	hasPkgFiles := false
	var dirchs []chan *Directory

	var synopses [3]string // prioritized package documentation (0 == highest priority)
	for _, d := range list {
		switch {
		case isPkgDir(d):
			ch := make(chan *Directory, 1)
			dirchs = append(dirchs, ch)
			go func(d os.FileInfo) {
				name := d.Name()
				ch <- b.newDirTree(fset, pathpkg.Join(path, name), name, depth+1)
			}(d)
		case isPkgFile(d):
			// looks like a package file, but may just be a file ending in ".go";
			// don't just count it yet (otherwise we may end up with hasPkgFiles even
			// though the directory doesn't contain any real package files - was bug)
			if synopses[0] == "" {
				// no "optimal" package synopsis yet; continue to collect synopses
				file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
					parser.ParseComments|parser.PackageClauseOnly)
				if err == nil {
					hasPkgFiles = true
					if file.Doc != nil {
						// prioritize documentation
						i := -1
						switch file.Name.Name {
						case name:
							i = 0 // normal case: directory name matches package name
						case "main":
							i = 1 // directory contains a main package
						default:
							i = 2 // none of the above
						}
						if 0 <= i && i < len(synopses) && synopses[i] == "" {
							synopses[i] = doc.Synopsis(file.Doc.Text())
						}
					}
				}
			}
		}
	}

	// create subdirectory tree
	var dirs []*Directory
	for _, ch := range dirchs {
		if d := <-ch; d != nil {
			dirs = append(dirs, d)
		}
	}

	// if there are no package files and no subdirectories
	// containing package files, ignore the directory
	if !hasPkgFiles && len(dirs) == 0 {
		return nil
	}

	// select the highest-priority synopsis for the directory entry, if any
	synopsis := ""
	for _, synopsis = range synopses {
		if synopsis != "" {
			break
		}
	}

	return &Directory{
		Depth:    depth,
		Path:     path,
		Name:     name,
		HasPkg:   hasPkgFiles,
		Synopsis: synopsis,
		Dirs:     dirs,
	}
}

// newDirectory creates a new package directory tree with at most maxDepth
// levels, anchored at root. The result tree is pruned such that it only
// contains directories that contain package files or that contain
// subdirectories containing package files (transitively). If a non-nil
// pathFilter is provided, directory paths additionally must be accepted
// by the filter (i.e., pathFilter(path) must be true). If a value >= 0 is
// provided for maxDepth, nodes at larger depths are pruned as well; they
// are assumed to contain package files even if their contents are not known
// (i.e., in this case the tree may contain directories w/o any package files).
//
func (c *Corpus) newDirectory(root string, maxDepth int) *Directory {
	// The root could be a symbolic link so use Stat not Lstat.
	d, err := c.fs.Stat(root)
	// If we fail here, report detailed error messages; otherwise
	// is is hard to see why a directory tree was not built.
	switch {
	case err != nil:
		log.Printf("newDirectory(%s): %s", root, err)
		return nil
	case !isPkgDir(d):
		log.Printf("newDirectory(%s): not a package directory", root)
		return nil
	}
	if maxDepth < 0 {
		maxDepth = 1e6 // "infinity"
	}
	b := treeBuilder{c, maxDepth}
	// the file set provided is only for local parsing, no position
	// information escapes and thus we don't need to save the set
	return b.newDirTree(token.NewFileSet(), root, d.Name(), 0)
}

func (dir *Directory) writeLeafs(buf *bytes.Buffer) {
	if dir != nil {
		if len(dir.Dirs) == 0 {
			buf.WriteString(dir.Path)
			buf.WriteByte('\n')
			return
		}

		for _, d := range dir.Dirs {
			d.writeLeafs(buf)
		}
	}
}

func (dir *Directory) walk(c chan<- *Directory, skipRoot bool) {
	if dir != nil {
		if !skipRoot {
			c <- dir
		}
		for _, d := range dir.Dirs {
			d.walk(c, false)
		}
	}
}

func (dir *Directory) iter(skipRoot bool) <-chan *Directory {
	c := make(chan *Directory)
	go func() {
		dir.walk(c, skipRoot)
		close(c)
	}()
	return c
}

func (dir *Directory) lookupLocal(name string) *Directory {
	for _, d := range dir.Dirs {
		if d.Name == name {
			return d
		}
	}
	return nil
}

func splitPath(p string) []string {
	p = strings.TrimPrefix(p, "/")
	if p == "" {
		return nil
	}
	return strings.Split(p, "/")
}

// lookup looks for the *Directory for a given path, relative to dir.
func (dir *Directory) lookup(path string) *Directory {
	d := splitPath(dir.Path)
	p := splitPath(path)
	i := 0
	for i < len(d) {
		if i >= len(p) || d[i] != p[i] {
			return nil
		}
		i++
	}
	for dir != nil && i < len(p) {
		dir = dir.lookupLocal(p[i])
		i++
	}
	return dir
}

// DirEntry describes a directory entry. The Depth and Height values
// are useful for presenting an entry in an indented fashion.
//
type DirEntry struct {
	Depth    int    // >= 0
	Height   int    // = DirList.MaxHeight - Depth, > 0
	Path     string // directory path; includes Name, relative to DirList root
	Name     string // directory name
	HasPkg   bool   // true if the directory contains at least one package
	Synopsis string // package documentation, if any
}

type DirList struct {
	MaxHeight int // directory tree height, > 0
	List      []DirEntry
}

// listing creates a (linear) directory listing from a directory tree.
// If skipRoot is set, the root directory itself is excluded from the list.
//
func (root *Directory) listing(skipRoot bool) *DirList {
	if root == nil {
		return nil
	}

	// determine number of entries n and maximum height
	n := 0
	minDepth := 1 << 30 // infinity
	maxDepth := 0
	for d := range root.iter(skipRoot) {
		n++
		if minDepth > d.Depth {
			minDepth = d.Depth
		}
		if maxDepth < d.Depth {
			maxDepth = d.Depth
		}
	}
	maxHeight := maxDepth - minDepth + 1

	if n == 0 {
		return nil
	}

	// create list
	list := make([]DirEntry, n)
	i := 0
	for d := range root.iter(skipRoot) {
		p := &list[i]
		p.Depth = d.Depth - minDepth
		p.Height = maxHeight - p.Depth
		// the path is relative to root.Path - remove the root.Path
		// prefix (the prefix should always be present but avoid
		// crashes and check)
		path := strings.TrimPrefix(d.Path, root.Path)
		// remove leading separator if any - path must be relative
		path = strings.TrimPrefix(path, "/")
		p.Path = path
		p.Name = d.Name
		p.HasPkg = d.HasPkg
		p.Synopsis = d.Synopsis
		i++
	}

	return &DirList{maxHeight, list}
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

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

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

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

package device

import (
	"flag"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/vmware/govmomi/govc/cli"
	"github.com/vmware/govmomi/govc/flags"
)

type ls struct {
	*flags.VirtualMachineFlag
}

func init() {
	cli.Register("device.ls", &ls{})
}

func (cmd *ls) Register(f *flag.FlagSet) {}

func (cmd *ls) Process() error { return nil }

func (cmd *ls) Run(f *flag.FlagSet) error {
	vm, err := cmd.VirtualMachine()
	if err != nil {
		return err
	}

	if vm == nil {
		return flag.ErrHelp
	}

	devices, err := vm.Device()
	if err != nil {
		return err
	}

	tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)

	for _, device := range devices {
		fmt.Fprintf(tw, "%s\t%s\t%s\n", devices.Name(device), devices.TypeName(device),
			device.GetVirtualDevice().DeviceInfo.GetDescription().Summary)
	}

	return tw.Flush()
}
<commit_msg>Add device.ls -boot option<commit_after>/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.

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

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

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

package device

import (
	"flag"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/vmware/govmomi/govc/cli"
	"github.com/vmware/govmomi/govc/flags"
)

type ls struct {
	*flags.VirtualMachineFlag

	boot bool
}

func init() {
	cli.Register("device.ls", &ls{})
}

func (cmd *ls) Register(f *flag.FlagSet) {
	f.BoolVar(&cmd.boot, "boot", false, "List devices configured in the VM's boot options")
}

func (cmd *ls) Process() error { return nil }

func (cmd *ls) Run(f *flag.FlagSet) error {
	vm, err := cmd.VirtualMachine()
	if err != nil {
		return err
	}

	if vm == nil {
		return flag.ErrHelp
	}

	devices, err := vm.Device()
	if err != nil {
		return err
	}

	if cmd.boot {
		options, err := vm.BootOptions()
		if err != nil {
			return err
		}

		devices = devices.SelectBootOrder(options.BootOrder)
	}

	tw := tabwriter.NewWriter(os.Stdout, 3, 0, 2, ' ', 0)

	for _, device := range devices {
		fmt.Fprintf(tw, "%s\t%s\t%s\n", devices.Name(device), devices.TypeName(device),
			device.GetVirtualDevice().DeviceInfo.GetDescription().Summary)
	}

	return tw.Flush()
}
<|endoftext|>