<commit_before>// Package networksecuritygroup provides a client for Network Security Groups.
package networksecuritygroup

import (
	"encoding/xml"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/management"
)

const (
	createSecurityGroupURL           = "services/networking/networksecuritygroups"
	deleteSecurityGroupURL           = "services/networking/networksecuritygroups/%s"
	getSecurityGroupURL              = "services/networking/networksecuritygroups/%s?detaillevel=full"
	listSecurityGroupsURL            = "services/networking/networksecuritygroups"
	addSecurityGroupToSubnetURL      = "services/virtualnetwork/%s/subnets/%s/networksecuritygroups"
	getSecurityGroupForSubnetURL     = "services/virtualnetwork/%s/subnets/%s/networksecuritygroups"
	removeSecurityGroupFromSubnetURL = "services/virtualnetwork/%s/subnets/%s/networksecuritygroups/%s"
	setSecurityGroupRuleURL          = "services/networking/networksecuritygroups/%s/rules/%s"
	deleteSecurityGroupRuleURL       = "services/networking/networksecuritygroups/%s/rules/%s"

	errParamNotSpecified = "Parameter %s is not specified."
)

// NewClient is used to instantiate a new SecurityGroupClient from an Azure client
func NewClient(client management.Client) SecurityGroupClient {
	return SecurityGroupClient{client: client}
}

// CreateNetworkSecurityGroup creates a new network security group within
// the context of the specified subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913818.aspx
func (sg SecurityGroupClient) CreateNetworkSecurityGroup(
	name string,
	label string,
	location string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if location == "" {
		return "", fmt.Errorf(errParamNotSpecified, "location")
	}

	data, err := xml.Marshal(SecurityGroupRequest{
		Name:     name,
		Label:    label,
		Location: location,
	})
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(createSecurityGroupURL)
	return sg.client.SendAzurePostRequest(requestURL, data)
}

// DeleteNetworkSecurityGroup deletes the specified network security group from the subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913825.aspx
func (sg SecurityGroupClient) DeleteNetworkSecurityGroup(
	name string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}

	requestURL := fmt.Sprintf(deleteSecurityGroupURL, name)
	return sg.client.SendAzureDeleteRequest(requestURL)
}

// GetNetworkSecurityGroup returns information about the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913821.aspx
func (sg SecurityGroupClient) GetNetworkSecurityGroup(name string) (SecurityGroupResponse, error) {
	if name == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "name")
	}

	var securityGroup SecurityGroupResponse

	requestURL := fmt.Sprintf(getSecurityGroupURL, name)
	response, err := sg.client.SendAzureGetRequest(requestURL)
	if err != nil {
		return securityGroup, err
	}

	err = xml.Unmarshal(response, &securityGroup)
	return securityGroup, err
}

// ListNetworkSecurityGroups returns a list of the network security groups
// in the specified subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913815.aspx
func (sg SecurityGroupClient) ListNetworkSecurityGroups() (SecurityGroupList, error) {
	var securityGroups SecurityGroupList

	response, err := sg.client.SendAzureGetRequest(listSecurityGroupsURL)
	if err != nil {
		return securityGroups, err
	}

	err = xml.Unmarshal(response, &securityGroups)
	return securityGroups, err
}

// AddNetworkSecurityToSubnet associates the network security group with
// specified subnet in a virtual network
//
// https://msdn.microsoft.com/en-us/library/azure/dn913822.aspx
func (sg SecurityGroupClient) AddNetworkSecurityToSubnet(
	name string,
	subnet string,
	virtualNetwork string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if subnet == "" {
		return "", fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return "", fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	data, err := xml.Marshal(SecurityGroupRequest{Name: name})
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(addSecurityGroupToSubnetURL, virtualNetwork, subnet)
	return sg.client.SendAzurePostRequest(requestURL, data)
}

// GetNetworkSecurityGroupForSubnet returns information about the network
// security group associated with a subnet
//
// https://msdn.microsoft.com/en-us/library/azure/dn913817.aspx
func (sg SecurityGroupClient) GetNetworkSecurityGroupForSubnet(
	subnet string,
	virtualNetwork string) (SecurityGroupResponse, error) {
	if subnet == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	var securityGroup SecurityGroupResponse

	requestURL := fmt.Sprintf(getSecurityGroupForSubnetURL, virtualNetwork, subnet)
	response, err := sg.client.SendAzureGetRequest(requestURL)
	if err != nil {
		return securityGroup, err
	}

	err = xml.Unmarshal(response, &securityGroup)
	return securityGroup, err
}

// RemoveNetworkSecurityGroupFromSubnet removes the association of the
// specified network security group from the specified subnet
//
// https://msdn.microsoft.com/en-us/library/azure/dn913820.aspx
func (sg SecurityGroupClient) RemoveNetworkSecurityGroupFromSubnet(
	name string,
	subnet string,
	virtualNetwork string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if subnet == "" {
		return "", fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return "", fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	requestURL := fmt.Sprintf(removeSecurityGroupFromSubnetURL, virtualNetwork, subnet, name)
	return sg.client.SendAzureDeleteRequest(requestURL)
}

// SetNetworkSecurityGroupRule adds or updates a network security rule that
// is associated with the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913819.aspx
func (sg SecurityGroupClient) SetNetworkSecurityGroupRule(
	securityGroup string,
	rule RuleRequest) (management.OperationID, error) {
	if securityGroup == "" {
		return "", fmt.Errorf(errParamNotSpecified, "securityGroup")
	}
	if rule.Name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Name")
	}
	if rule.Type == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Type")
	}
	if rule.Priority == 0 {
		return "", fmt.Errorf(errParamNotSpecified, "Priority")
	}
	if rule.Action == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Action")
	}
	if rule.SourceAddressPrefix == "" {
		return "", fmt.Errorf(errParamNotSpecified, "SourceAddressPrefix")
	}
	if rule.SourcePortRange == "" {
		return "", fmt.Errorf(errParamNotSpecified, "SourcePortRange")
	}
	if rule.DestinationAddressPrefix == "" {
		return "", fmt.Errorf(errParamNotSpecified, "DestinationAddressPrefix")
	}
	if rule.DestinationPortRange == "" {
		return "", fmt.Errorf(errParamNotSpecified, "DestinationPortRange")
	}
	if rule.Protocol == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Protocol")
	}

	data, err := xml.Marshal(rule)
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(setSecurityGroupRuleURL, securityGroup, rule.Name)
	return sg.client.SendAzurePutRequest(requestURL, "", data)
}

// DeleteNetworkSecurityGroupRule deletes a network security group rule from
// the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913816.aspx
func (sg SecurityGroupClient) DeleteNetworkSecurityGroupRule(
	securityGroup string,
	rule string) (management.OperationID, error) {
	if securityGroup == "" {
		return "", fmt.Errorf(errParamNotSpecified, "securityGroup")
	}
	if rule == "" {
		return "", fmt.Errorf(errParamNotSpecified, "rule")
	}

	requestURL := fmt.Sprintf(deleteSecurityGroupRuleURL, securityGroup, rule)
	return sg.client.SendAzureDeleteRequest(requestURL)
}
<commit_msg>Despite the docs, these are the correct URLs<commit_after>// Package networksecuritygroup provides a client for Network Security Groups.
package networksecuritygroup

import (
	"encoding/xml"
	"fmt"

	"github.com/Azure/azure-sdk-for-go/management"
)

const (
	createSecurityGroupURL           = "services/networking/networksecuritygroups"
	deleteSecurityGroupURL           = "services/networking/networksecuritygroups/%s"
	getSecurityGroupURL              = "services/networking/networksecuritygroups/%s?detaillevel=full"
	listSecurityGroupsURL            = "services/networking/networksecuritygroups"
	addSecurityGroupToSubnetURL      = "services/networking/virtualnetwork/%s/subnets/%s/networksecuritygroups"
	getSecurityGroupForSubnetURL     = "services/networking/virtualnetwork/%s/subnets/%s/networksecuritygroups"
	removeSecurityGroupFromSubnetURL = "services/networking/virtualnetwork/%s/subnets/%s/networksecuritygroups/%s"
	setSecurityGroupRuleURL          = "services/networking/networksecuritygroups/%s/rules/%s"
	deleteSecurityGroupRuleURL       = "services/networking/networksecuritygroups/%s/rules/%s"

	errParamNotSpecified = "Parameter %s is not specified."
)

// NewClient is used to instantiate a new SecurityGroupClient from an Azure client
func NewClient(client management.Client) SecurityGroupClient {
	return SecurityGroupClient{client: client}
}

// CreateNetworkSecurityGroup creates a new network security group within
// the context of the specified subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913818.aspx
func (sg SecurityGroupClient) CreateNetworkSecurityGroup(
	name string,
	label string,
	location string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if location == "" {
		return "", fmt.Errorf(errParamNotSpecified, "location")
	}

	data, err := xml.Marshal(SecurityGroupRequest{
		Name:     name,
		Label:    label,
		Location: location,
	})
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(createSecurityGroupURL)
	return sg.client.SendAzurePostRequest(requestURL, data)
}

// DeleteNetworkSecurityGroup deletes the specified network security group from the subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913825.aspx
func (sg SecurityGroupClient) DeleteNetworkSecurityGroup(
	name string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}

	requestURL := fmt.Sprintf(deleteSecurityGroupURL, name)
	return sg.client.SendAzureDeleteRequest(requestURL)
}

// GetNetworkSecurityGroup returns information about the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913821.aspx
func (sg SecurityGroupClient) GetNetworkSecurityGroup(name string) (SecurityGroupResponse, error) {
	if name == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "name")
	}

	var securityGroup SecurityGroupResponse

	requestURL := fmt.Sprintf(getSecurityGroupURL, name)
	response, err := sg.client.SendAzureGetRequest(requestURL)
	if err != nil {
		return securityGroup, err
	}

	err = xml.Unmarshal(response, &securityGroup)
	return securityGroup, err
}

// ListNetworkSecurityGroups returns a list of the network security groups
// in the specified subscription
//
// https://msdn.microsoft.com/en-us/library/azure/dn913815.aspx
func (sg SecurityGroupClient) ListNetworkSecurityGroups() (SecurityGroupList, error) {
	var securityGroups SecurityGroupList

	response, err := sg.client.SendAzureGetRequest(listSecurityGroupsURL)
	if err != nil {
		return securityGroups, err
	}

	err = xml.Unmarshal(response, &securityGroups)
	return securityGroups, err
}

