<commit_before>// Package dispatch provides a general purpose object dispatcher
// It can be used to asynchronously dispatch queues (channels)
// or synchronously dispatch single objects
// For example one could use it to dispatch events or messages
package dispatch

import (
	"errors"
	"reflect"
	"sync"
)

const (
	syncToken   = iota // See Dispatcher.SyncQueues()
	removeToken        // See Dispatcher.RemoveQueues()
)

// Dispatcher is used to register Handlers and dispatch objects
type Dispatcher struct {
	handlerLock    sync.Mutex
	tokenLock      sync.Mutex
	queueLock      sync.Mutex
	tokenWg        sync.WaitGroup
	queues         []chan interface{}
	handlers       map[reflect.Type][]reflect.Value
	cachedHandlers map[reflect.Type][]reflect.Value
}

// Dispatch dispatches an object to all it's handlers in the order in which the handlers were registered
func (d *Dispatcher) Dispatch(object interface{}) {
	d.handlerLock.Lock()
	defer d.handlerLock.Unlock()

	t := reflect.TypeOf(object)

	if d.cachedHandlers[t] == nil {
		d.initCache(t)
	}

	args := []reflect.Value{reflect.ValueOf(object)}

	for _, h := range d.cachedHandlers[t] {
		// Allow adding more handlers in handle function
		d.handlerLock.Unlock()
		h.Call(args)
		d.handlerLock.Lock()
	}
}

// We cache the handlers so we don't have to check the type of each handler group for every object of the same type
// Performance gained >15%, depending on the amount of handlers
func (d *Dispatcher) initCache(objectType reflect.Type) {
	// Read from nil map is allowed, so we initialize it only now if it's nil
	if d.cachedHandlers == nil {
		d.cachedHandlers = make(map[reflect.Type][]reflect.Value)
	}

	// Load handlers into cache
	d.cachedHandlers[objectType] = make([]reflect.Value, 0)
	for k := range d.handlers {
		if objectType.AssignableTo(k) {
			d.cachedHandlers[objectType] = append(d.cachedHandlers[objectType], d.handlers[k]...)
		}
	}
}

// AddQueue adds a channel as 'object-queue'
// All objects sent to the passed channel will be dispatched in a seperate go routine
func (d *Dispatcher) AddQueues(queues ...chan interface{}) {
	d.queueLock.Lock()
	defer d.queueLock.Unlock()

	d.queues = append(d.queues, queues...)
	for _, q := range queues {
		go d.dispatchQueue(q)
	}
}

// See AddQueue() & Dispatch()
func (d *Dispatcher) dispatchQueue(q <-chan interface{}) {
	var rem bool
	for e := range q {
		switch e {
		case syncToken:
			d.tokenWg.Done()
		case removeToken:
			rem = true
		default:
			d.Dispatch(e)
		}
		if rem {
			break
		}
	}
	// Remove closed or removed channel from queues
	d.removeQueue(q)

	// Only when manually removed, not closed
	if rem {
		d.tokenWg.Done()
	}
}

// RemoveQueues removes the given queues from the Dispatcher without closing them
func (d *Dispatcher) RemoveQueues(queues ...chan interface{}) error {
	return d.sendToken(queues, removeToken)
}

// RemoveAllQueues removes all queues from the Dispatcher without closing them
func (d *Dispatcher) RemoveAllQueues() {
	d.RemoveQueues(d.queues...)
}

// See RemoveQueues()
func (d *Dispatcher) removeQueue(q <-chan interface{}) {
	d.queueLock.Lock()
	defer d.queueLock.Unlock()

	// Might have been added multiple times (for whatever reason)
	for r := true; r; {
		r = false
		for i, _ := range d.queues {
			if d.queues[i] == q {
				d.queues = append(d.queues[:i], d.queues[i+1:]...)
				r = true
				break
			}
		}
	}
}

// SyncQueues syncs the channels dispatch routines to the current go routine
// This ensures all objects received in the passed channel up to this point will be handled before continuing
func (d *Dispatcher) SyncQueues(queues ...chan interface{}) error {
	// We can't just check the channel length as that does not tell us whether the last object has been fully dispatched
	return d.sendToken(queues, syncToken)
}

// SyncAllQueues calls SyncQueues for all queues in this Dispatcher
func (d *Dispatcher) SyncAllQueues() {
	d.SyncQueues(d.queues...)
}

// Sends a token to specific queues in the dispatcher and waits until they were handled
func (d *Dispatcher) sendToken(queues []chan interface{}, token interface{}) error {
	d.tokenLock.Lock()
	defer d.tokenLock.Unlock()

	var err error
	for _, q := range queues {
		found := false
		for _, dq := range d.queues {
			if q == dq {
				// Using sync.Cond would be a race against dispatchQueue
				d.tokenWg.Add(1)
				q <- token
				found = true
			}
		}
		if !found {
			err = errors.New("One or more queues not found")
		}
	}
	d.tokenWg.Wait()
	return err
}

// RegisterHandler registers an object handler (func) for the type of objects assignable to it's input parameter type
// If the handler registers a new handler in the function body, the new handler will only be active for new Dispatch calls
// Calling this method clears the internal type/handler mapping cache for interface handlers
func (d *Dispatcher) RegisterHandler(handler interface{}) {
	h := reflect.ValueOf(handler)
	ht := h.Type()
	if ht.NumIn() != 1 {
		panic("More than one input argument for handler function")
	}
	t := ht.In(0)

	d.handlerLock.Lock()
	defer d.handlerLock.Unlock()

	if d.handlers == nil {
		d.handlers = make(map[reflect.Type][]reflect.Value)
	}
	d.handlers[t] = append(d.handlers[t], h)

	if d.cachedHandlers != nil {
		// Reset cache for interface handlers
		if t.Kind() == reflect.Interface {
			d.cachedHandlers = nil
		} else {
			// For anything else we should be fine with adding the handler to the cache
			d.cachedHandlers[t] = append(d.cachedHandlers[t], h)
		}
	}
}
<commit_msg>Check if registered handler is of kind reflect.Func<commit_after>// Package dispatch provides a general purpose object dispatcher
// It can be used to asynchronously dispatch queues (channels)
// or synchronously dispatch single objects
// For example one could use it to dispatch events or messages
package dispatch

import (
	"errors"
	"reflect"
	"sync"
)

const (
	syncToken   = iota // See Dispatcher.SyncQueues()
	removeToken        // See Dispatcher.RemoveQueues()
)

// Dispatcher is used to register Handlers and dispatch objects
type Dispatcher struct {
	handlerLock    sync.Mutex
	tokenLock      sync.Mutex
	queueLock      sync.Mutex
	tokenWg        sync.WaitGroup
	queues         []chan interface{}
	handlers       map[reflect.Type][]reflect.Value
	cachedHandlers map[reflect.Type][]reflect.Value
}

// Dispatch dispatches an object to all it's handlers in the order in which the handlers were registered
func (d *Dispatcher) Dispatch(object interface{}) {
	d.handlerLock.Lock()
	defer d.handlerLock.Unlock()

	t := reflect.TypeOf(object)

	if d.cachedHandlers[t] == nil {
		d.initCache(t)
	}

	args := []reflect.Value{reflect.ValueOf(object)}

	for _, h := range d.cachedHandlers[t] {
		// Allow adding more handlers in handle function
		d.handlerLock.Unlock()
		h.Call(args)
		d.handlerLock.Lock()
	}
}

// We cache the handlers so we don't have to check the type of each handler group for every object of the same type
// Performance gained >15%, depending on the amount of handlers
func (d *Dispatcher) initCache(objectType reflect.Type) {
	// Read from nil map is allowed, so we initialize it only now if it's nil
	if d.cachedHandlers == nil {
		d.cachedHandlers = make(map[reflect.Type][]reflect.Value)
	}

	// Load handlers into cache
	d.cachedHandlers[objectType] = make([]reflect.Value, 0)
	for k := range d.handlers {
		if objectType.AssignableTo(k) {
			d.cachedHandlers[objectType] = append(d.cachedHandlers[objectType], d.handlers[k]...)
		}
	}
}

// AddQueues adds channels as 'object-queues'
// All objects sent to the passed queues will be dispatched to their handlers in a separate go routine per channel
func (d *Dispatcher) AddQueues(queues ...chan interface{}) {
	d.queueLock.Lock()
	defer d.queueLock.Unlock()

	d.queues = append(d.queues, queues...)
	for _, q := range queues {
		go d.dispatchQueue(q)
	}
}

// See AddQueue() & Dispatch()
func (d *Dispatcher) dispatchQueue(q <-chan interface{}) {
	var rem bool
	for e := range q {
		switch e {
		case syncToken:
			d.tokenWg.Done()
		case removeToken:
			rem = true
		default:
			d.Dispatch(e)
		}
		if rem {
			break
		}
	}
	// Remove closed or removed channel from queues
	d.removeQueue(q)

	// Only when manually removed, not closed
	if rem {
		d.tokenWg.Done()
	}
}

// RemoveQueues removes the given queues from the Dispatcher without closing them
func (d *Dispatcher) RemoveQueues(queues ...chan interface{}) error {
	return d.sendToken(queues, removeToken)
}

// RemoveAllQueues removes all queues from the Dispatcher without closing them
func (d *Dispatcher) RemoveAllQueues() {
	d.RemoveQueues(d.queues...)
}

// See RemoveQueues()
func (d *Dispatcher) removeQueue(q <-chan interface{}) {
	d.queueLock.Lock()
	defer d.queueLock.Unlock()

	// Might have been added multiple times (for whatever reason)
	for r := true; r; {
		r = false
		for i := range d.queues {
			if d.queues[i] == q {
				d.queues = append(d.queues[:i], d.queues[i+1:]...)
				r = true
				break
			}
		}
	}
}

// SyncQueues syncs the channels dispatch routines to the current go routine
// This ensures all objects received in the passed channels up to this point will be handled before continuing
func (d *Dispatcher) SyncQueues(queues ...chan interface{}) error {
	// We can't just check the channel length as that does not tell us whether the last object has been fully dispatched
	return d.sendToken(queues, syncToken)
}

// SyncAllQueues calls SyncQueues for all queues in this Dispatcher
func (d *Dispatcher) SyncAllQueues() {
	d.SyncQueues(d.queues...)
}

// Sends a token to specific queues in the dispatcher and waits until they were handled
func (d *Dispatcher) sendToken(queues []chan interface{}, token interface{}) error {
	d.tokenLock.Lock()
	defer d.tokenLock.Unlock()

	var err error
	for _, q := range queues {
		found := false
		for _, dq := range d.queues {
			if q == dq {
				// Using sync.Cond would be a race against dispatchQueue
				d.tokenWg.Add(1)
				q <- token
				found = true
			}
		}
		if !found {
			err = errors.New("One or more queues not found")
		}
	}
	d.tokenWg.Wait()
	return err
}

