<commit_before>package ipam

import (
	"github.com/weaveworks/weave/ipam/paxos"
	"github.com/weaveworks/weave/net/address"
)

type Status struct {
	Paxos            *paxos.Status
	Range            string
	RangeNumIPs      int
	DefaultSubnet    string
	Entries          []EntryStatus
	PendingClaims    []ClaimStatus
	PendingAllocates []string
}

type EntryStatus struct {
	Token       string
	Size        uint32
	Peer        string
	Nickname    string
	IsKnownPeer bool
	Version     uint32
}

type ClaimStatus struct {
	Ident   string
	Address address.Address
}

func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status {
	if allocator == nil {
		return nil
	}

	var paxosStatus *paxos.Status
	if allocator.paxosTicker != nil {
		paxosStatus = paxos.NewStatus(allocator.paxos)
	}

	resultChan := make(chan *Status)
	allocator.actionChan <- func() {
		resultChan <- &Status{
			paxosStatus,
			allocator.universe.String(),
			int(allocator.universe.Size()),
			defaultSubnet.String(),
			newEntryStatusSlice(allocator),
			newClaimStatusSlice(allocator),
			newAllocateIdentSlice(allocator)}
	}

	return <-resultChan
}

func newEntryStatusSlice(allocator *Allocator) []EntryStatus {
	var slice []EntryStatus

	if allocator.ring.Empty() {
		return slice
	}

	for _, r := range allocator.ring.AllRangeInfo() {
		slice = append(slice, EntryStatus{
			Token:       r.Start.String(),
			Size:        uint32(r.Size()),
			Peer:        r.Peer.String(),
			Nickname:    allocator.nicknames[r.Peer],
			IsKnownPeer: allocator.isKnownPeer(r.Peer),
			Version:     r.Version,
		})
	}

	return slice
}

func newClaimStatusSlice(allocator *Allocator) []ClaimStatus {
	var slice []ClaimStatus
	for _, op := range allocator.pendingClaims {
		claim := op.(*claim)
		slice = append(slice, ClaimStatus{claim.ident, claim.addr})
	}
	return slice
}

func newAllocateIdentSlice(allocator *Allocator) []string {
	var slice []string
	for _, op := range allocator.pendingAllocates {
		allocate := op.(*allocate)
		slice = append(slice, allocate.ident)
	}
	return slice
}
<commit_msg>Show which range is being allocated in `weave report`<commit_after>package ipam

import (
	"fmt"
	"github.com/weaveworks/weave/ipam/paxos"
	"github.com/weaveworks/weave/net/address"
)

type Status struct {
	Paxos            *paxos.Status
	Range            string
	RangeNumIPs      int
	DefaultSubnet    string
	Entries          []EntryStatus
	PendingClaims    []ClaimStatus
	PendingAllocates []string
}

type EntryStatus struct {
	Token       string
	Size        uint32
	Peer        string
	Nickname    string
	IsKnownPeer bool
	Version     uint32
}

type ClaimStatus struct {
	Ident   string
	Address address.Address
}

func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status {
	if allocator == nil {
		return nil
	}

	var paxosStatus *paxos.Status
	if allocator.paxosTicker != nil {
		paxosStatus = paxos.NewStatus(allocator.paxos)
	}

	resultChan := make(chan *Status)
	allocator.actionChan <- func() {
		resultChan <- &Status{
			paxosStatus,
			allocator.universe.String(),
			int(allocator.universe.Size()),
			defaultSubnet.String(),
			newEntryStatusSlice(allocator),
			newClaimStatusSlice(allocator),
			newAllocateIdentSlice(allocator)}
	}

	return <-resultChan
}

func newEntryStatusSlice(allocator *Allocator) []EntryStatus {
	var slice []EntryStatus

	if allocator.ring.Empty() {
		return slice
	}

	for _, r := range allocator.ring.AllRangeInfo() {
		slice = append(slice, EntryStatus{
			Token:       r.Start.String(),
			Size:        uint32(r.Size()),
			Peer:        r.Peer.String(),
			Nickname:    allocator.nicknames[r.Peer],
			IsKnownPeer: allocator.isKnownPeer(r.Peer),
			Version:     r.Version,
		})
	}

	return slice
}

func newClaimStatusSlice(allocator *Allocator) []ClaimStatus {
	var slice []ClaimStatus
	for _, op := range allocator.pendingClaims {
		claim := op.(*claim)
		slice = append(slice, ClaimStatus{claim.ident, claim.addr})
	}
	return slice
}

func newAllocateIdentSlice(allocator *Allocator) []string {
	var slice []string
	for _, op := range allocator.pendingAllocates {
		allocate := op.(*allocate)
		slice = append(slice, fmt.Sprintf("%s %s", allocate.ident, allocate.r.String()))
	}
	return slice
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"code.google.com/p/go.tools/go/vcs"
)

// These variables are copied from the gobuilder's environment
// to the envv of its subprocesses.
var extraEnv = []string{
	"GOARM",

	// For Unix derivatives.
	"CC",
	"PATH",
	"TMPDIR",
	"USER",

	// For Plan 9.
	"objtype",
	"cputype",
	"path",
}

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOHOSTOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOHOSTARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
	}

	for _, k := range extraEnv {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if _, err := repo.Clone(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error cloning repository: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to workpath/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gofrontendpath := filepath.Join(workpath, "gofrontend")
	gccpath := filepath.Join(workpath, "gcc")

	// get a handle to SVN vcs.Cmd for pulling down GCC.
	svn := vcs.ByCmd("svn")

	if err := timeout(*cmdTimeout, func() error {
		// pull down a working copy of GCC.
		return svn.Create(gccpath, *gccPath)
	}); err != nil {
		return "", err
	}

	// clone gofrontend repo at specified revision
	if _, err := repo.Clone(gofrontendpath, hash); err != nil {
		return "", err
	}

	// remove gccpath/gcc/go/gofrontend and gcc/libgo
	gccgopath := filepath.Join(gccpath, "gcc", "go", "gofrontend")
	gcclibgopath := filepath.Join(gccpath, "libgo")
	if err := os.RemoveAll(gccgopath); err != nil {
		return "", err
	}
	if err := os.RemoveAll(gcclibgopath); err != nil {
		return "", err
	}

	// copy gofrontend and libgo to appropriate locations
	if err := copyDir(filepath.Join(gofrontendpath, "go"), gccgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/go to gcc/go/gofrontend: %s\n", err)
	}
	if err := copyDir(filepath.Join(gofrontendpath, "libgo"), gcclibgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/libgo to gcc/libgo: %s\n", err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	gccConfigCmd := []string{filepath.Join(gccpath, "configure"), "--enable-languages=c,c++,go", "--disable-bootstrap"}
	if _, err := runOutput(*cmdTimeout, envv, ioutil.Discard, gccobjdir, gccConfigCmd...); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %s", err)
	}

	// build gcc
	if _, err := runOutput(*buildTimeout, envv, ioutil.Discard, gccobjdir, "make"); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil

}

// copyDir copies the src directory into the dst
func copyDir(src, dst string) error {
	return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
		dstPath := strings.Replace(path, src, dst, 1)
		if f.IsDir() {
			return os.Mkdir(dstPath, mkdirPerm)
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return err
		}

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
		return dstFile.Close()
	})
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}
<commit_msg>go.tools/dashboard/builder: only download gcc once for gccgo buildTool.<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"code.google.com/p/go.tools/go/vcs"
)

// These variables are copied from the gobuilder's environment
// to the envv of its subprocesses.
var extraEnv = []string{
	"GOARM",

	// For Unix derivatives.
	"CC",
	"PATH",
	"TMPDIR",
	"USER",

	// For Plan 9.
	"objtype",
	"cputype",
	"path",
}

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOHOSTOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOHOSTARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
	}

	for _, k := range extraEnv {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if _, err := repo.Clone(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error cloning repository: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gofrontendpath := filepath.Join(workpath, "gofrontend")
	gccpath := filepath.Join(repo.Path, "gcc")

	// get a handle to SVN vcs.Cmd for pulling down GCC.
	svn := vcs.ByCmd("svn")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return svn.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	}
	if err := svn.Download(gccpath); err != nil {
		return "", err
	}

	// clone gofrontend repo at specified revision
	if _, err := repo.Clone(gofrontendpath, hash); err != nil {
		return "", err
	}

	// remove gccpath/gcc/go/gofrontend and gcc/libgo
	gccgopath := filepath.Join(gccpath, "gcc", "go", "gofrontend")
	gcclibgopath := filepath.Join(gccpath, "libgo")
	if err := os.RemoveAll(gccgopath); err != nil {
		return "", err
	}
	if err := os.RemoveAll(gcclibgopath); err != nil {
		return "", err
	}

	// copy gofrontend and libgo to appropriate locations
	if err := copyDir(filepath.Join(gofrontendpath, "go"), gccgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/go to gcc/go/gofrontend: %s\n", err)
	}
	if err := copyDir(filepath.Join(gofrontendpath, "libgo"), gcclibgopath); err != nil {
		return "", fmt.Errorf("Failed to copy gofrontend/libgo to gcc/libgo: %s\n", err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	gccConfigCmd := []string{filepath.Join(gccpath, "configure"), "--enable-languages=c,c++,go", "--disable-bootstrap"}
	if _, err := runOutput(*cmdTimeout, envv, ioutil.Discard, gccobjdir, gccConfigCmd...); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %s", err)
	}

	// build gcc
	if _, err := runOutput(*buildTimeout, envv, ioutil.Discard, gccobjdir, "make"); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil

}

// copyDir copies the src directory into the dst
func copyDir(src, dst string) error {
	return filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
		dstPath := strings.Replace(path, src, dst, 1)
		if f.IsDir() {
			return os.Mkdir(dstPath, mkdirPerm)
		}

		srcFile, err := os.Open(path)
		if err != nil {
			return err
		}
		defer srcFile.Close()

		dstFile, err := os.Create(dstPath)
		if err != nil {
			return err
		}

		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
		return dstFile.Close()
	})
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}
<|endoftext|>


<commit_before>package caddytls

import (
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/mholt/caddy"
)

func init() {
	RegisterStorageProvider("file", NewFileStorage)
}

// storageBasePath is the root path in which all TLS/ACME assets are
// stored. Do not change this value during the lifetime of the program.
var storageBasePath = filepath.Join(caddy.AssetsPath(), "acme")

// NewFileStorage is a StorageConstructor function that creates a new
// Storage instance backed by the local disk. The resulting Storage
// instance is guaranteed to be non-nil if there is no error.
func NewFileStorage(caURL *url.URL) (Storage, error) {
	return &FileStorage{
		Path:      filepath.Join(storageBasePath, caURL.Host),
		nameLocks: make(map[string]*sync.WaitGroup),
	}, nil
}