// AddNetworkSecurityToSubnet associates the network security group with
// specified subnet in a virtual network
//
// https://msdn.microsoft.com/en-us/library/azure/dn913822.aspx
func (sg SecurityGroupClient) AddNetworkSecurityToSubnet(
	name string,
	subnet string,
	virtualNetwork string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if subnet == "" {
		return "", fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return "", fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	data, err := xml.Marshal(SecurityGroupRequest{Name: name})
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(addSecurityGroupToSubnetURL, virtualNetwork, subnet)
	return sg.client.SendAzurePostRequest(requestURL, data)
}

// GetNetworkSecurityGroupForSubnet returns information about the network
// security group associated with a subnet
//
// https://msdn.microsoft.com/en-us/library/azure/dn913817.aspx
func (sg SecurityGroupClient) GetNetworkSecurityGroupForSubnet(
	subnet string,
	virtualNetwork string) (SecurityGroupResponse, error) {
	if subnet == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return SecurityGroupResponse{}, fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	var securityGroup SecurityGroupResponse

	requestURL := fmt.Sprintf(getSecurityGroupForSubnetURL, virtualNetwork, subnet)
	response, err := sg.client.SendAzureGetRequest(requestURL)
	if err != nil {
		return securityGroup, err
	}

	err = xml.Unmarshal(response, &securityGroup)
	return securityGroup, err
}

// RemoveNetworkSecurityGroupFromSubnet removes the association of the
// specified network security group from the specified subnet
//
// https://msdn.microsoft.com/en-us/library/azure/dn913820.aspx
func (sg SecurityGroupClient) RemoveNetworkSecurityGroupFromSubnet(
	name string,
	subnet string,
	virtualNetwork string) (management.OperationID, error) {
	if name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "name")
	}
	if subnet == "" {
		return "", fmt.Errorf(errParamNotSpecified, "subnet")
	}
	if virtualNetwork == "" {
		return "", fmt.Errorf(errParamNotSpecified, "virtualNetwork")
	}

	requestURL := fmt.Sprintf(removeSecurityGroupFromSubnetURL, virtualNetwork, subnet, name)
	return sg.client.SendAzureDeleteRequest(requestURL)
}

// SetNetworkSecurityGroupRule adds or updates a network security rule that
// is associated with the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913819.aspx
func (sg SecurityGroupClient) SetNetworkSecurityGroupRule(
	securityGroup string,
	rule RuleRequest) (management.OperationID, error) {
	if securityGroup == "" {
		return "", fmt.Errorf(errParamNotSpecified, "securityGroup")
	}
	if rule.Name == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Name")
	}
	if rule.Type == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Type")
	}
	if rule.Priority == 0 {
		return "", fmt.Errorf(errParamNotSpecified, "Priority")
	}
	if rule.Action == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Action")
	}
	if rule.SourceAddressPrefix == "" {
		return "", fmt.Errorf(errParamNotSpecified, "SourceAddressPrefix")
	}
	if rule.SourcePortRange == "" {
		return "", fmt.Errorf(errParamNotSpecified, "SourcePortRange")
	}
	if rule.DestinationAddressPrefix == "" {
		return "", fmt.Errorf(errParamNotSpecified, "DestinationAddressPrefix")
	}
	if rule.DestinationPortRange == "" {
		return "", fmt.Errorf(errParamNotSpecified, "DestinationPortRange")
	}
	if rule.Protocol == "" {
		return "", fmt.Errorf(errParamNotSpecified, "Protocol")
	}

	data, err := xml.Marshal(rule)
	if err != nil {
		return "", err
	}

	requestURL := fmt.Sprintf(setSecurityGroupRuleURL, securityGroup, rule.Name)
	return sg.client.SendAzurePutRequest(requestURL, "", data)
}

// DeleteNetworkSecurityGroupRule deletes a network security group rule from
// the specified network security group
//
// https://msdn.microsoft.com/en-us/library/azure/dn913816.aspx
func (sg SecurityGroupClient) DeleteNetworkSecurityGroupRule(
	securityGroup string,
	rule string) (management.OperationID, error) {
	if securityGroup == "" {
		return "", fmt.Errorf(errParamNotSpecified, "securityGroup")
	}
	if rule == "" {
		return "", fmt.Errorf(errParamNotSpecified, "rule")
	}

	requestURL := fmt.Sprintf(deleteSecurityGroupRuleURL, securityGroup, rule)
	return sg.client.SendAzureDeleteRequest(requestURL)
}
<|endoftext|>


<commit_before>package md2man

import (
	"bytes"
	"fmt"
	"html"
	"strings"

	"github.com/russross/blackfriday"
)

type roffRenderer struct{}

var listCounter int

func RoffRenderer(flags int) blackfriday.Renderer {
	return &roffRenderer{}
}

func (r *roffRenderer) GetFlags() int {
	return 0
}

func (r *roffRenderer) TitleBlock(out *bytes.Buffer, text []byte) {
	out.WriteString(".TH ")

	splitText := bytes.Split(text, []byte("\n"))
	for i, line := range splitText {
		line = bytes.TrimPrefix(line, []byte("% "))
		if i == 0 {
			line = bytes.Replace(line, []byte("("), []byte("\" \""), 1)
			line = bytes.Replace(line, []byte(")"), []byte("\" \""), 1)
		}
		line = append([]byte("\""), line...)
		line = append(line, []byte("\" ")...)
		out.Write(line)
	}
	out.WriteString("\n")

	// disable hyphenation
	out.WriteString(".nh\n")
	// disable justification (adjust text to left margin only)
	out.WriteString(".ad l\n")
}

func (r *roffRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string) {
	out.WriteString("\n.PP\n.RS\n\n.nf\n")
	escapeSpecialChars(out, text)
	out.WriteString("\n.fi\n.RE\n")
}

func (r *roffRenderer) BlockQuote(out *bytes.Buffer, text []byte) {
	out.WriteString("\n.PP\n.RS\n")
	out.Write(text)
	out.WriteString("\n.RE\n")
}

func (r *roffRenderer) BlockHtml(out *bytes.Buffer, text []byte) {
	out.Write(text)
}

func (r *roffRenderer) Header(out *bytes.Buffer, text func() bool, level int, id string) {
	marker := out.Len()

	switch {
	case marker == 0:
		// This is the doc header
		out.WriteString(".TH ")
	case level == 1:
		out.WriteString("\n\n.SH ")
	case level == 2:
		out.WriteString("\n.SH ")
	default:
		out.WriteString("\n.SS ")
	}

	if !text() {
		out.Truncate(marker)
		return
	}
}

func (r *roffRenderer) HRule(out *bytes.Buffer) {
	out.WriteString("\n.ti 0\n\\l'\\n(.lu'\n")
}

func (r *roffRenderer) List(out *bytes.Buffer, text func() bool, flags int) {
	marker := out.Len()
	if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
		listCounter = 1
	}
	if !text() {
		out.Truncate(marker)
		return
	}
}

func (r *roffRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
	if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
		out.WriteString(fmt.Sprintf(".IP \"%3d.\" 5\n", listCounter))
		listCounter += 1
	} else {
		out.WriteString(".IP \\(bu 2\n")
	}
	out.Write(text)
	out.WriteString("\n")
}

func (r *roffRenderer) Paragraph(out *bytes.Buffer, text func() bool) {
	marker := out.Len()
	out.WriteString("\n.PP\n")
	if !text() {
		out.Truncate(marker)
		return
	}
	if marker != 0 {
		out.WriteString("\n")
	}
}

func (r *roffRenderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
	out.WriteString("\n.TS\nallbox;\n")

	max_delims := 0
	lines := strings.Split(strings.TrimRight(string(header), "\n")+"\n"+strings.TrimRight(string(body), "\n"), "\n")
	for _, w := range lines {
		cur_delims := strings.Count(w, "\t")
		if cur_delims > max_delims {
			max_delims = cur_delims
		}
	}
	out.Write([]byte(strings.Repeat("l ", max_delims+1) + "\n"))
	out.Write([]byte(strings.Repeat("l ", max_delims+1) + ".\n"))
	out.Write(header)
	if len(header) > 0 {
		out.Write([]byte("\n"))
	}

	out.Write(body)
	out.WriteString("\n.TE\n")
}

func (r *roffRenderer) TableRow(out *bytes.Buffer, text []byte) {
	if out.Len() > 0 {
		out.WriteString("\n")
	}
	out.Write(text)
}

func (r *roffRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {
	if out.Len() > 0 {
		out.WriteString("\t")
	}
	if len(text) == 0 {
		text = []byte{' '}
	}
	out.Write([]byte("\\fB\\fC" + string(text) + "\\fR"))
}

func (r *roffRenderer) TableCell(out *bytes.Buffer, text []byte, align int) {
	if out.Len() > 0 {
		out.WriteString("\t")
	}
	if len(text) > 30 {
		text = append([]byte("T{\n"), text...)
		text = append(text, []byte("\nT}")...)
	}
	if len(text) == 0 {
		text = []byte{' '}
	}
	out.Write(text)
}

func (r *roffRenderer) Footnotes(out *bytes.Buffer, text func() bool) {

}

func (r *roffRenderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {

}

func (r *roffRenderer) AutoLink(out *bytes.Buffer, link []byte, kind int) {
	out.WriteString("\n\\[la]")
	out.Write(link)
	out.WriteString("\\[ra]")
}

func (r *roffRenderer) CodeSpan(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fB\\fC")
	escapeSpecialChars(out, text)
	out.WriteString("\\fR")
}

func (r *roffRenderer) DoubleEmphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fB")
	out.Write(text)
	out.WriteString("\\fP")
}

func (r *roffRenderer) Emphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fI")
	out.Write(text)
	out.WriteString("\\fP")
}

func (r *roffRenderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
}

func (r *roffRenderer) LineBreak(out *bytes.Buffer) {
	out.WriteString("\n.br\n")
}

func (r *roffRenderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
	out.Write(content)
	r.AutoLink(out, link, 0)
}

func (r *roffRenderer) RawHtmlTag(out *bytes.Buffer, tag []byte) {
	out.Write(tag)
}

func (r *roffRenderer) TripleEmphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\s+2")
	out.Write(text)
	out.WriteString("\\s-2")
}

func (r *roffRenderer) StrikeThrough(out *bytes.Buffer, text []byte) {
}

