<commit_before>package transformer

import (
	"sort"
	"strings"

	"github.com/ampproject/amppackager/internal/pkg/amphtml"
	"github.com/ampproject/amppackager/internal/pkg/htmlnode"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

type headNodes struct {
	linkFavicon                   []*html.Node
	linkResourceHint              []*html.Node
	linkStylesheetBeforeAMPCustom []*html.Node
	metaCharset                   *html.Node
	metaOther                     []*html.Node
	noscript                      *html.Node
	other                         []*html.Node
	scriptAMPRuntime              *html.Node
	scriptNonRenderDelaying       []*html.Node
	scriptRenderDelaying          []*html.Node
	styleAMPBoilerplate           *html.Node
	styleAMPCustom                *html.Node
	styleAMPRuntime               *html.Node
}

// ReorderHeadTransformer reorders the children of <head>. Specifically, it
// orders the <head> like so:
// (0) <meta charset> tag
// (1) <style amp-runtime> (inserted by ServerSideRenderingTransformer)
// (2) remaining <meta> tags
// (3) AMP runtime .js <script> tag
// (4) <script> tags that are render delaying
// (5) remaining <script> tags
// (6) <link> tag for favicons
// (7) <link> tag for resource hints
// (8) <link rel=stylesheet> tags before <style amp-custom>
// (9) <style amp-custom>
// (10) any other tags allowed in <head>
// (11) AMP boilerplate (first <style amp-boilerplate>, then <noscript>)
func ReorderHeadTransformer(e *Engine) {
	dom, ok := amphtml.NewDOM(e.Doc)
	if !ok {
		return
	}

	hn := new(headNodes)

	// Register each set of children we care about the order of in <head>.
	for c := dom.HeadNode.FirstChild; c != nil; c = c.NextSibling {
		switch c.DataAtom {
		case atom.Link:
			registerLink(c, hn)
		case atom.Meta:
			registerMeta(c, hn)
		case atom.Noscript:
			hn.noscript = c
		case atom.Script:
			registerScript(c, hn)
		case atom.Style:
			registerStyle(c, hn)
		default:
			hn.other = append(hn.other, c)
		}
	}

	// Uniquifies custom-element and custom-template scripts such that only one
	// of each is included, prefering the first one encountered and sorting by
	// custom-element or custom-template attribute's value.
	hn.scriptRenderDelaying = uniquifyAndSortCustomScripts(hn.scriptRenderDelaying)
	hn.scriptNonRenderDelaying = uniquifyAndSortCustomScripts(hn.scriptNonRenderDelaying)

	// Remove children of <head>.
	htmlnode.RemoveAllChildren(dom.HeadNode)

	// Append children of <head> in specific order.
	if hn.metaCharset != nil {
		dom.HeadNode.AppendChild(hn.metaCharset)
	}
	if hn.styleAMPRuntime != nil {
		dom.HeadNode.AppendChild(hn.styleAMPRuntime)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.metaOther...)
	if hn.scriptAMPRuntime != nil {
		dom.HeadNode.AppendChild(hn.scriptAMPRuntime)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.scriptRenderDelaying...)
	htmlnode.AppendChildren(dom.HeadNode, hn.scriptNonRenderDelaying...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkFavicon...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkResourceHint...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkStylesheetBeforeAMPCustom...)
	if hn.styleAMPCustom != nil {
		dom.HeadNode.AppendChild(hn.styleAMPCustom)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.other...)
	if hn.styleAMPBoilerplate != nil {
		dom.HeadNode.AppendChild(hn.styleAMPBoilerplate)
	}
	if hn.noscript != nil {
		dom.HeadNode.AppendChild(hn.noscript)
	}
}

// registerLink registers <link> tags to different variables depending on the attributes on the <link> tag. These are (1) resource hint <link> tags, (2) favicon <link> tags, (3) stylesheets before AMP Custom stylesheet, and (4) all other <link> tags.
func registerLink(n *html.Node, hn *headNodes) {
	if a, ok := htmlnode.FindAttribute(n, "", "rel"); ok {
		switch strings.ToLower(a.Val) {
		case "dns-prefetch preconnect":
			hn.linkResourceHint = append(hn.linkResourceHint, n)
			return
		case "icon", "icon shortcut", "shortcut icon":
			hn.linkFavicon = append(hn.linkFavicon, n)
			return
		case "stylesheet":
			if hn.styleAMPCustom == nil {
				hn.linkStylesheetBeforeAMPCustom = append(hn.linkStylesheetBeforeAMPCustom, n)
				return
			}
		}
	}
	hn.other = append(hn.other, n)
}

// registerMeta registers <meta> tags to different variables depending on the attributes on the <meta> tag. These are (1) the required <meta charset> and (2) all other <meta> tags.
func registerMeta(n *html.Node, hn *headNodes) {
	if htmlnode.HasAttribute(n, "charset") {
		hn.metaCharset = n
		return
	}
	hn.metaOther = append(hn.metaOther, n)
}

// registerScript registers <script> tags to different variables depending on the attributes on the <script> tag. These are the (1) AMP Runtime script, (2) the render delaying AMP Custom Element scripts, (3) the non-render delaying AMP Custom Element scripts and (4) all other <script> tags.
func registerScript(n *html.Node, hn *headNodes) {
	if amphtml.IsScriptAMPRuntime(n) {
		hn.scriptAMPRuntime = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustomElement) {
		if amphtml.IsScriptRenderDelaying(n) {
			hn.scriptRenderDelaying = append(hn.scriptRenderDelaying, n)
			return
		}
		hn.scriptNonRenderDelaying = append(hn.scriptNonRenderDelaying, n)
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustomTemplate) {
		hn.scriptNonRenderDelaying = append(hn.scriptNonRenderDelaying, n)
		return
	}
	hn.other = append(hn.other, n)
}

// registerStyle registers <style> tags to different variables depending on the attributes on the <style> tag. These are the (1) AMP or AMP4Ads Boilerplate, (2)the AMP Custom stylesheet, (3) the AMP Runtime stylesheet and (4) all other <style> tags.
func registerStyle(n *html.Node, hn *headNodes) {
	if htmlnode.HasAttribute(n, amphtml.AMPBoilerplate) || htmlnode.HasAttribute(n, amphtml.AMP4AdsBoilerplate) {
		hn.styleAMPBoilerplate = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustom) {
		hn.styleAMPCustom = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPRuntime) {
		hn.styleAMPRuntime = n
		return
	}
	hn.other = append(hn.other, n)
}

// uniquifyAndSortCustomScripts returns the unique nodes (based on custom-element or custom-template attribute), keeping the first one encountered and sorted by custom-element or custom-template attribute's value.
func uniquifyAndSortCustomScripts(n []*html.Node) []*html.Node {
	var k []string
	var u []*html.Node
	m := make(map[string]*html.Node)
	for _, s := range n {
		if ce, ok := htmlnode.FindAttribute(s, "", amphtml.AMPCustomElement); ok {
			if _, ok := m[ce.Val]; !ok {
				m[ce.Val] = s
				k = append(k, ce.Val)
			}
		} else if ct, ok := htmlnode.FindAttribute(s, "", amphtml.AMPCustomTemplate); ok {
			if _, ok := m[ct.Val]; !ok {
				m[ct.Val] = s
				k = append(k, ct.Val)
			}
		}
	}
	sort.Strings(k)
	for _, e := range k {
		u = append(u, m[e])
	}
	return u
}
<commit_msg>Fix ReorderHead to handle changes that will be introduced by ExternalAmpRuntimeCssTransformer<commit_after>package transformer

import (
	"sort"
	"strings"

	"github.com/ampproject/amppackager/internal/pkg/amphtml"
	"github.com/ampproject/amppackager/internal/pkg/htmlnode"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

type headNodes struct {
	linkFavicon                   []*html.Node
	linkResourceHint              []*html.Node
	linkStylesheetBeforeAMPCustom []*html.Node
	linkStylesheetRuntimeCSS      *html.Node
	metaCharset                   *html.Node
	metaOther                     []*html.Node
	noscript                      *html.Node
	other                         []*html.Node
	scriptAMPRuntime              *html.Node
	scriptNonRenderDelaying       []*html.Node
	scriptRenderDelaying          []*html.Node
	styleAMPBoilerplate           *html.Node
	styleAMPCustom                *html.Node
	styleAMPRuntime               *html.Node
}

// ReorderHeadTransformer reorders the children of <head>. Specifically, it
// orders the <head> like so:
// (0) <meta charset> tag
// (1) <style amp-runtime> (inserted by ServerSideRenderingTransformer)
// (2) remaining <meta> tags
// (3) AMP runtime .js <script> tag
// (4) <script> tags that are render delaying
// (5) remaining <script> tags
// (6) <link> tag for favicons
// (7) <link> tag for resource hints
// (8) <link rel=stylesheet> tags before <style amp-custom>
// (9) <style amp-custom>
// (10) any other tags allowed in <head>
// (11) AMP boilerplate (first <style amp-boilerplate>, then <noscript>)
func ReorderHeadTransformer(e *Engine) {
	dom, ok := amphtml.NewDOM(e.Doc)
	if !ok {
		return
	}

	hn := new(headNodes)

	// Register each set of children we care about the order of in <head>.
	for c := dom.HeadNode.FirstChild; c != nil; c = c.NextSibling {
		switch c.DataAtom {
		case atom.Link:
			registerLink(c, hn)
		case atom.Meta:
			registerMeta(c, hn)
		case atom.Noscript:
			hn.noscript = c
		case atom.Script:
			registerScript(c, hn)
		case atom.Style:
			registerStyle(c, hn)
		default:
			hn.other = append(hn.other, c)
		}
	}

	// Uniquifies custom-element and custom-template scripts such that only one
	// of each is included, prefering the first one encountered and sorting by
	// custom-element or custom-template attribute's value.
	hn.scriptRenderDelaying = uniquifyAndSortCustomScripts(hn.scriptRenderDelaying)
	hn.scriptNonRenderDelaying = uniquifyAndSortCustomScripts(hn.scriptNonRenderDelaying)

	// Remove children of <head>.
	htmlnode.RemoveAllChildren(dom.HeadNode)

	// Append children of <head> in specific order.
	if hn.metaCharset != nil {
		dom.HeadNode.AppendChild(hn.metaCharset)
	}
	if hn.linkStylesheetRuntimeCSS != nil {
		dom.HeadNode.AppendChild(hn.linkStylesheetRuntimeCSS)
	}
	if hn.styleAMPRuntime != nil {
		dom.HeadNode.AppendChild(hn.styleAMPRuntime)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.metaOther...)
	if hn.scriptAMPRuntime != nil {
		dom.HeadNode.AppendChild(hn.scriptAMPRuntime)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.scriptRenderDelaying...)
	htmlnode.AppendChildren(dom.HeadNode, hn.scriptNonRenderDelaying...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkFavicon...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkResourceHint...)
	htmlnode.AppendChildren(dom.HeadNode, hn.linkStylesheetBeforeAMPCustom...)
	if hn.styleAMPCustom != nil {
		dom.HeadNode.AppendChild(hn.styleAMPCustom)
	}
	htmlnode.AppendChildren(dom.HeadNode, hn.other...)
	if hn.styleAMPBoilerplate != nil {
		dom.HeadNode.AppendChild(hn.styleAMPBoilerplate)
	}
	if hn.noscript != nil {
		dom.HeadNode.AppendChild(hn.noscript)
	}
}

// registerLink registers <link> tags to different variables depending on the attributes on the <link> tag. These are (1) resource hint <link> tags, (2) favicon <link> tags, (3) stylesheets before AMP Custom stylesheet, and (4) all other <link> tags.
func registerLink(n *html.Node, hn *headNodes) {
	if a, ok := htmlnode.FindAttribute(n, "", "rel"); ok {
		switch strings.ToLower(a.Val) {
		case "dns-prefetch preconnect":
			hn.linkResourceHint = append(hn.linkResourceHint, n)
			return
		case "icon", "icon shortcut", "shortcut icon":
			hn.linkFavicon = append(hn.linkFavicon, n)
			return
		case "stylesheet":
			// The AmpRuntimeCssTransformer inserts a stylesheet for the AMP Runtime CSS. It must remain early in the head immediately before <style amp-custom>.
			if v, ok := htmlnode.GetAttributeVal(n, "href"); ok && strings.HasPrefix(v, "https://cdn.ampproject.org/") && strings.HasSuffix(v, "/v0.css") {
				hn.linkStylesheetRuntimeCSS = n
				return
			}
			if hn.styleAMPCustom == nil {
				hn.linkStylesheetBeforeAMPCustom = append(hn.linkStylesheetBeforeAMPCustom, n)
				return
			}
		}
	}
	hn.other = append(hn.other, n)
}

// registerMeta registers <meta> tags to different variables depending on the attributes on the <meta> tag. These are (1) the required <meta charset> and (2) all other <meta> tags.
func registerMeta(n *html.Node, hn *headNodes) {
	if htmlnode.HasAttribute(n, "charset") {
		hn.metaCharset = n
		return
	}
	hn.metaOther = append(hn.metaOther, n)
}

// registerScript registers <script> tags to different variables depending on the attributes on the <script> tag. These are the (1) AMP Runtime script, (2) the render delaying AMP Custom Element scripts, (3) the non-render delaying AMP Custom Element scripts and (4) all other <script> tags.
func registerScript(n *html.Node, hn *headNodes) {
	if amphtml.IsScriptAMPRuntime(n) {
		hn.scriptAMPRuntime = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustomElement) {
		if amphtml.IsScriptRenderDelaying(n) {
			hn.scriptRenderDelaying = append(hn.scriptRenderDelaying, n)
			return
		}
		hn.scriptNonRenderDelaying = append(hn.scriptNonRenderDelaying, n)
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustomTemplate) {
		hn.scriptNonRenderDelaying = append(hn.scriptNonRenderDelaying, n)
		return
	}
	hn.other = append(hn.other, n)
}

// registerStyle registers <style> tags to different variables depending on the attributes on the <style> tag. These are the (1) AMP or AMP4Ads Boilerplate, (2)the AMP Custom stylesheet, (3) the AMP Runtime stylesheet and (4) all other <style> tags.
func registerStyle(n *html.Node, hn *headNodes) {
	if htmlnode.HasAttribute(n, amphtml.AMPBoilerplate) || htmlnode.HasAttribute(n, amphtml.AMP4AdsBoilerplate) {
		hn.styleAMPBoilerplate = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPCustom) {
		hn.styleAMPCustom = n
		return
	}
	if htmlnode.HasAttribute(n, amphtml.AMPRuntime) {
		hn.styleAMPRuntime = n
		return
	}
	hn.other = append(hn.other, n)
}

// uniquifyAndSortCustomScripts returns the unique nodes (based on custom-element or custom-template attribute), keeping the first one encountered and sorted by custom-element or custom-template attribute's value.
func uniquifyAndSortCustomScripts(n []*html.Node) []*html.Node {
	var k []string
	var u []*html.Node
	m := make(map[string]*html.Node)
	for _, s := range n {
		if ce, ok := htmlnode.FindAttribute(s, "", amphtml.AMPCustomElement); ok {
			if _, ok := m[ce.Val]; !ok {
				m[ce.Val] = s
				k = append(k, ce.Val)
			}
		} else if ct, ok := htmlnode.FindAttribute(s, "", amphtml.AMPCustomTemplate); ok {
			if _, ok := m[ct.Val]; !ok {
				m[ct.Val] = s
				k = append(k, ct.Val)
			}
		}
	}
	sort.Strings(k)
	for _, e := range k {
		u = append(u, m[e])
	}
	return u
}
<|endoftext|>


<commit_before>package URLextract

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/PuerkitoBio/goquery"
	"github.com/asaskevich/govalidator"
	"github.com/koffeinsource/go-URLextract/plugins"
	"github.com/koffeinsource/go-URLextract/webpage"
	"golang.org/x/net/html/charset"
)

// Extract extracts all information from URL
func (c *Client) Extract(sourceURL string) (webpage.Info, error) {

	// Create return value with default values
	returnee := webpage.Info{
		Caption: sourceURL,
		URL:     sourceURL,
	}

	// Check if the URL is valid
	if !govalidator.IsRequestURL(sourceURL) {
		errReturn := fmt.Errorf("Invalid URL: %v", sourceURL)
		c.Log.Errorf(errReturn.Error())
		return returnee, errReturn
	}

	contentType, body, err := c.getURL(sourceURL)
	if err != nil {
		return returnee, err
	}

	//  log.Infof(contentType)
	switch {
	case strings.Contains(contentType, "image/"):
		// Image hostet at imgur?
		if strings.Contains(sourceURL, "i.imgur.com/") {
			plugins.Imgurl(&returnee, sourceURL, c.HTTPClient, c.Log, c.ImgurClientID)
		} else {
			plugins.Image(&returnee, sourceURL, contentType, c.Log)
		}
	case strings.Contains(contentType, "text/html"):

		var doc *goquery.Document

		charsetReader, err := charset.NewReader(bytes.NewReader(body), contentType)
		if err == nil {
			doc, err = goquery.NewDocumentFromReader(charsetReader)
		} else {
			doc, err = goquery.NewDocumentFromReader(bytes.NewReader(body))
		}

		if err != nil {
			c.Log.Errorf("Problem parsing body. " + sourceURL + " - " + err.Error())
			return returnee, err
		}

		// Make sure to call this one first
		plugins.DefaultHTML(&returnee, sourceURL, doc, c.Log)

		plugins.Amazon(&returnee, sourceURL, doc, c.Log, c.AmazonAdID)
		plugins.Imgurl(&returnee, sourceURL, c.HTTPClient, c.Log, c.ImgurClientID)
		plugins.Gfycat(&returnee, sourceURL, doc, c.Log)

		plugins.Fefe(&returnee, sourceURL, doc, c.Log)

		plugins.Youtube(&returnee, sourceURL, doc, c.Log)
		plugins.Vimeo(&returnee, sourceURL, doc, c.Log)

		plugins.Dilbert(&returnee, sourceURL, doc, c.Log)
		plugins.Garfield(&returnee, sourceURL, doc, c.Log)
		plugins.Xkcd(&returnee, sourceURL, doc, c.Log)
		plugins.Littlegamers(&returnee, sourceURL, doc, c.Log)

		plugins.Pastebin(&returnee, sourceURL, doc, c.Log)
	default:
	}

	return returnee, nil
}
<commit_msg>Added a TODO with future design concept.<commit_after>package URLextract

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/PuerkitoBio/goquery"
	"github.com/asaskevich/govalidator"
	"github.com/koffeinsource/go-URLextract/plugins"
	"github.com/koffeinsource/go-URLextract/webpage"
	"golang.org/x/net/html/charset"
)