// FileStorage facilitates forming file paths derived from a root
// directory. It is used to get file paths in a consistent,
// cross-platform way or persisting ACME assets on the file system.
type FileStorage struct {
	Path        string
	nameLocks   map[string]*sync.WaitGroup
	nameLocksMu sync.Mutex
}

// sites gets the directory that stores site certificate and keys.
func (s *FileStorage) sites() string {
	return filepath.Join(s.Path, "sites")
}

// site returns the path to the folder containing assets for domain.
func (s *FileStorage) site(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.sites(), domain)
}

// siteCertFile returns the path to the certificate file for domain.
func (s *FileStorage) siteCertFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".crt")
}

// siteKeyFile returns the path to domain's private key file.
func (s *FileStorage) siteKeyFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".key")
}

// siteMetaFile returns the path to the domain's asset metadata file.
func (s *FileStorage) siteMetaFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".json")
}

// users gets the directory that stores account folders.
func (s *FileStorage) users() string {
	return filepath.Join(s.Path, "users")
}

// user gets the account folder for the user with email
func (s *FileStorage) user(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	return filepath.Join(s.users(), email)
}

// emailUsername returns the username portion of an email address (part before
// '@') or the original input if it can't find the "@" symbol.
func emailUsername(email string) string {
	at := strings.Index(email, "@")
	if at == -1 {
		return email
	} else if at == 0 {
		return email[1:]
	}
	return email[:at]
}

// userRegFile gets the path to the registration file for the user with the
// given email address.
func (s *FileStorage) userRegFile(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	fileName := emailUsername(email)
	if fileName == "" {
		fileName = "registration"
	}
	return filepath.Join(s.user(email), fileName+".json")
}

// userKeyFile gets the path to the private key file for the user with the
// given email address.
func (s *FileStorage) userKeyFile(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	fileName := emailUsername(email)
	if fileName == "" {
		fileName = "private"
	}
	return filepath.Join(s.user(email), fileName+".key")
}

// readFile abstracts a simple ioutil.ReadFile, making sure to return an
// ErrNotExist instance when the file is not found.
func (s *FileStorage) readFile(file string) ([]byte, error) {
	b, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		return nil, ErrNotExist(err)
	}
	return b, err
}

// SiteExists implements Storage.SiteExists by checking for the presence of
// cert and key files.
func (s *FileStorage) SiteExists(domain string) (bool, error) {
	_, err := os.Stat(s.siteCertFile(domain))
	if os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}

	_, err = os.Stat(s.siteKeyFile(domain))
	if err != nil {
		return false, err
	}
	return true, nil
}

// LoadSite implements Storage.LoadSite by loading it from disk. If it is not
// present, an instance of ErrNotExist is returned.
func (s *FileStorage) LoadSite(domain string) (*SiteData, error) {
	var err error
	siteData := new(SiteData)
	siteData.Cert, err = s.readFile(s.siteCertFile(domain))
	if err != nil {
		return nil, err
	}
	siteData.Key, err = s.readFile(s.siteKeyFile(domain))
	if err != nil {
		return nil, err
	}
	siteData.Meta, err = s.readFile(s.siteMetaFile(domain))
	if err != nil {
		return nil, err
	}
	return siteData, nil
}

// StoreSite implements Storage.StoreSite by writing it to disk. The base
// directories needed for the file are automatically created as needed.
func (s *FileStorage) StoreSite(domain string, data *SiteData) error {
	err := os.MkdirAll(s.site(domain), 0700)
	if err != nil {
		return fmt.Errorf("making site directory: %v", err)
	}
	err = ioutil.WriteFile(s.siteCertFile(domain), data.Cert, 0600)
	if err != nil {
		return fmt.Errorf("writing certificate file: %v", err)
	}
	err = ioutil.WriteFile(s.siteKeyFile(domain), data.Key, 0600)
	if err != nil {
		return fmt.Errorf("writing key file: %v", err)
	}
	err = ioutil.WriteFile(s.siteMetaFile(domain), data.Meta, 0600)
	if err != nil {
		return fmt.Errorf("writing cert meta file: %v", err)
	}
	return nil
}

// DeleteSite implements Storage.DeleteSite by deleting just the cert from
// disk. If it is not present, an instance of ErrNotExist is returned.
func (s *FileStorage) DeleteSite(domain string) error {
	err := os.Remove(s.siteCertFile(domain))
	if err != nil {
		if os.IsNotExist(err) {
			return ErrNotExist(err)
		}
		return err
	}
	return nil
}

// LoadUser implements Storage.LoadUser by loading it from disk. If it is not
// present, an instance of ErrNotExist is returned.
func (s *FileStorage) LoadUser(email string) (*UserData, error) {
	var err error
	userData := new(UserData)
	userData.Reg, err = s.readFile(s.userRegFile(email))
	if err != nil {
		return nil, err
	}
	userData.Key, err = s.readFile(s.userKeyFile(email))
	if err != nil {
		return nil, err
	}
	return userData, nil
}

// StoreUser implements Storage.StoreUser by writing it to disk. The base
// directories needed for the file are automatically created as needed.
func (s *FileStorage) StoreUser(email string, data *UserData) error {
	err := os.MkdirAll(s.user(email), 0700)
	if err != nil {
		return fmt.Errorf("making user directory: %v", err)
	}
	err = ioutil.WriteFile(s.userRegFile(email), data.Reg, 0600)
	if err != nil {
		return fmt.Errorf("writing user registration file: %v", err)
	}
	err = ioutil.WriteFile(s.userKeyFile(email), data.Key, 0600)
	if err != nil {
		return fmt.Errorf("writing user key file: %v", err)
	}
	return nil
}

// TryLock attempts to get a lock for name, otherwise it returns
// a Waiter value to wait until the other process is finished.
func (s *FileStorage) TryLock(name string) (Waiter, error) {
	s.nameLocksMu.Lock()
	defer s.nameLocksMu.Unlock()
	wg, ok := s.nameLocks[name]
	if ok {
		// lock already obtained, let caller wait on it
		return wg, nil
	}
	// caller gets lock
	wg = new(sync.WaitGroup)
	wg.Add(1)
	s.nameLocks[name] = wg
	return nil, nil
}

// Unlock unlocks name.
func (s *FileStorage) Unlock(name string) error {
	s.nameLocksMu.Lock()
	defer s.nameLocksMu.Unlock()
	wg, ok := s.nameLocks[name]
	if !ok {
		return fmt.Errorf("FileStorage: no lock to release for %s", name)
	}
	wg.Done()
	delete(s.nameLocks, name)
	return nil
}

// MostRecentUserEmail implements Storage.MostRecentUserEmail by finding the
// most recently written sub directory in the users' directory. It is named
// after the email address. This corresponds to the most recent call to
// StoreUser.
func (s *FileStorage) MostRecentUserEmail() string {
	userDirs, err := ioutil.ReadDir(s.users())
	if err != nil {
		return ""
	}
	var mostRecent os.FileInfo
	for _, dir := range userDirs {
		if !dir.IsDir() {
			continue
		}
		if mostRecent == nil || dir.ModTime().After(mostRecent.ModTime()) {
			mostRecent = dir
		}
	}
	if mostRecent != nil {
		return mostRecent.Name()
	}
	return ""
}
<commit_msg>Log certificate location<commit_after>package caddytls

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"github.com/mholt/caddy"
)

func init() {
	RegisterStorageProvider("file", NewFileStorage)
}

// storageBasePath is the root path in which all TLS/ACME assets are
// stored. Do not change this value during the lifetime of the program.
var storageBasePath = filepath.Join(caddy.AssetsPath(), "acme")

// NewFileStorage is a StorageConstructor function that creates a new
// Storage instance backed by the local disk. The resulting Storage
// instance is guaranteed to be non-nil if there is no error.
func NewFileStorage(caURL *url.URL) (Storage, error) {
	return &FileStorage{
		Path:      filepath.Join(storageBasePath, caURL.Host),
		nameLocks: make(map[string]*sync.WaitGroup),
	}, nil
}

// FileStorage facilitates forming file paths derived from a root
// directory. It is used to get file paths in a consistent,
// cross-platform way or persisting ACME assets on the file system.
type FileStorage struct {
	Path        string
	nameLocks   map[string]*sync.WaitGroup
	nameLocksMu sync.Mutex
}

// sites gets the directory that stores site certificate and keys.
func (s *FileStorage) sites() string {
	return filepath.Join(s.Path, "sites")
}

// site returns the path to the folder containing assets for domain.
func (s *FileStorage) site(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.sites(), domain)
}

// siteCertFile returns the path to the certificate file for domain.
func (s *FileStorage) siteCertFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".crt")
}

// siteKeyFile returns the path to domain's private key file.
func (s *FileStorage) siteKeyFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".key")
}

// siteMetaFile returns the path to the domain's asset metadata file.
func (s *FileStorage) siteMetaFile(domain string) string {
	domain = strings.ToLower(domain)
	return filepath.Join(s.site(domain), domain+".json")
}

// users gets the directory that stores account folders.
func (s *FileStorage) users() string {
	return filepath.Join(s.Path, "users")
}

// user gets the account folder for the user with email
func (s *FileStorage) user(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	return filepath.Join(s.users(), email)
}

// emailUsername returns the username portion of an email address (part before
// '@') or the original input if it can't find the "@" symbol.
func emailUsername(email string) string {
	at := strings.Index(email, "@")
	if at == -1 {
		return email
	} else if at == 0 {
		return email[1:]
	}
	return email[:at]
}

// userRegFile gets the path to the registration file for the user with the
// given email address.
func (s *FileStorage) userRegFile(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	fileName := emailUsername(email)
	if fileName == "" {
		fileName = "registration"
	}
	return filepath.Join(s.user(email), fileName+".json")
}

// userKeyFile gets the path to the private key file for the user with the
// given email address.
func (s *FileStorage) userKeyFile(email string) string {
	if email == "" {
		email = emptyEmail
	}
	email = strings.ToLower(email)
	fileName := emailUsername(email)
	if fileName == "" {
		fileName = "private"
	}
	return filepath.Join(s.user(email), fileName+".key")
}

// readFile abstracts a simple ioutil.ReadFile, making sure to return an
// ErrNotExist instance when the file is not found.
func (s *FileStorage) readFile(file string) ([]byte, error) {
	b, err := ioutil.ReadFile(file)
	if os.IsNotExist(err) {
		return nil, ErrNotExist(err)
	}
	return b, err
}

// SiteExists implements Storage.SiteExists by checking for the presence of
// cert and key files.
func (s *FileStorage) SiteExists(domain string) (bool, error) {
	_, err := os.Stat(s.siteCertFile(domain))
	if os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}

	_, err = os.Stat(s.siteKeyFile(domain))
	if err != nil {
		return false, err
	}
	return true, nil
}