func (r *roffRenderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {

}

func (r *roffRenderer) Entity(out *bytes.Buffer, entity []byte) {
	out.WriteString(html.UnescapeString(string(entity)))
}

func processFooterText(text []byte) []byte {
	text = bytes.TrimPrefix(text, []byte("% "))
	newText := []byte{}
	textArr := strings.Split(string(text), ") ")

	for i, w := range textArr {
		if i == 0 {
			w = strings.Replace(w, "(", "\" \"", 1)
			w = fmt.Sprintf("\"%s\"", w)
		} else {
			w = fmt.Sprintf(" \"%s\"", w)
		}
		newText = append(newText, []byte(w)...)
	}
	newText = append(newText, []byte(" \"\"")...)

	return newText
}

func (r *roffRenderer) NormalText(out *bytes.Buffer, text []byte) {
	escapeSpecialChars(out, text)
}

func (r *roffRenderer) DocumentHeader(out *bytes.Buffer) {
}

func (r *roffRenderer) DocumentFooter(out *bytes.Buffer) {
}

func needsBackslash(c byte) bool {
	for _, r := range []byte("-_&\\~") {
		if c == r {
			return true
		}
	}
	return false
}

func escapeSpecialChars(out *bytes.Buffer, text []byte) {
	for i := 0; i < len(text); i++ {
		// escape initial apostrophe or period
		if len(text) >= 1 && (text[0] == '\'' || text[0] == '.') {
			out.WriteString("\\&")
		}

		// directly copy normal characters
		org := i

		for i < len(text) && !needsBackslash(text[i]) {
			i++
		}
		if i > org {
			out.Write(text[org:i])
		}

		// escape a character
		if i >= len(text) {
			break
		}
		out.WriteByte('\\')
		out.WriteByte(text[i])
	}
}
<commit_msg>Improve rendering of nested lists<commit_after>package md2man

import (
	"bytes"
	"fmt"
	"html"
	"strings"

	"github.com/russross/blackfriday"
)

type roffRenderer struct{
    ListCounters []int
}

func RoffRenderer(flags int) blackfriday.Renderer {
	return &roffRenderer{}
}

func (r *roffRenderer) GetFlags() int {
	return 0
}

func (r *roffRenderer) TitleBlock(out *bytes.Buffer, text []byte) {
	out.WriteString(".TH ")

	splitText := bytes.Split(text, []byte("\n"))
	for i, line := range splitText {
		line = bytes.TrimPrefix(line, []byte("% "))
		if i == 0 {
			line = bytes.Replace(line, []byte("("), []byte("\" \""), 1)
			line = bytes.Replace(line, []byte(")"), []byte("\" \""), 1)
		}
		line = append([]byte("\""), line...)
		line = append(line, []byte("\" ")...)
		out.Write(line)
	}
	out.WriteString("\n")

	// disable hyphenation
	out.WriteString(".nh\n")
	// disable justification (adjust text to left margin only)
	out.WriteString(".ad l\n")
}

func (r *roffRenderer) BlockCode(out *bytes.Buffer, text []byte, lang string) {
	out.WriteString("\n.PP\n.RS\n\n.nf\n")
	escapeSpecialChars(out, text)
	out.WriteString("\n.fi\n.RE\n")
}

func (r *roffRenderer) BlockQuote(out *bytes.Buffer, text []byte) {
	out.WriteString("\n.PP\n.RS\n")
	out.Write(text)
	out.WriteString("\n.RE\n")
}

func (r *roffRenderer) BlockHtml(out *bytes.Buffer, text []byte) {
	out.Write(text)
}

func (r *roffRenderer) Header(out *bytes.Buffer, text func() bool, level int, id string) {
	marker := out.Len()

	switch {
	case marker == 0:
		// This is the doc header
		out.WriteString(".TH ")
	case level == 1:
		out.WriteString("\n\n.SH ")
	case level == 2:
		out.WriteString("\n.SH ")
	default:
		out.WriteString("\n.SS ")
	}

	if !text() {
		out.Truncate(marker)
		return
	}
}

func (r *roffRenderer) HRule(out *bytes.Buffer) {
	out.WriteString("\n.ti 0\n\\l'\\n(.lu'\n")
}

func (r *roffRenderer) List(out *bytes.Buffer, text func() bool, flags int) {
	marker := out.Len()
	r.ListCounters = append(r.ListCounters, 1)
	out.WriteString("\n.RS\n")
	if !text() {
		out.Truncate(marker)
		return
	}
	r.ListCounters = r.ListCounters[:len(r.ListCounters) - 1]
	out.WriteString("\n.RE\n")
}

func (r *roffRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
	if flags&blackfriday.LIST_TYPE_ORDERED != 0 {
		out.WriteString(fmt.Sprintf(".IP \"%3d.\" 5\n",
			r.ListCounters[len(r.ListCounters) - 1]))
		r.ListCounters[len(r.ListCounters) - 1] += 1
	} else {
		out.WriteString(".IP \\(bu 2\n")
	}
	out.Write(text)
	out.WriteString("\n")
}

func (r *roffRenderer) Paragraph(out *bytes.Buffer, text func() bool) {
	marker := out.Len()
	out.WriteString("\n.PP\n")
	if !text() {
		out.Truncate(marker)
		return
	}
	if marker != 0 {
		out.WriteString("\n")
	}
}

func (r *roffRenderer) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) {
	out.WriteString("\n.TS\nallbox;\n")

	max_delims := 0
	lines := strings.Split(strings.TrimRight(string(header), "\n")+"\n"+strings.TrimRight(string(body), "\n"), "\n")
	for _, w := range lines {
		cur_delims := strings.Count(w, "\t")
		if cur_delims > max_delims {
			max_delims = cur_delims
		}
	}
	out.Write([]byte(strings.Repeat("l ", max_delims+1) + "\n"))
	out.Write([]byte(strings.Repeat("l ", max_delims+1) + ".\n"))
	out.Write(header)
	if len(header) > 0 {
		out.Write([]byte("\n"))
	}

	out.Write(body)
	out.WriteString("\n.TE\n")
}

func (r *roffRenderer) TableRow(out *bytes.Buffer, text []byte) {
	if out.Len() > 0 {
		out.WriteString("\n")
	}
	out.Write(text)
}

func (r *roffRenderer) TableHeaderCell(out *bytes.Buffer, text []byte, align int) {
	if out.Len() > 0 {
		out.WriteString("\t")
	}
	if len(text) == 0 {
		text = []byte{' '}
	}
	out.Write([]byte("\\fB\\fC" + string(text) + "\\fR"))
}

func (r *roffRenderer) TableCell(out *bytes.Buffer, text []byte, align int) {
	if out.Len() > 0 {
		out.WriteString("\t")
	}
	if len(text) > 30 {
		text = append([]byte("T{\n"), text...)
		text = append(text, []byte("\nT}")...)
	}
	if len(text) == 0 {
		text = []byte{' '}
	}
	out.Write(text)
}

func (r *roffRenderer) Footnotes(out *bytes.Buffer, text func() bool) {

}

func (r *roffRenderer) FootnoteItem(out *bytes.Buffer, name, text []byte, flags int) {

}

func (r *roffRenderer) AutoLink(out *bytes.Buffer, link []byte, kind int) {
	out.WriteString("\n\\[la]")
	out.Write(link)
	out.WriteString("\\[ra]")
}

func (r *roffRenderer) CodeSpan(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fB\\fC")
	escapeSpecialChars(out, text)
	out.WriteString("\\fR")
}

func (r *roffRenderer) DoubleEmphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fB")
	out.Write(text)
	out.WriteString("\\fP")
}

func (r *roffRenderer) Emphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\fI")
	out.Write(text)
	out.WriteString("\\fP")
}

func (r *roffRenderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
}

func (r *roffRenderer) LineBreak(out *bytes.Buffer) {
	out.WriteString("\n.br\n")
}

func (r *roffRenderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
	out.Write(content)
	r.AutoLink(out, link, 0)
}

func (r *roffRenderer) RawHtmlTag(out *bytes.Buffer, tag []byte) {
	out.Write(tag)
}

func (r *roffRenderer) TripleEmphasis(out *bytes.Buffer, text []byte) {
	out.WriteString("\\s+2")
	out.Write(text)
	out.WriteString("\\s-2")
}

func (r *roffRenderer) StrikeThrough(out *bytes.Buffer, text []byte) {
}

func (r *roffRenderer) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {

}

func (r *roffRenderer) Entity(out *bytes.Buffer, entity []byte) {
	out.WriteString(html.UnescapeString(string(entity)))
}

func processFooterText(text []byte) []byte {
	text = bytes.TrimPrefix(text, []byte("% "))
	newText := []byte{}
	textArr := strings.Split(string(text), ") ")

	for i, w := range textArr {
		if i == 0 {
			w = strings.Replace(w, "(", "\" \"", 1)
			w = fmt.Sprintf("\"%s\"", w)
		} else {
			w = fmt.Sprintf(" \"%s\"", w)
		}
		newText = append(newText, []byte(w)...)
	}
	newText = append(newText, []byte(" \"\"")...)

	return newText
}

func (r *roffRenderer) NormalText(out *bytes.Buffer, text []byte) {
	escapeSpecialChars(out, text)
}

func (r *roffRenderer) DocumentHeader(out *bytes.Buffer) {
}

func (r *roffRenderer) DocumentFooter(out *bytes.Buffer) {
}

func needsBackslash(c byte) bool {
	for _, r := range []byte("-_&\\~") {
		if c == r {
			return true
		}
	}
	return false
}

func escapeSpecialChars(out *bytes.Buffer, text []byte) {
	for i := 0; i < len(text); i++ {
		// escape initial apostrophe or period
		if len(text) >= 1 && (text[0] == '\'' || text[0] == '.') {
			out.WriteString("\\&")
		}

		// directly copy normal characters
		org := i

		for i < len(text) && !needsBackslash(text[i]) {
			i++
		}
		if i > org {
			out.Write(text[org:i])
		}

		// escape a character
		if i >= len(text) {
			break
		}
		out.WriteByte('\\')
		out.WriteByte(text[i])
	}
}
<|endoftext|>


<commit_before>package libkbfs

import (
	"sort"

	"golang.org/x/net/context"
)

const (
	defaultIndirectPointerPrefetchCount int = 20
	fileIndirectBlockPrefetchPriority   int = -100
	dirEntryPrefetchPriority            int = -200
)

type dirEntries []DirEntry
type dirEntriesBySizeAsc struct{ dirEntries }
type dirEntriesBySizeDesc struct{ dirEntries }

func (d dirEntries) Len() int                     { return len(d) }
func (d dirEntries) Swap(i, j int)                { d[i], d[j] = d[j], d[i] }
func (d dirEntriesBySizeAsc) Less(i, j int) bool  { return d.dirEntries[i].Size < d.dirEntries[j].Size }
func (d dirEntriesBySizeDesc) Less(i, j int) bool { return d.dirEntries[i].Size > d.dirEntries[j].Size }