// RegisterHandler registers an object handler (func) for the type of objects assignable to it's input parameter type
// If the handler registers a new handler in the function body, the new handler will only be active for new Dispatch calls
// Calling this method clears the internal type/handler mapping cache for interface handlers
func (d *Dispatcher) RegisterHandler(handler interface{}) {
	h := reflect.ValueOf(handler)
	ht := h.Type()
	if ht.Kind() != reflect.Func {
		panic("Handler isn't a function")
	}
	if ht.NumIn() != 1 {
		panic("Handler function has more than one input parameter")
	}
	t := ht.In(0)

	d.handlerLock.Lock()
	defer d.handlerLock.Unlock()

	if d.handlers == nil {
		d.handlers = make(map[reflect.Type][]reflect.Value)
	}
	d.handlers[t] = append(d.handlers[t], h)

	if d.cachedHandlers != nil {
		// Reset cache for interface handlers
		if t.Kind() == reflect.Interface {
			d.cachedHandlers = nil
		} else {
			// For anything else we should be fine with adding the handler to the cache
			d.cachedHandlers[t] = append(d.cachedHandlers[t], h)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
	"path"
)

type Generator struct {
	templateDir  string
	dotGithubDir string
	repo         *Repository
}

func NewGenerator(temp string, repo *Repository) *Generator {
	dotdir := path.Join(repo.Path, ".github")
	if _, err := os.Stat(dotdir); os.IsNotExist(err) {
		if err := os.MkdirAll(dotdir, os.ModeDir|os.ModePerm); err != nil {
			panic(err)
		}
	}
	return &Generator{
		temp,
		dotdir,
		repo,
	}
}

func (g *Generator) applyTemplate(src_path string, dst_path string) {
	// XXX: Simply copy file
	src, err := os.Open(src_path)
	if err != nil {
		panic(err)
	}
	defer src.Close()

	dst, err := os.Open(dst_path)
	if err != nil {
		panic(err)
	}
	defer dst.Close()

	if _, err = io.Copy(dst, src); err != nil {
		panic(err)
	}
}

func (g *Generator) generateFile(name string, fallback string) {
	src := path.Join(g.templateDir, name)
	if len(fallback) != 0 {
		if _, err := os.Stat(src); os.IsNotExist(err) {
			src = path.Join(g.templateDir, fallback)
		}
	}
	if _, err := os.Stat(src); os.IsNotExist(err) {
		return
	}
	dst := path.Join(g.repo.Path, name)
	g.applyTemplate(src, dst)
}

func (g *Generator) GenerateIssueTemplate() {
	g.generateFile("ISSUE_TEMPLATE.md", "TEMPLATE.md")
}

func (g *Generator) GeneratePRTemplate() {
	g.generateFile("PULL_REQUEST_TEMPLATE.md", "TEMPLATE.md")
}

func (g *Generator) GenerateContributingTemplate() {
	g.generateFile("CONTRIBUTING.md", "")
}

func (g *Generator) GenerateAllTemplates() {
	g.GenerateIssueTemplate()
	g.GeneratePRTemplate()
	g.GenerateContributingTemplate()
}
<commit_msg>fix common template file name and fix creating destination file<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"path"
)

type Generator struct {
	templateDir  string
	dotGithubDir string
	repo         *Repository
}

func NewGenerator(temp string, repo *Repository) *Generator {
	dotdir := path.Join(repo.Path, ".github")
	if _, err := os.Stat(dotdir); os.IsNotExist(err) {
		if err := os.MkdirAll(dotdir, os.ModeDir|os.ModePerm); err != nil {
			panic(err)
		}
	}
	return &Generator{
		temp,
		dotdir,
		repo,
	}
}

func (g *Generator) applyTemplate(src_path string, dst_path string) {
	// XXX: Simply copy file
	src, err := os.Open(src_path)
	if err != nil {
		panic(err)
	}
	defer src.Close()

	dst, err := os.Create(dst_path)
	if err != nil {
		panic(err)
	}
	defer dst.Close()

	if _, err = io.Copy(dst, src); err != nil {
		panic(err)
	}

	fmt.Println("Created " + dst_path)
}

func (g *Generator) generateFile(name string, fallback string) {
	src := path.Join(g.templateDir, name)
	if len(fallback) != 0 {
		if _, err := os.Stat(src); os.IsNotExist(err) {
			src = path.Join(g.templateDir, fallback)
		}
	}
	if _, err := os.Stat(src); os.IsNotExist(err) {
		return
	}
	dst := path.Join(g.dotGithubDir, name)
	g.applyTemplate(src, dst)
}

func (g *Generator) GenerateIssueTemplate() {
	g.generateFile("ISSUE_TEMPLATE.md", "ISSUE_AND_PULL_REQUEST_TEMPLATE.md")
}

func (g *Generator) GeneratePRTemplate() {
	g.generateFile("PULL_REQUEST_TEMPLATE.md", "ISSUE_AND_PULL_REQUEST_TEMPLATE.md")
}

func (g *Generator) GenerateContributingTemplate() {
	g.generateFile("CONTRIBUTING.md", "")
}

func (g *Generator) GenerateAllTemplates() {
	g.GenerateIssueTemplate()
	g.GeneratePRTemplate()
	g.GenerateContributingTemplate()
}
<|endoftext|>


<commit_before>package goxsd

import (
	"bufio"
	"fmt"
	"github.com/realmfoo/caementarii/xsd"
	"os"
	"regexp"
	"strings"
)

type Generator struct {
	pkgName string
}

func (g *Generator) generate(s *xsd.Schema) {

	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()

	schema := &schema{}
	schema.targetNamespace = s.TargetNamespace

	for _, top := range s.SchemaTop {
		if node, ok := top.(xsd.Element); ok {
			// 3.3.2.1 Common Mapping Rules for Element Declarations
			elm := g.newElement(schema, node)

			// 3.3.2.2 Mapping Rules for Top-Level Element Declarations
			elm.name.Space = s.TargetNamespace

			elm.scope.variety = "global"

			fmt.Printf("%+v\n", elm)
			schema.elementDeclarations = append(schema.elementDeclarations, elm)
		}
	}

	w.WriteString("package " + g.pkgName + "\n\n")
	w.WriteString("import (\n")
	w.WriteString(")\n\n")
}

func (g *Generator) newComplexType(s *schema, parent interface{}, node *xsd.ComplexType) complexTypeDefinition {
	typeDef := complexTypeDefinition{}

	// The ·actual value· of the name [attribute].
	typeDef.name.Local = node.Name
	// The ·actual value· of the targetNamespace [attribute] of the <schema> ancestor element information item if present, otherwise ·absent·.
	typeDef.name.Space = s.targetNamespace
	// The ·actual value· of the abstract [attribute], if present, otherwise false.
	typeDef.abstract = node.Abstract

	typeDef.prohibitedSubstitutions = getBlocks(node, s, typeDef)
	typeDef.final = getFinals(node, s, typeDef)

	// If the name [attribute] is present, then ·absent·, otherwise (among the ancestor element information items there
	// will be a nearest <element>), the Element Declaration corresponding to the nearest <element> information item
	// among the the ancestor element information items.
	if node.Name == "" {
		typeDef.context = parent
	}

	// A sequence whose members are Assertions drawn from the following sources, in order:
	// 1 The {assertions} of the {base type definition}.
	// 2 Assertions corresponding to all the <assert> element information items among the [children] of <complexType>, <restriction> and <extension>, if any, in document order.
	//typeDef.assertions =

	// The ·annotation mapping· of the set of elements containing the <complexType>, the <openContent> [child], if
	// present, the <attributeGroup> [children], if present, the <simpleContent> and <complexContent> [children], if
	// present, and their <restriction> and <extension> [children], if present, and their <openContent> and
	// <attributeGroup> [children], if present, as defined in
	// XML Representation of Annotation Schema Components (§3.15.2).
	//typeDef.annotations =

	if node.SimpleContent != nil {

	} else {
		if node.ComplexContent != nil {
			// 3.4.2.3.1 Mapping Rules for Complex Types with Explicit Complex Content

			// The type definition ·resolved· to by the ·actual value· of the base [attribute]
			// typeDef.baseTypeDefinition =

			// If the <restriction> alternative is chosen, then restriction, otherwise (the <extension> alternative is
			// chosen) extension.
			if node.ComplexContent.Restriction != nil {
				typeDef.derivationMethod = "restriction"
			} else {
				typeDef.derivationMethod = "extension"
			}
		} else {
			// 3.4.2.3.2 Mapping Rules for Complex Types with Implicit Complex Content
			typeDef.baseTypeDefinition = nil
			typeDef.derivationMethod = "restriction"
		}

		// 3.4.2.3.3 Mapping Rules for Content Type Property of Complex Content
		//effectiveMixed := false
		//if node.ComplexContent.Mixed != nil {
		//	effectiveMixed = *node.ComplexContent.Mixed
		//} else if node.Mixed != nil {
		//	effectiveMixed = *node.Mixed
		//}

		//var explicitContent interface{}

	}

	return typeDef
}

func getBlocks(node *xsd.ComplexType, s *schema, typeDef complexTypeDefinition) []string {
	blocks := make([]string, 0)
	var effectiveBlockValue string
	if node.Block != "" {
		effectiveBlockValue = node.Block
	} else if s.blockDefault != "" {
		effectiveBlockValue = s.blockDefault
	} else {
		effectiveBlockValue = ""
	}
	if effectiveBlockValue == "#all" {
		blocks = []string{"extension", "restriction"}
	} else if effectiveBlockValue != "" {
		x := strings.Split(effectiveBlockValue, " ")
		for _, bl := range x {
			if bl == "extension" || bl == "restriction" {
				blocks = append(blocks, bl)
			}
		}
	}

	return blocks
}

func getFinals(node *xsd.ComplexType, s *schema, typeDef complexTypeDefinition) []string {
	blocks := make([]string, 0)
	var effectiveFinalValue string
	if node.Final != "" {
		effectiveFinalValue = node.Final
	} else if s.finalDefault != "" {
		effectiveFinalValue = s.finalDefault
	} else {
		effectiveFinalValue = ""
	}
	if effectiveFinalValue == "#all" {
		blocks = []string{"extension", "restriction"}
	} else if effectiveFinalValue != "" {
		x := strings.Split(effectiveFinalValue, " ")
		for _, bl := range x {
			if bl == "extension" || bl == "restriction" {
				blocks = append(blocks, bl)
			}
		}
	}

	return blocks
}

// 3.3.2.1 Common Mapping Rules for Element Declarations
func (g *Generator) newElement(s *schema, node xsd.Element) elementDeclaration {
	elm := elementDeclaration{}
	// The ·actual value· of the name [attribute].
	elm.name.Local = node.Name
	// The first of the following that applies:
	// 1 The type definition corresponding to the <simpleType> or <complexType> element information item in the
	//   [children], if either is present.
	// 2 The type definition ·resolved· to by the ·actual value· of the type [attribute], if it is present.
	// 3 The declared {type definition} of the Element Declaration ·resolved· to by the first QName in the
	//   ·actual value· of the substitutionGroup [attribute], if present.
	// 4 ·xs:anyType·.
	if node.ComplexType != nil {
		elm.typeDefinition = g.newComplexType(s, node, node.ComplexType)
	} else {
		elm.typeDefinition = nil
	}
	// A Type Table corresponding to the <alternative> element information items among the [children], if any, as
	// follows, otherwise ·absent·.
	// elm.typeTable
	elm.nillable = node.Nillable
	// If there is a default or a fixed [attribute], then a Value Constraint as follows, otherwise ·absent·.
	// [Definition:]  Use the name effective simple type definition for the declared {type definition}, if it is
	// a simple type definition, or, if {type definition}.{content type}.{variety} = simple, for {type definition}.
	// {content type}.{simple type definition}, or else for the built-in string simple type definition).
	if node.Default != "" {
		actualValue := node.Default
		elm.valueConstraint = &valueConstraint{
			variety: "default",
			// the ·actual value· (with respect to the ·effective simple type definition·) of the [attribute]
			value: actualValue,
			// the ·normalized value· (with respect to the ·effective simple type definition·) of the [attribute]
			lexicalForm: normalizeValue(actualValue),
		}
	}
	if node.Fixed != "" {
		actualValue := node.Fixed
		elm.valueConstraint = &valueConstraint{
			variety: "default",
			// the ·actual value· (with respect to the ·effective simple type definition·) of the [attribute]
			value: actualValue,
			// the ·normalized value· (with respect to the ·effective simple type definition·) of the [attribute]
			lexicalForm: normalizeValue(actualValue),
		}
	}
	// A set consisting of the identity-constraint-definitions corresponding to all the <key>, <unique> and
	// <keyref> element information items in the [children], if any, otherwise the empty set.
	// elm.identityConstraintDefinitions
	// A set of the element declarations ·resolved· to by the items in the ·actual value· of the substitutionGroup
	// [attribute], if present, otherwise the empty set.
	// elm.substitutionGroupAffiliations
	// A set depending on the ·actual value· of the block [attribute], if present, otherwise on the ·actual value·
	// of the blockDefault [attribute] of the ancestor <schema> element information item, if present, otherwise
	// on the empty string. Call this the EBV (for effective block value). Then the value of this property is the
	// appropriate case among the following:
	//
	// 1 If the EBV is the empty string, then the empty set;
	// 2 If the EBV is #all, then {extension, restriction, substitution};
	// 3 otherwise a set with members drawn from the set above, each being present or absent depending on whether
	//   the ·actual value· (which is a list) contains an equivalently named item.
	//
	// Note: Although the blockDefault [attribute] of <schema> may include values other than extension, restriction
	// or substitution, those values are ignored in the determination of {disallowed substitutions} for element
	// declarations (they are used elsewhere).
	// elm.disallowedSubstitutions
	// As for {disallowed substitutions} above, but using the final and finalDefault [attributes] in place of the
	// block and blockDefault [attributes] and with the relevant set being {extension, restriction}.
	//elm.substitutionGroupExclusions
	// The ·actual value· of the abstract [attribute], if present, otherwise false.
	elm.abstract = node.Abstract
	// The ·annotation mapping· of the <element> element and any of its <unique>, <key> and <keyref> [children]
	// with a ref [attribute], as defined in XML Representation of Annotation Schema Components (§3.15.2).
	// elm.annotations
	return elm
}

func normalizeValue(s string) string {
	// replace
	r := regexp.MustCompile("[\t\r\n]").ReplaceAllString(s, " ")
	// collapse
	r = strings.Trim(regexp.MustCompile(" +").ReplaceAllString(r, " "), " ")
	return r
}
<commit_msg>Added resolveType stub<commit_after>package goxsd

import (
	"bufio"
	"fmt"
	"github.com/realmfoo/caementarii/xsd"
	"os"
	"regexp"
	"strings"
)

type Generator struct {
	pkgName string
}

func (g *Generator) generate(s *xsd.Schema) {

	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()

	schema := &schema{}
	schema.targetNamespace = s.TargetNamespace

	for _, top := range s.SchemaTop {
		if node, ok := top.(xsd.Element); ok {
			// 3.3.2.1 Common Mapping Rules for Element Declarations
			elm := g.newElement(schema, node)

			// 3.3.2.2 Mapping Rules for Top-Level Element Declarations
			elm.name.Space = s.TargetNamespace

			elm.scope.variety = "global"

			schema.elementDeclarations = append(schema.elementDeclarations, elm)
		}
	}

	w.WriteString("package " + g.pkgName + "\n\n")
	w.WriteString("import (\n")
	w.WriteString(")\n\n")
}

func (g *Generator) newComplexType(s *schema, parent interface{}, node *xsd.ComplexType) complexTypeDefinition {
	typeDef := complexTypeDefinition{}

	// The ·actual value· of the name [attribute].
	typeDef.name.Local = node.Name
	// The ·actual value· of the targetNamespace [attribute] of the <schema> ancestor element information item if present, otherwise ·absent·.
	typeDef.name.Space = s.targetNamespace
	// The ·actual value· of the abstract [attribute], if present, otherwise false.
	typeDef.abstract = node.Abstract

	typeDef.prohibitedSubstitutions = getBlocks(node, s, typeDef)
	typeDef.final = getFinals(node, s, typeDef)

	// If the name [attribute] is present, then ·absent·, otherwise (among the ancestor element information items there
	// will be a nearest <element>), the Element Declaration corresponding to the nearest <element> information item
	// among the the ancestor element information items.
	if node.Name == "" {
		typeDef.context = parent
	}

	// A sequence whose members are Assertions drawn from the following sources, in order:
	// 1 The {assertions} of the {base type definition}.
	// 2 Assertions corresponding to all the <assert> element information items among the [children] of <complexType>, <restriction> and <extension>, if any, in document order.
	//typeDef.assertions =

	// The ·annotation mapping· of the set of elements containing the <complexType>, the <openContent> [child], if
	// present, the <attributeGroup> [children], if present, the <simpleContent> and <complexContent> [children], if
	// present, and their <restriction> and <extension> [children], if present, and their <openContent> and
	// <attributeGroup> [children], if present, as defined in
	// XML Representation of Annotation Schema Components (§3.15.2).
	//typeDef.annotations =

	if node.SimpleContent != nil {

	} else {
		if node.ComplexContent != nil {
			// 3.4.2.3.1 Mapping Rules for Complex Types with Explicit Complex Content

			// If the <restriction> alternative is chosen, then restriction, otherwise (the <extension> alternative is
			// chosen) extension.
			if node.ComplexContent.Restriction != nil {
				// The type definition ·resolved· to by the ·actual value· of the base [attribute] on the <restriction> or
				// <extension> element appearing as a child of <simpleContent>
				typeDef.baseTypeDefinition = g.resolveType(node.ComplexContent.Restriction.Base)
				typeDef.derivationMethod = "restriction"
			} else {
				// The type definition ·resolved· to by the ·actual value· of the base [attribute] on the <restriction> or
				// <extension> element appearing as a child of <simpleContent>
				typeDef.baseTypeDefinition = g.resolveType(node.ComplexContent.Extension.Base)
				typeDef.derivationMethod = "extension"
			}
		} else {
			// 3.4.2.3.2 Mapping Rules for Complex Types with Implicit Complex Content
			typeDef.baseTypeDefinition = nil
			typeDef.derivationMethod = "restriction"
		}

		// 3.4.2.3.3 Mapping Rules for Content Type Property of Complex Content
		//effectiveMixed := false
		//if node.ComplexContent.Mixed != nil {
		//	effectiveMixed = *node.ComplexContent.Mixed
		//} else if node.Mixed != nil {
		//	effectiveMixed = *node.Mixed
		//}

		//var explicitContent interface{}

	}

	return typeDef
}

func (g *Generator) resolveType(t string) interface{} {
	fmt.Println(t)
	return nil
}

func getBlocks(node *xsd.ComplexType, s *schema, typeDef complexTypeDefinition) []string {
	blocks := make([]string, 0)
	var effectiveBlockValue string
	if node.Block != "" {
		effectiveBlockValue = node.Block
	} else if s.blockDefault != "" {
		effectiveBlockValue = s.blockDefault
	} else {
		effectiveBlockValue = ""
	}
	if effectiveBlockValue == "#all" {
		blocks = []string{"extension", "restriction"}
	} else if effectiveBlockValue != "" {
		x := strings.Split(effectiveBlockValue, " ")
		for _, bl := range x {
			if bl == "extension" || bl == "restriction" {
				blocks = append(blocks, bl)
			}
		}
	}

	return blocks
}

func getFinals(node *xsd.ComplexType, s *schema, typeDef complexTypeDefinition) []string {
	blocks := make([]string, 0)
	var effectiveFinalValue string
	if node.Final != "" {
		effectiveFinalValue = node.Final
	} else if s.finalDefault != "" {
		effectiveFinalValue = s.finalDefault
	} else {
		effectiveFinalValue = ""
	}
	if effectiveFinalValue == "#all" {
		blocks = []string{"extension", "restriction"}
	} else if effectiveFinalValue != "" {
		x := strings.Split(effectiveFinalValue, " ")
		for _, bl := range x {
			if bl == "extension" || bl == "restriction" {
				blocks = append(blocks, bl)
			}
		}
	}

	return blocks
}

// 3.3.2.1 Common Mapping Rules for Element Declarations
func (g *Generator) newElement(s *schema, node xsd.Element) elementDeclaration {
	elm := elementDeclaration{}
	// The ·actual value· of the name [attribute].
	elm.name.Local = node.Name
	// The first of the following that applies:
	// 1 The type definition corresponding to the <simpleType> or <complexType> element information item in the
	//   [children], if either is present.
	// 2 The type definition ·resolved· to by the ·actual value· of the type [attribute], if it is present.
	// 3 The declared {type definition} of the Element Declaration ·resolved· to by the first QName in the
	//   ·actual value· of the substitutionGroup [attribute], if present.
	// 4 ·xs:anyType·.
	if node.ComplexType != nil {
		elm.typeDefinition = g.newComplexType(s, node, node.ComplexType)
	} else if node.SimpleType != nil {

	} else if node.Type != "" {
		elm.typeDefinition = g.resolveType(node.Type)
	} else {
		elm.typeDefinition = nil
	}
	// A Type Table corresponding to the <alternative> element information items among the [children], if any, as
	// follows, otherwise ·absent·.
	// elm.typeTable
	elm.nillable = node.Nillable
	// If there is a default or a fixed [attribute], then a Value Constraint as follows, otherwise ·absent·.
	// [Definition:]  Use the name effective simple type definition for the declared {type definition}, if it is
	// a simple type definition, or, if {type definition}.{content type}.{variety} = simple, for {type definition}.
	// {content type}.{simple type definition}, or else for the built-in string simple type definition).
	if node.Default != "" {
		actualValue := node.Default
		elm.valueConstraint = &valueConstraint{
			variety: "default",
			// the ·actual value· (with respect to the ·effective simple type definition·) of the [attribute]
			value: actualValue,
			// the ·normalized value· (with respect to the ·effective simple type definition·) of the [attribute]
			lexicalForm: normalizeValue(actualValue),
		}
	}
	if node.Fixed != "" {
		actualValue := node.Fixed
		elm.valueConstraint = &valueConstraint{
			variety: "default",
			// the ·actual value· (with respect to the ·effective simple type definition·) of the [attribute]
			value: actualValue,
			// the ·normalized value· (with respect to the ·effective simple type definition·) of the [attribute]
			lexicalForm: normalizeValue(actualValue),
		}
	}
	// A set consisting of the identity-constraint-definitions corresponding to all the <key>, <unique> and
	// <keyref> element information items in the [children], if any, otherwise the empty set.
	// elm.identityConstraintDefinitions
	// A set of the element declarations ·resolved· to by the items in the ·actual value· of the substitutionGroup
	// [attribute], if present, otherwise the empty set.
	// elm.substitutionGroupAffiliations
	// A set depending on the ·actual value· of the block [attribute], if present, otherwise on the ·actual value·
	// of the blockDefault [attribute] of the ancestor <schema> element information item, if present, otherwise
	// on the empty string. Call this the EBV (for effective block value). Then the value of this property is the
	// appropriate case among the following:
	//
	// 1 If the EBV is the empty string, then the empty set;
	// 2 If the EBV is #all, then {extension, restriction, substitution};
	// 3 otherwise a set with members drawn from the set above, each being present or absent depending on whether
	//   the ·actual value· (which is a list) contains an equivalently named item.
	//
	// Note: Although the blockDefault [attribute] of <schema> may include values other than extension, restriction
	// or substitution, those values are ignored in the determination of {disallowed substitutions} for element
	// declarations (they are used elsewhere).
	// elm.disallowedSubstitutions
	// As for {disallowed substitutions} above, but using the final and finalDefault [attributes] in place of the
	// block and blockDefault [attributes] and with the relevant set being {extension, restriction}.
	//elm.substitutionGroupExclusions
	// The ·actual value· of the abstract [attribute], if present, otherwise false.
	elm.abstract = node.Abstract
	// The ·annotation mapping· of the <element> element and any of its <unique>, <key> and <keyref> [children]
	// with a ref [attribute], as defined in XML Representation of Annotation Schema Components (§3.15.2).
	// elm.annotations
	return elm
}

func normalizeValue(s string) string {
	// replace
	r := regexp.MustCompile("[\t\r\n]").ReplaceAllString(s, " ")
	// collapse
	r = strings.Trim(regexp.MustCompile(" +").ReplaceAllString(r, " "), " ")
	return r
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"time"

	"github.com/garyburd/redigo/redis"
	uuid "github.com/satori/go.uuid"
)

const (
	//Key lock name.
	LOCK_NAME = "lock:gen"

	//Another generator is active
	LOCK_OTHER_EXISTS = iota

	//Lock have been successfully refreshed
	LOCK_REFRESHED

	//Lock exists, but belongs to another generator
	LOCK_NOT_REFRESHED

	CONNECTION_PROBLEM
)

type Generator struct {
	pool         *redis.Pool
	queue        string
	name         string
	interval     int
	pingInterval int
	stop         chan struct{}
	isActive     bool
}

//Creates new Generator
func NewGen(p *redis.Pool, queue string, interval, pinterval int) *Generator {
	return &Generator{
		pool:         p,
		queue:        queue,
		interval:     interval,
		pingInterval: pinterval,
		name:         uuid.NewV4().String(),
		stop:         make(chan struct{}),
	}
}

//Tries to acquire new lock. If there is no lock, that means there is no
//active generator. Acquiring lock means cuurrent generator will be activated.
func (g *Generator) AcquireLock() bool {
	pc := g.pool.Get()
	defer pc.Close()

	//Set lock expire time pingInterval+5 seconds.
	//5 is a "magic number", time for network lag, etc.
	lock, err := pc.Do("SET", LOCK_NAME, g.name, "EX", g.pingInterval+5, "NX")
	if err != nil {
		log.Println("acquirelock: unable to execute SET:", err)
		return false
	}

	return lock == "OK"
}

//Refreshes it's own lock
func (g *Generator) RefreshLock() byte {
	pc := g.pool.Get()
	defer pc.Close()

	_, err := pc.Do("WATCH", LOCK_NAME)
	if err != nil {
		log.Println("refreshlock: unable to execute WATCH:", err)
		//return LOCK_NOT_REFRESHED
		return CONNECTION_PROBLEM
	}

	cg, err := pc.Do("GET", LOCK_NAME)
	if err != nil {
		log.Println("refreshlock: unable to execute GET:", err)
		//return LOCK_NOT_REFRESHED
		return CONNECTION_PROBLEM
	}

	cg, err = redis.String(cg, err)
	LogIf(err)

	if cg == g.name {
		pc.Send("MULTI")
		pc.Send("SET", LOCK_NAME, g.name, "EX", g.pingInterval+5, "XX")
		lock, err := redis.Values(pc.Do("EXEC"))
		if err != nil {
			log.Println("refreshlock: unable to execute EXEC:", err)
			//return LOCK_NOT_REFRESHED
			return CONNECTION_PROBLEM
		}

		var s string
		redis.Scan(lock, &s)

		if s == "OK" {
			return LOCK_REFRESHED
		} else {
			return LOCK_NOT_REFRESHED
		}

	} else {
		_, err := pc.Do("UNWATCH")
		if err != nil {
			log.Println("refreshlock: unable to execute UNWATCH:", err)
			return LOCK_OTHER_EXISTS
		}
	}
	return LOCK_NOT_REFRESHED
}

//Generates random string
func (g *Generator) Message() string {
	return fmt.Sprintf("%s at %s", uuid.NewV4(), time.Now())
}

//Added data to redis list
func (g *Generator) Start() {
	if g.RefreshLock() == LOCK_OTHER_EXISTS {
		log.Println("generator run: another generator in progress")
		return
	}

	pc := g.pool.Get()
	defer pc.Close()

	defer func(g *Generator) {
		log.Printf("Generator stopped (name: %s).\n", g.name)
		g.isActive = false
	}(g)

	fmt.Println("Interval:", g.interval)
	ticker := time.NewTicker(time.Millisecond * time.Duration(g.interval))

	log.Printf("Generator started (name: %s).\n", g.name)
	g.isActive = true
	i := 0
	for {
		select {
		case <-ticker.C:
			i++
			if i >= 1000 {
				fmt.Printf("+")
				i = 0
			}
			fmt.Printf(".")
			if _, err := pc.Do("LPUSH", g.queue, g.Message()); err != nil {
				log.Println("messages: unable to push to redis:", err)
				return
			}
		case <-g.stop:
			return
		}
	}
}

func (g *Generator) Stop() {
	g.stop <- struct{}{}
}

func (g *Generator) IsActive() bool {
	return g.isActive
}
<commit_msg>Removed comments.<commit_after>package main

import (
	"fmt"
	"log"
	"time"

	"github.com/garyburd/redigo/redis"
	uuid "github.com/satori/go.uuid"
)

const (
	//Key lock name.
	LOCK_NAME = "lock:gen"

	//Another generator is active
	LOCK_OTHER_EXISTS = iota

	//Lock have been successfully refreshed
	LOCK_REFRESHED

	//Lock exists, but belongs to another generator
	LOCK_NOT_REFRESHED

	//Unable to connect to redis
	CONNECTION_PROBLEM
)

type Generator struct {
	pool         *redis.Pool
	queue        string
	name         string
	interval     int
	pingInterval int
	stop         chan struct{}
	isActive     bool
}

//Creates new Generator
func NewGen(p *redis.Pool, queue string, interval, pinterval int) *Generator {
	return &Generator{
		pool:         p,
		queue:        queue,
		interval:     interval,
		pingInterval: pinterval,
		name:         uuid.NewV4().String(),
		stop:         make(chan struct{}),
	}
}

//Tries to acquire new lock. If there is no lock, that means there is no
//active generator. Acquiring lock means cuurrent generator will be activated.
func (g *Generator) AcquireLock() bool {
	pc := g.pool.Get()
	defer pc.Close()

	//Set lock expire time pingInterval+5 seconds.
	//5 is a "magic number", time for network lag, etc.
	lock, err := pc.Do("SET", LOCK_NAME, g.name, "EX", g.pingInterval+5, "NX")
	if err != nil {
		log.Println("acquirelock: unable to execute SET:", err)
		return false
	}

	return lock == "OK"
}

//Refreshes it's own lock
func (g *Generator) RefreshLock() byte {
	pc := g.pool.Get()
	defer pc.Close()

	_, err := pc.Do("WATCH", LOCK_NAME)
	if err != nil {
		log.Println("refreshlock: unable to execute WATCH:", err)
		return CONNECTION_PROBLEM
	}

	cg, err := pc.Do("GET", LOCK_NAME)
	if err != nil {
		log.Println("refreshlock: unable to execute GET:", err)
		return CONNECTION_PROBLEM
	}

	cg, err = redis.String(cg, err)
	LogIf(err)

	if cg == g.name {
		pc.Send("MULTI")
		pc.Send("SET", LOCK_NAME, g.name, "EX", g.pingInterval+5, "XX")
		lock, err := redis.Values(pc.Do("EXEC"))
		if err != nil {
			log.Println("refreshlock: unable to execute EXEC:", err)
			return CONNECTION_PROBLEM
		}

		var s string
		redis.Scan(lock, &s)

		if s == "OK" {
			return LOCK_REFRESHED
		} else {
			return LOCK_NOT_REFRESHED
		}
	} else {
		_, err := pc.Do("UNWATCH")
		if err != nil {
			log.Println("refreshlock: unable to execute UNWATCH:", err)
			return CONNECTION_PROBLEM
		}
	}
	return LOCK_NOT_REFRESHED
}

//Generates random string
func (g *Generator) Message() string {
	return fmt.Sprintf("%s at %s", uuid.NewV4(), time.Now())
}

//Added data to redis list
func (g *Generator) Start() {
	if g.RefreshLock() == LOCK_OTHER_EXISTS {
		log.Println("generator run: another generator in progress")
		return
	}

	pc := g.pool.Get()
	defer pc.Close()

	defer func(g *Generator) {
		log.Printf("Generator stopped (name: %s).\n", g.name)
		g.isActive = false
	}(g)

	ticker := time.NewTicker(time.Millisecond * time.Duration(g.interval))

	log.Printf("Generator started (name: %s).\n", g.name)
	g.isActive = true
	i := 0
	for {
		select {
		case <-ticker.C:
			i++
			if i >= 1000 {
				fmt.Printf("+")
				i = 0
			}
			fmt.Printf(".")
			if _, err := pc.Do("LPUSH", g.queue, g.Message()); err != nil {
				log.Println("messages: unable to push to redis:", err)
				return
			}
		case <-g.stop:
			return
		}
	}
}

func (g *Generator) Stop() {
	g.stop <- struct{}{}
}

func (g *Generator) IsActive() bool {
	return g.isActive
}
<|endoftext|>


<commit_before>package acgen

import (
	"fmt"
	"io"
	"sync"
)

type Command struct {
	Name  string
	Flags []*Flag
}

type Flag struct {
	Short       []string
	Long        []string
	Arg         string
	Description string
}

type Generator func(w io.Writer, c *Command) error

var (
	generatorsMu sync.Mutex
	generators   = make(map[string]Generator)
)

func RegisterGenerator(name string, g Generator) {
	generatorsMu.Lock()
	defer generatorsMu.Unlock()
	if _, dup := generators[name]; dup {
		panic("RegisterGenerator called twice for generator " + name)
	}
	generators[name] = g
}

func LookGenerator(name string) (g Generator, err error) {
	generatorsMu.Lock()
	defer generatorsMu.Unlock()
	if _, ok := generators[name]; !ok {
		return nil, fmt.Errorf("%s: is not supported", name)
	}
	return generators[name], nil
}
<commit_msg>Add comments for types and functions to be published<commit_after>package acgen

import (
	"fmt"
	"io"
	"sync"
)

// A Command represents a command which has flags.
type Command struct {
	Name  string
	Flags []*Flag
}

// A Flag represents the information of a flag.
type Flag struct {
	Short       []string // short options
	Long        []string // long options
	Arg         string   // argument's name
	Description string   // help message
}

// A Generator writes a completion for command to w.
type Generator func(w io.Writer, c *Command) error

var (
	generatorsMu sync.Mutex
	generators   = make(map[string]Generator)
)

// RegisterGenerator makes a completion generator available
// by the provided name.
func RegisterGenerator(name string, g Generator) {
	generatorsMu.Lock()
	defer generatorsMu.Unlock()
	if _, dup := generators[name]; dup {
		panic("RegisterGenerator called twice for generator " + name)
	}
	generators[name] = g
}

// LookGenerator returns a completion generator
// specified by its completion generator name.
func LookGenerator(name string) (g Generator, err error) {
	generatorsMu.Lock()
	defer generatorsMu.Unlock()
	if _, ok := generators[name]; !ok {
		return nil, fmt.Errorf("%s: is not supported", name)
	}
	return generators[name], nil
}
<|endoftext|>


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

package main

import (
	"fmt"
	"log"

	"github.com/jroimartin/gocui"
)

func main() {
	g := gocui.NewGui()
	if err := g.Init(); err != nil {
		log.Fatalln(err)
	}
	defer g.Close()

	g.SetLayout(layout)
	if err := initKeybindings(g); err != nil {
		log.Fatalln(err)
	}

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		log.Fatalln(err)
	}
}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()

	if v, err := g.SetView("legend", maxX-23, 0, maxX-1, 3); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = "Keybindings"
		fmt.Fprintln(v, "^a: Set mask")
		fmt.Fprintln(v, "^c: Exit")
	}

	if v, err := g.SetView("input", 0, 0, maxX-24, maxY-1); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		if err := g.SetCurrentView("input"); err != nil {
			return err
		}
		v.Editable = true
		v.Wrap = true
	}

	return nil
}