// TODO refactor this function into two functions.
// 1.) ExtractFast() a functions that only parsers the webpage
// 2.) CompleteExtract() a functions that queries external services
// 3.) Extract := CompleteExtract(ExtractFast)

// Extract extracts all information from URL
func (c *Client) Extract(sourceURL string) (webpage.Info, error) {

	// Create return value with default values
	returnee := webpage.Info{
		Caption: sourceURL,
		URL:     sourceURL,
	}

	// Check if the URL is valid
	if !govalidator.IsRequestURL(sourceURL) {
		errReturn := fmt.Errorf("Invalid URL: %v", sourceURL)
		c.Log.Errorf(errReturn.Error())
		return returnee, errReturn
	}

	contentType, body, err := c.getURL(sourceURL)
	if err != nil {
		return returnee, err
	}

	//  log.Infof(contentType)
	switch {
	case strings.Contains(contentType, "image/"):
		// Image hostet at imgur?
		if strings.Contains(sourceURL, "i.imgur.com/") {
			plugins.Imgurl(&returnee, sourceURL, c.HTTPClient, c.Log, c.ImgurClientID)
		} else {
			plugins.Image(&returnee, sourceURL, contentType, c.Log)
		}
	case strings.Contains(contentType, "text/html"):

		var doc *goquery.Document

		charsetReader, err := charset.NewReader(bytes.NewReader(body), contentType)
		if err == nil {
			doc, err = goquery.NewDocumentFromReader(charsetReader)
		} else {
			doc, err = goquery.NewDocumentFromReader(bytes.NewReader(body))
		}

		if err != nil {
			c.Log.Errorf("Problem parsing body. " + sourceURL + " - " + err.Error())
			return returnee, err
		}

		// Make sure to call this one first
		plugins.DefaultHTML(&returnee, sourceURL, doc, c.Log)

		plugins.Amazon(&returnee, sourceURL, doc, c.Log, c.AmazonAdID)
		plugins.Imgurl(&returnee, sourceURL, c.HTTPClient, c.Log, c.ImgurClientID)
		plugins.Gfycat(&returnee, sourceURL, doc, c.Log)

		plugins.Fefe(&returnee, sourceURL, doc, c.Log)

		plugins.Youtube(&returnee, sourceURL, doc, c.Log)
		plugins.Vimeo(&returnee, sourceURL, doc, c.Log)

		plugins.Dilbert(&returnee, sourceURL, doc, c.Log)
		plugins.Garfield(&returnee, sourceURL, doc, c.Log)
		plugins.Xkcd(&returnee, sourceURL, doc, c.Log)
		plugins.Littlegamers(&returnee, sourceURL, doc, c.Log)

		plugins.Pastebin(&returnee, sourceURL, doc, c.Log)
	default:
	}

	return returnee, nil
}
<|endoftext|>


<commit_before>package ics

import (
	"time"

	"github.com/MJKWoolnough/bitmask"
)

const (
	vTimezone = "VTIMEZONE"
	standard  = "STANDARD"
	daylight  = "DAYLIGHT"
)

type Timezone struct {
	ID           string
	LastModified time.Time
	URL          timezoneURL
	Timezones    []TimezoneData
}

func (c *Calendar) decodeTimezone(d Decoder) error {
	bm := bitmask.New(4)
	var t Timezone
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case timezoneID:
			if !bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			t.ID = string(p)
		case lastModified:
			if !bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			t.LastModified = p.Time
		case timezoneURL:
			if !bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			t.URL = p
		case begin:
			var td TimezoneData
			switch p {
			case daylight:
				td.IsDaylight = true
				fallthrough
			case standard:
				bm.Set(3, true)
				err = td.decode(d)
				if err != nil {
					return err
				}
				t.Timezones = append(t.Timezones, td)
			default:
				if err = d.readUnknownComponent(string(p)); err != nil {
					return err
				}
			}
		case end:
			if p != vTimezone {
				return ErrInvalidEnd
			}
			if !bm.Get(0) || !bm.Get(3) {
				return ErrRequiredMissing
			}
			return nil
		}
	}
	return nil
}

type TimezoneData struct {
	IsDaylight      bool
	Start           dateTime
	OffsetFrom      timezoneOffsetFrom
	OffsetTo        timezoneOffsetTo
	RecurrenceRule  recurrenceRule
	Comments        []comment
	RecurrenceDates []recurrenceDate
	Names           map[string][]string
}

func (t *TimezoneData) decode(d Decoder) error {
	bm := bitmask.New(3)
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case dateTimeStart:
			if !bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			t.Start = p.dateTime
		case timezoneOffsetTo:
			if !bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			t.OffsetTo = p
		case timezoneOffsetFrom:
			if !bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			t.OffsetFrom = p
		case recurrenceRule:
			t.RecurrenceRule = p
		case comment:
			t.Comments = append(t.Comments, p)
		case recurrenceDate:
			t.RecurrenceDates = append(t.RecurrenceDates, p)
		case timezoneName:
			var names []string
			if n, ok := t.Names[p.Language]; ok {
				names = n
			}
			names = append(names, p.Name)
			t.Names[p.Language] = names
		case begin:
			if err = d.readUnknownComponent(string(p)); err != nil {
				return err
			}
		case end:
			if t.IsDaylight {
				if p != daylight {
					return ErrInvalidEnd
				}
			} else {
				if p != standard {
					return ErrInvalidEnd
				}
			}
			if !bm.Get(0) || !bm.Get(1) || !bm.Get(2) {
				return ErrRequiredMissing
			}
			return nil
		}
	}
}