// LoadSite implements Storage.LoadSite by loading it from disk. If it is not
// present, an instance of ErrNotExist is returned.
func (s *FileStorage) LoadSite(domain string) (*SiteData, error) {
	var err error
	siteData := new(SiteData)
	siteData.Cert, err = s.readFile(s.siteCertFile(domain))
	if err != nil {
		return nil, err
	}
	siteData.Key, err = s.readFile(s.siteKeyFile(domain))
	if err != nil {
		return nil, err
	}
	siteData.Meta, err = s.readFile(s.siteMetaFile(domain))
	if err != nil {
		return nil, err
	}
	return siteData, nil
}

// StoreSite implements Storage.StoreSite by writing it to disk. The base
// directories needed for the file are automatically created as needed.
func (s *FileStorage) StoreSite(domain string, data *SiteData) error {
	err := os.MkdirAll(s.site(domain), 0700)
	if err != nil {
		return fmt.Errorf("making site directory: %v", err)
	}
	err = ioutil.WriteFile(s.siteCertFile(domain), data.Cert, 0600)
	if err != nil {
		return fmt.Errorf("writing certificate file: %v", err)
	}
	err = ioutil.WriteFile(s.siteKeyFile(domain), data.Key, 0600)
	if err != nil {
		return fmt.Errorf("writing key file: %v", err)
	}
	err = ioutil.WriteFile(s.siteMetaFile(domain), data.Meta, 0600)
	if err != nil {
		return fmt.Errorf("writing cert meta file: %v", err)
	}
	log.Printf("[INFO][%v] Certificate written to disk: %v", domain, s.siteCertFile(domain))
	return nil
}

// DeleteSite implements Storage.DeleteSite by deleting just the cert from
// disk. If it is not present, an instance of ErrNotExist is returned.
func (s *FileStorage) DeleteSite(domain string) error {
	err := os.Remove(s.siteCertFile(domain))
	if err != nil {
		if os.IsNotExist(err) {
			return ErrNotExist(err)
		}
		return err
	}
	return nil
}

// LoadUser implements Storage.LoadUser by loading it from disk. If it is not
// present, an instance of ErrNotExist is returned.
func (s *FileStorage) LoadUser(email string) (*UserData, error) {
	var err error
	userData := new(UserData)
	userData.Reg, err = s.readFile(s.userRegFile(email))
	if err != nil {
		return nil, err
	}
	userData.Key, err = s.readFile(s.userKeyFile(email))
	if err != nil {
		return nil, err
	}
	return userData, nil
}

// StoreUser implements Storage.StoreUser by writing it to disk. The base
// directories needed for the file are automatically created as needed.
func (s *FileStorage) StoreUser(email string, data *UserData) error {
	err := os.MkdirAll(s.user(email), 0700)
	if err != nil {
		return fmt.Errorf("making user directory: %v", err)
	}
	err = ioutil.WriteFile(s.userRegFile(email), data.Reg, 0600)
	if err != nil {
		return fmt.Errorf("writing user registration file: %v", err)
	}
	err = ioutil.WriteFile(s.userKeyFile(email), data.Key, 0600)
	if err != nil {
		return fmt.Errorf("writing user key file: %v", err)
	}
	return nil
}

// TryLock attempts to get a lock for name, otherwise it returns
// a Waiter value to wait until the other process is finished.
func (s *FileStorage) TryLock(name string) (Waiter, error) {
	s.nameLocksMu.Lock()
	defer s.nameLocksMu.Unlock()
	wg, ok := s.nameLocks[name]
	if ok {
		// lock already obtained, let caller wait on it
		return wg, nil
	}
	// caller gets lock
	wg = new(sync.WaitGroup)
	wg.Add(1)
	s.nameLocks[name] = wg
	return nil, nil
}

// Unlock unlocks name.
func (s *FileStorage) Unlock(name string) error {
	s.nameLocksMu.Lock()
	defer s.nameLocksMu.Unlock()
	wg, ok := s.nameLocks[name]
	if !ok {
		return fmt.Errorf("FileStorage: no lock to release for %s", name)
	}
	wg.Done()
	delete(s.nameLocks, name)
	return nil
}

// MostRecentUserEmail implements Storage.MostRecentUserEmail by finding the
// most recently written sub directory in the users' directory. It is named
// after the email address. This corresponds to the most recent call to
// StoreUser.
func (s *FileStorage) MostRecentUserEmail() string {
	userDirs, err := ioutil.ReadDir(s.users())
	if err != nil {
		return ""
	}
	var mostRecent os.FileInfo
	for _, dir := range userDirs {
		if !dir.IsDir() {
			continue
		}
		if mostRecent == nil || dir.ModTime().After(mostRecent.ModTime()) {
			mostRecent = dir
		}
	}
	if mostRecent != nil {
		return mostRecent.Name()
	}
	return ""
}
<|endoftext|>


<commit_before>package files

import (
	"errors"
	"io"
	"time"

	"honnef.co/go/js/dom"

	"github.com/gopherjs/gopherjs/js"
)

type Blob struct {
	b *js.Object
}

func NewBlob(b *js.Object) Blob {
	return Blob{b}
}

func (b Blob) Len() int {
	return b.b.Get("size").Int()
}

func (b Blob) Type() string {
	return b.b.Get("type").String()
}

func (b Blob) Slice(i, j int) Blob {
	return NewBlob(b.b.Call("slice", i, j))
}

type File struct {
	Blob
}

func NewFile(f *dom.File) File {
	return File{NewBlob(f.Object)}
}

func (f File) LastModifiedDate() time.Time {
	return f.b.Get("lastModifiedDate").Interface().(time.Time)
}

func (f File) Name() string {
	return f.b.Get("name").String()
}

type FileReader struct {
	File
	fr           *js.Object
	offset, size int64
}

func NewFileReader(f File) *FileReader {
	return &FileReader{
		f,
		js.Global.Get("FileReader").New(),
		0,
		int64(f.Len()),
	}
}

func (fr *FileReader) Close() error {
	fr.fr = nil
	return nil
}

func (fr *FileReader) Read(b []byte) (int, error) {
	n, err := fr.ReadAt(b, int64(fr.offset))
	fr.offset += int64(n)
	return n, err
}

func (fr *FileReader) ReadAt(b []byte, off int64) (int, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	if off >= fr.size {
		return 0, io.EOF
	}

	type readResult struct {
		size int
		err  error
	}

	c := make(chan readResult)
	fr.fr.Set("onloadend", func(*js.Object) {
		arr := js.Global.Get("Uint8Array").New(fr.fr.Get("result"))
		buf := arr.Interface().([]byte)
		go func() {
			if len(buf) == 0 {
				c <- readResult{0, io.EOF}
			} else {
				copy(b, buf)
				c <- readResult{len(buf), nil}
			}
		}()
	})
	e := off + int64(len(b))
	if e > fr.size {
		e = fr.size
	}
	blob := fr.b.Call("slice", fr.offset, e)
	fr.fr.Call("readAsArrayBuffer", blob)
	r := <-c
	return r.size, r.err
}

func (fr *FileReader) Seek(offset int64, whence int) (int64, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	switch whence {
	case 0:
		fr.offset = offset
	case 1:
		fr.offset += offset
	case 2:
		fr.offset = fr.size + offset
	}
	if fr.offset < 0 {
		fr.offset = 0
	}
	return fr.offset, nil
}

// Errors
var (
	ErrClosed = errors.New("file closed")
)
<commit_msg>Added comments<commit_after>// Package files turns javascript files into io.Reader's
package files

import (
	"errors"
	"io"
	"time"

	"honnef.co/go/js/dom"

	"github.com/gopherjs/gopherjs/js"
)

// Blob is a wrapped javascript blob
type Blob struct {
	b *js.Object
}

// NewBlob wraps a javascript blob
func NewBlob(b *js.Object) Blob {
	return Blob{b}
}

// Len returns the length of the blob
func (b Blob) Len() int {
	return b.b.Get("size").Int()
}

// Type returns the type of the blob
func (b Blob) Type() string {
	return b.b.Get("type").String()
}

// Slice returns a new blob sliced with the given indicies
func (b Blob) Slice(i, j int) Blob {
	return NewBlob(b.b.Call("slice", i, j))
}

// File wraps a Blob
type File struct {
	Blob
}

// NewFile wraps a javascript File to access
func NewFile(f *dom.File) File {
	return File{NewBlob(f.Object)}
}

// LastModifiedDate returns the last modified time for the file
func (f File) LastModifiedDate() time.Time {
	return f.b.Get("lastModifiedDate").Interface().(time.Time)
}

// Name returns the files name
func (f File) Name() string {
	return f.b.Get("name").String()
}

// FileReader wraps a File to allow for reading
type FileReader struct {
	File
	fr           *js.Object
	offset, size int64
}

// NewFileReader opens a File for reading
func NewFileReader(f File) *FileReader {
	return &FileReader{
		f,
		js.Global.Get("FileReader").New(),
		0,
		int64(f.Len()),
	}
}

// Close implements the io.Closer interface
func (fr *FileReader) Close() error {
	fr.fr = nil
	return nil
}

// Read implements the io.Reader interface
func (fr *FileReader) Read(b []byte) (int, error) {
	n, err := fr.ReadAt(b, int64(fr.offset))
	fr.offset += int64(n)
	return n, err
}

//ReadAt implements the io.ReaderAt interface
func (fr *FileReader) ReadAt(b []byte, off int64) (int, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	if off >= fr.size {
		return 0, io.EOF
	}

	type readResult struct {
		size int
		err  error
	}

	c := make(chan readResult)
	fr.fr.Set("onloadend", func(*js.Object) {
		arr := js.Global.Get("Uint8Array").New(fr.fr.Get("result"))
		buf := arr.Interface().([]byte)
		go func() {
			if len(buf) == 0 {
				c <- readResult{0, io.EOF}
			} else {
				copy(b, buf)
				c <- readResult{len(buf), nil}
			}
		}()
	})
	e := off + int64(len(b))
	if e > fr.size {
		e = fr.size
	}
	blob := fr.b.Call("slice", fr.offset, e)
	fr.fr.Call("readAsArrayBuffer", blob)
	r := <-c
	return r.size, r.err
}

// Seek implements the io.Seeker interface
func (fr *FileReader) Seek(offset int64, whence int) (int64, error) {
	if fr.fr == nil {
		return 0, ErrClosed
	}
	switch whence {
	case 0:
		fr.offset = offset
	case 1:
		fr.offset += offset
	case 2:
		fr.offset = fr.size + offset
	}
	if fr.offset < 0 {
		fr.offset = 0
	}
	return fr.offset, nil
}

// Errors
var (
	ErrClosed = errors.New("file closed")
)
<|endoftext|>


<commit_before>package notification

import (
	"fmt"
	socialapimodels "socialapi/models"
	"socialapi/workers/notification/models"
	"time"

	"github.com/koding/logging"
	"github.com/koding/rabbitmq"
	"github.com/streadway/amqp"
)