func initKeybindings(g *gocui.Gui) error {
	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
		func(g *gocui.Gui, v *gocui.View) error {
			return gocui.ErrQuit
		}); err != nil {
		return err
	}
	if err := g.SetKeybinding("input", gocui.KeyCtrlA, gocui.ModNone,
		func(g *gocui.Gui, v *gocui.View) error {
			v.Mask ^= '*'
			return nil
		}); err != nil {
		return err
	}
	return nil
}
<commit_msg>Show cursor in _examples/mask.go<commit_after>// Copyright 2015 The gocui Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"

	"github.com/jroimartin/gocui"
)

func main() {
	g := gocui.NewGui()
	if err := g.Init(); err != nil {
		log.Fatalln(err)
	}
	defer g.Close()

	g.SetLayout(layout)
	if err := initKeybindings(g); err != nil {
		log.Fatalln(err)
	}
	g.Cursor = true

	if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
		log.Fatalln(err)
	}
}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()

	if v, err := g.SetView("legend", maxX-23, 0, maxX-1, 3); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		v.Title = "Keybindings"
		fmt.Fprintln(v, "^a: Set mask")
		fmt.Fprintln(v, "^c: Exit")
	}

	if v, err := g.SetView("input", 0, 0, maxX-24, maxY-1); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		if err := g.SetCurrentView("input"); err != nil {
			return err
		}
		v.Editable = true
		v.Wrap = true
	}

	return nil
}