func (c *Calendar) writeTimezoneData(e *Encoder) {
}
<commit_msg>added comment<commit_after>package ics

import (
	"time"

	"github.com/MJKWoolnough/bitmask"
)

const (
	vTimezone = "VTIMEZONE"
	standard  = "STANDARD"
	daylight  = "DAYLIGHT"
)

type Timezone struct {
	ID           string
	LastModified time.Time
	URL          timezoneURL
	Timezones    []TimezoneData
}

func (c *Calendar) decodeTimezone(d Decoder) error {
	bm := bitmask.New(4)
	var t Timezone
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case timezoneID:
			if !bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			t.ID = string(p)
		case lastModified:
			if !bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			t.LastModified = p.Time
		case timezoneURL:
			if !bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			t.URL = p
		case begin:
			var td TimezoneData
			switch p {
			case daylight:
				td.IsDaylight = true
				fallthrough
			case standard:
				bm.Set(3, true)
				err = td.decode(d)
				if err != nil {
					return err
				}
				t.Timezones = append(t.Timezones, td)
			default:
				if err = d.readUnknownComponent(string(p)); err != nil {
					return err
				}
			}
		case end:
			if p != vTimezone {
				return ErrInvalidEnd
			}
			if !bm.Get(0) || !bm.Get(3) {
				return ErrRequiredMissing
			}
			return nil
		}
	}
	return nil
}

type TimezoneData struct {
	IsDaylight      bool
	Start           dateTime
	OffsetFrom      timezoneOffsetFrom
	OffsetTo        timezoneOffsetTo
	RecurrenceRule  recurrenceRule
	Comments        []comment
	RecurrenceDates []recurrenceDate
	Names           map[string][]string
}

func (t *TimezoneData) decode(d Decoder) error {
	bm := bitmask.New(3)
	for {
		p, err := d.p.GetProperty()
		if err != nil {
			return err
		}
		switch p := p.(type) {
		case dateTimeStart:
			if !bm.SetIfNot(0, true) {
				return ErrMultipleUnique
			}
			t.Start = p.dateTime
		case timezoneOffsetTo:
			if !bm.SetIfNot(1, true) {
				return ErrMultipleUnique
			}
			t.OffsetTo = p
		case timezoneOffsetFrom:
			if !bm.SetIfNot(2, true) {
				return ErrMultipleUnique
			}
			t.OffsetFrom = p
		case recurrenceRule:
			t.RecurrenceRule = p
		case comment:
			t.Comments = append(t.Comments, p)
		case recurrenceDate:
			t.RecurrenceDates = append(t.RecurrenceDates, p)
		case timezoneName:
			var names []string
			if n, ok := t.Names[p.Language]; ok {
				names = n
			}
			names = append(names, p.Name)
			t.Names[p.Language] = names
		case begin:
			if err = d.readUnknownComponent(string(p)); err != nil {
				return err
			}
		case end:
			if t.IsDaylight {
				if p != daylight {
					return ErrInvalidEnd
				}
			} else {
				if p != standard {
					return ErrInvalidEnd
				}
			}
			if !bm.Get(0) || !bm.Get(1) || !bm.Get(2) {
				return ErrRequiredMissing
			}
			return nil
		}
	}
}

func (c *Calendar) writeTimezoneData(e *Encoder) {
	// not implemented
}
<|endoftext|>


<commit_before>/*
 * This file is part of the libvirt-go-xml project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirtxml

import (
	"encoding/xml"
)

type DomainCaps struct {
	XMLName   xml.Name             `xml:"domainCapabilities"`
	Path      string               `xml:"path"`
	Domain    string               `xml:"domain"`
	Machine   string               `xml:"machine,omitempty"`
	Arch      string               `xml:"arch"`
	VCPU      *DomainCapsVCPU      `xml:"vcpu"`
	IOThreads *DomainCapsIOThreads `xml:"iothreads"`
	OS        DomainCapsOS         `xml:"os"`
	CPU       *DomainCapsCPU       `xml:"cpu"`
	Devices   *DomainCapsDevices   `xml:"devices"`
	Features  *DomainCapsFeatures  `xml:"features"`
}

type DomainCapsVCPU struct {
	Max uint `xml:"max,attr"`
}

type DomainCapsOS struct {
	Supported string              `xml:"supported,attr"`
	Loader    *DomainCapsOSLoader `xml:"loader"`
}

type DomainCapsOSLoader struct {
	Supported string           `xml:"supported,attr"`
	Values    []string         `xml:"value"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsIOThreads struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsCPU struct {
	Modes []DomainCapsCPUMode `xml:"mode"`
}

type DomainCapsCPUMode struct {
	Name      string                 `xml:"name,attr"`
	Supported string                 `xml:"supported,attr"`
	Models    []DomainCapsCPUModel   `xml:"model"`
	Vendor    string                 `xml:"vendor,omitempty"`
	Features  []DomainCapsCPUFeature `xml:"feature"`
}

type DomainCapsCPUModel struct {
	Name     string `xml:",chardata"`
	Usable   string `xml:"usable,attr,omitempty"`
	Fallback string `xml:"fallback,attr,omitempty"`
}

type DomainCapsCPUFeature struct {
	Policy string `xml:"policy,attr,omitempty"`
	Name   string `xml:"name,attr"`
}

type DomainCapsEnum struct {
	Name   string   `xml:"name,attr"`
	Values []string `xml:"value"`
}

type DomainCapsDevices struct {
	Disk     *DomainCapsDevice `xml:"disk"`
	Graphics *DomainCapsDevice `xml:"graphics"`
	Video    *DomainCapsDevice `xml:"video"`
	HostDev  *DomainCapsDevice `xml:"hostdev"`
}

type DomainCapsDevice struct {
	Supported string           `xml:"supported,attr"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsFeatures struct {
	GIC        *DomainCapsFeatureGIC        `xml:"gic"`
	VMCoreInfo *DomainCapsFeatureVMCoreInfo `xml:"vmcoreinfo"`
	GenID      *DomainCapsFeatureGenID      `xml:"genid"`
	SEV        *DomainCapsFeatureSEV        `xml:"sev"`
}

type DomainCapsFeatureGIC struct {
	Supported string           `xml:"supported,attr"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsFeatureVMCoreInfo struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsFeatureGenID struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsFeatureSEV struct {
	Supported       string `xml:"supported,attr"`
	CBitPos         uint   `xml:"cbitpos,omitempty"`
	ReducedPhysBits uint   `xml:"reducedPhysBits,omitempty"`
}

func (c *DomainCaps) Unmarshal(doc string) error {
	return xml.Unmarshal([]byte(doc), c)
}

func (c *DomainCaps) Marshal() (string, error) {
	doc, err := xml.MarshalIndent(c, "", "  ")
	if err != nil {
		return "", err
	}
	return string(doc), nil
}
<commit_msg>Make domain capabilities OS block optional<commit_after>/*
 * This file is part of the libvirt-go-xml project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 */

package libvirtxml

import (
	"encoding/xml"
)

type DomainCaps struct {
	XMLName   xml.Name             `xml:"domainCapabilities"`
	Path      string               `xml:"path"`
	Domain    string               `xml:"domain"`
	Machine   string               `xml:"machine,omitempty"`
	Arch      string               `xml:"arch"`
	VCPU      *DomainCapsVCPU      `xml:"vcpu"`
	IOThreads *DomainCapsIOThreads `xml:"iothreads"`
	OS        *DomainCapsOS        `xml:"os"`
	CPU       *DomainCapsCPU       `xml:"cpu"`
	Devices   *DomainCapsDevices   `xml:"devices"`
	Features  *DomainCapsFeatures  `xml:"features"`
}

type DomainCapsVCPU struct {
	Max uint `xml:"max,attr"`
}

type DomainCapsOS struct {
	Supported string              `xml:"supported,attr"`
	Loader    *DomainCapsOSLoader `xml:"loader"`
}