const (
	NOTIFICATION_TYPE_SUBSCRIBE   = "subscribe"
	NOTIFICATION_TYPE_UNSUBSCRIBE = "unsubscribe"
)

type Controller struct {
	log             logging.Logger
	rmqConn         *amqp.Connection
	notifierRmqConn *amqp.Connection
}

func (n *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	n.log.Error("an error occurred: %s", err)
	delivery.Ack(false)

	return false
}

func New(rmq *rabbitmq.RabbitMQ, log logging.Logger) *Controller {
	return &Controller{
		log:     log,
		rmqConn: rmq.Conn(),
	}
}

// CreateReplyNotification notifies main thread owner.
func (n *Controller) CreateReplyNotification(mr *socialapimodels.MessageReply) error {
	// fetch replier
	reply := socialapimodels.NewChannelMessage()
	if err := reply.ById(mr.ReplyId); err != nil {
		return err
	}

	cm := socialapimodels.NewChannelMessage()
	// notify message owner
	if err := cm.ById(mr.MessageId); err != nil {
		return err
	}

	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_POST {
		return nil
	}

	rn := models.NewReplyNotification()
	rn.TargetId = mr.MessageId
	rn.NotifierId = reply.AccountId
	rn.MessageId = reply.Id

	subscribedAt := time.Now()

	nc, err := models.CreateNotificationContent(rn)
	if err != nil {
		return err
	}

	groupChannel, err := reply.FetchParentChannel()
	if err != nil {
		return err
	}

	// if it is not notifier's own message then add replier to subscribers
	// for further reply notifications
	if cm.AccountId != rn.NotifierId {
		n.subscribe(nc.Id, cm.AccountId, subscribedAt, groupChannel)
	}

	notifiedUsers, err := rn.GetNotifiedUsers(nc.Id)
	if err != nil {
		return err
	}

	mentionedUsers, err := n.CreateMentionNotification(reply, cm.Id)
	if err != nil {
		return err
	}

	// if a user is already subscribed to a post, and also mentioned in a reply
	// just send mention notification -no need for reply notification.
	notifiedUsers = filterRepliers(notifiedUsers, mentionedUsers)

	notifierSubscribed := false
	for _, recipient := range notifiedUsers {
		if recipient == rn.NotifierId {
			notifierSubscribed = true
		}
		n.notify(nc.Id, recipient, groupChannel)
	}

	if !notifierSubscribed {
		n.subscribe(nc.Id, rn.NotifierId, subscribedAt, groupChannel)
	}

	return nil
}

// func (n *Controller) UnsubscribeMessage(data *socialapimodels.ChannelMessageList) error {
// 	return subscription(data, NOTIFICATION_TYPE_UNSUBSCRIBE)
// }

//func subscription(cml *socialapimodels.ChannelMessageList, typeConstant string) error {
//    c := socialapimodels.NewChannel()
//    if err := c.ById(cml.ChannelId); err != nil {
//        return err
//    }

//    if c.TypeConstant != socialapimodels.Channel_TYPE_PINNED_ACTIVITY {
//        return nil
//    }

//     user pinned (followed) a message
//    nc := models.NewNotificationContent()
//    nc.TargetId = cml.MessageId

//    n := models.NewNotification()
//    n.AccountId = c.CreatorId

//    switch typeConstant {
//    case NOTIFICATION_TYPE_SUBSCRIBE:
//        return n.Subscribe(nc)
//    case NOTIFICATION_TYPE_UNSUBSCRIBE:
//        return n.Unsubscribe(nc)
//    }

//    return nil
//}

func (n *Controller) HandleMessage(cm *socialapimodels.ChannelMessage) error {
	switch cm.TypeConstant {
	case socialapimodels.ChannelMessage_TYPE_POST:
		_, err := n.CreateMentionNotification(cm, cm.Id)
		return err
	default:
		return nil
	}
}

func (n *Controller) DeleteNotification(cm *socialapimodels.ChannelMessage) error {
	nc := models.NewNotificationContent()
	contentIds, err := nc.FetchIdsByTargetId(cm.Id)
	if err != nil {
		return err
	}

	if len(contentIds) == 0 {
		return nil
	}

	return models.NewNotification().HideByContentIds(contentIds)
}

// CreateMentionNotification creates mention notifications for the related channel messages
func (n *Controller) CreateMentionNotification(reply *socialapimodels.ChannelMessage, targetId int64) ([]int64, error) {
	mentionedUserIds := make([]int64, 0)
	usernames := reply.GetMentionedUsernames()

	// message does not contain any mentioned users
	if len(usernames) == 0 {
		return mentionedUserIds, nil
	}

	mentionedUsers, err := socialapimodels.FetchAccountsByNicks(usernames)
	if err != nil {
		return nil, err
	}

	groupChannel, err := reply.FetchParentChannel()
	if err != nil {
		return nil, err
	}

	for _, mentionedUser := range mentionedUsers {
		// if user mentions herself ignore it
		if mentionedUser.Id == reply.AccountId {
			continue
		}
		mn := models.NewMentionNotification()
		mn.TargetId = targetId
		mn.MessageId = reply.Id
		mn.NotifierId = reply.AccountId
		nc, err := models.CreateNotificationContent(mn)
		if err != nil {
			return nil, err
		}

		n.instantNotify(nc.Id, mentionedUser.Id, groupChannel)

		mentionedUserIds = append(mentionedUserIds, mentionedUser.Id)
	}

	return mentionedUserIds, nil
}

func (n *Controller) notify(contentId, notifierId int64, contextChannel *socialapimodels.Channel) {
	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ContextChannelId = contextChannel.Id
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) instantNotify(contentId, notifierId int64, contextChannel *socialapimodels.Channel) {
	notification := prepareActiveNotification(contentId, notifierId)
	notification.ContextChannelId = contextChannel.Id
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) notifyOnce(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func prepareActiveNotification(contentId, notifierId int64) *models.Notification {
	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ActivatedAt = time.Now()

	return notification
}

func (n *Controller) subscribe(contentId, notifierId int64, subscribedAt time.Time, c *socialapimodels.Channel) {
	notification := buildNotification(contentId, notifierId, subscribedAt)
	notification.SubscribeOnly = true
	notification.ContextChannelId = c.Id
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while subscribing user %d: %s", notification.AccountId, err.Error())
	}
}

func buildNotification(contentId, notifierId int64, subscribedAt time.Time) *models.Notification {
	notification := models.NewNotification()
	notification.NotificationContentId = contentId
	notification.AccountId = notifierId
	notification.SubscribedAt = subscribedAt

	return notification
}

func (n *Controller) CreateInteractionNotification(i *socialapimodels.Interaction) error {
	cm := socialapimodels.NewChannelMessage()
	if err := cm.ById(i.MessageId); err != nil {
		return err
	}

	// user likes her own message, so we bypass notification
	if cm.AccountId == i.AccountId {
		return nil
	}

	in := models.NewInteractionNotification(i.TypeConstant)
	if cm.TypeConstant == socialapimodels.ChannelMessage_TYPE_POST {
		in.TargetId = i.MessageId
	} else {
		mr := socialapimodels.NewMessageReply()
		mr.ReplyId = i.MessageId

		cm, err := mr.FetchParent()
		if err != nil {
			return err
		}

		in.TargetId = cm.Id
	}

	in.MessageId = i.MessageId
	in.NotifierId = i.AccountId
	nc, err := models.CreateNotificationContent(in)
	if err != nil {
		return err
	}

	groupChannel, err := cm.FetchParentChannel()
	if err != nil {
		return err
	}

	notification := models.NewNotification()
	notification.NotificationContentId = nc.Id
	notification.AccountId = cm.AccountId // notify message owner
	notification.ActivatedAt = time.Now() // enables notification immediately
	notification.ContextChannelId = groupChannel.Id
	if err = notification.Upsert(); err != nil {
		return fmt.Errorf("An error occurred while notifying user %d: %s", cm.AccountId, err.Error())
	}

	return nil
}

func filterRepliers(repliers, mentionedUsers []int64) []int64 {
	mentionMap := map[int64]struct{}{}
	flattened := make([]int64, 0)
	if len(mentionedUsers) == 0 {
		return repliers
	}

	for _, user := range mentionedUsers {
		mentionMap[user] = struct{}{}
	}

	for _, replier := range repliers {
		if _, ok := mentionMap[replier]; !ok {
			flattened = append(flattened, replier)
		}
	}

	return flattened
}
<commit_msg>notification: do not notify users when they are not participants of the channel<commit_after>package notification

import (
	"fmt"
	socialapimodels "socialapi/models"
	"socialapi/workers/notification/models"
	"time"

	"github.com/koding/logging"
	"github.com/koding/rabbitmq"
	"github.com/streadway/amqp"
)

const (
	NOTIFICATION_TYPE_SUBSCRIBE   = "subscribe"
	NOTIFICATION_TYPE_UNSUBSCRIBE = "unsubscribe"
)

type Controller struct {
	log             logging.Logger
	rmqConn         *amqp.Connection
	notifierRmqConn *amqp.Connection
}

func (n *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	n.log.Error("an error occurred: %s", err)
	delivery.Ack(false)

	return false
}

func New(rmq *rabbitmq.RabbitMQ, log logging.Logger) *Controller {
	return &Controller{
		log:     log,
		rmqConn: rmq.Conn(),
	}
}

// CreateReplyNotification notifies main thread owner.
func (n *Controller) CreateReplyNotification(mr *socialapimodels.MessageReply) error {
	// fetch replier
	reply := socialapimodels.NewChannelMessage()
	if err := reply.ById(mr.ReplyId); err != nil {
		return err
	}

	cm := socialapimodels.NewChannelMessage()
	// notify message owner
	if err := cm.ById(mr.MessageId); err != nil {
		return err
	}

	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_POST {
		return nil
	}

	rn := models.NewReplyNotification()
	rn.TargetId = mr.MessageId
	rn.NotifierId = reply.AccountId
	rn.MessageId = reply.Id

	subscribedAt := time.Now()

	nc, err := models.CreateNotificationContent(rn)
	if err != nil {
		return err
	}

	groupChannel, err := reply.FetchParentChannel()
	if err != nil {
		return err
	}

	// if it is not notifier's own message then add replier to subscribers
	// for further reply notifications
	if cm.AccountId != rn.NotifierId {
		n.subscribe(nc.Id, cm.AccountId, subscribedAt, groupChannel)
	}

	notifiedUsers, err := rn.GetNotifiedUsers(nc.Id)
	if err != nil {
		return err
	}

	mentionedUsers, err := n.CreateMentionNotification(reply, cm.Id)
	if err != nil {
		return err
	}

	// if a user is already subscribed to a post, and also mentioned in a reply
	// just send mention notification -no need for reply notification.
	notifiedUsers = filterRepliers(notifiedUsers, mentionedUsers)

	notifierSubscribed := false
	for _, recipient := range notifiedUsers {
		if recipient == rn.NotifierId {
			notifierSubscribed = true
		}
		n.notify(nc.Id, recipient, groupChannel)
	}

	if !notifierSubscribed {
		n.subscribe(nc.Id, rn.NotifierId, subscribedAt, groupChannel)
	}

	return nil
}