func initKeybindings(g *gocui.Gui) error {
	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
		func(g *gocui.Gui, v *gocui.View) error {
			return gocui.ErrQuit
		}); err != nil {
		return err
	}
	if err := g.SetKeybinding("input", gocui.KeyCtrlA, gocui.ModNone,
		func(g *gocui.Gui, v *gocui.View) error {
			v.Mask ^= '*'
			return nil
		}); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


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

package testing

import (
	"github.com/juju/juju/worker/uniter/runner/jujuc"
)

// RelationHook holds the values for the hook context.
type RelationHook struct {
	HookRelation   jujuc.ContextRelation
	RemoteUnitName string
}

// ContextRelationHook is a test double for jujuc.RelationHookContext.
type ContextRelationHook struct {
	contextBase
	info *RelationHook
}

// HookRelation implements jujuc.RelationHookContext.
func (c *ContextRelationHook) HookRelation() (jujuc.ContextRelation, bool) {
	c.stub.AddCall("HookRelation")
	c.stub.NextErr()

	return c.info.HookRelation, c.info.HookRelation == nil
}

// RemoteUnitName implements jujuc.RelationHookContext.
func (c *ContextRelationHook) RemoteUnitName() (string, bool) {
	c.stub.AddCall("RemoteUnitName")
	c.stub.NextErr()

	return c.info.RemoteUnitName, c.info.RemoteUnitName != ""
}
<commit_msg>Fix a typo.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package testing