func dirEntryMapToDirEntries(entryMap map[string]DirEntry) dirEntries {
	dirEntries := make(dirEntries, 0, len(entryMap))
	for _, entry := range entryMap {
		dirEntries = append(dirEntries, entry)
	}
	return dirEntries
}

type prefetcher interface {
	HandleBlock(b Block, kmd KeyMetadata, priority int) error
}

var _ prefetcher = (*blockPrefetcher)(nil)

type blockPrefetcher struct {
	retriever blockRetriever
}

func newPrefetcher(retriever blockRetriever) prefetcher {
	return &blockPrefetcher{
		retriever: retriever,
	}
}

func (p *blockPrefetcher) HandleBlock(b Block, kmd KeyMetadata, priority int) error {
	switch b := b.(type) {
	case *FileBlock:
		// If this is an indirect block and the priority is on demand, prefetch
		// the first <n> indirect block pointers.
		// TODO: do something smart with subsequent blocks.
		if b.IsInd && priority >= defaultOnDemandRequestPriority {
			numIPtrs := len(b.IPtrs)
			if numIPtrs > defaultIndirectPointerPrefetchCount {
				numIPtrs = defaultIndirectPointerPrefetchCount
			}
			for _, ptr := range b.IPtrs[:numIPtrs] {
				p.request(fileIndirectBlockPrefetchPriority, kmd,
					ptr.BlockPointer, NewFileBlock(), TransientEntry)
			}
		}
	case *DirBlock:
		// If this is an on-demand request:
		// - If the block is indirect, prefetch the first <n> indirect block
		// pointers.
		// - If the block is direct (has Children), prefetch all DirEntry root
		// blocks.
		if priority >= defaultOnDemandRequestPriority {
			if b.IsInd {
				numIPtrs := len(b.IPtrs)
				if numIPtrs > defaultIndirectPointerPrefetchCount {
					numIPtrs = defaultIndirectPointerPrefetchCount
				}
				for _, ptr := range b.IPtrs[:numIPtrs] {
					p.request(fileIndirectBlockPrefetchPriority, kmd,
						ptr.BlockPointer, NewFileBlock(), TransientEntry)
				}
			} else {
				dirEntries := dirEntriesBySizeAsc{dirEntryMapToDirEntries(b.Children)}
				sort.Sort(dirEntries)
				for i, entry := range dirEntries.dirEntries {
					// Prioritize small files
					priority := dirEntryPrefetchPriority - i
					var block Block
					switch entry.Type {
					case Dir:
						block = NewDirBlock()
					case File:
						block = NewFileBlock()
					case Exec:
						block = NewFileBlock()
					default:
						continue
					}
					p.request(priority, kmd, entry.BlockPointer,
						block, TransientEntry)
				}
			}
		}
	default:
	}
	return nil
}

func (p *blockPrefetcher) request(priority int, kmd KeyMetadata, ptr BlockPointer, block Block, lifetime BlockCacheLifetime) {
	// TODO: track these requests and do something intelligent with
	// cancellation
	ctx := context.Background()
	// Returns a buffered channel, so we don't need to read from it.
	_ = p.retriever.Request(ctx, priority, kmd, ptr, block, lifetime)
}
<commit_msg>prefetcher: refactor to make the various prefetch scenarios testable<commit_after>package libkbfs

import (
	"sort"

	"golang.org/x/net/context"
)

const (
	defaultIndirectPointerPrefetchCount int = 20
	fileIndirectBlockPrefetchPriority   int = -100
	dirEntryPrefetchPriority            int = -200
)

type dirEntries []DirEntry
type dirEntriesBySizeAsc struct{ dirEntries }
type dirEntriesBySizeDesc struct{ dirEntries }

func (d dirEntries) Len() int                     { return len(d) }
func (d dirEntries) Swap(i, j int)                { d[i], d[j] = d[j], d[i] }
func (d dirEntriesBySizeAsc) Less(i, j int) bool  { return d.dirEntries[i].Size < d.dirEntries[j].Size }
func (d dirEntriesBySizeDesc) Less(i, j int) bool { return d.dirEntries[i].Size > d.dirEntries[j].Size }

func dirEntryMapToDirEntries(entryMap map[string]DirEntry) dirEntries {
	dirEntries := make(dirEntries, 0, len(entryMap))
	for _, entry := range entryMap {
		dirEntries = append(dirEntries, entry)
	}
	return dirEntries
}

type prefetcher interface {
	HandleBlock(b Block, kmd KeyMetadata, priority int)
}

var _ prefetcher = (*blockPrefetcher)(nil)

type blockPrefetcher struct {
	retriever blockRetriever
}

func newPrefetcher(retriever blockRetriever) prefetcher {
	return &blockPrefetcher{
		retriever: retriever,
	}
}

func (p *blockPrefetcher) prefetchIndirectFileBlock(b *FileBlock, kmd KeyMetadata, priority int) {
	// prefetch the first <n> indirect block pointers.
	// TODO: do something smart with subsequent blocks.
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, NewFileBlock(), TransientEntry)
	}
}

func (p *blockPrefetcher) prefetchIndirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	numIPtrs := len(b.IPtrs)
	if numIPtrs > defaultIndirectPointerPrefetchCount {
		numIPtrs = defaultIndirectPointerPrefetchCount
	}
	for _, ptr := range b.IPtrs[:numIPtrs] {
		p.request(fileIndirectBlockPrefetchPriority, kmd,
			ptr.BlockPointer, NewFileBlock(), TransientEntry)
	}
}

func (p *blockPrefetcher) prefetchDirectDirBlock(b *DirBlock, kmd KeyMetadata, priority int) {
	dirEntries := dirEntriesBySizeAsc{dirEntryMapToDirEntries(b.Children)}
	sort.Sort(dirEntries)
	for i, entry := range dirEntries.dirEntries {
		// Prioritize small files
		priority := dirEntryPrefetchPriority - i
		var block Block
		switch entry.Type {
		case Dir:
			block = NewDirBlock()
		case File:
			block = NewFileBlock()
		case Exec:
			block = NewFileBlock()
		default:
			continue
		}
		p.request(priority, kmd, entry.BlockPointer,
			block, TransientEntry)
	}
}

func (p *blockPrefetcher) HandleBlock(b Block, kmd KeyMetadata, priority int) {
	switch b := b.(type) {
	case *FileBlock:
		if b.IsInd && priority >= defaultOnDemandRequestPriority {
			p.prefetchIndirectFileBlock(b, kmd, priority)
		}
	case *DirBlock:
		// If this is an on-demand request:
		// - If the block is indirect, prefetch the first <n> indirect block
		// pointers.
		// - If the block is direct (has Children), prefetch all DirEntry root
		// blocks.
		if priority >= defaultOnDemandRequestPriority {
			if b.IsInd {
				p.prefetchIndirectDirBlock(b, kmd, priority)
			} else {
				p.prefetchDirectDirBlock(b, kmd, priority)
			}
		}
	default:
	}
}

func (p *blockPrefetcher) request(priority int, kmd KeyMetadata, ptr BlockPointer, block Block, lifetime BlockCacheLifetime) {
	// TODO: track these requests and do something intelligent with
	// cancellation
	ctx := context.Background()
	// Returns a buffered channel, so we don't need to read from it.
	_ = p.retriever.Request(ctx, priority, kmd, ptr, block, lifetime)
}
<|endoftext|>


<commit_before>package regsrc

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
)

var (
	ErrInvalidModuleSource = errors.New("not a valid registry module source")

	// nameSubRe is the sub-expression that matches a valid module namespace or
	// name. It's strictly a super-set of what GitHub allows for user/org and
	// repo names respectively, but more restrictive than our original repo-name
	// regex which allowed periods but could cause ambiguity with hostname
	// prefixes. It does not anchor the start or end so it can be composed into
	// more complex RegExps below. Alphanumeric with - and _ allowed in non
	// leading or trailing positions. Max length 64 chars. (GitHub username is
	// 38 max.)
	nameSubRe = "[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?"

	// providerSubRe is the sub-expression that matches a valid provider. It
	// does not anchor the start or end so it can be composed into more complex
	// RegExps below. Only lowercase chars and digits are supported in practice.
	// Max length 64 chars.
	providerSubRe = "[0-9a-z]{1,64}"

	// moduleSourceRe is a regular expression that matches the basic
	// namespace/name/provider[//...] format for registry sources. It assumes
	// any FriendlyHost prefix has already been removed if present.
	moduleSourceRe = regexp.MustCompile(
		fmt.Sprintf("^(%s)\\/(%s)\\/(%s)(?:\\/\\/(.*))?$",
			nameSubRe, nameSubRe, providerSubRe))

	// NameRe is a regular expression defining the format allowed for namespace
	// or name fields in module registry implementations.
	NameRe = regexp.MustCompile("^" + nameSubRe + "$")

	// ProviderRe is a regular expression defining the format allowed for
	// provider fields in module registry implementations.
	ProviderRe = regexp.MustCompile("^" + providerSubRe + "$")

	// these hostnames are not allowed as registry sources, because they are
	// already special case module sources in terraform.
	disallowed = map[string]bool{
		"github.com":    true,
		"bitbucket.org": true,
	}
)

// Module describes a Terraform Registry Module source.
type Module struct {
	// RawHost is the friendly host prefix if one was present. It might be nil
	// if the original source had no host prefix which implies
	// PublicRegistryHost but is distinct from having an actual pointer to
	// PublicRegistryHost since it encodes the fact the original string didn't
	// include a host prefix at all which is significant for recovering actual
	// input not just normalized form. Most callers should access it with Host()
	// which will return public registry host instance if it's nil.
	RawHost      *FriendlyHost
	RawNamespace string
	RawName      string
	RawProvider  string
	RawSubmodule string
}

// NewModule construct a new module source from separate parts. Pass empty
// string if host or submodule are not needed.
func NewModule(host, namespace, name, provider, submodule string) (*Module, error) {
	m := &Module{
		RawNamespace: namespace,
		RawName:      name,
		RawProvider:  provider,
		RawSubmodule: submodule,
	}
	if host != "" {
		h := NewFriendlyHost(host)
		if h != nil {
			fmt.Println("HOST:", h)
			if !h.Valid() || disallowed[h.Display()] {
				return nil, ErrInvalidModuleSource
			}
		}
		m.RawHost = h
	}
	return m, nil
}