// func (n *Controller) UnsubscribeMessage(data *socialapimodels.ChannelMessageList) error {
// 	return subscription(data, NOTIFICATION_TYPE_UNSUBSCRIBE)
// }

//func subscription(cml *socialapimodels.ChannelMessageList, typeConstant string) error {
//    c := socialapimodels.NewChannel()
//    if err := c.ById(cml.ChannelId); err != nil {
//        return err
//    }

//    if c.TypeConstant != socialapimodels.Channel_TYPE_PINNED_ACTIVITY {
//        return nil
//    }

//     user pinned (followed) a message
//    nc := models.NewNotificationContent()
//    nc.TargetId = cml.MessageId

//    n := models.NewNotification()
//    n.AccountId = c.CreatorId

//    switch typeConstant {
//    case NOTIFICATION_TYPE_SUBSCRIBE:
//        return n.Subscribe(nc)
//    case NOTIFICATION_TYPE_UNSUBSCRIBE:
//        return n.Unsubscribe(nc)
//    }

//    return nil
//}

func (n *Controller) HandleMessage(cm *socialapimodels.ChannelMessage) error {
	switch cm.TypeConstant {
	case socialapimodels.ChannelMessage_TYPE_POST:
		_, err := n.CreateMentionNotification(cm, cm.Id)
		return err
	default:
		return nil
	}
}

func (n *Controller) DeleteNotification(cm *socialapimodels.ChannelMessage) error {
	nc := models.NewNotificationContent()
	contentIds, err := nc.FetchIdsByTargetId(cm.Id)
	if err != nil {
		return err
	}

	if len(contentIds) == 0 {
		return nil
	}

	return models.NewNotification().HideByContentIds(contentIds)
}

// CreateMentionNotification creates mention notifications for the related channel messages
func (n *Controller) CreateMentionNotification(reply *socialapimodels.ChannelMessage, targetId int64) ([]int64, error) {
	mentionedUserIds := make([]int64, 0)
	usernames := reply.GetMentionedUsernames()

	// message does not contain any mentioned users
	if len(usernames) == 0 {
		return mentionedUserIds, nil
	}

	mentionedUsers, err := socialapimodels.FetchAccountsByNicks(usernames)
	if err != nil {
		return nil, err
	}

	groupChannel, err := reply.FetchParentChannel()
	if err != nil {
		return nil, err
	}

	for _, mentionedUser := range mentionedUsers {
		// if user mentions herself ignore it
		if mentionedUser.Id == reply.AccountId {
			continue
		}
		mn := models.NewMentionNotification()
		mn.TargetId = targetId
		mn.MessageId = reply.Id
		mn.NotifierId = reply.AccountId
		nc, err := models.CreateNotificationContent(mn)
		if err != nil {
			return nil, err
		}

		n.instantNotify(nc.Id, mentionedUser.Id, groupChannel)

		mentionedUserIds = append(mentionedUserIds, mentionedUser.Id)
	}

	return mentionedUserIds, nil
}

func (n *Controller) notify(contentId, notifierId int64, contextChannel *socialapimodels.Channel) {
	isParticipant, err := isParticipant(notifierId, contextChannel)
	if err != nil {
		n.log.Error("Could not check participation info for user %d: %s", notifierId, err)
		return
	}

	// this can be a message of an old participant, and we do not want to send
	// further notifications
	if !isParticipant {
		return
	}

	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ContextChannelId = contextChannel.Id
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) instantNotify(contentId, notifierId int64, contextChannel *socialapimodels.Channel) {
	isParticipant, err := isParticipant(notifierId, contextChannel)
	if err != nil {
		n.log.Error("Could not check participation info for user %d: %s", notifierId, err)
		return
	}

	// when mentioned user does not exist within the group, do not send notification
	if !isParticipant {
		return
	}

	notification := prepareActiveNotification(contentId, notifierId)
	notification.ContextChannelId = contextChannel.Id
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func isParticipant(accountId int64, c *socialapimodels.Channel) (bool, error) {
	cp := socialapimodels.NewChannelParticipant()
	cp.ChannelId = c.Id

	return cp.IsParticipant(accountId)
}

func (n *Controller) notifyOnce(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func prepareActiveNotification(contentId, notifierId int64) *models.Notification {
	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ActivatedAt = time.Now()

	return notification
}

func (n *Controller) subscribe(contentId, notifierId int64, subscribedAt time.Time, c *socialapimodels.Channel) {
	notification := buildNotification(contentId, notifierId, subscribedAt)
	notification.SubscribeOnly = true
	notification.ContextChannelId = c.Id
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while subscribing user %d: %s", notification.AccountId, err.Error())
	}
}

func buildNotification(contentId, notifierId int64, subscribedAt time.Time) *models.Notification {
	notification := models.NewNotification()
	notification.NotificationContentId = contentId
	notification.AccountId = notifierId
	notification.SubscribedAt = subscribedAt

	return notification
}

func (n *Controller) CreateInteractionNotification(i *socialapimodels.Interaction) error {
	cm := socialapimodels.NewChannelMessage()
	if err := cm.ById(i.MessageId); err != nil {
		return err
	}

	// user likes her own message, so we bypass notification
	if cm.AccountId == i.AccountId {
		return nil
	}

	groupChannel, err := cm.FetchParentChannel()
	if err != nil {
		return err
	}

	isParticipant, err := isParticipant(cm.AccountId, groupChannel)
	if err != nil {
		return err
	}

	if !isParticipant {
		return nil
	}

	in := models.NewInteractionNotification(i.TypeConstant)
	if cm.TypeConstant == socialapimodels.ChannelMessage_TYPE_POST {
		in.TargetId = i.MessageId
	} else {
		mr := socialapimodels.NewMessageReply()
		mr.ReplyId = i.MessageId

		cm, err := mr.FetchParent()
		if err != nil {
			return err
		}

		in.TargetId = cm.Id
	}

	in.MessageId = i.MessageId
	in.NotifierId = i.AccountId
	nc, err := models.CreateNotificationContent(in)
	if err != nil {
		return err
	}

	notification := models.NewNotification()
	notification.NotificationContentId = nc.Id
	notification.AccountId = cm.AccountId // notify message owner
	notification.ActivatedAt = time.Now() // enables notification immediately
	notification.ContextChannelId = groupChannel.Id
	if err = notification.Upsert(); err != nil {
		return fmt.Errorf("An error occurred while notifying user %d: %s", cm.AccountId, err.Error())
	}

	return nil
}

func filterRepliers(repliers, mentionedUsers []int64) []int64 {
	mentionMap := map[int64]struct{}{}
	flattened := make([]int64, 0)
	if len(mentionedUsers) == 0 {
		return repliers
	}

	for _, user := range mentionedUsers {
		mentionMap[user] = struct{}{}
	}

	for _, replier := range repliers {
		if _, ok := mentionMap[replier]; !ok {
			flattened = append(flattened, replier)
		}
	}

	return flattened
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"strings"
	"text/template"
)

const headerTemplate = `#ifndef RESPPGEN_H
#define RESPPGEN_H

namespace ResPP
{
const char* R(const char* prefix, const char* path);
}

#endif // RESPPGEN_H
`

const sourceTemplate = `#include "ResPP.h"
#include <map>
#include <string>
{{$len := len .Contents}}
namespace
{
	typedef std::map<std::string, const char*> fileToContent;
	{{range .Contents}}
	fileToContent {{.Prefix | prefixToMapName}} = {
		{{- range .Files}}
		{"{{.Name}}", "{{.EncodedContent}}"},
		{{- end}}
	};
	{{- end}}

	std::map<std::string, const fileToContent* const> prefixToIdx = {
		{{- range .Contents}}
		{"{{.Prefix}}", &{{.Prefix | prefixToMapName}}},
		{{- end}}
	};
}

namespace ResPP
{
const char* R(const char* prefix, const char* path)
{
	auto prefix_it = prefixToIdx.find(prefix);

	if(prefix_it!=prefixToIdx.cend())
	{
		auto m = prefix_it->second;

		auto path_it = m->find(path);

		if(path_it!=m->cend())
		{
			auto encodedContent = path_it->second;
			return encodedContent;
		}
	}

	return nullptr;
}
}
`

func generateCpp(config *configuration) error {
	funcs := template.FuncMap{
		"addOne": func(i int) int {
			return i + 1
		},
		"prefixToMapName": func(prefix string) string {
			return strings.Replace(prefix, "/", "_", -1)
		},
	}

	tmpl, err := template.New("cpp").Funcs(funcs).Parse(sourceTemplate)

	if err != nil {
		return err
	}

	if _, err := os.Stat("cpp"); os.IsNotExist(err) {
		os.Mkdir("cpp", 0755)
	}

	if err != nil {
		return err
	}

	ioutil.WriteFile("cpp/ResPP.h", []byte(headerTemplate), 0644)

	f, err := os.Create("cpp/ResPP.cpp")

	if err != nil {
		return err
	}

	return tmpl.Execute(f, config)
}
<commit_msg>Just fixed typo.<commit_after>package main

import (
	"io/ioutil"
	"os"
	"strings"
	"text/template"
)

const headerTemplate = `#ifndef RESPPGEN_H
#define RESPP_H

namespace ResPP
{
const char* R(const char* prefix, const char* path);
}

#endif // RESPP_H
`

const sourceTemplate = `#include "ResPP.h"
#include <map>
#include <string>
{{$len := len .Contents}}
namespace
{
	typedef std::map<std::string, const char*> fileToContent;
	{{range .Contents}}
	fileToContent {{.Prefix | prefixToMapName}} = {
		{{- range .Files}}
		{"{{.Name}}", "{{.EncodedContent}}"},
		{{- end}}
	};
	{{- end}}

	std::map<std::string, const fileToContent* const> prefixToIdx = {
		{{- range .Contents}}
		{"{{.Prefix}}", &{{.Prefix | prefixToMapName}}},
		{{- end}}
	};
}

namespace ResPP
{
const char* R(const char* prefix, const char* path)
{
	auto prefix_it = prefixToIdx.find(prefix);

	if(prefix_it!=prefixToIdx.cend())
	{
		auto m = prefix_it->second;

		auto path_it = m->find(path);

		if(path_it!=m->cend())
		{
			auto encodedContent = path_it->second;
			return encodedContent;
		}
	}

	return nullptr;
}
}
`

func generateCpp(config *configuration) error {
	funcs := template.FuncMap{
		"addOne": func(i int) int {
			return i + 1
		},
		"prefixToMapName": func(prefix string) string {
			return strings.Replace(prefix, "/", "_", -1)
		},
	}

	tmpl, err := template.New("cpp").Funcs(funcs).Parse(sourceTemplate)

	if err != nil {
		return err
	}

	if _, err := os.Stat("cpp"); os.IsNotExist(err) {
		os.Mkdir("cpp", 0755)
	}

	if err != nil {
		return err
	}

	ioutil.WriteFile("cpp/ResPP.h", []byte(headerTemplate), 0644)

	f, err := os.Create("cpp/ResPP.cpp")

	if err != nil {
		return err
	}

	return tmpl.Execute(f, config)
}
<|endoftext|>


<commit_before><commit_msg>Added stub implementations.<commit_after><|endoftext|>


<commit_before>package main

import (
	"io"
	"os"
)

// These are the environmental variables that determine if we log, and if
// we log whether or not the log should go to a file.
const EnvLog = "TF_LOG"          //Set to True
const EnvLogFile = "TF_LOG_PATH" //Set to a file

// logOutput determines where we should send logs (if anywhere).
func logOutput() (logOutput io.Writer, err error) {
	logOutput = nil
	if os.Getenv(EnvLog) != "" {
		logOutput = os.Stderr

		if logPath := os.Getenv(EnvLogFile); logPath != "" {
			var err error
			logOutput, err = os.Create(logPath)
			if err != nil {
				return nil, err
			}
		}
	}

	return
}
<commit_msg>log: support for user defined log levels<commit_after>package main

import (
	"io"
	"log"
	"os"
	"strings"

	"github.com/hashicorp/logutils"
)

// These are the environmental variables that determine if we log, and if
// we log whether or not the log should go to a file.
const (
	EnvLog     = "TF_LOG"      // Set to True
	EnvLogFile = "TF_LOG_PATH" // Set to a file
)

var validLevels = []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}