type DomainCapsOSLoader struct {
	Supported string           `xml:"supported,attr"`
	Values    []string         `xml:"value"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsIOThreads struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsCPU struct {
	Modes []DomainCapsCPUMode `xml:"mode"`
}

type DomainCapsCPUMode struct {
	Name      string                 `xml:"name,attr"`
	Supported string                 `xml:"supported,attr"`
	Models    []DomainCapsCPUModel   `xml:"model"`
	Vendor    string                 `xml:"vendor,omitempty"`
	Features  []DomainCapsCPUFeature `xml:"feature"`
}

type DomainCapsCPUModel struct {
	Name     string `xml:",chardata"`
	Usable   string `xml:"usable,attr,omitempty"`
	Fallback string `xml:"fallback,attr,omitempty"`
}

type DomainCapsCPUFeature struct {
	Policy string `xml:"policy,attr,omitempty"`
	Name   string `xml:"name,attr"`
}

type DomainCapsEnum struct {
	Name   string   `xml:"name,attr"`
	Values []string `xml:"value"`
}

type DomainCapsDevices struct {
	Disk     *DomainCapsDevice `xml:"disk"`
	Graphics *DomainCapsDevice `xml:"graphics"`
	Video    *DomainCapsDevice `xml:"video"`
	HostDev  *DomainCapsDevice `xml:"hostdev"`
}

type DomainCapsDevice struct {
	Supported string           `xml:"supported,attr"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsFeatures struct {
	GIC        *DomainCapsFeatureGIC        `xml:"gic"`
	VMCoreInfo *DomainCapsFeatureVMCoreInfo `xml:"vmcoreinfo"`
	GenID      *DomainCapsFeatureGenID      `xml:"genid"`
	SEV        *DomainCapsFeatureSEV        `xml:"sev"`
}

type DomainCapsFeatureGIC struct {
	Supported string           `xml:"supported,attr"`
	Enums     []DomainCapsEnum `xml:"enum"`
}

type DomainCapsFeatureVMCoreInfo struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsFeatureGenID struct {
	Supported string `xml:"supported,attr"`
}

type DomainCapsFeatureSEV struct {
	Supported       string `xml:"supported,attr"`
	CBitPos         uint   `xml:"cbitpos,omitempty"`
	ReducedPhysBits uint   `xml:"reducedPhysBits,omitempty"`
}

func (c *DomainCaps) Unmarshal(doc string) error {
	return xml.Unmarshal([]byte(doc), c)
}

func (c *DomainCaps) Marshal() (string, error) {
	doc, err := xml.MarshalIndent(c, "", "  ")
	if err != nil {
		return "", err
	}
	return string(doc), nil
}
<|endoftext|>


<commit_before>package routes

import "github.com/tedsuo/rata"

const (
	StopLRPInstance = "StopLRPInstance"
)

var StopLRPRoutes = rata.Routes{
	{Name: StopLRPInstance, Method: "POST", Path: "/lrps/:process_guid/instances/:instance_guid/stop"},
}
<commit_msg>Remove unused routes package<commit_after><|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 main

import (
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/repr"
	"log"
)

var blobStore blob.Store

// Restore the directory whose contents are described by the referenced blob to
// the supplied target, which must already exist.
func restoreDir(target string, hexHash string) error {
	// Load the appropriate blob.
}

func main() {
}
<commit_msg>Implemented main.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 main

import (
	"fmt"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/disk"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/repr"
	"log"
	"os"
	"path"
)

const (
	gTarget = "/tmp/restore_target"
)

var blobStore blob.Store

func fromHexHash(hexHash string) (blob.Score, error) {
	return nil, fmt.Errorf("TODO: fromHexHash")
}

// Restore the file whose contents are described by the referenced blobs to the
// supplied target, whose parent must already exist.
func restoreFile(target string, scores []blob.Score) error {
	return fmt.Errorf("TODO: restoreFile")
}

// Restore the directory whose contents are described by the referenced blob to
// the supplied target, which must already exist.
func restoreDir(target string, score blob.Score) error {
	// Load the appropriate blob.
	blob, err := blobStore.Load(score)
	if err != nil {
		return fmt.Errorf("Loading blob: %v", err)
	}

	// Parse its contents.
	entries, err := repr.Unmarshal(blob)
	if err != nil {
		return fmt.Errorf("Parsing blob: %v", err)
	}

	// Deal with each entry.
	for _, entry := range entries {
		entryPath := path.Join(target, entry.Name)

		// Switch on type.
		switch entry.Type {
		case fs.TypeFile:
			err = restoreFile(entryPath, entry.Scores)
			if err != nil {
				return err
			}

		case fs.TypeDirectory:
			if len(entry.Scores) != 1 {
				return fmt.Errorf("Wrong number of scores: %v", entry)
			}

			if err = os.Mkdir(entryPath, 0700); err != nil {
				return err
			}

			if err = restoreDir(entryPath, entry.Scores[0]); err != nil {
				return err
			}

		default:
			return fmt.Errorf("Don't know how to deal with entry: %v", entry)
		}
	}

	return nil
}

func main() {
	var err error

	// Create the blob store.
	blobStore, err = disk.NewBlobStore("/tmp/blobs")
	if err != nil {
		log.Fatalf("Creating store: %v", err)
	}

	// Parse the score.
	score, err := fromHexHash("ee905ccc3416d120c962dc983023c28401ae39ae")
	if err != nil {
		log.Fatalf("Parsing score: %v", err)
	}

	// Make sure the target doesn't exist.
	err = os.RemoveAll(gTarget)
	if err != nil {
		log.Fatalf("RemoveAll: %v", err)
	}

	// Create the target.
	err = os.Mkdir("/tmp/restore_target", 0700)
	if err != nil {
		log.Fatalf("Mkdir: %v", err)
	}

	// Attempt a restore.
	err = restoreDir(gTarget, score)
	if err != nil {
		log.Fatalf("Restoring: %v", err)
	}
}
<|endoftext|>


<commit_before>// memory is an in memory storage backend for Shade.
//
// It stores files and chunks transiently in RAM.
package memory

import (
	"errors"
	"sync"

	"github.com/asjoyner/shade/drive"
)

func init() {
	drive.RegisterProvider("memory", NewClient)
}

func NewClient(c drive.Config) (drive.Client, error) {
	client := &MemoryDrive{
		config: c,
		chunks: make(map[string][]byte),
	}
	return client, nil
}

type MemoryDrive struct {
	config drive.Config
	files  [][]byte
	chunks map[string][]byte
	sync.RWMutex
}

// ListFiles retrieves all of the File objects known to the client.  The return
// is a list of sha256sums of the file object.  The keys may be passed to
// GetFile() to retrieve the corresponding shade.File.
func (s *MemoryDrive) ListFiles() ([][]byte, error) {
	s.RLock()
	defer s.RUnlock()
	return s.files, nil
}

// PutFile writes the metadata describing a new file.
// f should be marshalled JSON, and may be encrypted.
func (s *MemoryDrive) PutFile(sha256sum, f []byte) error {
	s.Lock()
	s.files = append(s.files, sha256sum)
	s.chunks[string(sha256sum)] = f
	s.Unlock()
	return nil
}

// GetChunk retrieves a chunk with a given SHA-256 sum
func (s *MemoryDrive) GetChunk(sha256sum []byte) ([]byte, error) {
	s.RLock()
	defer s.RUnlock()
	if chunk, ok := s.chunks[string(sha256sum)]; ok {
		return chunk, nil
	}
	return nil, errors.New("chunk not found")
}

// PutChunk writes a chunk and returns its SHA-256 sum
func (s *MemoryDrive) PutChunk(sha256sum []byte, chunk []byte) error {
	s.Lock()
	defer s.Unlock()
	s.chunks[string(sha256sum)] = chunk
	return nil
}

func (s *MemoryDrive) GetConfig() drive.Config {
	return s.config
}

func (s *MemoryDrive) Local() bool { return true }
<commit_msg>Update comment for ListFiles to reference GetChunk<commit_after>// memory is an in memory storage backend for Shade.
//
// It stores files and chunks transiently in RAM.
package memory

import (
	"errors"
	"sync"

	"github.com/asjoyner/shade/drive"
)

func init() {
	drive.RegisterProvider("memory", NewClient)
}

func NewClient(c drive.Config) (drive.Client, error) {
	client := &MemoryDrive{
		config: c,
		chunks: make(map[string][]byte),
	}
	return client, nil
}

type MemoryDrive struct {
	config drive.Config
	files  [][]byte
	chunks map[string][]byte
	sync.RWMutex
}

// ListFiles retrieves all of the File objects known to the client.  The return
// is a list of sha256sums of the file object.  The keys may be passed to
// GetChunk() to retrieve the corresponding shade.File.
func (s *MemoryDrive) ListFiles() ([][]byte, error) {
	s.RLock()
	defer s.RUnlock()
	return s.files, nil
}

// PutFile writes the metadata describing a new file.
// f should be marshalled JSON, and may be encrypted.
func (s *MemoryDrive) PutFile(sha256sum, f []byte) error {
	s.Lock()
	s.files = append(s.files, sha256sum)
	s.chunks[string(sha256sum)] = f
	s.Unlock()
	return nil
}

// GetChunk retrieves a chunk with a given SHA-256 sum
func (s *MemoryDrive) GetChunk(sha256sum []byte) ([]byte, error) {
	s.RLock()
	defer s.RUnlock()
	if chunk, ok := s.chunks[string(sha256sum)]; ok {
		return chunk, nil
	}
	return nil, errors.New("chunk not found")
}

// PutChunk writes a chunk and returns its SHA-256 sum
func (s *MemoryDrive) PutChunk(sha256sum []byte, chunk []byte) error {
	s.Lock()
	defer s.Unlock()
	s.chunks[string(sha256sum)] = chunk
	return nil
}

func (s *MemoryDrive) GetConfig() drive.Config {
	return s.config
}

func (s *MemoryDrive) Local() bool { return true }
<|endoftext|>


<commit_before>// Copyright 2017 Google 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 main implements a client that reads a line
// from stdin and then sends it as a UDP packet to the
// -address flag
package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
)

const (
	bufferSize = 1024
)

var (
	maxMessageSize = bufferSize - len([]byte("ACK: "))
)

// Program client reads a line in from stdin and sends it to a server as a UDP packet.
func main() {
	address := flag.String("address", "localhost:7654", "The address to send the UDP packets to")
	flag.Parse()

	log.Printf("Starting client, connecting to %s", *address)
	conn, err := net.Dial("udp", *address)
	if err != nil {
		log.Fatalf("Could not connect: %v", err)
	}
	defer conn.Close()

	go func() {
		b := make([]byte, bufferSize)
		for {
			n, err := conn.Read(b)
			if err != nil {
				log.Fatalf("Could not read packet: %v", err)
			}
			log.Printf("Recieved Packet: %s", b[:n])
		}
	}()

	scanner := bufio.NewScanner(os.Stdin)
	fmt.Print(">> Send Line: ")
	for scanner.Scan() {
		line := scanner.Bytes()
		len := len(line)

		if len > maxMessageSize {
			log.Printf("Messages cannot be larger than the buffer of %d bytes. Please try again.", maxMessageSize)
			continue
		}

		log.Printf("Sending %d bytes string %s via UDP", len, line)
		_, err = conn.Write(line)
		if err != nil {
			log.Fatalf("Could not write line %s to %s: %v", line, *address, err)
		}

		fmt.Print(">> Send Line: ")
	}
}
<commit_msg>fix typo found by report card<commit_after>// Copyright 2017 Google 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 main implements a client that reads a line
// from stdin and then sends it as a UDP packet to the
// -address flag
package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
)

const (
	bufferSize = 1024
)

var (
	maxMessageSize = bufferSize - len([]byte("ACK: "))
)

// Program client reads a line in from stdin and sends it to a server as a UDP packet.
func main() {
	address := flag.String("address", "localhost:7654", "The address to send the UDP packets to")
	flag.Parse()

	log.Printf("Starting client, connecting to %s", *address)
	conn, err := net.Dial("udp", *address)
	if err != nil {
		log.Fatalf("Could not connect: %v", err)
	}
	defer conn.Close()

	go func() {
		b := make([]byte, bufferSize)
		for {
			n, err := conn.Read(b)
			if err != nil {
				log.Fatalf("Could not read packet: %v", err)
			}
			log.Printf("Received Packet: %s", b[:n])
		}
	}()

	scanner := bufio.NewScanner(os.Stdin)
	fmt.Print(">> Send Line: ")
	for scanner.Scan() {
		line := scanner.Bytes()
		len := len(line)

		if len > maxMessageSize {
			log.Printf("Messages cannot be larger than the buffer of %d bytes. Please try again.", maxMessageSize)
			continue
		}

		log.Printf("Sending %d bytes string %s via UDP", len, line)
		_, err = conn.Write(line)
		if err != nil {
			log.Fatalf("Could not write line %s to %s: %v", line, *address, err)
		}

		fmt.Print(">> Send Line: ")
	}
}
<|endoftext|>


<commit_before>package action

import (
	bosherr "bosh/errors"
	boshplatform "bosh/platform"
	boshsettings "bosh/settings"
	boshdirs "bosh/settings/directories"
)

type MountDiskAction struct {
	settings    boshsettings.Service
	platform    boshplatform.Platform
	dirProvider boshdirs.DirectoriesProvider
}

func NewMountDisk(settings boshsettings.Service, platform boshplatform.Platform, dirProvider boshdirs.DirectoriesProvider) (mountDisk MountDiskAction) {
	mountDisk.settings = settings
	mountDisk.platform = platform
	mountDisk.dirProvider = dirProvider
	return
}

func (a MountDiskAction) IsAsynchronous() bool {
	return true
}

func (a MountDiskAction) Run(volumeId string) (value interface{}, err error) {
	err = a.settings.Refresh()
	if err != nil {
		err = bosherr.WrapError(err, "Refreshing the settings")
		return
	}

	disksSettings := a.settings.GetDisks()
	devicePath, found := disksSettings.Persistent[volumeId]
	if !found {
		err = bosherr.New("Persistent disk with volume id '%s' could not be found", volumeId)
		return
	}

	mountPoint := a.dirProvider.StoreDir()

	isMountPoint, err := a.platform.IsMountPoint(mountPoint)
	if err != nil {
		err = bosherr.WrapError(err, "Checking mount point")
		return
	}
	if isMountPoint {
		mountPoint = a.dirProvider.StoreMigrationDir()
	}

	err = a.platform.MountPersistentDisk(devicePath, mountPoint)
	if err != nil {
		err = bosherr.WrapError(err, "Mounting persistent disk")
		return
	}

	value = make(map[string]string)
	return
}
<commit_msg>Use an unexported interface for mounting disk<commit_after>package action

import (
	bosherr "bosh/errors"
	boshsettings "bosh/settings"
	boshdirs "bosh/settings/directories"
)

type diskMounter interface {
	MountPersistentDisk(volumeId string, mountPoint string) error
	IsMountPoint(string) (bool, error)
}

type MountDiskAction struct {
	settings    boshsettings.Service
	platform    diskMounter
	dirProvider boshdirs.DirectoriesProvider
}

func NewMountDisk(settings boshsettings.Service, platform diskMounter, dirProvider boshdirs.DirectoriesProvider) (mountDisk MountDiskAction) {
	mountDisk.settings = settings
	mountDisk.platform = platform
	mountDisk.dirProvider = dirProvider
	return
}

func (a MountDiskAction) IsAsynchronous() bool {
	return true
}

func (a MountDiskAction) Run(volumeId string) (value interface{}, err error) {
	err = a.settings.Refresh()
	if err != nil {
		err = bosherr.WrapError(err, "Refreshing the settings")
		return
	}

	disksSettings := a.settings.GetDisks()
	devicePath, found := disksSettings.Persistent[volumeId]
	if !found {
		err = bosherr.New("Persistent disk with volume id '%s' could not be found", volumeId)
		return
	}

	mountPoint := a.dirProvider.StoreDir()

	isMountPoint, err := a.platform.IsMountPoint(mountPoint)
	if err != nil {
		err = bosherr.WrapError(err, "Checking mount point")
		return
	}
	if isMountPoint {
		mountPoint = a.dirProvider.StoreMigrationDir()
	}

	err = a.platform.MountPersistentDisk(devicePath, mountPoint)
	if err != nil {
		err = bosherr.WrapError(err, "Mounting persistent disk")
		return
	}

	value = make(map[string]string)
	return
}
<|endoftext|>