// ParseModuleSource attempts to parse source as a Terraform registry module
// source. If the string is not found to be in a valid format,
// ErrInvalidModuleSource is returned. Note that this can only be used on
// "input" strings, e.g. either ones supplied by the user or potentially
// normalised but in Display form (unicode). It will fail to parse a source with
// a punycoded domain since this is not permitted input from a user. If you have
// an already normalized string internally, you can compare it without parsing
// by comparing with the normalized version of the subject with the normal
// string equality operator.
func ParseModuleSource(source string) (*Module, error) {
	// See if there is a friendly host prefix.
	host, rest := ParseFriendlyHost(source)
	if host != nil {
		if !host.Valid() || disallowed[host.Display()] {
			return nil, ErrInvalidModuleSource
		}
	}

	matches := moduleSourceRe.FindStringSubmatch(rest)
	if len(matches) < 4 {
		return nil, ErrInvalidModuleSource
	}

	m := &Module{
		RawHost:      host,
		RawNamespace: matches[1],
		RawName:      matches[2],
		RawProvider:  matches[3],
	}

	if len(matches) == 5 {
		m.RawSubmodule = matches[4]
	}

	return m, nil
}

// Display returns the source formatted for display to the user in CLI or web
// output.
func (m *Module) Display() string {
	return m.formatWithPrefix(m.normalizedHostPrefix(m.Host().Display()), false)
}

// Normalized returns the source formatted for internal reference or comparison.
func (m *Module) Normalized() string {
	return m.formatWithPrefix(m.normalizedHostPrefix(m.Host().Normalized()), false)
}

// String returns the source formatted as the user originally typed it assuming
// it was parsed from user input.
func (m *Module) String() string {
	// Don't normalize public registry hostname - leave it exactly like the user
	// input it.
	hostPrefix := ""
	if m.RawHost != nil {
		hostPrefix = m.RawHost.String() + "/"
	}
	return m.formatWithPrefix(hostPrefix, true)
}

// Equal compares the module source against another instance taking
// normalization into account.
func (m *Module) Equal(other *Module) bool {
	return m.Normalized() == other.Normalized()
}

// Host returns the FriendlyHost object describing which registry this module is
// in. If the original source string had not host component this will return the
// PublicRegistryHost.
func (m *Module) Host() *FriendlyHost {
	if m.RawHost == nil {
		return PublicRegistryHost
	}
	return m.RawHost
}

func (m *Module) normalizedHostPrefix(host string) string {
	if m.Host().Equal(PublicRegistryHost) {
		return ""
	}
	return host + "/"
}

func (m *Module) formatWithPrefix(hostPrefix string, preserveCase bool) string {
	suffix := ""
	if m.RawSubmodule != "" {
		suffix = "//" + m.RawSubmodule
	}
	str := fmt.Sprintf("%s%s/%s/%s%s", hostPrefix, m.RawNamespace, m.RawName,
		m.RawProvider, suffix)

	// lower case by default
	if !preserveCase {
		return strings.ToLower(str)
	}
	return str
}
<commit_msg>add Module method for module name only<commit_after>package regsrc

import (
	"errors"
	"fmt"
	"regexp"
	"strings"
)

var (
	ErrInvalidModuleSource = errors.New("not a valid registry module source")

	// nameSubRe is the sub-expression that matches a valid module namespace or
	// name. It's strictly a super-set of what GitHub allows for user/org and
	// repo names respectively, but more restrictive than our original repo-name
	// regex which allowed periods but could cause ambiguity with hostname
	// prefixes. It does not anchor the start or end so it can be composed into
	// more complex RegExps below. Alphanumeric with - and _ allowed in non
	// leading or trailing positions. Max length 64 chars. (GitHub username is
	// 38 max.)
	nameSubRe = "[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?"

	// providerSubRe is the sub-expression that matches a valid provider. It
	// does not anchor the start or end so it can be composed into more complex
	// RegExps below. Only lowercase chars and digits are supported in practice.
	// Max length 64 chars.
	providerSubRe = "[0-9a-z]{1,64}"

	// moduleSourceRe is a regular expression that matches the basic
	// namespace/name/provider[//...] format for registry sources. It assumes
	// any FriendlyHost prefix has already been removed if present.
	moduleSourceRe = regexp.MustCompile(
		fmt.Sprintf("^(%s)\\/(%s)\\/(%s)(?:\\/\\/(.*))?$",
			nameSubRe, nameSubRe, providerSubRe))

	// NameRe is a regular expression defining the format allowed for namespace
	// or name fields in module registry implementations.
	NameRe = regexp.MustCompile("^" + nameSubRe + "$")

	// ProviderRe is a regular expression defining the format allowed for
	// provider fields in module registry implementations.
	ProviderRe = regexp.MustCompile("^" + providerSubRe + "$")

	// these hostnames are not allowed as registry sources, because they are
	// already special case module sources in terraform.
	disallowed = map[string]bool{
		"github.com":    true,
		"bitbucket.org": true,
	}
)

// Module describes a Terraform Registry Module source.
type Module struct {
	// RawHost is the friendly host prefix if one was present. It might be nil
	// if the original source had no host prefix which implies
	// PublicRegistryHost but is distinct from having an actual pointer to
	// PublicRegistryHost since it encodes the fact the original string didn't
	// include a host prefix at all which is significant for recovering actual
	// input not just normalized form. Most callers should access it with Host()
	// which will return public registry host instance if it's nil.
	RawHost      *FriendlyHost
	RawNamespace string
	RawName      string
	RawProvider  string
	RawSubmodule string
}

// NewModule construct a new module source from separate parts. Pass empty
// string if host or submodule are not needed.
func NewModule(host, namespace, name, provider, submodule string) (*Module, error) {
	m := &Module{
		RawNamespace: namespace,
		RawName:      name,
		RawProvider:  provider,
		RawSubmodule: submodule,
	}
	if host != "" {
		h := NewFriendlyHost(host)
		if h != nil {
			fmt.Println("HOST:", h)
			if !h.Valid() || disallowed[h.Display()] {
				return nil, ErrInvalidModuleSource
			}
		}
		m.RawHost = h
	}
	return m, nil
}

// ParseModuleSource attempts to parse source as a Terraform registry module
// source. If the string is not found to be in a valid format,
// ErrInvalidModuleSource is returned. Note that this can only be used on
// "input" strings, e.g. either ones supplied by the user or potentially
// normalised but in Display form (unicode). It will fail to parse a source with
// a punycoded domain since this is not permitted input from a user. If you have
// an already normalized string internally, you can compare it without parsing
// by comparing with the normalized version of the subject with the normal
// string equality operator.
func ParseModuleSource(source string) (*Module, error) {
	// See if there is a friendly host prefix.
	host, rest := ParseFriendlyHost(source)
	if host != nil {
		if !host.Valid() || disallowed[host.Display()] {
			return nil, ErrInvalidModuleSource
		}
	}

	matches := moduleSourceRe.FindStringSubmatch(rest)
	if len(matches) < 4 {
		return nil, ErrInvalidModuleSource
	}

	m := &Module{
		RawHost:      host,
		RawNamespace: matches[1],
		RawName:      matches[2],
		RawProvider:  matches[3],
	}

	if len(matches) == 5 {
		m.RawSubmodule = matches[4]
	}

	return m, nil
}

// Display returns the source formatted for display to the user in CLI or web
// output.
func (m *Module) Display() string {
	return m.formatWithPrefix(m.normalizedHostPrefix(m.Host().Display()), false)
}

// Normalized returns the source formatted for internal reference or comparison.
func (m *Module) Normalized() string {
	return m.formatWithPrefix(m.normalizedHostPrefix(m.Host().Normalized()), false)
}

// String returns the source formatted as the user originally typed it assuming
// it was parsed from user input.
func (m *Module) String() string {
	// Don't normalize public registry hostname - leave it exactly like the user
	// input it.
	hostPrefix := ""
	if m.RawHost != nil {
		hostPrefix = m.RawHost.String() + "/"
	}
	return m.formatWithPrefix(hostPrefix, true)
}

// Equal compares the module source against another instance taking
// normalization into account.
func (m *Module) Equal(other *Module) bool {
	return m.Normalized() == other.Normalized()
}

// Host returns the FriendlyHost object describing which registry this module is
// in. If the original source string had not host component this will return the
// PublicRegistryHost.
func (m *Module) Host() *FriendlyHost {
	if m.RawHost == nil {
		return PublicRegistryHost
	}
	return m.RawHost
}

func (m *Module) normalizedHostPrefix(host string) string {
	if m.Host().Equal(PublicRegistryHost) {
		return ""
	}
	return host + "/"
}

func (m *Module) formatWithPrefix(hostPrefix string, preserveCase bool) string {
	suffix := ""
	if m.RawSubmodule != "" {
		suffix = "//" + m.RawSubmodule
	}
	str := fmt.Sprintf("%s%s/%s/%s%s", hostPrefix, m.RawNamespace, m.RawName,
		m.RawProvider, suffix)

	// lower case by default
	if !preserveCase {
		return strings.ToLower(str)
	}
	return str
}

// Module returns just the registry ID of the module, without a hostname or
// suffix.
func (m *Module) Module() string {
	return fmt.Sprintf("%s/%s/%s", m.RawNamespace, m.RawName, m.RawProvider)
}
<|endoftext|>


<commit_before>package libvirt

import (
	"encoding/xml"
)

type defDomain struct {
	XMLName  xml.Name  `xml:"domain"`
	Name     string    `xml:"name"`
	Type     string    `xml:"type,attr"`
	Os       defOs     `xml:"os"`
	Memory   defMemory `xml:"memory"`
	VCpu     defVCpu   `xml:"vcpu"`
	Metadata struct {
		XMLName          xml.Name `xml:"metadata"`
		TerraformLibvirt defMetadata
	}
	Features struct {
		Acpi string `xml:"acpi"`
		Apic string `xml:"apic"`
		Pae  string `xml:"pae"`
	} `xml:"features"`
	Devices struct {
		Disks             []defDisk             `xml:"disk"`
		NetworkInterfaces []defNetworkInterface `xml:"interface"`
		Spice             struct {
			Type     string `xml:"type,attr"`
			Autoport string `xml:"autoport,attr"`
		} `xml:"graphics"`
		// QEMU guest agent channel
		QemuGAChannel struct {
			Type   string `xml:"type,attr"`
			Source struct {
				Mode string `xml:"mode,attr"`
			} `xml:"source"`
			Target struct {
				Type string `xml:"type,attr"`
				Name string `xml:"name,attr"`
			} `xml:"target"`
		} `xml:"channel"`
		Rng struct {
			Model   string `xml:"model,attr"`
			Backend struct {
				Model string `xml:"model,attr"`
			} `xml:"backend"`
		} `xml:"rng"`
	} `xml:"devices"`
}

type defMetadata struct {
	XMLName xml.Name `xml:"http://github.com/dmacvicar/terraform-provider-libvirt/ user_data"`
	Xml     string   `xml:",cdata"`
}