// logOutput determines where we should send logs (if anywhere) and the log level.
func logOutput() (logOutput io.Writer, err error) {
	logOutput = nil
	envLevel := os.Getenv(EnvLog)
	if envLevel == "" {
		return
	}

	logOutput = os.Stderr
	if logPath := os.Getenv(EnvLogFile); logPath != "" {
		var err error
		logOutput, err = os.Create(logPath)
		if err != nil {
			return nil, err
		}
	}

	// This was the default since the beginning
	logLevel := logutils.LogLevel("TRACE")

	if isValidLogLevel(envLevel) {
		// allow following for better ux: info, Info or INFO
		logLevel = logutils.LogLevel(strings.ToUpper(envLevel))
	} else {
		log.Printf("[WARN] Invalid log level: %q. Defaulting to level: TRACE. Valid levels are: %+v",
			envLevel, validLevels)
	}

	logOutput = &logutils.LevelFilter{
		Levels:   validLevels,
		MinLevel: logLevel,
		Writer:   logOutput,
	}

	return
}

func isValidLogLevel(level string) bool {
	for _, l := range validLevels {
		if strings.ToUpper(level) == string(l) {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes 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 app

import (
	"regexp"
	"testing"

	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/stretchr/testify/assert"
	fed_v1a1 "k8s.io/kubernetes/federation/apis/federation/v1alpha1"
	"k8s.io/kubernetes/federation/cmd/federated-apiserver/app/options"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

func TestLongRunningRequestRegexp(t *testing.T) {
	regexp := regexp.MustCompile(options.NewAPIServer().LongRunningRequestRE)
	dontMatch := []string{
		"/api/v1/watch-namespace/",
		"/api/v1/namespace-proxy/",
		"/api/v1/namespace-watch",
		"/api/v1/namespace-proxy",
		"/api/v1/namespace-portforward/pods",
		"/api/v1/portforward/pods",
		". anything",
		"/ that",
	}
	doMatch := []string{
		"/api/v1/pods/watch",
		"/api/v1/watch/stuff",
		"/api/v1/default/service/proxy",
		"/api/v1/pods/proxy/path/to/thing",
		"/api/v1/namespaces/myns/pods/mypod/log",
		"/api/v1/namespaces/myns/pods/mypod/logs",
		"/api/v1/namespaces/myns/pods/mypod/portforward",
		"/api/v1/namespaces/myns/pods/mypod/exec",
		"/api/v1/namespaces/myns/pods/mypod/attach",
		"/api/v1/namespaces/myns/pods/mypod/log/",
		"/api/v1/namespaces/myns/pods/mypod/logs/",
		"/api/v1/namespaces/myns/pods/mypod/portforward/",
		"/api/v1/namespaces/myns/pods/mypod/exec/",
		"/api/v1/namespaces/myns/pods/mypod/attach/",
		"/api/v1/watch/namespaces/myns/pods",
	}
	for _, path := range dontMatch {
		if regexp.MatchString(path) {
			t.Errorf("path should not have match regexp but did: %s", path)
		}
	}
	for _, path := range doMatch {
		if !regexp.MatchString(path) {
			t.Errorf("path should have match regexp did not: %s", path)
		}
	}
}

var insecurePort = 8081
var serverIP = fmt.Sprintf("http://localhost:%v", insecurePort)
var groupVersion = fed_v1a1.SchemeGroupVersion

func TestRun(t *testing.T) {
	s := options.NewAPIServer()
	s.InsecurePort = insecurePort
	_, ipNet, _ := net.ParseCIDR("10.10.10.0/24")
	s.ServiceClusterIPRange = *ipNet
	s.StorageConfig.ServerList = []string{"http://localhost:4001"}
	go func() {
		if err := Run(s); err != nil {
			t.Fatalf("Error in bringing up the server: %v", err)
		}
	}()
	if err := waitForApiserverUp(); err != nil {
		t.Fatalf("%v", err)
	}
	testSwaggerSpec(t)
	testSupport(t)
	testAPIGroupList(t)
	testAPIGroup(t)
	testAPIResourceList(t)
}

func waitForApiserverUp() error {
	for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
		_, err := http.Get(serverIP)
		if err == nil {
			return nil
		}
	}
	return fmt.Errorf("waiting for apiserver timed out")
}

func readResponse(serverURL string) ([]byte, error) {
	response, err := http.Get(serverURL)
	if err != nil {
		return nil, fmt.Errorf("Error in fetching %s: %v", serverURL, err)
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status: %d for URL: %s, expected status: %d", response.StatusCode, serverURL, http.StatusOK)
	}
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("Error reading response from %s: %v", serverURL, err)
	}
	return contents, nil
}

func testSwaggerSpec(t *testing.T) {
	serverURL := serverIP + "/swaggerapi"
	_, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
}

func testSupport(t *testing.T) {
	serverURL := serverIP + "/version"
	_, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
}

func findGroup(groups []unversioned.APIGroup, groupName string) *unversioned.APIGroup {
	for _, group := range groups {
		if group.Name == groupName {
			return &group
		}
	}
	return nil
}

func testAPIGroupList(t *testing.T) {
	var groupVersionForDiscovery = unversioned.GroupVersionForDiscovery{
		GroupVersion: groupVersion.String(),
		Version:      groupVersion.Version,
	}

	serverURL := serverIP + "/apis"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiGroupList unversioned.APIGroupList
	err = json.Unmarshal(contents, &apiGroupList)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}

	found := findGroup(apiGroupList.Groups, groupVersion.Group)
	assert.NotNil(t, found)
	assert.Equal(t, found.Name, groupVersion.Group)
	assert.Equal(t, 1, len(found.Versions))
	assert.Equal(t, found.Versions[0], groupVersionForDiscovery)
	assert.Equal(t, found.PreferredVersion, groupVersionForDiscovery)
}

func testAPIGroup(t *testing.T) {
	serverURL := serverIP + "/apis/federation"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiGroup unversioned.APIGroup
	err = json.Unmarshal(contents, &apiGroup)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}
	assert.Equal(t, apiGroup.APIVersion, "v1")
	assert.Equal(t, apiGroup.Name, groupVersion.Group)
	assert.Equal(t, 1, len(apiGroup.Versions))
	assert.Equal(t, apiGroup.Versions[0].GroupVersion, groupVersion.String())
	assert.Equal(t, apiGroup.Versions[0].Version, groupVersion.Version)
	assert.Equal(t, apiGroup.Versions[0], apiGroup.PreferredVersion)
}

func findResource(resources []unversioned.APIResource, resourceName string) *unversioned.APIResource {
	for _, resource := range resources {
		if resource.Name == resourceName {
			return &resource
		}
	}
	return nil
}