<commit_before>package docker

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"

	"github.com/hashicorp/go-version"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type DockerDriver struct {
	Ui  packer.Ui
	Ctx *interpolate.Context

	l sync.Mutex
}

func (d *DockerDriver) DeleteImage(id string) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "rmi", id)
	cmd.Stderr = &stderr

	log.Printf("Deleting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error deleting image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Commit(id string, author string, changes []string, message string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer

	args := []string{"commit"}
	if author != "" {
		args = append(args, "--author", author)
	}
	for _, change := range changes {
		args = append(args, "--change", change)
	}
	if message != "" {
		args = append(args, "--message", message)
	}
	args = append(args, id)

	log.Printf("Committing container with args: %v", args)
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error committing container: %s\nStderr: %s",
			err, stderr.String())
		return "", err
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Export(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "export", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting container: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Import(path string, repo string) (string, error) {
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", "import", "-", repo)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return "", err
	}

	// There should be only one artifact of the Docker builder
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	if err := cmd.Start(); err != nil {
		return "", err
	}

	go func() {
		defer stdin.Close()
		io.Copy(stdin, file)
	}()

	if err := cmd.Wait(); err != nil {
		return "", fmt.Errorf("Error importing container: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) IPAddress(id string) (string, error) {
	var stderr, stdout bytes.Buffer
	cmd := exec.Command(
		"docker",
		"inspect",
		"--format",
		"{{ .NetworkSettings.IPAddress }}",
		id)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Login(repo, email, user, pass string) error {
	d.l.Lock()

	args := []string{"login"}
	if email != "" {
		args = append(args, "-e", email)
	}
	if user != "" {
		args = append(args, "-u", user)
	}
	if pass != "" {
		args = append(args, "-p", pass)
	}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	if err != nil {
		d.l.Unlock()
	}

	return err
}

func (d *DockerDriver) Logout(repo string) error {
	args := []string{"logout"}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	d.l.Unlock()
	return err
}

func (d *DockerDriver) Pull(image string) error {
	cmd := exec.Command("docker", "pull", image)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) Push(name string) error {
	cmd := exec.Command("docker", "push", name)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) SaveImage(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "save", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
	// Build up the template data
	var tplData startContainerTemplate
	tplData.Image = config.Image
	ctx := *d.Ctx
	ctx.Data = &tplData

	// Args that we're going to pass to Docker
	args := []string{"run"}
	if config.Privileged {
		args = append(args, "--privileged")
	}
	for host, guest := range config.Volumes {
		args = append(args, "-v", fmt.Sprintf("%s:%s", host, guest))
	}
	for _, v := range config.RunCommand {
		v, err := interpolate.Render(v, &ctx)
		if err != nil {
			return "", err
		}

		args = append(args, v)
	}
	d.Ui.Message(fmt.Sprintf(
		"Run command: docker %s", strings.Join(args, " ")))

	// Start the container
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	log.Printf("Starting container with args: %v", args)
	if err := cmd.Start(); err != nil {
		return "", err
	}

	log.Println("Waiting for container to finish starting")
	if err := cmd.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			err = fmt.Errorf("Docker exited with a non-zero exit status.\nStderr: %s",
				stderr.String())
		}

		return "", err
	}

	// Capture the container ID, which is alone on stdout
	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) StopContainer(id string) error {
	if err := exec.Command("docker", "kill", id).Run(); err != nil {
		return err
	}

	return exec.Command("docker", "rm", id).Run()
}

func (d *DockerDriver) TagImage(id string, repo string, force bool) error {
	args := []string{"tag"}

	// detect running docker version before tagging
	// flag `force` for docker tagging was removed after Docker 1.12.0
	// to keep its backward compatibility, we are not going to remove `force`
	// option, but to ignore it when Docker version >= 1.12.0
	//
	// for more detail, please refer to the following links:
	// - https://docs.docker.com/engine/deprecated/#/f-flag-on-docker-tag
	// - https://github.com/docker/docker/pull/23090
	version_running, err := d.Version()
	if err != nil {
		return err
	}

	version_deprecated, err := version.NewVersion(string("1.12.0"))
	if err != nil {
		// should never reach this line
		return err
	}

	if force {
		if version_running.LessThan(version_deprecated) {
			args = append(args, "-f")
		} else {
			// do nothing if Docker version >= 1.12.0
			log.Printf("[WARN] option: \"force\" will be ignored here")
			log.Printf("since it was removed after Docker 1.12.0 released")
		}
	}
	args = append(args, id, repo)

	var stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error tagging image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Verify() error {
	if _, err := exec.LookPath("docker"); err != nil {
		return err
	}

	return nil
}

func (d *DockerDriver) Version() (*version.Version, error) {
	output, err := exec.Command("docker", "-v").Output()
	if err != nil {
		return nil, err
	}

	match := regexp.MustCompile(version.VersionRegexpRaw).FindSubmatch(output)
	if match == nil {
		return nil, fmt.Errorf("unknown version: %s", output)
	}

	return version.NewVersion(string(match[0]))
}
<commit_msg>de-mangle windows filepath to something docker can handle<commit_after>package docker

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"

	"github.com/hashicorp/go-version"
	"github.com/hashicorp/packer/packer"
	"github.com/hashicorp/packer/template/interpolate"
)

type DockerDriver struct {
	Ui  packer.Ui
	Ctx *interpolate.Context

	l sync.Mutex
}

func (d *DockerDriver) DeleteImage(id string) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "rmi", id)
	cmd.Stderr = &stderr

	log.Printf("Deleting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error deleting image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Commit(id string, author string, changes []string, message string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer

	args := []string{"commit"}
	if author != "" {
		args = append(args, "--author", author)
	}
	for _, change := range changes {
		args = append(args, "--change", change)
	}
	if message != "" {
		args = append(args, "--message", message)
	}
	args = append(args, id)

	log.Printf("Committing container with args: %v", args)
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return "", err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error committing container: %s\nStderr: %s",
			err, stderr.String())
		return "", err
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Export(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "export", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting container: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Import(path string, repo string) (string, error) {
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", "import", "-", repo)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return "", err
	}

	// There should be only one artifact of the Docker builder
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer file.Close()

	if err := cmd.Start(); err != nil {
		return "", err
	}

	go func() {
		defer stdin.Close()
		io.Copy(stdin, file)
	}()

	if err := cmd.Wait(); err != nil {
		return "", fmt.Errorf("Error importing container: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) IPAddress(id string) (string, error) {
	var stderr, stdout bytes.Buffer
	cmd := exec.Command(
		"docker",
		"inspect",
		"--format",
		"{{ .NetworkSettings.IPAddress }}",
		id)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	if err := cmd.Run(); err != nil {
		return "", fmt.Errorf("Error: %s\n\nStderr: %s", err, stderr.String())
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) Login(repo, email, user, pass string) error {
	d.l.Lock()

	args := []string{"login"}
	if email != "" {
		args = append(args, "-e", email)
	}
	if user != "" {
		args = append(args, "-u", user)
	}
	if pass != "" {
		args = append(args, "-p", pass)
	}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	if err != nil {
		d.l.Unlock()
	}

	return err
}

func (d *DockerDriver) Logout(repo string) error {
	args := []string{"logout"}
	if repo != "" {
		args = append(args, repo)
	}

	cmd := exec.Command("docker", args...)
	err := runAndStream(cmd, d.Ui)
	d.l.Unlock()
	return err
}

func (d *DockerDriver) Pull(image string) error {
	cmd := exec.Command("docker", "pull", image)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) Push(name string) error {
	cmd := exec.Command("docker", "push", name)
	return runAndStream(cmd, d.Ui)
}

func (d *DockerDriver) SaveImage(id string, dst io.Writer) error {
	var stderr bytes.Buffer
	cmd := exec.Command("docker", "save", id)
	cmd.Stdout = dst
	cmd.Stderr = &stderr

	log.Printf("Exporting image: %s", id)
	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error exporting: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) {
	// Build up the template data
	var tplData startContainerTemplate
	tplData.Image = config.Image
	ctx := *d.Ctx
	ctx.Data = &tplData

	// Args that we're going to pass to Docker
	args := []string{"run"}
	if config.Privileged {
		args = append(args, "--privileged")
	}
	for host, guest := range config.Volumes {
		if runtime.GOOS == "windows" {
			// docker-toolbox can't handle the normal C:\filepath format in CLI
			host = strings.Replace(host, "\\", "/", -1)
			host = strings.Replace(host, "C:/", "/c/", 1)
		}
		args = append(args, "-v", fmt.Sprintf("%s:%s", host, guest))
	}
	for _, v := range config.RunCommand {
		v, err := interpolate.Render(v, &ctx)
		if err != nil {
			return "", err
		}

		args = append(args, v)
	}
	d.Ui.Message(fmt.Sprintf(
		"Run command: docker %s", strings.Join(args, " ")))

	// Start the container
	var stdout, stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	log.Printf("Starting container with args: %v", args)
	if err := cmd.Start(); err != nil {
		return "", err
	}

	log.Println("Waiting for container to finish starting")
	if err := cmd.Wait(); err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			err = fmt.Errorf("Docker exited with a non-zero exit status.\nStderr: %s",
				stderr.String())
		}

		return "", err
	}

	// Capture the container ID, which is alone on stdout
	return strings.TrimSpace(stdout.String()), nil
}

func (d *DockerDriver) StopContainer(id string) error {
	if err := exec.Command("docker", "kill", id).Run(); err != nil {
		return err
	}

	return exec.Command("docker", "rm", id).Run()
}

func (d *DockerDriver) TagImage(id string, repo string, force bool) error {
	args := []string{"tag"}

	// detect running docker version before tagging
	// flag `force` for docker tagging was removed after Docker 1.12.0
	// to keep its backward compatibility, we are not going to remove `force`
	// option, but to ignore it when Docker version >= 1.12.0
	//
	// for more detail, please refer to the following links:
	// - https://docs.docker.com/engine/deprecated/#/f-flag-on-docker-tag
	// - https://github.com/docker/docker/pull/23090
	version_running, err := d.Version()
	if err != nil {
		return err
	}

	version_deprecated, err := version.NewVersion(string("1.12.0"))
	if err != nil {
		// should never reach this line
		return err
	}

	if force {
		if version_running.LessThan(version_deprecated) {
			args = append(args, "-f")
		} else {
			// do nothing if Docker version >= 1.12.0
			log.Printf("[WARN] option: \"force\" will be ignored here")
			log.Printf("since it was removed after Docker 1.12.0 released")
		}
	}
	args = append(args, id, repo)

	var stderr bytes.Buffer
	cmd := exec.Command("docker", args...)
	cmd.Stderr = &stderr

	if err := cmd.Start(); err != nil {
		return err
	}

	if err := cmd.Wait(); err != nil {
		err = fmt.Errorf("Error tagging image: %s\nStderr: %s",
			err, stderr.String())
		return err
	}

	return nil
}

func (d *DockerDriver) Verify() error {
	if _, err := exec.LookPath("docker"); err != nil {
		return err
	}

	return nil
}

func (d *DockerDriver) Version() (*version.Version, error) {
	output, err := exec.Command("docker", "-v").Output()
	if err != nil {
		return nil, err
	}

	match := regexp.MustCompile(version.VersionRegexpRaw).FindSubmatch(output)
	if match == nil {
		return nil, fmt.Errorf("unknown version: %s", output)
	}

	return version.NewVersion(string(match[0]))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	"io"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
	"time"

	"github.com/jbenet/go-random"
)

// Warning: these tests assume some networking capabilities... sorry

var (
	gitPath string
)

// rand strings
func init() {
	rand.Seed(time.Now().Unix())
}

// checks for the needed tools
func checkInstalled(t *testing.T) {
	var err error
	gitPath, err = exec.LookPath("git")
	checkFatal(t, err)
	_, err = exec.LookPath("git-remote-ipfs")
	if err != nil {
		t.Log("git-remote-ipfs is not installed")
		if out, err := exec.Command("go", "install", "github.com/cryptix/git-remote-ipfs").CombinedOutput(); err != nil {
			t.Log(fmt.Sprintf("%q", string(out)))
			t.Fatal("go install failed:", err)
		}
	}
}

// oh well.. just some rand string
func mkRandTmpDir(t *testing.T) string {
	var buf bytes.Buffer
	for i := 0; i < 10; i++ {
		checkFatal(t, random.WriteRandomBytes(20, &buf))
		randStr := fmt.Sprintf("git-remote-ipfs-test-%x", buf.String())
		tmpDir := filepath.Join("/", os.TempDir(), randStr)
		_, err := os.Stat(tmpDir)
		if os.IsNotExist(err) {
			checkFatal(t, os.MkdirAll(tmpDir, 0700))
			t.Logf("tmpDir created: %s", tmpDir)
			return tmpDir
		}
		buf.Reset()
	}
	t.Fatal("couldnt find a tmpDir")
	return ""
}

var expectedClone = map[string][]byte{
	"testA":     []byte("\x94\x17\xd0\x11\x82+\x87]\xa7\"!\xc8ш\b\x9c\xbf\xce\xe8\x06"),
	"hello.txt": []byte("⃚\xd2\xe4s\x86\xd3B\x03\x89X\xfb\xa9A\xfcx\xe3x\x0e"),
	"notes":     []byte("2\xed\x91`K'(`\xec\x91\x1f¿J\xe61\xb7\x90\n\xa8"),
}

func TestClone(t *testing.T) {
	// pinned by pinbot, prepared with 'git-ipfs-rehost https://github.com/cryptix/git-remote-ipfs-testcase'
	rmDir(t, cloneAndCheckout(t, "ipfs://QmNRzJ6weMUs8SpeGApfY6XZEPcVbg1PTAARFZJ2C2McJq/git-remote-ipfs-testcase", expectedClone))
}

func TestClone_unpacked(t *testing.T) {
	// pinned by pinbot, prepared with 'git-ipfs-rehost --unpack https://github.com/cryptix/git-remote-ipfs-testcase unpackedTest'
	rmDir(t, cloneAndCheckout(t, "ipfs://QmYFpZJs82hLTyEpwkzVpaXGUabVVwiT8yrd6TK81XnoGB/unpackedTest", expectedClone))
}

func cloneAndCheckout(t *testing.T, repo string, expected map[string][]byte) (tmpDir string) {
	checkInstalled(t)

	tmpDir = mkRandTmpDir(t)

	var buf bytes.Buffer
	cloneCmd := exec.Command(gitPath, "clone", repo, tmpDir)
	cloneCmd.Stdout = &buf
	cloneCmd.Stderr = &buf
	err := cloneCmd.Run()
	t.Log(buf.String())
	if err != nil { // exit status 0?
		t.Fatalf("git clone ipfs:// failed: %s\nOutput:%s", err, buf.String())
	}

	hashMap(t, tmpDir, expected)

	return tmpDir
}

func rmDir(t *testing.T, dir string) {
	if err := os.RemoveAll(dir); err != nil { // cleanup tmpDir
		t.Fatal(err)
	}
}
func hashMap(t *testing.T, dir string, files map[string][]byte) {
	for fname, want := range files {
		f, err := os.Open(filepath.Join(dir, fname))
		checkFatal(t, err)
		h := sha1.New()

		_, err = io.Copy(h, f)
		checkFatal(t, err)

		got := h.Sum(nil)
		if bytes.Compare(want, got) != 0 {
			t.Errorf("hashMap: compare of %s failed\nWant: %q\nGot:  %q", fname, want, got)
		}

	}
}
<commit_msg>always (re-)install helper before tests<commit_after>package main

import (
	"bytes"
	"crypto/sha1"
	"fmt"
	"io"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
	"time"

	"github.com/jbenet/go-random"
)

// Warning: these tests assume some networking capabilities... sorry

var (
	gitPath string
)

// rand strings
func init() {
	rand.Seed(time.Now().Unix())
}

// checks for the needed tools
func checkInstalled(t *testing.T) {
	var err error
	gitPath, err = exec.LookPath("git")
	checkFatal(t, err)
	out, err := exec.Command("go", "install", "github.com/cryptix/git-remote-ipfs").CombinedOutput()
	t.Log(fmt.Sprintf("%q", string(out)))
	checkFatal(t, err)
	_, err = exec.LookPath("git-remote-ipfs")
	checkFatal(t, err)
}

// oh well.. just some rand string
func mkRandTmpDir(t *testing.T) string {
	var buf bytes.Buffer
	for i := 0; i < 10; i++ {
		checkFatal(t, random.WriteRandomBytes(20, &buf))
		randStr := fmt.Sprintf("git-remote-ipfs-test-%x", buf.String())
		tmpDir := filepath.Join("/", os.TempDir(), randStr)
		_, err := os.Stat(tmpDir)
		if os.IsNotExist(err) {
			checkFatal(t, os.MkdirAll(tmpDir, 0700))
			t.Logf("tmpDir created: %s", tmpDir)
			return tmpDir
		}
		buf.Reset()
	}
	t.Fatal("couldnt find a tmpDir")
	return ""
}

var expectedClone = map[string][]byte{
	"testA":     []byte("\x94\x17\xd0\x11\x82+\x87]\xa7\"!\xc8ш\b\x9c\xbf\xce\xe8\x06"),
	"hello.txt": []byte("⃚\xd2\xe4s\x86\xd3B\x03\x89X\xfb\xa9A\xfcx\xe3x\x0e"),
	"notes":     []byte("2\xed\x91`K'(`\xec\x91\x1f¿J\xe61\xb7\x90\n\xa8"),
}

func TestClone(t *testing.T) {
	// pinned by pinbot, prepared with 'git-ipfs-rehost https://github.com/cryptix/git-remote-ipfs-testcase'
	rmDir(t, cloneAndCheckout(t, "ipfs://QmNRzJ6weMUs8SpeGApfY6XZEPcVbg1PTAARFZJ2C2McJq/git-remote-ipfs-testcase", expectedClone))
}

func TestClone_unpacked(t *testing.T) {
	// pinned by pinbot, prepared with 'git-ipfs-rehost --unpack https://github.com/cryptix/git-remote-ipfs-testcase unpackedTest'
	rmDir(t, cloneAndCheckout(t, "ipfs://QmYFpZJs82hLTyEpwkzVpaXGUabVVwiT8yrd6TK81XnoGB/unpackedTest", expectedClone))
}

func cloneAndCheckout(t *testing.T, repo string, expected map[string][]byte) (tmpDir string) {
	checkInstalled(t)

	tmpDir = mkRandTmpDir(t)

	var buf bytes.Buffer
	cloneCmd := exec.Command(gitPath, "clone", repo, tmpDir)
	cloneCmd.Stdout = &buf
	cloneCmd.Stderr = &buf
	err := cloneCmd.Run()
	t.Log(buf.String())
	if err != nil { // exit status 0?
		t.Fatalf("git clone ipfs:// failed: %s\nOutput:%s", err, buf.String())
	}

	hashMap(t, tmpDir, expected)

	return tmpDir
}

func rmDir(t *testing.T, dir string) {
	if err := os.RemoveAll(dir); err != nil { // cleanup tmpDir
		t.Fatal(err)
	}
}
func hashMap(t *testing.T, dir string, files map[string][]byte) {
	for fname, want := range files {
		f, err := os.Open(filepath.Join(dir, fname))
		checkFatal(t, err)
		h := sha1.New()

		_, err = io.Copy(h, f)
		checkFatal(t, err)

		got := h.Sum(nil)
		if bytes.Compare(want, got) != 0 {
			t.Errorf("hashMap: compare of %s failed\nWant: %q\nGot:  %q", fname, want, got)
		}

	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"fmt"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"golang.org/x/net/context"
)

type CmdTeamCreate struct {
	TeamName  keybase1.TeamName
	Subteam   bool
	SessionID int
	libkb.Contextified
}

func (v *CmdTeamCreate) ParseArgv(ctx *cli.Context) error {
	var err error
	v.TeamName, err = ParseOneTeamNameK1(ctx)
	if err != nil {
		return err
	}

	v.Subteam = ctx.Bool("subteam")

	return nil
}

func (v *CmdTeamCreate) Run() (err error) {

	if v.TeamName.IsRootTeam() && v.Subteam {
		return fmt.Errorf("Leave off --subteam when creating a root team")
	}

	if !v.TeamName.IsRootTeam() && !v.Subteam {
		return fmt.Errorf("Use --subteam to create a subteam. Team names with dots are subteams.")
	}

	cli, err := GetTeamsClient(v.G())
	if err != nil {
		return err
	}

	protocols := []rpc.Protocol{
		NewSecretUIProtocol(v.G()),
	}
	if err = RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	if v.TeamName.IsRootTeam() {
		err = cli.TeamCreate(context.TODO(), keybase1.TeamCreateArg{
			Name:      v.TeamName,
			SessionID: v.SessionID,
		})
	} else {
		err = cli.TeamCreateSubteam(context.TODO(), keybase1.TeamCreateSubteamArg{
			Name:      v.TeamName,
			SessionID: v.SessionID,
		})
	}
	if err != nil {
		return err
	}

	dui := v.G().UI.GetDumbOutputUI()
	dui.Printf("Success!\n")

	return nil
}

func newCmdTeamCreate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "create",
		ArgumentHelp: "teamname",
		Usage:        "Create a team or a subteam.",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "subteam",
				Usage: "Create a subteam",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdTeamCreateRunner(g), "teamcreate", c)
		},
		Description: "Create a team or a subteam with specified name.",
	}
}