type defOs struct {
	Type   defOsType  `xml:"type"`
	Loader *defLoader `xml:"loader,omitempty"`
	NvRam  *defNvRam  `xml:"nvram,omitempty"`
}

type defOsType struct {
	Arch    string `xml:"arch,attr,omitempty"`
	Machine string `xml:"machine,attr,omitempty"`
	Name    string `xml:",chardata"`
}

type defMemory struct {
	Unit   string `xml:"unit,attr"`
	Amount int    `xml:",chardata"`
}

type defVCpu struct {
	Placement string `xml:"unit,attr"`
	Amount    int    `xml:",chardata"`
}

type defLoader struct {
	ReadOnly string `xml:"readonly,attr,omitempty"`
	Type     string `xml:"type,attr,omitempty"`
	File     string `xml:",chardata"`
}

// <nvram>/var/lib/libvirt/qemu/nvram/sled12sp1_VARS.fd</nvram>
type defNvRam struct {
	File string `xml:",chardata"`
}

// Creates a domain definition with the defaults
// the provider uses
func newDomainDef() defDomain {
	// libvirt domain definition
	domainDef := defDomain{}
	domainDef.Type = "kvm"

	domainDef.Os = defOs{}
	domainDef.Os.Type = defOsType{}
	domainDef.Os.Type.Name = "hvm"

	domainDef.Memory = defMemory{}
	domainDef.Memory.Unit = "MiB"
	domainDef.Memory.Amount = 512

	domainDef.VCpu = defVCpu{}
	domainDef.VCpu.Placement = "static"
	domainDef.VCpu.Amount = 1

	domainDef.Devices.Spice.Type = "spice"
	domainDef.Devices.Spice.Autoport = "yes"

	domainDef.Devices.QemuGAChannel.Type = "unix"
	domainDef.Devices.QemuGAChannel.Source.Mode = "bind"
	domainDef.Devices.QemuGAChannel.Target.Type = "virtio"
	domainDef.Devices.QemuGAChannel.Target.Name = "org.qemu.guest_agent.0"

	domainDef.Devices.Rng.Model = "virtio"
	domainDef.Devices.Rng.Backend.Model = "random"

	return domainDef
}
<commit_msg>Specify listen option with none type value. This will avoid slotting a spice connection.<commit_after>package libvirt

import (
	"encoding/xml"
)

type defDomain struct {
	XMLName  xml.Name  `xml:"domain"`
	Name     string    `xml:"name"`
	Type     string    `xml:"type,attr"`
	Os       defOs     `xml:"os"`
	Memory   defMemory `xml:"memory"`
	VCpu     defVCpu   `xml:"vcpu"`
	Metadata struct {
		XMLName          xml.Name `xml:"metadata"`
		TerraformLibvirt defMetadata
	}
	Features struct {
		Acpi string `xml:"acpi"`
		Apic string `xml:"apic"`
		Pae  string `xml:"pae"`
	} `xml:"features"`
	Devices struct {
		Disks             []defDisk             `xml:"disk"`
		NetworkInterfaces []defNetworkInterface `xml:"interface"`
		Graphics struct {
			Type   string `xml:"type,attr"`
			Listen struct {
				Type string `xml:"type,attr"`
			} `xml:"listen"`
		} `xml:"graphics"`
		// QEMU guest agent channel
		QemuGAChannel struct {
			Type   string `xml:"type,attr"`
			Source struct {
				Mode string `xml:"mode,attr"`
			} `xml:"source"`
			Target struct {
				Type string `xml:"type,attr"`
				Name string `xml:"name,attr"`
			} `xml:"target"`
		} `xml:"channel"`
		Rng struct {
			Model   string `xml:"model,attr"`
			Backend struct {
				Model string `xml:"model,attr"`
			} `xml:"backend"`
		} `xml:"rng"`
	} `xml:"devices"`
}

type defMetadata struct {
	XMLName xml.Name `xml:"http://github.com/dmacvicar/terraform-provider-libvirt/ user_data"`
	Xml     string   `xml:",cdata"`
}

type defOs struct {
	Type   defOsType  `xml:"type"`
	Loader *defLoader `xml:"loader,omitempty"`
	NvRam  *defNvRam  `xml:"nvram,omitempty"`
}

type defOsType struct {
	Arch    string `xml:"arch,attr,omitempty"`
	Machine string `xml:"machine,attr,omitempty"`
	Name    string `xml:",chardata"`
}

type defMemory struct {
	Unit   string `xml:"unit,attr"`
	Amount int    `xml:",chardata"`
}

type defVCpu struct {
	Placement string `xml:"unit,attr"`
	Amount    int    `xml:",chardata"`
}

type defLoader struct {
	ReadOnly string `xml:"readonly,attr,omitempty"`
	Type     string `xml:"type,attr,omitempty"`
	File     string `xml:",chardata"`
}

// <nvram>/var/lib/libvirt/qemu/nvram/sled12sp1_VARS.fd</nvram>
type defNvRam struct {
	File string `xml:",chardata"`
}

// Creates a domain definition with the defaults
// the provider uses
func newDomainDef() defDomain {
	// libvirt domain definition
	domainDef := defDomain{}
	domainDef.Type = "kvm"

	domainDef.Os = defOs{}
	domainDef.Os.Type = defOsType{}
	domainDef.Os.Type.Name = "hvm"

	domainDef.Memory = defMemory{}
	domainDef.Memory.Unit = "MiB"
	domainDef.Memory.Amount = 512

	domainDef.VCpu = defVCpu{}
	domainDef.VCpu.Placement = "static"
	domainDef.VCpu.Amount = 1

	domainDef.Devices.Graphics.Type = "spice"
	domainDef.Devices.Graphics.Listen.Type = "none"

	domainDef.Devices.QemuGAChannel.Type = "unix"
	domainDef.Devices.QemuGAChannel.Source.Mode = "bind"
	domainDef.Devices.QemuGAChannel.Target.Type = "virtio"
	domainDef.Devices.QemuGAChannel.Target.Name = "org.qemu.guest_agent.0"

	domainDef.Devices.Rng.Model = "virtio"
	domainDef.Devices.Rng.Backend.Model = "random"

	return domainDef
}
<|endoftext|>


<commit_before>package view

import (
	"fmt"
	"html/template"
	"io"
	"path/filepath"
	"strings"
	"sync"

	"github.com/eknkc/amber"
)

// AmberEngine contains the amber view engine structure.
type AmberEngine struct {
	// files configuration
	directory string
	extension string
	assetFn   func(name string) ([]byte, error) // for embedded, in combination with directory & extension
	namesFn   func() []string                   // for embedded, in combination with directory & extension
	reload    bool
	//
	rmu           sync.RWMutex // locks for funcs
	funcs         map[string]interface{}
	mu            sync.Mutex // locks for template files load
	templateCache map[string]*template.Template
}

var _ Engine = &AmberEngine{}

// Amber creates and returns a new amber view engine.
func Amber(directory, extension string) *AmberEngine {
	s := &AmberEngine{
		directory:     directory,
		extension:     extension,
		templateCache: make(map[string]*template.Template, 0),
		funcs:         make(map[string]interface{}, 0),
	}

	return s
}

// Ext returns the file extension which this view engine is responsible to render.
func (s *AmberEngine) Ext() string {
	return s.extension
}

// Binary optionally, use it when template files are distributed
// inside the app executable (.go generated files).
//
// The assetFn and namesFn can come from the go-bindata library.
func (s *AmberEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *AmberEngine {
	s.assetFn, s.namesFn = assetFn, namesFn
	return s
}

// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
func (s *AmberEngine) Reload(developmentMode bool) *AmberEngine {
	s.reload = developmentMode
	return s
}

// AddFunc adds the function to the template's function map.
// It is legal to overwrite elements of the default actions:
// - url func(routeName string, args ...string) string
// - urlpath func(routeName string, args ...string) string
// - render func(fullPartialName string) (template.HTML, error).
func (s *AmberEngine) AddFunc(funcName string, funcBody interface{}) {
	s.rmu.Lock()
	s.funcs[funcName] = funcBody
	s.rmu.Unlock()
}

// Load parses the templates to the engine.
// It's alos responsible to add the necessary global functions.
//
// Returns an error if something bad happens, user is responsible to catch it.
func (s *AmberEngine) Load() error {
	if s.assetFn != nil && s.namesFn != nil {
		// embedded
		return s.loadAssets()
	}

	// load from directory, make the dir absolute here too.
	dir, err := filepath.Abs(s.directory)
	if err != nil {
		return err
	}
	// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
	s.directory = dir
	return s.loadDirectory()
}

// loadDirectory loads the amber templates from directory.
func (s *AmberEngine) loadDirectory() error {
	dir, extension := s.directory, s.extension

	opt := amber.DirOptions{}
	opt.Recursive = true

	// prepare the global amber funcs
	funcs := template.FuncMap{}

	for k, v := range amber.FuncMap { // add the amber's default funcs
		funcs[k] = v
	}

	for k, v := range s.funcs {
		funcs[k] = v
	}

	amber.FuncMap = funcs //set the funcs
	opt.Ext = extension

	templates, err := amber.CompileDir(dir, opt, amber.DefaultOptions) // this returns the map with stripped extension, we want extension so we copy the map
	if err == nil {
		s.mu.Lock()
		defer s.mu.Unlock()
		s.templateCache = make(map[string]*template.Template)
		for k, v := range templates {
			name := filepath.ToSlash(k + opt.Ext)
			s.templateCache[name] = v
			delete(templates, k)
		}

	}
	return err
}

// loadAssets builds the templates by binary, embedded.
func (s *AmberEngine) loadAssets() error {
	virtualDirectory, virtualExtension := s.directory, s.extension
	assetFn, namesFn := s.assetFn, s.namesFn

	// prepare the global amber funcs
	funcs := template.FuncMap{}

	for k, v := range amber.FuncMap { // add the amber's default funcs
		funcs[k] = v
	}

	for k, v := range s.funcs {
		funcs[k] = v
	}

	if len(virtualDirectory) > 0 {
		if virtualDirectory[0] == '.' { // first check for .wrong
			virtualDirectory = virtualDirectory[1:]
		}
		if virtualDirectory[0] == '/' || virtualDirectory[0] == filepath.Separator { // second check for /something, (or ./something if we had dot on 0 it will be removed
			virtualDirectory = virtualDirectory[1:]
		}
	}
	amber.FuncMap = funcs //set the funcs

	s.mu.Lock()
	defer s.mu.Unlock()

	names := namesFn()

	for _, path := range names {
		if !strings.HasPrefix(path, virtualDirectory) {
			continue
		}
		ext := filepath.Ext(path)
		if ext == virtualExtension {

			rel, err := filepath.Rel(virtualDirectory, path)
			if err != nil {
				return err
			}

			buf, err := assetFn(path)
			if err != nil {
				return err
			}

			name := filepath.ToSlash(rel)
			tmpl, err := amber.CompileData(buf, name, amber.DefaultOptions)

			if err != nil {
				return err
			}

			s.templateCache[name] = tmpl
		}
	}

	return nil
}

func (s *AmberEngine) fromCache(relativeName string) *template.Template {
	s.mu.Lock()
	tmpl, ok := s.templateCache[relativeName]
	if ok {
		s.mu.Unlock()
		return tmpl
	}
	s.mu.Unlock()
	return nil
}

// ExecuteWriter executes a template and writes its result to the w writer.
// layout here is useless.
func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
	// reload the templates if reload configuration field is true
	if s.reload {
		if err := s.Load(); err != nil {
			return err
		}
	}

	if tmpl := s.fromCache(filename); tmpl != nil {
		return tmpl.ExecuteTemplate(w, filename, bindingData)
	}

	return fmt.Errorf("Template with name %s doesn't exists in the dir", filename)
}
<commit_msg>Fix subfolder templating issue<commit_after>package view