import (
	"github.com/juju/juju/worker/uniter/runner/jujuc"
)

// RelationHook holds the values for the hook context.
type RelationHook struct {
	HookRelation   jujuc.ContextRelation
	RemoteUnitName string
}

// ContextRelationHook is a test double for jujuc.RelationHookContext.
type ContextRelationHook struct {
	contextBase
	info *RelationHook
}

// HookRelation implements jujuc.RelationHookContext.
func (c *ContextRelationHook) HookRelation() (jujuc.ContextRelation, bool) {
	c.stub.AddCall("HookRelation")
	c.stub.NextErr()

	return c.info.HookRelation, c.info.HookRelation != nil
}

// RemoteUnitName implements jujuc.RelationHookContext.
func (c *ContextRelationHook) RemoteUnitName() (string, bool) {
	c.stub.AddCall("RemoteUnitName")
	c.stub.NextErr()

	return c.info.RemoteUnitName, c.info.RemoteUnitName != ""
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/glcv-go/cv"
	gl "github.com/chsc/gogl/gl21"
	"log"
)

type testCanvas struct {
	cv.Canvas
}

func (c *testCanvas) OnInit() {
	log.Println("Init")
}

func (c *testCanvas) OnTerm() {
	log.Println("Term")
}

func (c *testCanvas) OnGLInit() {
	log.Println("GLInit")
	gl.Init()
}

func (c *testCanvas) OnGLTerm() {
	log.Println("GLTerm")
}

func (c *testCanvas) OnPress(k cv.Key) {
	log.Println("Press", k.Name())
	if k == cv.KEY_ESCAPE {
		c.Quit()
	}
}

func (c *testCanvas) OnRelease(k cv.Key) {
	log.Println("Release", k.Name())
}

func (c *testCanvas) OnUnicode(u uint) {
	log.Printf("Unicode %c", u)
}

func (c *testCanvas) OnMotion(x, y int) {
	c.NextResponder().OnMotion(x, y)
	log.Println("Motion", x, y)
}

func (c *testCanvas) OnResize(w, h int) {
	log.Println("Resize", w, h)
}

func (c *testCanvas) OnUpdate() {
	if c.Pressed(cv.KEY_A) {
		log.Println("A pressed")
	}
	if c.Released(cv.KEY_A) {
		log.Println("A released")
	}
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
}

func (c *testCanvas) Name() string {
	return "test"
}

func (c *testCanvas) Geometry() (x, y, w, h int) {
	return 20, 20, 512, 512
}

func (c *testCanvas) Borders() bool {
	return true
}

func main() {
	var c testCanvas
	c.InitCanvas(&c)
	c.Go()
}
<commit_msg>Handle OnClose()<commit_after>package main

import (
	"code.google.com/p/glcv-go/cv"
	gl "github.com/chsc/gogl/gl21"
	"log"
)

type testCanvas struct {
	cv.Canvas
}

func (c *testCanvas) OnInit() {
	log.Println("Init")
}

func (c *testCanvas) OnTerm() {
	log.Println("Term")
}

func (c *testCanvas) OnGLInit() {
	log.Println("GLInit")
	gl.Init()
}

func (c *testCanvas) OnGLTerm() {
	log.Println("GLTerm")
}

func (c *testCanvas) OnPress(k cv.Key) {
	log.Println("Press", k.Name())
	if k == cv.KEY_ESCAPE {
		c.Quit()
	}
}

func (c *testCanvas) OnRelease(k cv.Key) {
	log.Println("Release", k.Name())
}

func (c *testCanvas) OnUnicode(u uint) {
	log.Printf("Unicode %c", u)
}

func (c *testCanvas) OnMotion(x, y int) {
	c.NextResponder().OnMotion(x, y)
	log.Println("Motion", x, y)
}

func (c *testCanvas) OnClose() {
	log.Println("Close")
	c.Quit()
}

func (c *testCanvas) OnResize(w, h int) {
	log.Println("Resize", w, h)
}

func (c *testCanvas) OnUpdate() {
	if c.Pressed(cv.KEY_A) {
		log.Println("A pressed")
	}
	if c.Released(cv.KEY_A) {
		log.Println("A released")
	}
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
}

func (c *testCanvas) Name() string {
	return "test"
}

func (c *testCanvas) Geometry() (x, y, w, h int) {
	return 20, 20, 512, 512
}

func (c *testCanvas) Borders() bool {
	return true
}

func main() {
	var c testCanvas
	c.InitCanvas(&c)
	c.Go()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/exercism/cli/configuration"
	"github.com/stretchr/testify/assert"
)

func asserFileDoesNotExist(t *testing.T, filename string) {
	_, err := os.Stat(filename)

	if err == nil {
		t.Errorf("File [%s] already exist.", filename)
	}
}

func TestLogoutDeletesConfigFile(t *testing.T) {
	tmpDir, err := ioutil.TempDir("", "")
	assert.NoError(t, err)

	c := configuration.Config{}

	configuration.ToFile(tmpDir, c)

	logout(tmpDir)

	asserFileDoesNotExist(t, configuration.Filename(tmpDir))
}

func TestAskForConfigInfoAllowsSpaces(t *testing.T) {
	oldStdin := os.Stdin
	dirName := "dirname with spaces"
	userName := "TestUsername"
	apiKey := "abc123"

	fakeStdin, err := ioutil.TempFile("", "stdin_mock")
	assert.NoError(t, err)

	fakeStdin.WriteString(fmt.Sprintf("%s\r\n%s\r\n%s\r\n", userName, apiKey, dirName))
	assert.NoError(t, err)

	_, err = fakeStdin.Seek(0, os.SEEK_SET)
	assert.NoError(t, err)

	defer fakeStdin.Close()

	os.Stdin = fakeStdin

	c, err := askForConfigInfo()
	if err != nil {
		t.Errorf("Error asking for configuration info [%v]", err)
	}
	os.Stdin = oldStdin
	absoluteDirName, _ := absolutePath(dirName)
	_, err = os.Stat(absoluteDirName)
	if err != nil {
		t.Errorf("Excercism directory [%s] was not created.", absoluteDirName)
	}
	os.Remove(absoluteDirName)
	os.Remove(fakeStdin.Name())

	assert.Equal(t, c.ExercismDirectory, absoluteDirName)
	assert.Equal(t, c.GithubUsername, userName)
	assert.Equal(t, c.ApiKey, apiKey)
}
<commit_msg>fix small typo in spec<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"testing"

	"github.com/exercism/cli/configuration"
	"github.com/stretchr/testify/assert"
)

func assertFileDoesNotExist(t *testing.T, filename string) {
	_, err := os.Stat(filename)

	if err == nil {
		t.Errorf("File [%s] already exist.", filename)
	}
}