func NewCmdTeamCreateRunner(g *libkb.GlobalContext) *CmdTeamCreate {
	return &CmdTeamCreate{Contextified: libkb.NewContextified(g)}
}

func (v *CmdTeamCreate) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
}
<commit_msg>Remove --subteam flag<commit_after>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package client

import (
	"github.com/keybase/cli"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"golang.org/x/net/context"
)

type CmdTeamCreate struct {
	TeamName  keybase1.TeamName
	SessionID int
	libkb.Contextified
}

func (v *CmdTeamCreate) ParseArgv(ctx *cli.Context) error {
	var err error
	v.TeamName, err = ParseOneTeamNameK1(ctx)
	if err != nil {
		return err
	}

	return nil
}

func (v *CmdTeamCreate) Run() (err error) {
	cli, err := GetTeamsClient(v.G())
	if err != nil {
		return err
	}

	protocols := []rpc.Protocol{
		NewSecretUIProtocol(v.G()),
	}
	if err = RegisterProtocolsWithContext(protocols, v.G()); err != nil {
		return err
	}

	if v.TeamName.IsRootTeam() {
		err = cli.TeamCreate(context.TODO(), keybase1.TeamCreateArg{
			Name:      v.TeamName,
			SessionID: v.SessionID,
		})
	} else {
		err = cli.TeamCreateSubteam(context.TODO(), keybase1.TeamCreateSubteamArg{
			Name:      v.TeamName,
			SessionID: v.SessionID,
		})
	}
	if err != nil {
		return err
	}

	dui := v.G().UI.GetDumbOutputUI()
	dui.Printf("Success!\n")

	return nil
}

func newCmdTeamCreate(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name:         "create",
		ArgumentHelp: "teamname",
		Usage:        "Create a team or a subteam.",
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "subteam",
				Usage: "Create a subteam",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewCmdTeamCreateRunner(g), "teamcreate", c)
		},
		Description: "Create a team or a subteam with specified name.",
	}
}

func NewCmdTeamCreateRunner(g *libkb.GlobalContext) *CmdTeamCreate {
	return &CmdTeamCreate{Contextified: libkb.NewContextified(g)}
}

func (v *CmdTeamCreate) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

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

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

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

// Package dbconfigs provides the registration for command line options
// to collect db connection parameters. Once registered and collected,
// it provides variables and functions to build connection parameters
// for connecting to the database.
package dbconfigs

import (
	"encoding/json"
	"flag"
	"fmt"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sync2"
	"vitess.io/vitess/go/vt/log"
)

var (
	dbConfigs  = DBConfigs{userConfigs: make(map[string]*userConfig)}
	baseConfig = mysql.ConnParams{}
)