import (
	"fmt"
	"html/template"
	"io"
	"path/filepath"
	"strings"
	"sync"

	"github.com/eknkc/amber"
)

// AmberEngine contains the amber view engine structure.
type AmberEngine struct {
	// files configuration
	directory string
	extension string
	assetFn   func(name string) ([]byte, error) // for embedded, in combination with directory & extension
	namesFn   func() []string                   // for embedded, in combination with directory & extension
	reload    bool
	//
	rmu           sync.RWMutex // locks for funcs
	funcs         map[string]interface{}
	mu            sync.Mutex // locks for template files load
	templateCache map[string]*template.Template
}

var _ Engine = &AmberEngine{}

// Amber creates and returns a new amber view engine.
func Amber(directory, extension string) *AmberEngine {
	s := &AmberEngine{
		directory:     directory,
		extension:     extension,
		templateCache: make(map[string]*template.Template, 0),
		funcs:         make(map[string]interface{}, 0),
	}

	return s
}

// Ext returns the file extension which this view engine is responsible to render.
func (s *AmberEngine) Ext() string {
	return s.extension
}

// Binary optionally, use it when template files are distributed
// inside the app executable (.go generated files).
//
// The assetFn and namesFn can come from the go-bindata library.
func (s *AmberEngine) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *AmberEngine {
	s.assetFn, s.namesFn = assetFn, namesFn
	return s
}

// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
func (s *AmberEngine) Reload(developmentMode bool) *AmberEngine {
	s.reload = developmentMode
	return s
}

// AddFunc adds the function to the template's function map.
// It is legal to overwrite elements of the default actions:
// - url func(routeName string, args ...string) string
// - urlpath func(routeName string, args ...string) string
// - render func(fullPartialName string) (template.HTML, error).
func (s *AmberEngine) AddFunc(funcName string, funcBody interface{}) {
	s.rmu.Lock()
	s.funcs[funcName] = funcBody
	s.rmu.Unlock()
}

// Load parses the templates to the engine.
// It's alos responsible to add the necessary global functions.
//
// Returns an error if something bad happens, user is responsible to catch it.
func (s *AmberEngine) Load() error {
	if s.assetFn != nil && s.namesFn != nil {
		// embedded
		return s.loadAssets()
	}

	// load from directory, make the dir absolute here too.
	dir, err := filepath.Abs(s.directory)
	if err != nil {
		return err
	}
	// change the directory field configuration, load happens after directory has been setted, so we will not have any problems here.
	s.directory = dir
	return s.loadDirectory()
}

// loadDirectory loads the amber templates from directory.
func (s *AmberEngine) loadDirectory() error {
	dir, extension := s.directory, s.extension

	opt := amber.DirOptions{}
	opt.Recursive = true

	// prepare the global amber funcs
	funcs := template.FuncMap{}

	for k, v := range amber.FuncMap { // add the amber's default funcs
		funcs[k] = v
	}

	for k, v := range s.funcs {
		funcs[k] = v
	}

	amber.FuncMap = funcs //set the funcs
	opt.Ext = extension

	templates, err := amber.CompileDir(dir, opt, amber.DefaultOptions) // this returns the map with stripped extension, we want extension so we copy the map
	if err == nil {
		s.mu.Lock()
		defer s.mu.Unlock()
		s.templateCache = make(map[string]*template.Template)
		for k, v := range templates {
			name := filepath.ToSlash(k + opt.Ext)
			s.templateCache[name] = v
			delete(templates, k)
		}

	}
	return err
}

// loadAssets builds the templates by binary, embedded.
func (s *AmberEngine) loadAssets() error {
	virtualDirectory, virtualExtension := s.directory, s.extension
	assetFn, namesFn := s.assetFn, s.namesFn

	// prepare the global amber funcs
	funcs := template.FuncMap{}

	for k, v := range amber.FuncMap { // add the amber's default funcs
		funcs[k] = v
	}

	for k, v := range s.funcs {
		funcs[k] = v
	}

	if len(virtualDirectory) > 0 {
		if virtualDirectory[0] == '.' { // first check for .wrong
			virtualDirectory = virtualDirectory[1:]
		}
		if virtualDirectory[0] == '/' || virtualDirectory[0] == filepath.Separator { // second check for /something, (or ./something if we had dot on 0 it will be removed
			virtualDirectory = virtualDirectory[1:]
		}
	}
	amber.FuncMap = funcs //set the funcs

	s.mu.Lock()
	defer s.mu.Unlock()

	names := namesFn()

	for _, path := range names {
		if !strings.HasPrefix(path, virtualDirectory) {
			continue
		}
		ext := filepath.Ext(path)
		if ext == virtualExtension {

			rel, err := filepath.Rel(virtualDirectory, path)
			if err != nil {
				return err
			}

			buf, err := assetFn(path)
			if err != nil {
				return err
			}

			name := filepath.ToSlash(rel)
			tmpl, err := amber.CompileData(buf, name, amber.DefaultOptions)

			if err != nil {
				return err
			}

			s.templateCache[name] = tmpl
		}
	}

	return nil
}

func (s *AmberEngine) fromCache(relativeName string) *template.Template {
	s.mu.Lock()
	tmpl, ok := s.templateCache[relativeName]
	if ok {
		s.mu.Unlock()
		return tmpl
	}
	s.mu.Unlock()
	return nil
}

// ExecuteWriter executes a template and writes its result to the w writer.
// layout here is useless.
func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
	// reload the templates if reload configuration field is true
	if s.reload {
		if err := s.Load(); err != nil {
			return err
		}
	}

	if tmpl := s.fromCache(filename); tmpl != nil {
		return tmpl.Execute(w, bindingData)
	}

	return fmt.Errorf("Template with name %s doesn't exists in the dir", filename)
}
<|endoftext|>


<commit_before>package tracer

import (
	"bytes"
	"testing"
)

func TestBinary(t *testing.T) {
	sp := &Span{
		RawSpan: RawSpan{
			SpanID:   1,
			ParentID: 2,
			TraceID:  3,
			Baggage: map[string]string{
				"k1": "v1",
				"k2": "",
			},
		},
	}
	buf := &bytes.Buffer{}
	if err := binaryInjecter(sp, buf); err != nil {
		t.Fatal("unexpected error: ", err)
	}
	traceID, parentID, spanID, baggage, err := binaryJoiner(buf)
	if err != nil {
		t.Fatal("unexpected error: ", err)
	}
	if traceID != sp.TraceID || parentID != sp.ParentID || spanID != sp.SpanID ||
		len(baggage) != 2 || baggage["k1"] != "v1" || baggage["k2"] != "" {

		t.Errorf("got (%d, %d, %d, %v), want (%d, %d, %d, %v)",
			traceID, parentID, spanID, baggage,
			sp.TraceID, sp.ParentID, sp.SpanID, sp.Baggage)
	}
}
<commit_msg>Add test for text carrier<commit_after>package tracer