func TestLogoutDeletesConfigFile(t *testing.T) {
	tmpDir, err := ioutil.TempDir("", "")
	assert.NoError(t, err)

	c := configuration.Config{}

	configuration.ToFile(tmpDir, c)

	logout(tmpDir)

	assertFileDoesNotExist(t, configuration.Filename(tmpDir))
}

func TestAskForConfigInfoAllowsSpaces(t *testing.T) {
	oldStdin := os.Stdin
	dirName := "dirname with spaces"
	userName := "TestUsername"
	apiKey := "abc123"

	fakeStdin, err := ioutil.TempFile("", "stdin_mock")
	assert.NoError(t, err)

	fakeStdin.WriteString(fmt.Sprintf("%s\r\n%s\r\n%s\r\n", userName, apiKey, dirName))
	assert.NoError(t, err)

	_, err = fakeStdin.Seek(0, os.SEEK_SET)
	assert.NoError(t, err)

	defer fakeStdin.Close()

	os.Stdin = fakeStdin

	c, err := askForConfigInfo()
	if err != nil {
		t.Errorf("Error asking for configuration info [%v]", err)
	}
	os.Stdin = oldStdin
	absoluteDirName, _ := absolutePath(dirName)
	_, err = os.Stat(absoluteDirName)
	if err != nil {
		t.Errorf("Excercism directory [%s] was not created.", absoluteDirName)
	}
	os.Remove(absoluteDirName)
	os.Remove(fakeStdin.Name())

	assert.Equal(t, c.ExercismDirectory, absoluteDirName)
	assert.Equal(t, c.GithubUsername, userName)
	assert.Equal(t, c.ApiKey, apiKey)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"os"
	"text/template"

	"github.com/jroimartin/gocui"
	bloomsky "github.com/patrickalin/bloomsky-api-go"
	"github.com/patrickalin/bloomsky-client-go/assembly"
	log "github.com/sirupsen/logrus"
)

type console struct {
	in           chan bloomsky.BloomskyStructure
	testTemplate *template.Template
}

func initTemplate() *template.Template {
	if config.dev {
		t, err := template.New("bloomsky.txt").Funcs(map[string]interface{}{
			"T": config.translateFunc,
		}).ParseFiles("tmpl/bloomsky.txt")

		if err != nil {
			log.Fatalf("Load template console : %v", err)
		}
		return t
	}

	assetBloomsky, err := assembly.Asset("tmpl/bloomsky.txt")
	t, err := template.New("bloomsky.txt").Funcs(map[string]interface{}{
		"T": config.translateFunc}).Parse(string(assetBloomsky[:]))
	if err != nil {
		log.Fatalf("Load template console : %v", err)
	}
	return t
}

//InitConsole listen on the chanel
func initConsole(messages chan bloomsky.BloomskyStructure) (console, error) {
	c := console{in: messages, testTemplate: initTemplate()}
	return c, nil
}

func (c *console) listen(context context.Context) {
	go func() {

		/*
			TODO

			g, err := gocui.NewGui(gocui.OutputNormal)
			if err != nil {
				log.Panicln(err)
			}
			defer g.Close()

			g.SetManagerFunc(layout)

			if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
				log.Panicln(err)
			}

			if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
				log.Panicln(err)
			}*/

		log.Debug("Init the queue to receive message to export to console")

		for {
			msg := <-c.in

			if err := c.testTemplate.Execute(os.Stdout, msg); err != nil {
				fmt.Printf("%v", err)
			}
		}

	}()

}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		fmt.Fprintln(v, "Hello world!")
	}
	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}
<commit_msg>first step towards refactoring<commit_after>package main

import (
	"context"
	"fmt"
	"os"
	"text/template"

	"github.com/jroimartin/gocui"
	bloomsky "github.com/patrickalin/bloomsky-api-go"
	"github.com/patrickalin/bloomsky-client-go/assembly"
	log "github.com/sirupsen/logrus"
)

type console struct {
	in           chan bloomsky.BloomskyStructure
	testTemplate *template.Template
}

//bloomsky "bloomsky.txt" "tmpl/bloomsky.txt" map[string]interface{}{
//			"T": config.translateFunc
func getTemplate(templateName string, templateLocation string, funcs map[string]interface{}, dev bool) *template.Template {
	if dev {
		t, err := template.New(templateName).Funcs(funcs).ParseFiles(templateLocation)

		if err != nil {
			log.Fatalf("Load template console : %v", err)
		}
		return t
	}

	assetBloomsky, err := assembly.Asset(templateLocation)
	t, err := template.New(templateName).Funcs(funcs).Parse(string(assetBloomsky[:]))
	if err != nil {
		log.Fatalf("Load template console : %v", err)
	}
	return t
}

//InitConsole listen on the chanel
func initConsole(messages chan bloomsky.BloomskyStructure) (console, error) {
	f := map[string]interface{}{"T": config.translateFunc}
	c := console{in: messages, testTemplate: getTemplate("bloomsky.txt", "tmpl/bloomsky.txt", f, config.dev)}
	return c, nil
}

func (c *console) listen(context context.Context) {
	go func() {

		/*
			TODO

			g, err := gocui.NewGui(gocui.OutputNormal)
			if err != nil {
				log.Panicln(err)
			}
			defer g.Close()

			g.SetManagerFunc(layout)

			if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
				log.Panicln(err)
			}

			if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
				log.Panicln(err)
			}*/

		log.Debug("Init the queue to receive message to export to console")

		for {
			msg := <-c.in

			if err := c.testTemplate.Execute(os.Stdout, msg); err != nil {
				fmt.Printf("%v", err)
			}
		}

	}()

}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2); err != nil {
		if err != gocui.ErrUnknownView {
			return err
		}
		fmt.Fprintln(v, "Hello world!")
	}
	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}
<|endoftext|>


<commit_before>// Copyright 2017 The casbin Authors. 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 casbin

import (
	"log"
	"sync"
	"time"

	"github.com/Knetic/govaluate"
	"github.com/casbin/casbin/v2/persist"
)

// SyncedEnforcer wraps Enforcer and provides synchronized access
type SyncedEnforcer struct {
	*Enforcer
	m               sync.RWMutex
	stopAutoLoad    chan struct{}
	autoLoadRunning bool
}

// NewSyncedEnforcer creates a synchronized enforcer via file or DB.
func NewSyncedEnforcer(params ...interface{}) (*SyncedEnforcer, error) {
	e := &SyncedEnforcer{}
	var err error
	e.Enforcer, err = NewEnforcer(params...)
	if err != nil {
		return nil, err
	}

	e.stopAutoLoad = make(chan struct{}, 1)
	return e, nil
}

// StartAutoLoadPolicy starts a go routine that will every specified duration call LoadPolicy
func (e *SyncedEnforcer) StartAutoLoadPolicy(d time.Duration) {
	// Don't start another goroutine if there is already one running
	if e.autoLoadRunning {
		return
	}
	e.autoLoadRunning = true
	ticker := time.NewTicker(d)
	go func() {
		defer func() {
			ticker.Stop()
			e.autoLoadRunning = false
		}()
		n := 1
		log.Print("Start automatically load policy")
		for {
			select {
			case <-ticker.C:
				// error intentionally ignored
				_ = e.LoadPolicy()
				// Uncomment this line to see when the policy is loaded.
				// log.Print("Load policy for time: ", n)
				n++
			case <-e.stopAutoLoad:
				log.Print("Stop automatically load policy")
				return
			}
		}
	}()
}

// StopAutoLoadPolicy causes the go routine to exit.
func (e *SyncedEnforcer) StopAutoLoadPolicy() {
	if e.autoLoadRunning {
		e.stopAutoLoad <- struct{}{}
	}
}

// SetWatcher sets the current watcher.
func (e *SyncedEnforcer) SetWatcher(watcher persist.Watcher) error {
	e.watcher = watcher
	return watcher.SetUpdateCallback(func(string) { e.LoadPolicy() })
}

// ClearPolicy clears all policy.
func (e *SyncedEnforcer) ClearPolicy() {
	e.m.Lock()
	defer e.m.Unlock()
	e.Enforcer.ClearPolicy()
}

// LoadPolicy reloads the policy from file/database.
func (e *SyncedEnforcer) LoadPolicy() error {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.LoadPolicy()
}

// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database.
func (e *SyncedEnforcer) SavePolicy() error {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.SavePolicy()
}

// BuildRoleLinks manually rebuild the role inheritance relations.
func (e *SyncedEnforcer) BuildRoleLinks() error {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.BuildRoleLinks()
}

// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
func (e *SyncedEnforcer) Enforce(rvals ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.Enforce(rvals...)
}

// GetAllSubjects gets the list of subjects that show up in the current policy.
func (e *SyncedEnforcer) GetAllSubjects() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllSubjects()
}

// GetAllNamedSubjects gets the list of subjects that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedSubjects(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedSubjects(ptype)
}

// GetAllObjects gets the list of objects that show up in the current policy.
func (e *SyncedEnforcer) GetAllObjects() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllObjects()
}

// GetAllNamedObjects gets the list of objects that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedObjects(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedObjects(ptype)
}

// GetAllActions gets the list of actions that show up in the current policy.
func (e *SyncedEnforcer) GetAllActions() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllActions()
}

// GetAllNamedActions gets the list of actions that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedActions(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedActions(ptype)
}

// GetAllRoles gets the list of roles that show up in the current policy.
func (e *SyncedEnforcer) GetAllRoles() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllRoles()
}

// GetAllNamedRoles gets the list of roles that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedRoles(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedRoles(ptype)
}

// GetPolicy gets all the authorization rules in the policy.
func (e *SyncedEnforcer) GetPolicy() [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetPolicy()
}

// GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredPolicy(fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredPolicy(fieldIndex, fieldValues...)
}

// GetNamedPolicy gets all the authorization rules in the named policy.
func (e *SyncedEnforcer) GetNamedPolicy(ptype string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetNamedPolicy(ptype)
}

// GetFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredNamedPolicy(ptype, fieldIndex, fieldValues...)
}

// GetGroupingPolicy gets all the role inheritance rules in the policy.
func (e *SyncedEnforcer) GetGroupingPolicy() [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetGroupingPolicy()
}

// GetFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredGroupingPolicy(fieldIndex, fieldValues...)
}

// GetNamedGroupingPolicy gets all the role inheritance rules in the policy.
func (e *SyncedEnforcer) GetNamedGroupingPolicy(ptype string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetNamedGroupingPolicy(ptype)
}

// GetFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues...)
}

// HasPolicy determines whether an authorization rule exists.
func (e *SyncedEnforcer) HasPolicy(params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasPolicy(params...)
}

// HasNamedPolicy determines whether a named authorization rule exists.
func (e *SyncedEnforcer) HasNamedPolicy(ptype string, params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasNamedPolicy(ptype, params...)
}

// AddPolicy adds an authorization rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddPolicy(params...)
}

// AddNamedPolicy adds an authorization rule to the current named policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddNamedPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddNamedPolicy(ptype, params...)
}

// RemovePolicy removes an authorization rule from the current policy.
func (e *SyncedEnforcer) RemovePolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemovePolicy(params...)
}

// RemoveFilteredPolicy removes an authorization rule from the current policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredPolicy(fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredPolicy(fieldIndex, fieldValues...)
}