// DBConfigs stores all the data needed to build various connection
// parameters for the db. It stores credentials for app, appdebug,
// allprivs, dba, filtered and repl users.
// It contains other connection parameters like socket, charset, etc.
// It also stores the default db name, which it can combine with the
// rest of the data to build db-sepcific connection parameters.
// It also supplies the SidecarDBName. This is currently hardcoded
// to "_vt", but will soon become customizable.
// The life-cycle of this package is as follows:
// App must call RegisterFlags to request the types of connections
// it wants support for. This must be done before involing flags.Parse.
// After flag parsing, app invokes the Init function, which will return
// a DBConfigs object.
// The app must store the DBConfigs object internally, and use it to
// build connection parameters as needed.
// The DBName is initially empty and may later be set or changed by the app.
type DBConfigs struct {
	userConfigs   map[string]*userConfig
	DBName        sync2.AtomicString
	SidecarDBName sync2.AtomicString
}

type userConfig struct {
	useSSL bool
	param  mysql.ConnParams
}

// config flags
const (
	App      = "app"
	AppDebug = "appdebug"
	// AllPrivs user should have more privileges than App (should include possibility to do
	// schema changes and write to internal Vitess tables), but it shouldn't have SUPER
	// privilege like Dba has.
	AllPrivs = "allprivs"
	Dba      = "dba"
	Filtered = "filtered"
	Repl     = "repl"
)

// All can be used to register all flags: RegisterFlags(All...)
var All = []string{App, AppDebug, AllPrivs, Dba, Filtered, Repl}

// RegisterFlags registers the flags for the given DBConfigFlag.
// For instance, vttablet will register client, dba and repl.
// Returns all registered flags.
func RegisterFlags(userKeys ...string) {
	registerBaseFlags()
	for _, userKey := range userKeys {
		uc := &userConfig{}
		dbConfigs.userConfigs[userKey] = uc
		registerPerUserFlags(uc, userKey)
	}
}

func registerBaseFlags() {
	flag.StringVar(&baseConfig.UnixSocket, "db_socket", "", "The unix socket to connect on. If this is specifed, host and port will not be used.")
	flag.StringVar(&baseConfig.Host, "db_host", "", "The host name for the tcp connection.")
	flag.IntVar(&baseConfig.Port, "db_port", 0, "tcp port")
	flag.StringVar(&baseConfig.Charset, "db_charset", "utf8", "Character set. Only utf8 or latin1 based character sets are supported.")
	flag.Uint64Var(&baseConfig.Flags, "db_flags", 0, "Flag values as defined by MySQL.")
	flag.StringVar(&baseConfig.SslCa, "db_ssl_ca", "", "connection ssl ca")
	flag.StringVar(&baseConfig.SslCaPath, "db_ssl_ca_path", "", "connection ssl ca path")
	flag.StringVar(&baseConfig.SslCert, "db_ssl_cert", "", "connection ssl certificate")
	flag.StringVar(&baseConfig.SslKey, "db_ssl_key", "", "connection ssl key")
}

// The flags will change the global singleton
// TODO(sougou): deprecate the legacy flags.
func registerPerUserFlags(dbc *userConfig, userKey string) {
	newUserFlag := "db_" + userKey + "_user"
	flag.StringVar(&dbc.param.Uname, "db-config-"+userKey+"-uname", "vt_"+userKey, "deprecated: use "+newUserFlag)
	flag.StringVar(&dbc.param.Uname, newUserFlag, "vt_"+userKey, "db "+userKey+" user userKey")

	newPasswordFlag := "db_" + userKey + "_password"
	flag.StringVar(&dbc.param.Pass, "db-config-"+userKey+"-pass", "", "db "+userKey+" deprecated: use "+newPasswordFlag)
	flag.StringVar(&dbc.param.Pass, newPasswordFlag, "", "db "+userKey+" password")

	flag.BoolVar(&dbc.useSSL, "db_"+userKey+"_use_ssl", true, "Set this flag to false to make the "+userKey+" connection to not use ssl")

	flag.StringVar(&dbc.param.Host, "db-config-"+userKey+"-host", "", "deprecated: use db_host")
	flag.IntVar(&dbc.param.Port, "db-config-"+userKey+"-port", 0, "deprecated: use db_port")
	flag.StringVar(&dbc.param.UnixSocket, "db-config-"+userKey+"-unixsocket", "", "deprecated: use db_socket")
	flag.StringVar(&dbc.param.Charset, "db-config-"+userKey+"-charset", "utf8", "deprecated: use db_charset")
	flag.Uint64Var(&dbc.param.Flags, "db-config-"+userKey+"-flags", 0, "deprecated: use db_flags")
	flag.StringVar(&dbc.param.SslCa, "db-config-"+userKey+"-ssl-ca", "", "deprecated: use db_ssl_ca")
	flag.StringVar(&dbc.param.SslCaPath, "db-config-"+userKey+"-ssl-ca-path", "", "deprecated: use db_ssl_ca_path")
	flag.StringVar(&dbc.param.SslCert, "db-config-"+userKey+"-ssl-cert", "", "deprecated: use db_ssl_cert")
	flag.StringVar(&dbc.param.SslKey, "db-config-"+userKey+"-ssl-key", "", "deprecated: use db_ssl_key")

	flag.StringVar(&dbc.param.DeprecatedDBName, "db-config-"+userKey+"-dbname", "", "deprecated: dbname does not need to be explicitly configured")

}

// AppWithDB returns connection parameters for app with dbname set.
func (dbcfgs *DBConfigs) AppWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(App, true)
}

// AppDebugWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) AppDebugWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(AppDebug, true)
}

// AllPrivsWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) AllPrivsWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(AllPrivs, true)
}

// Dba returns connection parameters for dba with no dbname set.
func (dbcfgs *DBConfigs) Dba() *mysql.ConnParams {
	return dbcfgs.makeParams(Dba, false)
}

// DbaWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) DbaWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(Dba, true)
}

// FilteredWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) FilteredWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(Filtered, true)
}

// Repl returns connection parameters for appdebug with no dbname set.
func (dbcfgs *DBConfigs) Repl() *mysql.ConnParams {
	return dbcfgs.makeParams(Repl, false)
}

// AppWithDB returns connection parameters for app with dbname set.
func (dbcfgs *DBConfigs) makeParams(userKey string, withDB bool) *mysql.ConnParams {
	orig := dbcfgs.userConfigs[userKey]
	if orig == nil {
		return &mysql.ConnParams{}
	}
	result := orig.param
	if withDB {
		result.DbName = dbcfgs.DBName.Get()
	}
	return &result
}

// IsZero returns true if DBConfigs was uninitialized.
func (dbcfgs *DBConfigs) IsZero() bool {
	return len(dbcfgs.userConfigs) == 0
}

func (dbcfgs *DBConfigs) String() string {
	out := struct {
		Conn  mysql.ConnParams
		Users map[string]string
	}{
		Users: make(map[string]string),
	}
	if conn := dbcfgs.userConfigs[App]; conn != nil {
		out.Conn = conn.param
	} else if conn := dbcfgs.userConfigs[Dba]; conn != nil {
		out.Conn = conn.param
	}
	out.Conn.Pass = "****"
	for k, uc := range dbcfgs.userConfigs {
		out.Users[k] = uc.param.Uname
	}
	data, err := json.MarshalIndent(out, "", "  ")
	if err != nil {
		return err.Error()
	}
	return string(data)
}

// Copy returns a copy of the DBConfig.
func (dbcfgs *DBConfigs) Copy() *DBConfigs {
	result := &DBConfigs{userConfigs: make(map[string]*userConfig)}
	for k, u := range dbcfgs.userConfigs {
		newu := *u
		result.userConfigs[k] = &newu
	}
	result.DBName.Set(dbcfgs.DBName.Get())
	result.SidecarDBName.Set(dbcfgs.SidecarDBName.Get())
	return result
}

// HasConnectionParams returns true if connection parameters were
// specified in the command-line. This will allow the caller to
// search for alternate ways to connect, like looking in the my.cnf
// file.
func HasConnectionParams() bool {
	return baseConfig.Host != "" || baseConfig.UnixSocket != ""
}

// Init will initialize all the necessary connection parameters.
// Precedence is as follows: if baseConfig command line options are
// set, they supersede all other settings.
// If baseConfig is not set, the next priority is with per-user connection
// parameters. This is only for legacy support.
// If no per-user parameters are supplied, then the defaultSocketFile
// is used to initialize the per-user conn params.
func Init(defaultSocketFile string) (*DBConfigs, error) {
	// The new base configs, if set, supersede legacy settings.
	if HasConnectionParams() {
		for _, uc := range dbConfigs.userConfigs {
			uc.param.Host = baseConfig.Host
			uc.param.Port = baseConfig.Port
			uc.param.UnixSocket = baseConfig.UnixSocket
			uc.param.Charset = baseConfig.Charset
			uc.param.Flags = baseConfig.Flags
			if uc.useSSL {
				uc.param.SslCa = baseConfig.SslCa
				uc.param.SslCaPath = baseConfig.SslCaPath
				uc.param.SslCert = baseConfig.SslCert
				uc.param.SslKey = baseConfig.SslKey
			}
		}
	} else {
		// Use supplied socket value if conn parameters are not specified.
		for _, uc := range dbConfigs.userConfigs {
			if uc.param.UnixSocket == "" && uc.param.Host == "" {
				uc.param.UnixSocket = defaultSocketFile
			}
		}
	}

	// See if the CredentialsServer is working. We do not use the
	// result for anything, this is just a check.
	for _, uc := range dbConfigs.userConfigs {
		if _, err := WithCredentials(&uc.param); err != nil {
			return nil, fmt.Errorf("dbconfig cannot be initialized: %v", err)
		}
		// Check for only one.
		break
	}
	dbConfigs.SidecarDBName.Set("_vt")

	log.Infof("DBConfigs: %v\n", dbConfigs.String())
	return &dbConfigs, nil
}