import (
	"bytes"
	"testing"

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

func TestText(t *testing.T) {
	sp := &Span{
		RawSpan: RawSpan{
			SpanID:   1,
			ParentID: 2,
			TraceID:  3,
			Baggage: map[string]string{
				"k1": "v1",
				"k2": "",
			},
		},
	}

	carrier := opentracing.TextMapCarrier{}
	if err := textInjecter(sp, carrier); err != nil {
		t.Fatal("unexpected error: ", err)
	}
	traceID, parentID, spanID, baggage, err := textJoiner(carrier)
	if err != nil {
		t.Fatal("unexpected error: ", err)
	}
	if traceID != sp.TraceID || parentID != sp.ParentID || spanID != sp.SpanID ||
		len(baggage) != 2 || baggage["k1"] != "v1" || baggage["k2"] != "" {

		t.Errorf("got (%d, %d, %d, %v), want (%d, %d, %d, %v)",
			traceID, parentID, spanID, baggage,
			sp.TraceID, sp.ParentID, sp.SpanID, sp.Baggage)
	}
}

func TestBinary(t *testing.T) {
	sp := &Span{
		RawSpan: RawSpan{
			SpanID:   1,
			ParentID: 2,
			TraceID:  3,
			Baggage: map[string]string{
				"k1": "v1",
				"k2": "",
			},
		},
	}
	buf := &bytes.Buffer{}
	if err := binaryInjecter(sp, buf); err != nil {
		t.Fatal("unexpected error: ", err)
	}
	traceID, parentID, spanID, baggage, err := binaryJoiner(buf)
	if err != nil {
		t.Fatal("unexpected error: ", err)
	}
	if traceID != sp.TraceID || parentID != sp.ParentID || spanID != sp.SpanID ||
		len(baggage) != 2 || baggage["k1"] != "v1" || baggage["k2"] != "" {

		t.Errorf("got (%d, %d, %d, %v), want (%d, %d, %d, %v)",
			traceID, parentID, spanID, baggage,
			sp.TraceID, sp.ParentID, sp.SpanID, sp.Baggage)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
)

func NewTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("new-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func DeleteTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("delete-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func TransactionHash(name string) (string, error) {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("transaction-hash", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}
	type transactionResponse struct {
		Name           string `json:"tx-name"`
		TxID           string `json:"txid,omitempty"`
		TotalInputs    uint64 `json:"totalinputs"`
		TotalOutputs   uint64 `json:"totaloutputs"`
		TotalECOutputs uint64 `json:"totalecoutputs"`
	}
	tx := new(transactionResponse)
	if err := json.Unmarshal(resp.JSONResult(), tx); err != nil {
		return "", err
	}

	return tx.TxID, nil
}

func ListTransactions() ([]string, error) {
	type transactionResponse struct {
		Name           string `json:"tx-name"`
		TxID           string `json:"txid,omitempty"`
		TotalInputs    uint64 `json:"totalinputs"`
		TotalOutputs   uint64 `json:"totaloutputs"`
		TotalECOutputs uint64 `json:"totalecoutputs"`
	}

	type multiTransactionResponse struct {
		Transactions []transactionResponse `json:"transactions"`
	}

	req := NewJSON2Request("transactions", apiCounter(), nil)
	resp, err := walletRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	r := make([]string, 0)
	txs := new(multiTransactionResponse)
	if err := json.Unmarshal(resp.JSONResult(), txs); err != nil {
		return nil, err
	}
	for _, tx := range txs.Transactions {
		r = append(r, fmt.Sprintf("%#v", tx))
	}
	return r, nil
}

func AddTransactionInput(name, address string, amount uint64) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-input", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionOutput(name, address string, amount uint64) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-output", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionECOutput(name, address string, amount uint64) error {
	if AddressStringType(address) != ECPub {
		return fmt.Errorf("%s is not an Entry Credit address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-ec-output", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionFee(name, address string) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address}
	req := NewJSON2Request("add-fee", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func SubTransactionFee(name, address string) error {
	params := transactionValueRequest{
		Name:    name,
		Address: address}
	req := NewJSON2Request("sub-fee", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func SignTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("sign-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func ComposeTransaction(name string) ([]byte, error) {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("compose-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	return resp.JSONResult(), nil
}

func SendTransaction(name string) error {
	params := transactionRequest{Name: name}

	wreq := NewJSON2Request("compose-transaction", apiCounter(), params)
	wresp, err := walletRequest(wreq)
	if err != nil {
		return err
	}
	if wresp.Error != nil {
		return wresp.Error
	}

	freq := new(JSON2Request)
	json.Unmarshal(wresp.JSONResult(), freq)
	fresp, err := factomdRequest(freq)
	if err != nil {
		return err
	}
	if fresp.Error != nil {
		return fresp.Error
	}
	if err := DeleteTransaction(name); err != nil {
		return err
	}

	return nil
}

func SendFactoid(from, to string, ammount uint64) error {
	n := make([]byte, 16)
	if _, err := rand.Read(n); err != nil {
		return err
	}
	name := hex.EncodeToString(n)
	if err := NewTransaction(name); err != nil {
		return err
	}
	if err := AddTransactionInput(name, from, ammount); err != nil {
		return err
	}
	if err := AddTransactionOutput(name, to, ammount); err != nil {
		return err
	}
	if err := AddTransactionFee(name, from); err != nil {
		return err
	}
	if err := SignTransaction(name); err != nil {
		return err
	}
	if err := SendTransaction(name); err != nil {
		return err
	}

	return nil
}

func BuyEC(from, to string, ammount uint64) error {
	n := make([]byte, 16)
	if _, err := rand.Read(n); err != nil {
		return err
	}
	name := hex.EncodeToString(n)
	if err := NewTransaction(name); err != nil {
		return err
	}
	if err := AddTransactionInput(name, from, ammount); err != nil {
		return err
	}
	if err := AddTransactionECOutput(name, to, ammount); err != nil {
		return err
	}
	if err := AddTransactionFee(name, from); err != nil {
		return err
	}
	if err := SignTransaction(name); err != nil {
		return err
	}
	if err := SendTransaction(name); err != nil {
		return err
	}

	return nil
}
<commit_msg>Fixed the ACK fetching by transaction name bug.<commit_after>// Copyright 2016 Factom Foundation
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package factom

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
)

func NewTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("new-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func DeleteTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("delete-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func TransactionHash(name string) (string, error) {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("transaction-hash", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return "", err
	}
	if resp.Error != nil {
		return "", resp.Error
	}
	type transactionResponse struct {
		Name           string `json:"tx-name"`
		TxID           string `json:"txid,omitempty"`
		TotalInputs    uint64 `json:"totalinputs"`
		TotalOutputs   uint64 `json:"totaloutputs"`
		TotalECOutputs uint64 `json:"totalecoutputs"`
	}
	tx := new(transactionResponse)
	if err := json.Unmarshal(resp.JSONResult(), tx); err != nil {
		return "", err
	}

	return tx.TxID, nil
}

func ListTransactions() ([]string, error) {
	type transactionResponse struct {
		Name           string `json:"tx-name"`
		TxID           string `json:"txid,omitempty"`
		TotalInputs    uint64 `json:"totalinputs"`
		TotalOutputs   uint64 `json:"totaloutputs"`
		TotalECOutputs uint64 `json:"totalecoutputs"`
	}

	type multiTransactionResponse struct {
		Transactions []transactionResponse `json:"transactions"`
	}

	req := NewJSON2Request("transactions", apiCounter(), nil)
	resp, err := walletRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	r := make([]string, 0)
	txs := new(multiTransactionResponse)
	if err := json.Unmarshal(resp.JSONResult(), txs); err != nil {
		return nil, err
	}
	for _, tx := range txs.Transactions {
		r = append(r, fmt.Sprintf("%#v", tx))
	}
	return r, nil
}

func AddTransactionInput(name, address string, amount uint64) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-input", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionOutput(name, address string, amount uint64) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-output", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionECOutput(name, address string, amount uint64) error {
	if AddressStringType(address) != ECPub {
		return fmt.Errorf("%s is not an Entry Credit address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address,
		Amount:  amount}
	req := NewJSON2Request("add-ec-output", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func AddTransactionFee(name, address string) error {
	if AddressStringType(address) != FactoidPub {
		return fmt.Errorf("%s is not a Factoid address", address)
	}

	params := transactionValueRequest{
		Name:    name,
		Address: address}
	req := NewJSON2Request("add-fee", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func SubTransactionFee(name, address string) error {
	params := transactionValueRequest{
		Name:    name,
		Address: address}
	req := NewJSON2Request("sub-fee", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func SignTransaction(name string) error {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("sign-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return err
	}
	if resp.Error != nil {
		return resp.Error
	}

	return nil
}

func ComposeTransaction(name string) ([]byte, error) {
	params := transactionRequest{Name: name}
	req := NewJSON2Request("compose-transaction", apiCounter(), params)

	resp, err := walletRequest(req)
	if err != nil {
		return nil, err
	}
	if resp.Error != nil {
		return nil, resp.Error
	}

	return resp.JSONResult(), nil
}

func SendTransaction(name string) error {
	params := transactionRequest{Name: name}

	wreq := NewJSON2Request("compose-transaction", apiCounter(), params)
	wresp, err := walletRequest(wreq)
	if err != nil {
		return err
	}
	if wresp.Error != nil {
		return wresp.Error
	}

	freq := new(JSON2Request)
	json.Unmarshal(wresp.JSONResult(), freq)
	fresp, err := factomdRequest(freq)
	if err != nil {
		return err
	}
	if fresp.Error != nil {
		return fresp.Error
	}
	/*if err := DeleteTransaction(name); err != nil {
		return err
	}*/

	return nil
}

func SendFactoid(from, to string, ammount uint64) error {
	n := make([]byte, 16)
	if _, err := rand.Read(n); err != nil {
		return err
	}
	name := hex.EncodeToString(n)
	if err := NewTransaction(name); err != nil {
		return err
	}
	if err := AddTransactionInput(name, from, ammount); err != nil {
		return err
	}
	if err := AddTransactionOutput(name, to, ammount); err != nil {
		return err
	}
	if err := AddTransactionFee(name, from); err != nil {
		return err
	}
	if err := SignTransaction(name); err != nil {
		return err
	}
	if err := SendTransaction(name); err != nil {
		return err
	}

	return nil
}

func BuyEC(from, to string, ammount uint64) error {
	n := make([]byte, 16)
	if _, err := rand.Read(n); err != nil {
		return err
	}
	name := hex.EncodeToString(n)
	if err := NewTransaction(name); err != nil {
		return err
	}
	if err := AddTransactionInput(name, from, ammount); err != nil {
		return err
	}
	if err := AddTransactionECOutput(name, to, ammount); err != nil {
		return err
	}
	if err := AddTransactionFee(name, from); err != nil {
		return err
	}
	if err := SignTransaction(name); err != nil {
		return err
	}
	if err := SendTransaction(name); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package traps

type Id int

const (
	Exit = Id(iota)
	MissingFunction

	CallStackExhausted
	IndirectCallIndex
	IndirectCallSignature
	MemoryOutOfBounds
	Unreachable
	IntegerDivideByZero
	IntegerOverflow

	NumTraps
)

func (id Id) String() string {
	switch id {
	case Exit:
		return "exit"

	case MissingFunction:
		return "missing function"

	case CallStackExhausted:
		return "call stack exhausted"

	case IndirectCallIndex:
		return "indirect call index out of bounds"

	case IndirectCallSignature:
		return "indirect call signature mismatch"

	case MemoryOutOfBounds:
		return "out of bounds memory access"

	case Unreachable:
		return "unreachable"

	case IntegerDivideByZero:
		return "integer divide by zero"

	case IntegerOverflow:
		return "integer overflow"

	default:
		return "unknown trap"
	}
}

func (id Id) Error() string {
	return "trap: " + id.String()
}
<commit_msg>traps: stringify unknown trap id<commit_after>package traps

import (
	"fmt"
)

type Id int

const (
	Exit = Id(iota)
	MissingFunction

	CallStackExhausted
	IndirectCallIndex
	IndirectCallSignature
	MemoryOutOfBounds
	Unreachable
	IntegerDivideByZero
	IntegerOverflow

	NumTraps
)

func (id Id) String() string {
	switch id {
	case Exit:
		return "exit"

	case MissingFunction:
		return "missing function"

	case CallStackExhausted:
		return "call stack exhausted"

	case IndirectCallIndex:
		return "indirect call index out of bounds"

	case IndirectCallSignature:
		return "indirect call signature mismatch"

	case MemoryOutOfBounds:
		return "out of bounds memory access"

	case Unreachable:
		return "unreachable"

	case IntegerDivideByZero:
		return "integer divide by zero"

	case IntegerOverflow:
		return "integer overflow"

	default:
		return fmt.Sprintf("unknown trap %d", id)
	}
}

func (id Id) Error() string {
	return "trap: " + id.String()
}
<|endoftext|>