func testAPIResourceList(t *testing.T) {
	serverURL := serverIP + "/apis/federation/v1alpha1"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiResourceList unversioned.APIResourceList
	err = json.Unmarshal(contents, &apiResourceList)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}
	assert.Equal(t, apiResourceList.APIVersion, "v1")
	assert.Equal(t, apiResourceList.GroupVersion, groupVersion.String())

	found := findResource(apiResourceList.APIResources, "clusters")
	assert.NotNil(t, found)
	assert.False(t, found.Namespaced)
	found = findResource(apiResourceList.APIResources, "clusters/status")
	assert.NotNil(t, found)
	assert.False(t, found.Namespaced)
}
<commit_msg>change port of tests for federated-apiserver to avoid conflict<commit_after>/*
Copyright 2015 The Kubernetes 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 app

import (
	"regexp"
	"testing"

	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"

	"github.com/stretchr/testify/assert"
	fed_v1a1 "k8s.io/kubernetes/federation/apis/federation/v1alpha1"
	"k8s.io/kubernetes/federation/cmd/federated-apiserver/app/options"
	"k8s.io/kubernetes/pkg/api/unversioned"
)

func TestLongRunningRequestRegexp(t *testing.T) {
	regexp := regexp.MustCompile(options.NewAPIServer().LongRunningRequestRE)
	dontMatch := []string{
		"/api/v1/watch-namespace/",
		"/api/v1/namespace-proxy/",
		"/api/v1/namespace-watch",
		"/api/v1/namespace-proxy",
		"/api/v1/namespace-portforward/pods",
		"/api/v1/portforward/pods",
		". anything",
		"/ that",
	}
	doMatch := []string{
		"/api/v1/pods/watch",
		"/api/v1/watch/stuff",
		"/api/v1/default/service/proxy",
		"/api/v1/pods/proxy/path/to/thing",
		"/api/v1/namespaces/myns/pods/mypod/log",
		"/api/v1/namespaces/myns/pods/mypod/logs",
		"/api/v1/namespaces/myns/pods/mypod/portforward",
		"/api/v1/namespaces/myns/pods/mypod/exec",
		"/api/v1/namespaces/myns/pods/mypod/attach",
		"/api/v1/namespaces/myns/pods/mypod/log/",
		"/api/v1/namespaces/myns/pods/mypod/logs/",
		"/api/v1/namespaces/myns/pods/mypod/portforward/",
		"/api/v1/namespaces/myns/pods/mypod/exec/",
		"/api/v1/namespaces/myns/pods/mypod/attach/",
		"/api/v1/watch/namespaces/myns/pods",
	}
	for _, path := range dontMatch {
		if regexp.MatchString(path) {
			t.Errorf("path should not have match regexp but did: %s", path)
		}
	}
	for _, path := range doMatch {
		if !regexp.MatchString(path) {
			t.Errorf("path should have match regexp did not: %s", path)
		}
	}
}

var insecurePort = 8082
var serverIP = fmt.Sprintf("http://localhost:%v", insecurePort)
var groupVersion = fed_v1a1.SchemeGroupVersion

func TestRun(t *testing.T) {
	s := options.NewAPIServer()
	s.InsecurePort = insecurePort
	_, ipNet, _ := net.ParseCIDR("10.10.10.0/24")
	s.ServiceClusterIPRange = *ipNet
	s.StorageConfig.ServerList = []string{"http://localhost:4001"}
	go func() {
		if err := Run(s); err != nil {
			t.Fatalf("Error in bringing up the server: %v", err)
		}
	}()
	if err := waitForApiserverUp(); err != nil {
		t.Fatalf("%v", err)
	}
	testSwaggerSpec(t)
	testSupport(t)
	testAPIGroupList(t)
	testAPIGroup(t)
	testAPIResourceList(t)
}

func waitForApiserverUp() error {
	for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
		_, err := http.Get(serverIP)
		if err == nil {
			return nil
		}
	}
	return fmt.Errorf("waiting for apiserver timed out")
}

func readResponse(serverURL string) ([]byte, error) {
	response, err := http.Get(serverURL)
	if err != nil {
		return nil, fmt.Errorf("Error in fetching %s: %v", serverURL, err)
	}
	defer response.Body.Close()
	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status: %d for URL: %s, expected status: %d", response.StatusCode, serverURL, http.StatusOK)
	}
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("Error reading response from %s: %v", serverURL, err)
	}
	return contents, nil
}

func testSwaggerSpec(t *testing.T) {
	serverURL := serverIP + "/swaggerapi"
	_, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
}

func testSupport(t *testing.T) {
	serverURL := serverIP + "/version"
	_, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
}

func findGroup(groups []unversioned.APIGroup, groupName string) *unversioned.APIGroup {
	for _, group := range groups {
		if group.Name == groupName {
			return &group
		}
	}
	return nil
}

func testAPIGroupList(t *testing.T) {
	var groupVersionForDiscovery = unversioned.GroupVersionForDiscovery{
		GroupVersion: groupVersion.String(),
		Version:      groupVersion.Version,
	}

	serverURL := serverIP + "/apis"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiGroupList unversioned.APIGroupList
	err = json.Unmarshal(contents, &apiGroupList)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}

	found := findGroup(apiGroupList.Groups, groupVersion.Group)
	assert.NotNil(t, found)
	assert.Equal(t, found.Name, groupVersion.Group)
	assert.Equal(t, 1, len(found.Versions))
	assert.Equal(t, found.Versions[0], groupVersionForDiscovery)
	assert.Equal(t, found.PreferredVersion, groupVersionForDiscovery)
}

func testAPIGroup(t *testing.T) {
	serverURL := serverIP + "/apis/federation"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiGroup unversioned.APIGroup
	err = json.Unmarshal(contents, &apiGroup)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}
	assert.Equal(t, apiGroup.APIVersion, "v1")
	assert.Equal(t, apiGroup.Name, groupVersion.Group)
	assert.Equal(t, 1, len(apiGroup.Versions))
	assert.Equal(t, apiGroup.Versions[0].GroupVersion, groupVersion.String())
	assert.Equal(t, apiGroup.Versions[0].Version, groupVersion.Version)
	assert.Equal(t, apiGroup.Versions[0], apiGroup.PreferredVersion)
}

func findResource(resources []unversioned.APIResource, resourceName string) *unversioned.APIResource {
	for _, resource := range resources {
		if resource.Name == resourceName {
			return &resource
		}
	}
	return nil
}

func testAPIResourceList(t *testing.T) {
	serverURL := serverIP + "/apis/federation/v1alpha1"
	contents, err := readResponse(serverURL)
	if err != nil {
		t.Fatalf("%v", err)
	}
	var apiResourceList unversioned.APIResourceList
	err = json.Unmarshal(contents, &apiResourceList)
	if err != nil {
		t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
	}
	assert.Equal(t, apiResourceList.APIVersion, "v1")
	assert.Equal(t, apiResourceList.GroupVersion, groupVersion.String())

	found := findResource(apiResourceList.APIResources, "clusters")
	assert.NotNil(t, found)
	assert.False(t, found.Namespaced)
	found = findResource(apiResourceList.APIResources, "clusters/status")
	assert.NotNil(t, found)
	assert.False(t, found.Namespaced)
}
<|endoftext|>


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

// +build ignore

// The run program is invoked via "go run" from src/run.bash or
// src/run.bat conditionally builds and runs the cmd/api tool.
//
// TODO(bradfitz): the "conditional" condition is always true.
// We should only do this if the user has the hg codereview extension
// enabled and verifies that the go.tools subrepo is checked out with
// a suitably recently version. In prep for the cmd/api rewrite.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// goToolsVersion is the hg revision of the go.tools subrepo we need
// to build cmd/api.  This only needs to be updated whenever a go/types
// bug fix is needed by the cmd/api tool.
const goToolsVersion = "6698ca2900e2"

var goroot string

func main() {
	log.SetFlags(0)
	goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat}
	if goroot == "" {
		log.Fatal("No $GOROOT set.")
	}
	_, err := exec.LookPath("hg")
	if err != nil {
		fmt.Println("Skipping cmd/api checks; hg not available")
		return
	}

	gopath := prepGoPath()

	cmd := exec.Command("go", "install", "--tags=api_tool", "cmd/api")
	cmd.Env = append([]string{"GOPATH=" + gopath}, filterOut(os.Environ(), "GOARCH")...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		log.Fatalf("Error installing cmd/api: %v\n%s", err, out)
	}

	out, err = exec.Command("go", "tool", "api",
		"-c", file("go1", "go1.1"),
		"-next", file("next"),
		"-except", file("except")).CombinedOutput()
	if err != nil {
		log.Fatalf("Error running API checker: %v\n%s", err, out)
	}
	fmt.Print(string(out))
}

// filterOut returns a copy of the src environment without environment
// variables from remove.
// TODO: delete when issue 6201 is fixed.
func filterOut(src []string, remove ...string) (out []string) {
S:
	for _, s := range src {
		for _, r := range remove {
			if strings.HasPrefix(s, r) && strings.HasPrefix(s, r+"=") {
				continue S
			}
		}
		out = append(out, s)
	}
	return
}

// file expands s to $GOROOT/api/s.txt.
// If there are more than 1, they're comma-separated.
func file(s ...string) string {
	if len(s) > 1 {
		return file(s[0]) + "," + file(s[1:]...)
	}
	return filepath.Join(goroot, "api", s[0]+".txt")
}

// prepGoPath returns a GOPATH for the "go" tool to compile the API tool with.
// It tries to re-use a go.tools checkout from a previous run if possible,
// else it hg clones it.
func prepGoPath() string {
	const tempBase = "go.tools.TMP"

	u, err := user.Current()
	if err != nil {
		log.Fatalf("Error getting current user: %v", err)
	}

	// The GOPATH we'll return
	gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(u.Username), goToolsVersion)

	// cloneDir is where we run "hg clone".
	cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")

	// The dir we clone into. We only atomically rename it to finalDir on
	// clone success.
	tmpDir := filepath.Join(cloneDir, tempBase)

	// finalDir is where the checkout will live once it's complete.
	finalDir := filepath.Join(cloneDir, "go.tools")

	if goToolsCheckoutGood(finalDir) {
		return gopath
	}
	os.RemoveAll(finalDir) // in case it's there but corrupt
	os.RemoveAll(tmpDir)   // in case of aborted hg clone before

	if err := os.MkdirAll(cloneDir, 0700); err != nil {
		log.Fatal(err)
	}
	cmd := exec.Command("hg",
		"clone", "--rev="+goToolsVersion,
		"https://code.google.com/p/go.tools",
		tempBase)
	cmd.Dir = cloneDir
	out, err := cmd.CombinedOutput()
	if err != nil {
		if _, err := http.Head("http://ip.appspot.com/"); err != nil {
			log.Printf("# Skipping API check; network appears to be unavailable")
			os.Exit(0)
		}
		log.Fatalf("Error running hg clone on go.tools: %v\n%s", err, out)
	}
	if err := os.Rename(tmpDir, finalDir); err != nil {
		log.Fatal(err)
	}
	return gopath
}

func cleanUsername(n string) string {
	b := make([]rune, len(n))
	for i, r := range n {
		if r == '\\' || r == '/' || r == ':' {
			b[i] = '_'
		} else {
			b[i] = r
		}
	}
	return string(b)
}

func goToolsCheckoutGood(dir string) bool {
	if _, err := os.Stat(dir); err != nil {
		return false
	}

	cmd := exec.Command("hg", "id", "--id")
	cmd.Dir = dir
	out, err := cmd.Output()
	if err != nil {
		return false
	}
	id := strings.TrimSpace(string(out))
	if id != goToolsVersion {
		return false
	}

	cmd = exec.Command("hg", "status")
	cmd.Dir = dir
	out, err = cmd.Output()
	if err != nil || len(out) > 0 {
		return false
	}

	return true
}
<commit_msg>cmd/api: make it work even when cgo is disabled make use of $USER or %USERNAME% to determine the current user. Fixes issue 6578.<commit_after>// Copyright 2013 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

// The run program is invoked via "go run" from src/run.bash or
// src/run.bat conditionally builds and runs the cmd/api tool.
//
// TODO(bradfitz): the "conditional" condition is always true.
// We should only do this if the user has the hg codereview extension
// enabled and verifies that the go.tools subrepo is checked out with
// a suitably recently version. In prep for the cmd/api rewrite.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// goToolsVersion is the hg revision of the go.tools subrepo we need
// to build cmd/api.  This only needs to be updated whenever a go/types
// bug fix is needed by the cmd/api tool.
const goToolsVersion = "6698ca2900e2"

var goroot string

func main() {
	log.SetFlags(0)
	goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat}
	if goroot == "" {
		log.Fatal("No $GOROOT set.")
	}
	_, err := exec.LookPath("hg")
	if err != nil {
		fmt.Println("Skipping cmd/api checks; hg not available")
		return
	}

	gopath := prepGoPath()

	cmd := exec.Command("go", "install", "--tags=api_tool", "cmd/api")
	cmd.Env = append([]string{"GOPATH=" + gopath}, filterOut(os.Environ(), "GOARCH")...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		log.Fatalf("Error installing cmd/api: %v\n%s", err, out)
	}

	out, err = exec.Command("go", "tool", "api",
		"-c", file("go1", "go1.1"),
		"-next", file("next"),
		"-except", file("except")).CombinedOutput()
	if err != nil {
		log.Fatalf("Error running API checker: %v\n%s", err, out)
	}
	fmt.Print(string(out))
}

// filterOut returns a copy of the src environment without environment
// variables from remove.
// TODO: delete when issue 6201 is fixed.
func filterOut(src []string, remove ...string) (out []string) {
S:
	for _, s := range src {
		for _, r := range remove {
			if strings.HasPrefix(s, r) && strings.HasPrefix(s, r+"=") {
				continue S
			}
		}
		out = append(out, s)
	}
	return
}

// file expands s to $GOROOT/api/s.txt.
// If there are more than 1, they're comma-separated.
func file(s ...string) string {
	if len(s) > 1 {
		return file(s[0]) + "," + file(s[1:]...)
	}
	return filepath.Join(goroot, "api", s[0]+".txt")
}

// prepGoPath returns a GOPATH for the "go" tool to compile the API tool with.
// It tries to re-use a go.tools checkout from a previous run if possible,
// else it hg clones it.
func prepGoPath() string {
	const tempBase = "go.tools.TMP"

	username := ""
	u, err := user.Current()
	if err == nil {
		username = u.Username
	} else {
		// Only need to handle Unix here, as Windows's os/user uses
		// native syscall and should work fine without cgo.
		username = os.Getenv("USER")
		if username == "" {
			log.Fatalf("Error getting current user: %v", err)
		}
	}

	// The GOPATH we'll return
	gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)

	// cloneDir is where we run "hg clone".
	cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")

	// The dir we clone into. We only atomically rename it to finalDir on
	// clone success.
	tmpDir := filepath.Join(cloneDir, tempBase)

	// finalDir is where the checkout will live once it's complete.
	finalDir := filepath.Join(cloneDir, "go.tools")

	if goToolsCheckoutGood(finalDir) {
		return gopath
	}
	os.RemoveAll(finalDir) // in case it's there but corrupt
	os.RemoveAll(tmpDir)   // in case of aborted hg clone before

	if err := os.MkdirAll(cloneDir, 0700); err != nil {
		log.Fatal(err)
	}
	cmd := exec.Command("hg",
		"clone", "--rev="+goToolsVersion,
		"https://code.google.com/p/go.tools",
		tempBase)
	cmd.Dir = cloneDir
	out, err := cmd.CombinedOutput()
	if err != nil {
		if _, err := http.Head("http://ip.appspot.com/"); err != nil {
			log.Printf("# Skipping API check; network appears to be unavailable")
			os.Exit(0)
		}
		log.Fatalf("Error running hg clone on go.tools: %v\n%s", err, out)
	}
	if err := os.Rename(tmpDir, finalDir); err != nil {
		log.Fatal(err)
	}
	return gopath
}

func cleanUsername(n string) string {
	b := make([]rune, len(n))
	for i, r := range n {
		if r == '\\' || r == '/' || r == ':' {
			b[i] = '_'
		} else {
			b[i] = r
		}
	}
	return string(b)
}

func goToolsCheckoutGood(dir string) bool {
	if _, err := os.Stat(dir); err != nil {
		return false
	}

	cmd := exec.Command("hg", "id", "--id")
	cmd.Dir = dir
	out, err := cmd.Output()
	if err != nil {
		return false
	}
	id := strings.TrimSpace(string(out))
	if id != goToolsVersion {
		return false
	}

	cmd = exec.Command("hg", "status")
	cmd.Dir = dir
	out, err = cmd.Output()
	if err != nil || len(out) > 0 {
		return false
	}

	return true
}
<|endoftext|>


<commit_before>// Package dialect handles differences in various
// SQL dialects.
package dialect

import (
	"database/sql"
	"fmt"
	"strings"
)

// Dialect is an interface used to handle differences
// in SQL dialects.
type Dialect interface {
	// Name of the dialect.
	Name() string

	// Quote a table name or column name so that it does
	// not clash with any reserved words. The SQL-99 standard
	// specifies double quotes (eg "table_name"), but many
	// dialects, including MySQL use the backtick (eg `table_name`).
	// SQL server uses square brackets (eg [table_name]).
	Quote(name string) string

	// Return the placeholder for binding a variable value.
	// Most SQL dialects support a single question mark (?), but
	// PostgreSQL uses numbered placeholders (eg $1).
	Placeholder(n int) string
}

// For returns a dialect for the specified database driver.
// If name is blank, then the dialect returned is for the first
// driver returned by sql.Drivers(). If the driver name is
// unknown, the default dialect is returned.
//
// Supported dialects include:
//
//  name      alternative names
//  ----      -----------------
//  mssql
//  mysql
//  postgres  pq, postgresql
//  sqlite3   sqlite
//  ql        ql-mem
func For(name string) Dialect {
	if name == "" {
		drivers := sql.Drivers()
		if len(drivers) > 0 {
			name = drivers[0]
		}
	}
	name = strings.TrimSpace(strings.ToLower(name))

	d := dialects[name]
	if d == nil {
		d = defaultDialect
	}

	return d
}

// dialectT implements the Dialect interface.
type dialectT struct {
	name            string
	altnames        []string
	quoteFunc       func(name string) string
	placeholderFunc func(n int) string
}

func (d *dialectT) Name() string {
	return d.name
}

func (d *dialectT) Quote(name string) string {
	return d.quoteFunc(name)
}

func (d *dialectT) Placeholder(n int) string {
	if d.placeholderFunc == nil {
		return "?"
	}
	return d.placeholderFunc(n)
}

// SQL Dialects for supported database servers.
var (
	dialects       map[string]*dialectT
	defaultDialect *dialectT
)

func init() {
	dialects = make(map[string]*dialectT)
	defaultDialect = &dialectT{name: "default", quoteFunc: quoteFunc(`"`, `"`)}

	for _, d := range []*dialectT{
		&dialectT{
			name:      "mysql",
			quoteFunc: quoteFunc("`", "`"),
		},
		&dialectT{
			name:      "sqlite",
			altnames:  []string{"sqlite3"},
			quoteFunc: quoteFunc("`", "`"),
		},
		&dialectT{
			name:      "mssql",
			quoteFunc: quoteFunc("[", "]"),
		},
		&dialectT{
			name:            "postgres",
			altnames:        []string{"pq", "postgresql"},
			quoteFunc:       quoteFunc(`"`, `"`),
			placeholderFunc: placeholderFunc("$%d"),
		},
		&dialectT{
			name:            "ql",
			altnames:        []string{"ql-mem"},
			quoteFunc:       quoteFunc("", ""),
			placeholderFunc: placeholderFunc("?%d"),
		},
	} {
		dialects[d.name] = d
		for _, altname := range d.altnames {
			dialects[altname] = d
		}
	}
}

func quoteFunc(begin string, end string) func(name string) string {
	return func(name string) string {
		var names []string
		for _, n := range strings.Split(name, ".") {
			n = strings.TrimLeft(n, "\"`[ \t"+begin)
			n = strings.TrimRight(n, "\"`] \t"+end)
			names = append(names, begin+n+end)
		}
		return strings.Join(names, ".")
	}
}

func placeholderFunc(format string) func(n int) string {
	return func(n int) string {
		return fmt.Sprintf(format, n)
	}
}
<commit_msg>Dialect handles not having a quote function.<commit_after>// Package dialect handles differences in various
// SQL dialects.
package dialect

import (
	"database/sql"
	"fmt"
	"strings"
)

// Dialect is an interface used to handle differences
// in SQL dialects.
type Dialect interface {
	// Name of the dialect.
	Name() string

	// Quote a table name or column name so that it does
	// not clash with any reserved words. The SQL-99 standard
	// specifies double quotes (eg "table_name"), but many
	// dialects, including MySQL use the backtick (eg `table_name`).
	// SQL server uses square brackets (eg [table_name]).
	Quote(name string) string

	// Return the placeholder for binding a variable value.
	// Most SQL dialects support a single question mark (?), but
	// PostgreSQL uses numbered placeholders (eg $1).
	Placeholder(n int) string
}

// For returns a dialect for the specified database driver.
// If name is blank, then the dialect returned is for the first
// driver returned by sql.Drivers(). If the driver name is
// unknown, the default dialect is returned.
//
// Supported dialects include:
//
//  name      alternative names
//  ----      -----------------
//  mssql
//  mysql
//  postgres  pq, postgresql
//  sqlite3   sqlite
//  ql        ql-mem
func For(name string) Dialect {
	if name == "" {
		drivers := sql.Drivers()
		if len(drivers) > 0 {
			name = drivers[0]
		}
	}
	name = strings.TrimSpace(strings.ToLower(name))

	d := dialects[name]
	if d == nil {
		d = defaultDialect
	}

	return d
}

// dialectT implements the Dialect interface.
type dialectT struct {
	name            string
	altnames        []string
	quoteFunc       func(name string) string
	placeholderFunc func(n int) string
}

func (d *dialectT) Name() string {
	return d.name
}

func (d *dialectT) Quote(name string) string {
	if d.quoteFunc == nil {
		return name
	}
	return d.quoteFunc(name)
}

func (d *dialectT) Placeholder(n int) string {
	if d.placeholderFunc == nil {
		return "?"
	}
	return d.placeholderFunc(n)
}

// SQL Dialects for supported database servers.
var (
	dialects       map[string]*dialectT
	defaultDialect *dialectT
)

func init() {
	dialects = make(map[string]*dialectT)
	defaultDialect = &dialectT{name: "default", quoteFunc: quoteFunc(`"`, `"`)}

	for _, d := range []*dialectT{
		&dialectT{
			name:      "mysql",
			quoteFunc: quoteFunc("`", "`"),
		},
		&dialectT{
			name:      "sqlite",
			altnames:  []string{"sqlite3"},
			quoteFunc: quoteFunc("`", "`"),
		},
		&dialectT{
			name:      "mssql",
			quoteFunc: quoteFunc("[", "]"),
		},
		&dialectT{
			name:            "postgres",
			altnames:        []string{"pq", "postgresql"},
			quoteFunc:       quoteFunc(`"`, `"`),
			placeholderFunc: placeholderFunc("$%d"),
		},
		&dialectT{
			name:            "ql",
			altnames:        []string{"ql-mem"},
			placeholderFunc: placeholderFunc("?%d"),
		},
	} {
		dialects[d.name] = d
		for _, altname := range d.altnames {
			dialects[altname] = d
		}
	}
}

func quoteFunc(begin string, end string) func(name string) string {
	return func(name string) string {
		var names []string
		for _, n := range strings.Split(name, ".") {
			n = strings.TrimLeft(n, "\"`[ \t"+begin)
			n = strings.TrimRight(n, "\"`] \t"+end)
			names = append(names, begin+n+end)
		}
		return strings.Join(names, ".")
	}
}

func placeholderFunc(format string) func(n int) string {
	return func(n int) string {
		return fmt.Sprintf(format, n)
	}
}
<|endoftext|>