// RemoveNamedPolicy removes an authorization rule from the current named policy.
func (e *SyncedEnforcer) RemoveNamedPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveNamedPolicy(ptype, params...)
}

// RemoveFilteredNamedPolicy removes an authorization rule from the current named policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredNamedPolicy(ptype, fieldIndex, fieldValues...)
}

// HasGroupingPolicy determines whether a role inheritance rule exists.
func (e *SyncedEnforcer) HasGroupingPolicy(params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasGroupingPolicy(params...)
}

// HasNamedGroupingPolicy determines whether a named role inheritance rule exists.
func (e *SyncedEnforcer) HasNamedGroupingPolicy(ptype string, params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasNamedGroupingPolicy(ptype, params...)
}

// AddGroupingPolicy adds a role inheritance rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddGroupingPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddGroupingPolicy(params...)
}

// AddNamedGroupingPolicy adds a named role inheritance rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddNamedGroupingPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddNamedGroupingPolicy(ptype, params...)
}

// RemoveGroupingPolicy removes a role inheritance rule from the current policy.
func (e *SyncedEnforcer) RemoveGroupingPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveGroupingPolicy(params...)
}

// RemoveFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredGroupingPolicy(fieldIndex, fieldValues...)
}

// RemoveNamedGroupingPolicy removes a role inheritance rule from the current named policy.
func (e *SyncedEnforcer) RemoveNamedGroupingPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveNamedGroupingPolicy(ptype, params...)
}

// RemoveFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues...)
}

// AddFunction adds a customized function.
func (e *SyncedEnforcer) AddFunction(name string, function govaluate.ExpressionFunction) {
	e.m.Lock()
	defer e.m.Unlock()
	e.Enforcer.AddFunction(name, function)
}
<commit_msg>Add synced version of LoadFilteredPolicy.<commit_after>// Copyright 2017 The casbin Authors. 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 casbin

import (
	"log"
	"sync"
	"time"

	"github.com/Knetic/govaluate"
	"github.com/casbin/casbin/v2/persist"
)

// SyncedEnforcer wraps Enforcer and provides synchronized access
type SyncedEnforcer struct {
	*Enforcer
	m               sync.RWMutex
	stopAutoLoad    chan struct{}
	autoLoadRunning bool
}

// NewSyncedEnforcer creates a synchronized enforcer via file or DB.
func NewSyncedEnforcer(params ...interface{}) (*SyncedEnforcer, error) {
	e := &SyncedEnforcer{}
	var err error
	e.Enforcer, err = NewEnforcer(params...)
	if err != nil {
		return nil, err
	}

	e.stopAutoLoad = make(chan struct{}, 1)
	return e, nil
}

// StartAutoLoadPolicy starts a go routine that will every specified duration call LoadPolicy
func (e *SyncedEnforcer) StartAutoLoadPolicy(d time.Duration) {
	// Don't start another goroutine if there is already one running
	if e.autoLoadRunning {
		return
	}
	e.autoLoadRunning = true
	ticker := time.NewTicker(d)
	go func() {
		defer func() {
			ticker.Stop()
			e.autoLoadRunning = false
		}()
		n := 1
		log.Print("Start automatically load policy")
		for {
			select {
			case <-ticker.C:
				// error intentionally ignored
				_ = e.LoadPolicy()
				// Uncomment this line to see when the policy is loaded.
				// log.Print("Load policy for time: ", n)
				n++
			case <-e.stopAutoLoad:
				log.Print("Stop automatically load policy")
				return
			}
		}
	}()
}

// StopAutoLoadPolicy causes the go routine to exit.
func (e *SyncedEnforcer) StopAutoLoadPolicy() {
	if e.autoLoadRunning {
		e.stopAutoLoad <- struct{}{}
	}
}

// SetWatcher sets the current watcher.
func (e *SyncedEnforcer) SetWatcher(watcher persist.Watcher) error {
	e.watcher = watcher
	return watcher.SetUpdateCallback(func(string) { e.LoadPolicy() })
}

// ClearPolicy clears all policy.
func (e *SyncedEnforcer) ClearPolicy() {
	e.m.Lock()
	defer e.m.Unlock()
	e.Enforcer.ClearPolicy()
}

// LoadPolicy reloads the policy from file/database.
func (e *SyncedEnforcer) LoadPolicy() error {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.LoadPolicy()
}

// LoadFilteredPolicy reloads a filtered policy from file/database.
func (e *SyncedEnforcer) LoadFilteredPolicy(filter interface{}) error {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.LoadFilteredPolicy(filter)
}

// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database.
func (e *SyncedEnforcer) SavePolicy() error {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.SavePolicy()
}

// BuildRoleLinks manually rebuild the role inheritance relations.
func (e *SyncedEnforcer) BuildRoleLinks() error {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.BuildRoleLinks()
}

// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
func (e *SyncedEnforcer) Enforce(rvals ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.Enforce(rvals...)
}

// GetAllSubjects gets the list of subjects that show up in the current policy.
func (e *SyncedEnforcer) GetAllSubjects() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllSubjects()
}

// GetAllNamedSubjects gets the list of subjects that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedSubjects(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedSubjects(ptype)
}

// GetAllObjects gets the list of objects that show up in the current policy.
func (e *SyncedEnforcer) GetAllObjects() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllObjects()
}

// GetAllNamedObjects gets the list of objects that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedObjects(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedObjects(ptype)
}

// GetAllActions gets the list of actions that show up in the current policy.
func (e *SyncedEnforcer) GetAllActions() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllActions()
}

// GetAllNamedActions gets the list of actions that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedActions(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedActions(ptype)
}

// GetAllRoles gets the list of roles that show up in the current policy.
func (e *SyncedEnforcer) GetAllRoles() []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllRoles()
}

// GetAllNamedRoles gets the list of roles that show up in the current named policy.
func (e *SyncedEnforcer) GetAllNamedRoles(ptype string) []string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetAllNamedRoles(ptype)
}

// GetPolicy gets all the authorization rules in the policy.
func (e *SyncedEnforcer) GetPolicy() [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetPolicy()
}

// GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredPolicy(fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredPolicy(fieldIndex, fieldValues...)
}

// GetNamedPolicy gets all the authorization rules in the named policy.
func (e *SyncedEnforcer) GetNamedPolicy(ptype string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetNamedPolicy(ptype)
}

// GetFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredNamedPolicy(ptype, fieldIndex, fieldValues...)
}

// GetGroupingPolicy gets all the role inheritance rules in the policy.
func (e *SyncedEnforcer) GetGroupingPolicy() [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetGroupingPolicy()
}

// GetFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredGroupingPolicy(fieldIndex, fieldValues...)
}

// GetNamedGroupingPolicy gets all the role inheritance rules in the policy.
func (e *SyncedEnforcer) GetNamedGroupingPolicy(ptype string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetNamedGroupingPolicy(ptype)
}

// GetFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified.
func (e *SyncedEnforcer) GetFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.GetFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues...)
}

// HasPolicy determines whether an authorization rule exists.
func (e *SyncedEnforcer) HasPolicy(params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasPolicy(params...)
}

// HasNamedPolicy determines whether a named authorization rule exists.
func (e *SyncedEnforcer) HasNamedPolicy(ptype string, params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasNamedPolicy(ptype, params...)
}

// AddPolicy adds an authorization rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddPolicy(params...)
}

// AddNamedPolicy adds an authorization rule to the current named policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddNamedPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddNamedPolicy(ptype, params...)
}

// RemovePolicy removes an authorization rule from the current policy.
func (e *SyncedEnforcer) RemovePolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemovePolicy(params...)
}

// RemoveFilteredPolicy removes an authorization rule from the current policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredPolicy(fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredPolicy(fieldIndex, fieldValues...)
}

// RemoveNamedPolicy removes an authorization rule from the current named policy.
func (e *SyncedEnforcer) RemoveNamedPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveNamedPolicy(ptype, params...)
}

// RemoveFilteredNamedPolicy removes an authorization rule from the current named policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredNamedPolicy(ptype, fieldIndex, fieldValues...)
}

// HasGroupingPolicy determines whether a role inheritance rule exists.
func (e *SyncedEnforcer) HasGroupingPolicy(params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasGroupingPolicy(params...)
}

// HasNamedGroupingPolicy determines whether a named role inheritance rule exists.
func (e *SyncedEnforcer) HasNamedGroupingPolicy(ptype string, params ...interface{}) bool {
	e.m.RLock()
	defer e.m.RUnlock()
	return e.Enforcer.HasNamedGroupingPolicy(ptype, params...)
}

// AddGroupingPolicy adds a role inheritance rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddGroupingPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddGroupingPolicy(params...)
}

// AddNamedGroupingPolicy adds a named role inheritance rule to the current policy.
// If the rule already exists, the function returns false and the rule will not be added.
// Otherwise the function returns true by adding the new rule.
func (e *SyncedEnforcer) AddNamedGroupingPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.AddNamedGroupingPolicy(ptype, params...)
}

// RemoveGroupingPolicy removes a role inheritance rule from the current policy.
func (e *SyncedEnforcer) RemoveGroupingPolicy(params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveGroupingPolicy(params...)
}

// RemoveFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredGroupingPolicy(fieldIndex, fieldValues...)
}

// RemoveNamedGroupingPolicy removes a role inheritance rule from the current named policy.
func (e *SyncedEnforcer) RemoveNamedGroupingPolicy(ptype string, params ...interface{}) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveNamedGroupingPolicy(ptype, params...)
}

// RemoveFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified.
func (e *SyncedEnforcer) RemoveFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) (bool, error) {
	e.m.Lock()
	defer e.m.Unlock()
	return e.Enforcer.RemoveFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues...)
}

// AddFunction adds a customized function.
func (e *SyncedEnforcer) AddFunction(name string, function govaluate.ExpressionFunction) {
	e.m.Lock()
	defer e.m.Unlock()
	e.Enforcer.AddFunction(name, function)
}
<|endoftext|>


<commit_before>package util

import (
	"fmt"
	"log"
	"reflect"
	"sync"
	"time"

	api "github.com/armon/consul-api"
)

const (
	// The amount of time to do a blocking query for
	defaultWaitTime = 60 * time.Second

	// pollErrorSleep the amount of time to sleep when an error occurs
	// TODO: make this an exponential backoff.
	pollErrorSleep = 5 * time.Second
)

type Watcher struct {
	// DataCh is the chan where new WatchData will be published
	DataCh chan *WatchData

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// FinishCh is the chan where the watcher reports it is "done"
	FinishCh chan struct{}

	// stopCh is a chan that is only published when polling should stop
	stopCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// dependencies is the slice of Dependencies this Watcher will poll
	dependencies []Dependency

	// waitGroup is the WaitGroup to ensure all Go routines return when we stop
	waitGroup sync.WaitGroup
}