// NewTestDBConfigs returns a DBConfigs meant for testing.
func NewTestDBConfigs(genParams, appDebugParams mysql.ConnParams, dbName string) *DBConfigs {
	dbcfgs := &DBConfigs{
		userConfigs: map[string]*userConfig{
			App:      {param: genParams},
			AppDebug: {param: appDebugParams},
			AllPrivs: {param: genParams},
			Dba:      {param: genParams},
			Filtered: {param: genParams},
			Repl:     {param: genParams},
		},
	}
	dbcfgs.DBName.Set(dbName)
	dbcfgs.SidecarDBName.Set("_vt")
	return dbcfgs
}
<commit_msg>Adds setting the DB server name using a parameter.<commit_after>/*
Copyright 2017 Google Inc.

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

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

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

// Package dbconfigs provides the registration for command line options
// to collect db connection parameters. Once registered and collected,
// it provides variables and functions to build connection parameters
// for connecting to the database.
package dbconfigs

import (
	"encoding/json"
	"flag"
	"fmt"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/sync2"
	"vitess.io/vitess/go/vt/log"
)

var (
	dbConfigs  = DBConfigs{userConfigs: make(map[string]*userConfig)}
	baseConfig = mysql.ConnParams{}
)

// DBConfigs stores all the data needed to build various connection
// parameters for the db. It stores credentials for app, appdebug,
// allprivs, dba, filtered and repl users.
// It contains other connection parameters like socket, charset, etc.
// It also stores the default db name, which it can combine with the
// rest of the data to build db-sepcific connection parameters.
// It also supplies the SidecarDBName. This is currently hardcoded
// to "_vt", but will soon become customizable.
// The life-cycle of this package is as follows:
// App must call RegisterFlags to request the types of connections
// it wants support for. This must be done before involing flags.Parse.
// After flag parsing, app invokes the Init function, which will return
// a DBConfigs object.
// The app must store the DBConfigs object internally, and use it to
// build connection parameters as needed.
// The DBName is initially empty and may later be set or changed by the app.
type DBConfigs struct {
	userConfigs   map[string]*userConfig
	DBName        sync2.AtomicString
	SidecarDBName sync2.AtomicString
}

type userConfig struct {
	useSSL bool
	param  mysql.ConnParams
}

// config flags
const (
	App      = "app"
	AppDebug = "appdebug"
	// AllPrivs user should have more privileges than App (should include possibility to do
	// schema changes and write to internal Vitess tables), but it shouldn't have SUPER
	// privilege like Dba has.
	AllPrivs = "allprivs"
	Dba      = "dba"
	Filtered = "filtered"
	Repl     = "repl"
)

// All can be used to register all flags: RegisterFlags(All...)
var All = []string{App, AppDebug, AllPrivs, Dba, Filtered, Repl}

// RegisterFlags registers the flags for the given DBConfigFlag.
// For instance, vttablet will register client, dba and repl.
// Returns all registered flags.
func RegisterFlags(userKeys ...string) {
	registerBaseFlags()
	for _, userKey := range userKeys {
		uc := &userConfig{}
		dbConfigs.userConfigs[userKey] = uc
		registerPerUserFlags(uc, userKey)
	}
}

func registerBaseFlags() {
	flag.StringVar(&baseConfig.UnixSocket, "db_socket", "", "The unix socket to connect on. If this is specifed, host and port will not be used.")
	flag.StringVar(&baseConfig.Host, "db_host", "", "The host name for the tcp connection.")
	flag.IntVar(&baseConfig.Port, "db_port", 0, "tcp port")
	flag.StringVar(&baseConfig.Charset, "db_charset", "utf8", "Character set. Only utf8 or latin1 based character sets are supported.")
	flag.Uint64Var(&baseConfig.Flags, "db_flags", 0, "Flag values as defined by MySQL.")
	flag.StringVar(&baseConfig.SslCa, "db_ssl_ca", "", "connection ssl ca")
	flag.StringVar(&baseConfig.SslCaPath, "db_ssl_ca_path", "", "connection ssl ca path")
	flag.StringVar(&baseConfig.SslCert, "db_ssl_cert", "", "connection ssl certificate")
	flag.StringVar(&baseConfig.SslKey, "db_ssl_key", "", "connection ssl key")
	flag.StringVar(&baseConfig.ServerName, "db_server_name", "", "server name of the DB we are connecting to.")

}

// The flags will change the global singleton
// TODO(sougou): deprecate the legacy flags.
func registerPerUserFlags(dbc *userConfig, userKey string) {
	newUserFlag := "db_" + userKey + "_user"
	flag.StringVar(&dbc.param.Uname, "db-config-"+userKey+"-uname", "vt_"+userKey, "deprecated: use "+newUserFlag)
	flag.StringVar(&dbc.param.Uname, newUserFlag, "vt_"+userKey, "db "+userKey+" user userKey")

	newPasswordFlag := "db_" + userKey + "_password"
	flag.StringVar(&dbc.param.Pass, "db-config-"+userKey+"-pass", "", "db "+userKey+" deprecated: use "+newPasswordFlag)
	flag.StringVar(&dbc.param.Pass, newPasswordFlag, "", "db "+userKey+" password")

	flag.BoolVar(&dbc.useSSL, "db_"+userKey+"_use_ssl", true, "Set this flag to false to make the "+userKey+" connection to not use ssl")

	flag.StringVar(&dbc.param.Host, "db-config-"+userKey+"-host", "", "deprecated: use db_host")
	flag.IntVar(&dbc.param.Port, "db-config-"+userKey+"-port", 0, "deprecated: use db_port")
	flag.StringVar(&dbc.param.UnixSocket, "db-config-"+userKey+"-unixsocket", "", "deprecated: use db_socket")
	flag.StringVar(&dbc.param.Charset, "db-config-"+userKey+"-charset", "utf8", "deprecated: use db_charset")
	flag.Uint64Var(&dbc.param.Flags, "db-config-"+userKey+"-flags", 0, "deprecated: use db_flags")
	flag.StringVar(&dbc.param.SslCa, "db-config-"+userKey+"-ssl-ca", "", "deprecated: use db_ssl_ca")
	flag.StringVar(&dbc.param.SslCaPath, "db-config-"+userKey+"-ssl-ca-path", "", "deprecated: use db_ssl_ca_path")
	flag.StringVar(&dbc.param.SslCert, "db-config-"+userKey+"-ssl-cert", "", "deprecated: use db_ssl_cert")
	flag.StringVar(&dbc.param.SslKey, "db-config-"+userKey+"-ssl-key", "", "deprecated: use db_ssl_key")
	flag.StringVar(&dbc.param.ServerName, "db-config-"+userKey+"-server_name", "", "deprecated: use db_server_name")

	flag.StringVar(&dbc.param.DeprecatedDBName, "db-config-"+userKey+"-dbname", "", "deprecated: dbname does not need to be explicitly configured")

}

// AppWithDB returns connection parameters for app with dbname set.
func (dbcfgs *DBConfigs) AppWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(App, true)
}

// AppDebugWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) AppDebugWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(AppDebug, true)
}

// AllPrivsWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) AllPrivsWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(AllPrivs, true)
}

// Dba returns connection parameters for dba with no dbname set.
func (dbcfgs *DBConfigs) Dba() *mysql.ConnParams {
	return dbcfgs.makeParams(Dba, false)
}

// DbaWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) DbaWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(Dba, true)
}

// FilteredWithDB returns connection parameters for appdebug with dbname set.
func (dbcfgs *DBConfigs) FilteredWithDB() *mysql.ConnParams {
	return dbcfgs.makeParams(Filtered, true)
}

// Repl returns connection parameters for appdebug with no dbname set.
func (dbcfgs *DBConfigs) Repl() *mysql.ConnParams {
	return dbcfgs.makeParams(Repl, false)
}

// AppWithDB returns connection parameters for app with dbname set.
func (dbcfgs *DBConfigs) makeParams(userKey string, withDB bool) *mysql.ConnParams {
	orig := dbcfgs.userConfigs[userKey]
	if orig == nil {
		return &mysql.ConnParams{}
	}
	result := orig.param
	if withDB {
		result.DbName = dbcfgs.DBName.Get()
	}
	return &result
}

// IsZero returns true if DBConfigs was uninitialized.
func (dbcfgs *DBConfigs) IsZero() bool {
	return len(dbcfgs.userConfigs) == 0
}

func (dbcfgs *DBConfigs) String() string {
	out := struct {
		Conn  mysql.ConnParams
		Users map[string]string
	}{
		Users: make(map[string]string),
	}
	if conn := dbcfgs.userConfigs[App]; conn != nil {
		out.Conn = conn.param
	} else if conn := dbcfgs.userConfigs[Dba]; conn != nil {
		out.Conn = conn.param
	}
	out.Conn.Pass = "****"
	for k, uc := range dbcfgs.userConfigs {
		out.Users[k] = uc.param.Uname
	}
	data, err := json.MarshalIndent(out, "", "  ")
	if err != nil {
		return err.Error()
	}
	return string(data)
}

// Copy returns a copy of the DBConfig.
func (dbcfgs *DBConfigs) Copy() *DBConfigs {
	result := &DBConfigs{userConfigs: make(map[string]*userConfig)}
	for k, u := range dbcfgs.userConfigs {
		newu := *u
		result.userConfigs[k] = &newu
	}
	result.DBName.Set(dbcfgs.DBName.Get())
	result.SidecarDBName.Set(dbcfgs.SidecarDBName.Get())
	return result
}

// HasConnectionParams returns true if connection parameters were
// specified in the command-line. This will allow the caller to
// search for alternate ways to connect, like looking in the my.cnf
// file.
func HasConnectionParams() bool {
	return baseConfig.Host != "" || baseConfig.UnixSocket != ""
}

// Init will initialize all the necessary connection parameters.
// Precedence is as follows: if baseConfig command line options are
// set, they supersede all other settings.
// If baseConfig is not set, the next priority is with per-user connection
// parameters. This is only for legacy support.
// If no per-user parameters are supplied, then the defaultSocketFile
// is used to initialize the per-user conn params.
func Init(defaultSocketFile string) (*DBConfigs, error) {
	// The new base configs, if set, supersede legacy settings.
	if HasConnectionParams() {
		for _, uc := range dbConfigs.userConfigs {
			uc.param.Host = baseConfig.Host
			uc.param.Port = baseConfig.Port
			uc.param.UnixSocket = baseConfig.UnixSocket
			uc.param.Charset = baseConfig.Charset
			uc.param.Flags = baseConfig.Flags
			if uc.useSSL {
				uc.param.SslCa = baseConfig.SslCa
				uc.param.SslCaPath = baseConfig.SslCaPath
				uc.param.SslCert = baseConfig.SslCert
				uc.param.SslKey = baseConfig.SslKey
				uc.param.ServerName = baseConfig.ServerName
			}
		}
	} else {
		// Use supplied socket value if conn parameters are not specified.
		for _, uc := range dbConfigs.userConfigs {
			if uc.param.UnixSocket == "" && uc.param.Host == "" {
				uc.param.UnixSocket = defaultSocketFile
			}
		}
	}

	// See if the CredentialsServer is working. We do not use the
	// result for anything, this is just a check.
	for _, uc := range dbConfigs.userConfigs {
		if _, err := WithCredentials(&uc.param); err != nil {
			return nil, fmt.Errorf("dbconfig cannot be initialized: %v", err)
		}
		// Check for only one.
		break
	}
	dbConfigs.SidecarDBName.Set("_vt")

	log.Infof("DBConfigs: %v\n", dbConfigs.String())
	return &dbConfigs, nil
}

// NewTestDBConfigs returns a DBConfigs meant for testing.
func NewTestDBConfigs(genParams, appDebugParams mysql.ConnParams, dbName string) *DBConfigs {
	dbcfgs := &DBConfigs{
		userConfigs: map[string]*userConfig{
			App:      {param: genParams},
			AppDebug: {param: appDebugParams},
			AllPrivs: {param: genParams},
			Dba:      {param: genParams},
			Filtered: {param: genParams},
			Repl:     {param: genParams},
		},
	}
	dbcfgs.DBName.Set(dbName)
	dbcfgs.SidecarDBName.Set("_vt")
	return dbcfgs
}
<|endoftext|>


<commit_before>package model

import (
	"testing"
)

func TestFindPhysicianBy(t *testing.T) {
	p, err := FindPhysicianBy("name", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	if p.Name != "TuoHua" {
		t.Error("FindPhysicianBy error!")
	}
}

func TestPhysicianGetPatients(t *testing.T) {
	p, err := FindPhysicianBy("name", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	err = p.GetPatients()
	if err != nil {
		t.Error(err)
	}
	if len(p.Patients) != 4 {
		t.Error("Physician's GetPatients error!")
	}
}

func TestPhysicianIncludesWhere(t *testing.T) {
	ps, err := PhysicianIncludesWhere([]string{"patients"}, "name = ?", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	if len(ps[0].Patients) != 4 {
		t.Error("PhysicianIncludesWhere error!")
	}
}
<commit_msg>add more tests in models_test.go<commit_after>package model

import (
	"testing"
)

// TestFindPhysicianBy test the function FindPhysicianBy()
func TestFindPhysicianBy(t *testing.T) {
	p, err := FindPhysicianBy("name", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	if p.Name != "TuoHua" {
		t.Error("FindPhysicianBy error!")
	}
}

// TestFindPhysician test the function FindPhysician()
func TestFindPhysician(t *testing.T) {
	p, err := FindPhysicianBy("name", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	pp, err := FindPhysician(p.Id)
	if err != nil {
		t.Error(err)
	}
	if p.Name != pp.Name {
		t.Error("FindPhysician error!")
	}
}

// TestPhysicianGetPatients test the method GetPatients()
func TestPhysicianGetPatients(t *testing.T) {
	p, err := FindPhysicianBy("name", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	err = p.GetPatients()
	if err != nil {
		t.Error(err)
	}
	if len(p.Patients) != 4 {
		t.Error("Physician's GetPatients error!")
	}
}

// TestPhysicianIncludesWhere test the method PhysicianIncludesWhere()
func TestPhysicianIncludesWhere(t *testing.T) {
	ps, err := PhysicianIncludesWhere([]string{"patients"}, "name = ?", "TuoHua")
	if err != nil {
		t.Error(err)
	}
	if len(ps[0].Patients) != 4 {
		t.Error("PhysicianIncludesWhere error!")
	}
}
<|endoftext|>