//
func NewWatcher(client *api.Client, dependencies []Dependency) (*Watcher, error) {
	watcher := &Watcher{
		client:       client,
		dependencies: dependencies,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

//
func (w *Watcher) Watch(once bool) {
	log.Printf("[DEBUG] (watcher) starting watch")

	// In once mode, we want to immediately close the stopCh. This tells the
	// underlying WatchData objects to terminate after they get data for the first
	// time.
	if once {
		log.Printf("[DEBUG] (watcher) detected once mode")
		w.Stop()
	}

	views := make([]*WatchData, 0, len(w.dependencies))
	for _, dependency := range w.dependencies {
		view, err := NewWatchData(dependency)
		if err != nil {
			w.ErrCh <- err
			return
		}

		views = append(views, view)
	}

	for _, view := range views {
		w.waitGroup.Add(1)
		go func(view *WatchData) {
			defer w.waitGroup.Done()
			view.poll(w)
		}(view)
	}

	log.Printf("[DEBUG] (watcher) all pollers have started, waiting for finish")
	w.waitGroup.Wait()

	if once {
		log.Printf("[DEBUG] (watcher) closing finish channel")
		close(w.FinishCh)
	}
}

//
func (w *Watcher) Stop() {
	close(w.stopCh)
}

//
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	if len(w.dependencies) == 0 {
		log.Printf("[WARN] (watcher) no dependencies in template(s)")
	}

	// Setup the chans
	w.DataCh = make(chan *WatchData)
	w.ErrCh = make(chan error)
	w.FinishCh = make(chan struct{})
	w.stopCh = make(chan struct{})

	return nil
}

/// ------------------------- ///

type WatchData struct {
	Dependency Dependency
	Data       interface{}

	receivedData bool
	lastIndex    uint64
}

//
func NewWatchData(dependency Dependency) (*WatchData, error) {
	if dependency == nil {
		return nil, fmt.Errorf("watchdata: missing Dependency")
	}

	return &WatchData{Dependency: dependency}, nil
}

//
func (wd *WatchData) poll(w *Watcher) {
	for {
		log.Printf("[DEBUG] (%s) starting poll", wd.Display())

		options := &api.QueryOptions{
			WaitTime:  defaultWaitTime,
			WaitIndex: wd.lastIndex,
		}
		data, qm, err := wd.Dependency.Fetch(w.client, options)
		if err != nil {
			log.Printf("[ERR] (%s) %s", wd.Display(), err.Error())
			w.ErrCh <- err
			time.Sleep(pollErrorSleep)
			continue
		}

		// Consul is allowed to return even if there's no new data. Ignore data if
		// the index is the same. For files, the data is fake, index is always 0
		if qm.LastIndex == wd.lastIndex {
			log.Printf("[DEBUG] (%s) no new data (index was the same)", wd.Display())
			continue
		}

		// Update the index in case we got a new version, but the data is the same
		wd.lastIndex = qm.LastIndex

		// Do not trigger a render if we have gotten data and the data is the same
		if wd.receivedData && reflect.DeepEqual(data, wd.Data) {
			log.Printf("[DEBUG] (%s) no new data (contents were the same)", wd.Display())
			continue
		}

		log.Printf("[DEBUG] (%s) writing data to channel", wd.Display())

		// If we got this far, there is new data!
		wd.Data = data
		wd.receivedData = true
		w.DataCh <- wd

		// Break from the function if we are done
		select {
		case <-w.stopCh:
			log.Printf("[DEBUG] (%s) stopping poll (received on stopCh)", wd.Display())
			return
		default:
			continue
		}
	}
}

//
func (wd *WatchData) Display() string {
	return wd.Dependency.Display()
}
<commit_msg>Do not panic if qm is nil<commit_after>package util

import (
	"fmt"
	"log"
	"reflect"
	"sync"
	"time"

	api "github.com/armon/consul-api"
)

const (
	// The amount of time to do a blocking query for
	defaultWaitTime = 60 * time.Second

	// pollErrorSleep the amount of time to sleep when an error occurs
	// TODO: make this an exponential backoff.
	pollErrorSleep = 5 * time.Second
)

type Watcher struct {
	// DataCh is the chan where new WatchData will be published
	DataCh chan *WatchData

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// FinishCh is the chan where the watcher reports it is "done"
	FinishCh chan struct{}

	// stopCh is a chan that is only published when polling should stop
	stopCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// dependencies is the slice of Dependencies this Watcher will poll
	dependencies []Dependency

	// waitGroup is the WaitGroup to ensure all Go routines return when we stop
	waitGroup sync.WaitGroup
}

//
func NewWatcher(client *api.Client, dependencies []Dependency) (*Watcher, error) {
	watcher := &Watcher{
		client:       client,
		dependencies: dependencies,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

//
func (w *Watcher) Watch(once bool) {
	log.Printf("[DEBUG] (watcher) starting watch")

	// In once mode, we want to immediately close the stopCh. This tells the
	// underlying WatchData objects to terminate after they get data for the first
	// time.
	if once {
		log.Printf("[DEBUG] (watcher) detected once mode")
		w.Stop()
	}

	views := make([]*WatchData, 0, len(w.dependencies))
	for _, dependency := range w.dependencies {
		view, err := NewWatchData(dependency)
		if err != nil {
			w.ErrCh <- err
			return
		}

		views = append(views, view)
	}

	for _, view := range views {
		w.waitGroup.Add(1)
		go func(view *WatchData) {
			defer w.waitGroup.Done()
			view.poll(w)
		}(view)
	}

	log.Printf("[DEBUG] (watcher) all pollers have started, waiting for finish")
	w.waitGroup.Wait()

	if once {
		log.Printf("[DEBUG] (watcher) closing finish channel")
		close(w.FinishCh)
	}
}

//
func (w *Watcher) Stop() {
	close(w.stopCh)
}

//
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	if len(w.dependencies) == 0 {
		log.Printf("[WARN] (watcher) no dependencies in template(s)")
	}

	// Setup the chans
	w.DataCh = make(chan *WatchData)
	w.ErrCh = make(chan error)
	w.FinishCh = make(chan struct{})
	w.stopCh = make(chan struct{})

	return nil
}

/// ------------------------- ///

type WatchData struct {
	Dependency Dependency
	Data       interface{}

	receivedData bool
	lastIndex    uint64
}

//
func NewWatchData(dependency Dependency) (*WatchData, error) {
	if dependency == nil {
		return nil, fmt.Errorf("watchdata: missing Dependency")
	}

	return &WatchData{Dependency: dependency}, nil
}

//
func (wd *WatchData) poll(w *Watcher) {
	for {
		log.Printf("[DEBUG] (%s) starting poll", wd.Display())

		options := &api.QueryOptions{
			WaitTime:  defaultWaitTime,
			WaitIndex: wd.lastIndex,
		}
		data, qm, err := wd.Dependency.Fetch(w.client, options)
		if err != nil {
			log.Printf("[ERR] (%s) %s", wd.Display(), err.Error())
			w.ErrCh <- err
			time.Sleep(pollErrorSleep)
			continue
		}

		// If the query metadata is nil, return an error instead of panicing. See
		// (GH-72) for more information. This does not actually "fix" the issue,
		// which appears to be a bug in armon/consul-api, but will at least give a
		// nicer error message to the user and help us better trace this issue.
		if qm == nil {
			err := fmt.Errorf("consul returned nil qm; this should never happen" +
				"and is probably a bug in consul-template or consulapi")
			log.Printf("[ERR] (%s) %s", wd.Display(), err)
			w.ErrCh <- err
			continue
		}

		// Consul is allowed to return even if there's no new data. Ignore data if
		// the index is the same. For files, the data is fake, index is always 0
		if qm.LastIndex == wd.lastIndex {
			log.Printf("[DEBUG] (%s) no new data (index was the same)", wd.Display())
			continue
		}

		// Update the index in case we got a new version, but the data is the same
		wd.lastIndex = qm.LastIndex

		// Do not trigger a render if we have gotten data and the data is the same
		if wd.receivedData && reflect.DeepEqual(data, wd.Data) {
			log.Printf("[DEBUG] (%s) no new data (contents were the same)", wd.Display())
			continue
		}

		log.Printf("[DEBUG] (%s) writing data to channel", wd.Display())

		// If we got this far, there is new data!
		wd.Data = data
		wd.receivedData = true
		w.DataCh <- wd

		// Break from the function if we are done
		select {
		case <-w.stopCh:
			log.Printf("[DEBUG] (%s) stopping poll (received on stopCh)", wd.Display())
			return
		default:
			continue
		}
	}
}

//
func (wd *WatchData) Display() string {
	return wd.Dependency.Display()
}
<|endoftext|>


<commit_before>// Copyright 2014 The Serviced Authors.
// 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 utils

import (
	"fmt"
	"net/url"
	"os"

	"github.com/docker/docker/registry"
	"github.com/zenoss/glog"
)

func DockerLogin(username, password, email string) (string, error) {

	u, err := url.Parse(registry.IndexServerAddress())
	if err != nil {
		return "", fmt.Errorf("Error: bad URL %s: %s", registry.IndexServerAddress(), err)
	}
	endpoint := registry.Endpoint{URL: u, Version: 1, IsSecure: false}

	if username == "" && password == "" && email == "" {
		// Attempt login with .dockercfg file.
		configFile, err := registry.LoadConfig(os.Getenv("HOME"))
		if err != nil {
			return "", err
		}

		authconfig, ok := configFile.Configs[registry.IndexServerAddress()]
		if !ok {
			glog.Warningf("unable to login to docker.io using credentials in %s/.dockercfg", os.Getenv("HOME"))
			return "", fmt.Errorf("Error: Unable to login, no data for index server.")
		}
		status, err := registry.Login(&authconfig, &endpoint, registry.HTTPRequestFactory(nil))
		if err != nil {
			return "", err
		}
		return status, nil
	} else {
		// Attempt login with this function's auth params.
		authconfig := registry.AuthConfig{
			Username:      username,
			Email:         email,
			Password:      password,
			ServerAddress: registry.IndexServerAddress(),
		}
		endpoint.IsSecure = true
		status, err := registry.Login(&authconfig, &endpoint, registry.HTTPRequestFactory(nil))
		if err != nil {
			return "", err
		}
		return status, nil
	}
}

func DockerIsLoggedIn() bool {
	_, err := DockerLogin("", "", "")
	if err != nil {
		return false
	}
	return true
}
<commit_msg>Update Docker Hub login check to be compatible with the docker 1.7.1 library.<commit_after>// Copyright 2014 The Serviced Authors.
// 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 utils

import (
	"github.com/zenoss/glog"

	"github.com/docker/docker/cliconfig"
	"github.com/docker/docker/registry"
)

func DockerIsLoggedIn() bool {

	// Load the user's ~/.docker/config.json file if it exists.
	configFile, err := cliconfig.Load("")
	if err != nil {
		glog.Errorf("Error checking Docker Hub login: %s", err)
		return false
	}

	// Make sure there is at least one AuthConfig (credential set).
	if len(configFile.AuthConfigs) < 1 {
		glog.Errorf("Error checking Docker Hub login: config.json is not populated")
		return false
	}

	// Create a registry endpoint to the official registry.
	endpoint, err := registry.NewEndpoint(&registry.IndexInfo{Official: true}, nil)
	if err != nil {
		glog.Errorf("Error checking Docker Hub login: %s", err)
		return false
	}

	// Iterate over AuthConfigs and attempt to login.
	for _, authConfig := range configFile.AuthConfigs {
		_, err := registry.Login(&authConfig, endpoint)
		if err == nil {
			return true
		}
	}

	glog.Errorf("Error checking Docker Hub login: no credentials in config.json succeeded")
	return false
}
<|endoftext|>