<commit_before>package ungocheck

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

type MultiError []error

func (me MultiError) Err() error {
	if len(me) == 0 {
		return nil
	}
	var s []string
	for _, err := range me {
		s = append(s, err.Error())
	}
	return errors.New(strings.Join(s, "\n"))
}

func (me MultiError) Error() (s string) {
	if err := me.Err(); err != nil {
		s = err.Error()
	}
	return
}

func (me *MultiError) Consume(v ...interface{}) *MultiError {
	for _, v := range v {
		if err, ok := v.(error); ok && err != nil {
			*me = append(*me, err)
		} else if err, ok := v.(MultiError); ok && err != nil && len(err) != 0 {
			for _, err := range err {
				*me = append(*me, err)
			}
		}
	}
	return me
}

type Ungocheck struct {
	FS Filesystem
}

func New() *Ungocheck {
	return &Ungocheck{}
}

func (u Ungocheck) Packages(args []string) (pkgs []string) {
	// TODO(rjeczalik): filter out space-separated values for -test.* flags
	for _, arg := range args {
		if !strings.HasPrefix(arg, "-") {
			pkgs = append(pkgs, arg)
		}
	}
	if len(pkgs) == 0 {
		pkgs = append(pkgs, ".")
	}
	return
}

func istestfile(name string) bool {
	return strings.HasSuffix(name, "_test.go") && !strings.HasSuffix(name, "_ungocheck_test.go")
}

var vcs = map[string]struct{}{
	".bzr": {},
	".git": {},
	".hg":  {},
	".svn": {},
}

func isnotvcs(name string) bool {
	_, ok := vcs[name]
	return !ok
}

func lookup(fs Filesystem, paths []string, pkg string) (dir string, err error) {
	for _, path := range paths {
		dir = filepath.Join(path, "src", pkg)
		if _, err = fs.Stat(dir); err == nil {
			break
		}
	}
	return
}

func (u Ungocheck) Files(pkgs []string) (files []string, err error) {
	var (
		wd, dir string
		f       File
		fi      []os.FileInfo
		fs      = u.fs()
		dirs    = make(map[string]struct{})
		paths   = strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator))
	)
	if wd, err = os.Getwd(); err != nil {
		return
	}
	for _, pkg := range pkgs {
		switch {
		case pkg == ".":
			dirs[wd] = struct{}{}
		case strings.HasSuffix(pkg, "/..."):
			var glob []string
			pkg = pkg[:len(pkg)-4]
			if pkg == "." {
				glob = append(glob, wd)
			} else {
				if dir, err = lookup(fs, paths, pkg); err != nil {
					return
				}
				glob = append(glob, dir)
			}
			for len(glob) > 0 {
				dir, glob = glob[len(glob)-1], glob[:len(glob)-1]
				if f, err = fs.Open(dir); err != nil {
					return
				}
				if fi, err = f.Readdir(0); err != nil {
					f.Close()
					return
				}
				f.Close()
				for _, fi := range fi {
					if fi.IsDir() && isnotvcs(fi.Name()) {
						glob = append(glob, filepath.Join(dir, fi.Name()))
					}
				}
				dirs[dir] = struct{}{}
			}
		default:
			if dir, err = lookup(fs, paths, pkg); err != nil {
				return
			}
			dirs[dir] = struct{}{}
		}
	}
	for dir := range dirs {
		if f, err = fs.Open(dir); err != nil {
			files = nil
			return
		}
		if fi, err = f.Readdir(0); err != nil {
			f.Close()
			files = nil
			return
		}
		f.Close()
		for _, fi := range fi {
			if !fi.IsDir() && istestfile(fi.Name()) {
				files = append(files, filepath.Join(dir, fi.Name()))
			}
		}
	}
	return
}

func (u Ungocheck) Rewrite(files []string) (tests []string, err error) {
	fs := u.fs()
	defer func() {
		if err != nil {
			for _, test := range tests {
				fs.Remove(test)
			}
			tests = nil
		}
	}()
	var n int
	for _, file := range files {
		test := filepath.Base(file)
		test = test[:len(test)-len("_test.go")] + "_ungocheck_test.go"
		test = filepath.Join(filepath.Dir(file), test)
		if n, err = u.rewriteSingle(file, test); err != nil {
			return
		}
		if n == 0 {
			fs.Remove(test)
		} else {
			tests = append(tests, test)
		}
	}
	return
}

var re = regexp.MustCompile(`func \(.*\) Test([\w\d_]+)\(([\w\d_]+) \*C\) {`)

const f = "func Test%s(%s *testing.T) { // ungocheck\n	%s.Parallel() // ungocheck\n"

func (u Ungocheck) rewriteSingle(file, test string) (n int, err error) {
	var (
		fs  = u.fs()
		src File
		dst File
	)
	if src, err = fs.Open(file); err != nil {
		return
	}
	defer src.Close()
	if dst, err = fs.OpenFile(test, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644); err != nil {
		return
	}
	defer dst.Close()
	// TODO(rjeczalik): reimplement with go/ast
	r, w, p := bufio.NewReader(src), bytes.NewBuffer([]byte("// +build ungocheck\n\n")), []byte{}
	for {
		if p, err = r.ReadBytes('\n'); len(p) == 0 {
			if err == io.EOF {
				_, err = io.Copy(dst, bytes.NewReader(w.Bytes()))
				return
			}
			if err != nil {
				return
			}
		}
		if bytes.HasPrefix(p, []byte("package ")) {
			w.Write(p)
			w.WriteString("\nimport \"testing\"\n")
			continue
		}
		if bytes.Contains(p, []byte("// +build")) && bytes.Contains(p, []byte("!ungocheck")) {
			continue
		}
		m := re.FindAllSubmatch(p, 1)
		if m != nil && len(m) == 1 && len(m[0]) == 3 {
			n += 1
			p = []byte(fmt.Sprintf(f, m[0][1], m[0][2], m[0][2]))
		} else if bytes.Contains(p, []byte("c *C")) {
			p = bytes.Replace(p, []byte("c *C"), []byte("c *testing.T"), 1)
		}

		w.Write(p)
	}
	return
}

func (u Ungocheck) Run(args []string) (err error) {
	var (
		tests []string
		me    MultiError
	)
	defer func() {
		err = me.Consume(err).Consume(u.runTest(args, tests)).Err()
	}()
	s := u.Packages(args[1:])
	if s, err = u.Files(s); err != nil {
		return
	}
	tests, err = u.Rewrite(s)
	return
}
func (u Ungocheck) fs() (fs Filesystem) {
	fs = DefaultFilesystem
	if u.FS != nil {
		fs = u.FS
	}
	return
}

func (u Ungocheck) runTest(args, tests []string) error {
	var (
		me  MultiError
		arg = append([]string{"test", "-tags=ungocheck"}, args[1:]...)
	)
	fs := u.fs()
	out, err := exec.Command("go", arg...).CombinedOutput()
	me.Consume(err).Consume(io.Copy(os.Stdout, bytes.NewReader(out)))
	for _, test := range tests {
		me.Consume(fs.Remove(test))
	}
	return me
}
<commit_msg>Fix go get warnings<commit_after>package ungocheck

import (
	"bufio"
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

type MultiError []error

func (me MultiError) Err() error {
	if len(me) == 0 {
		return nil
	}
	var s []string
	for _, err := range me {
		s = append(s, err.Error())
	}
	return errors.New(strings.Join(s, "\n"))
}

func (me MultiError) Error() (s string) {
	if err := me.Err(); err != nil {
		s = err.Error()
	}
	return
}

func (me *MultiError) Consume(v ...interface{}) *MultiError {
	for _, v := range v {
		if err, ok := v.(error); ok && err != nil {
			*me = append(*me, err)
		} else if err, ok := v.(MultiError); ok && err != nil && len(err) != 0 {
			for _, err := range err {
				*me = append(*me, err)
			}
		}
	}
	return me
}

type Ungocheck struct {
	FS Filesystem
}

func New() *Ungocheck {
	return &Ungocheck{}
}

func (u Ungocheck) Packages(args []string) (pkgs []string) {
	// TODO(rjeczalik): filter out space-separated values for -test.* flags
	for _, arg := range args {
		if !strings.HasPrefix(arg, "-") {
			pkgs = append(pkgs, arg)
		}
	}
	if len(pkgs) == 0 {
		pkgs = append(pkgs, ".")
	}
	return
}

func istestfile(name string) bool {
	return strings.HasSuffix(name, "_test.go") && !strings.HasSuffix(name, "_ungocheck_test.go")
}

var vcs = map[string]struct{}{
	".bzr": {},
	".git": {},
	".hg":  {},
	".svn": {},
}

func isnotvcs(name string) bool {
	_, ok := vcs[name]
	return !ok
}

func lookup(fs Filesystem, paths []string, pkg string) (dir string, err error) {
	for _, path := range paths {
		dir = filepath.Join(path, "src", pkg)
		if _, err = fs.Stat(dir); err == nil {
			break
		}
	}
	return
}

func (u Ungocheck) Files(pkgs []string) (files []string, err error) {
	var (
		wd, dir string
		f       File
		fi      []os.FileInfo
		fs      = u.fs()
		dirs    = make(map[string]struct{})
		paths   = strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator))
	)
	if wd, err = os.Getwd(); err != nil {
		return
	}
	for _, pkg := range pkgs {
		switch {
		case pkg == ".":
			dirs[wd] = struct{}{}
		case strings.HasSuffix(pkg, "/..."):
			var glob []string
			pkg = pkg[:len(pkg)-4]
			if pkg == "." {
				glob = append(glob, wd)
			} else {
				if dir, err = lookup(fs, paths, pkg); err != nil {
					return
				}
				glob = append(glob, dir)
			}
			for len(glob) > 0 {
				dir, glob = glob[len(glob)-1], glob[:len(glob)-1]
				if f, err = fs.Open(dir); err != nil {
					return
				}
				if fi, err = f.Readdir(0); err != nil {
					f.Close()
					return
				}
				f.Close()
				for _, fi := range fi {
					if fi.IsDir() && isnotvcs(fi.Name()) {
						glob = append(glob, filepath.Join(dir, fi.Name()))
					}
				}
				dirs[dir] = struct{}{}
			}
		default:
			if dir, err = lookup(fs, paths, pkg); err != nil {
				return
			}
			dirs[dir] = struct{}{}
		}
	}
	for dir := range dirs {
		if f, err = fs.Open(dir); err != nil {
			files = nil
			return
		}
		if fi, err = f.Readdir(0); err != nil {
			f.Close()
			files = nil
			return
		}
		f.Close()
		for _, fi := range fi {
			if !fi.IsDir() && istestfile(fi.Name()) {
				files = append(files, filepath.Join(dir, fi.Name()))
			}
		}
	}
	return
}

func (u Ungocheck) Rewrite(files []string) (tests []string, err error) {
	fs := u.fs()
	defer func() {
		if err != nil {
			for _, test := range tests {
				fs.Remove(test)
			}
			tests = nil
		}
	}()
	var n int
	for _, file := range files {
		test := filepath.Base(file)
		test = test[:len(test)-len("_test.go")] + "_ungocheck_test.go"
		test = filepath.Join(filepath.Dir(file), test)
		if n, err = u.rewriteSingle(file, test); err != nil {
			return
		}
		if n == 0 {
			fs.Remove(test)
		} else {
			tests = append(tests, test)
		}
	}
	return
}

var re = regexp.MustCompile(`func \(.*\) Test([\w\d_]+)\(([\w\d_]+) \*C\) {`)

const f = "func Test%s(%s *testing.T) { // ungocheck\n	%s.Parallel() // ungocheck\n"

func (u Ungocheck) rewriteSingle(file, test string) (n int, err error) {
	var (
		fs  = u.fs()
		src File
		dst File
	)
	if src, err = fs.Open(file); err != nil {
		return
	}
	defer src.Close()
	if dst, err = fs.OpenFile(test, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644); err != nil {
		return
	}
	defer dst.Close()
	// TODO(rjeczalik): reimplement with go/ast
	r, w, p := bufio.NewReader(src), bytes.NewBuffer([]byte("// +build ungocheck\n\n")), []byte{}
	for {
		if p, err = r.ReadBytes('\n'); len(p) == 0 {
			if err == io.EOF {
				_, err = io.Copy(dst, bytes.NewReader(w.Bytes()))
				return
			}
			if err != nil {
				return
			}
		}
		if bytes.HasPrefix(p, []byte("package ")) {
			w.Write(p)
			w.WriteString("\nimport \"testing\"\n")
			continue
		}
		if bytes.Contains(p, []byte("// +build")) && bytes.Contains(p, []byte("!ungocheck")) {
			continue
		}
		m := re.FindAllSubmatch(p, 1)
		if m != nil && len(m) == 1 && len(m[0]) == 3 {
			n += 1
			p = []byte(fmt.Sprintf(f, m[0][1], m[0][2], m[0][2]))
		} else if bytes.Contains(p, []byte("c *C")) {
			p = bytes.Replace(p, []byte("c *C"), []byte("c *testing.T"), 1)
		}

		w.Write(p)
	}
}

func (u Ungocheck) Run(args []string) (err error) {
	var (
		tests []string
		me    MultiError
	)
	defer func() {
		err = me.Consume(err).Consume(u.runTest(args, tests)).Err()
	}()
	s := u.Packages(args[1:])
	if s, err = u.Files(s); err != nil {
		return
	}
	tests, err = u.Rewrite(s)
	return
}
func (u Ungocheck) fs() (fs Filesystem) {
	fs = DefaultFilesystem
	if u.FS != nil {
		fs = u.FS
	}
	return
}

func (u Ungocheck) runTest(args, tests []string) error {
	var (
		me  MultiError
		arg = append([]string{"test", "-tags=ungocheck"}, args[1:]...)
	)
	fs := u.fs()
	out, err := exec.Command("go", arg...).CombinedOutput()
	me.Consume(err).Consume(io.Copy(os.Stdout, bytes.NewReader(out)))
	for _, test := range tests {
		me.Consume(fs.Remove(test))
	}
	return me
}
<|endoftext|>


<commit_before>package client

import (
	"errors"
	"fmt"
	"os"

	"golang.org/x/net/context"

	"google.golang.org/grpc"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pps"

	google_protobuf "go.pedge.io/pb/go/google/protobuf"
)

// PfsAPIClient is an alias for pfs.APIClient.
type PfsAPIClient pfs.APIClient

// PpsAPIClient is an alias for pps.APIClient.
type PpsAPIClient pps.APIClient

// BlockAPIClient is an alias for pfs.BlockAPIClient.
type BlockAPIClient pfs.BlockAPIClient

// An APIClient is a wrapper around pfs, pps and block APIClients.
type APIClient struct {
	PfsAPIClient
	PpsAPIClient
	BlockAPIClient
}

// NewFromAddress constructs a new APIClient for the server at pachAddr.
func NewFromAddress(pachAddr string) (*APIClient, error) {
	clientConn, err := grpc.Dial(pachAddr, grpc.WithInsecure())
	if err != nil {
		return nil, err
	}

	return &APIClient{
		pfs.NewAPIClient(clientConn),
		pps.NewAPIClient(clientConn),
		pfs.NewBlockAPIClient(clientConn),
	}, nil
}

// NewInCluster constructs a new APIClient using env vars that Kubernetes creates.
// This should be used to access Pachyderm from within a Kubernetes cluster
// with Pachyderm running on it.
func NewInCluster() (*APIClient, error) {
	pachAddr := os.Getenv("PACHD_PORT_650_TCP_ADDR")

	if pachAddr == "" {
		return nil, fmt.Errorf("PACHD_PORT_650_TCP_ADDR not set")
	}

	return NewFromAddress(fmt.Sprintf("%v:650", pachAddr))
}

// DeleteAll deletes everything in the cluster.
// Use with caution, there is no undo.
func (c APIClient) DeleteAll() error {
	if _, err := c.PpsAPIClient.DeleteAll(
		context.Background(),
		google_protobuf.EmptyInstance,
	); err != nil {
		return sanitizeErr(err)
	}
	if _, err := c.PfsAPIClient.DeleteAll(
		context.Background(),
		google_protobuf.EmptyInstance,
	); err != nil {
		return sanitizeErr(err)
	}
	return nil
}

func sanitizeErr(err error) error {
	if err == nil {
		return nil
	}

	return errors.New(grpc.ErrorDesc(err))
}
<commit_msg>Add gRPC connection as property of the ApiClient struct so it can be closed at a later time<commit_after>package client

import (
	"errors"
	"fmt"
	"os"

	"golang.org/x/net/context"

	"google.golang.org/grpc"

	"github.com/pachyderm/pachyderm/src/client/pfs"
	"github.com/pachyderm/pachyderm/src/client/pps"

	google_protobuf "go.pedge.io/pb/go/google/protobuf"
)

// PfsAPIClient is an alias for pfs.APIClient.
type PfsAPIClient pfs.APIClient

// PpsAPIClient is an alias for pps.APIClient.
type PpsAPIClient pps.APIClient

// BlockAPIClient is an alias for pfs.BlockAPIClient.
type BlockAPIClient pfs.BlockAPIClient

// An APIClient is a wrapper around pfs, pps and block APIClients.
type APIClient struct {
	PfsAPIClient
	PpsAPIClient
	BlockAPIClient
	GRPCConn *grpc.ClientConn
}

// NewFromAddress constructs a new APIClient for the server at pachAddr.
func NewFromAddress(pachAddr string) (*APIClient, error) {
	clientConn, err := grpc.Dial(pachAddr, grpc.WithInsecure())
	if err != nil {
		return nil, err
	}

	return &APIClient{
		pfs.NewAPIClient(clientConn),
		pps.NewAPIClient(clientConn),
		pfs.NewBlockAPIClient(clientConn),
		clientConn,
	}, nil
}

// NewInCluster constructs a new APIClient using env vars that Kubernetes creates.
// This should be used to access Pachyderm from within a Kubernetes cluster
// with Pachyderm running on it.
func NewInCluster() (*APIClient, error) {
	pachAddr := os.Getenv("PACHD_PORT_650_TCP_ADDR")

	if pachAddr == "" {
		return nil, fmt.Errorf("PACHD_PORT_650_TCP_ADDR not set")
	}

	return NewFromAddress(fmt.Sprintf("%v:650", pachAddr))
}

// Close the connection to gRPC
func (c *APIClient) Close() error {
	return c.GRPCConn.Close()
}

// DeleteAll deletes everything in the cluster.
// Use with caution, there is no undo.
func (c APIClient) DeleteAll() error {
	if _, err := c.PpsAPIClient.DeleteAll(
		context.Background(),
		google_protobuf.EmptyInstance,
	); err != nil {
		return sanitizeErr(err)
	}
	if _, err := c.PfsAPIClient.DeleteAll(
		context.Background(),
		google_protobuf.EmptyInstance,
	); err != nil {
		return sanitizeErr(err)
	}
	return nil
}

func sanitizeErr(err error) error {
	if err == nil {
		return nil
	}

	return errors.New(grpc.ErrorDesc(err))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"regexp"
)

var fileRoute = regexp.MustCompile("^/files/([^/]+)$")

func serveHttp() error {
	http.HandleFunc("/", route)

	addr := ":1080"
	log.Printf("serving clients at %s", addr)

	return http.ListenAndServe(addr, nil)
}

func route(w http.ResponseWriter, r *http.Request) {
	log.Printf("request: %s %s", r.Method, r.URL.RequestURI())

	w.Header().Set("Server", "tusd")

	if r.Method == "POST" && r.URL.Path == "/files" {
		postFiles(w, r)
	} else if match := fileRoute.FindStringSubmatch(r.URL.Path); match != nil {
		id := match[1]
		// WIP
		switch r.Method {
		case "HEAD":
			headFile(w, r, id)
		case "GET":
			reply(w, http.StatusNotImplemented, "File download")
		case "PUT":
			putFile(w, r, id)
		default:
			reply(w, http.StatusMethodNotAllowed, "Invalid http method")
		}
	} else {
		reply(w, http.StatusNotFound, "No matching route")
	}
}

func reply(w http.ResponseWriter, code int, message string) {
	w.WriteHeader(code)
	fmt.Fprintf(w, "%d - %s: %s\n", code, http.StatusText(code), message)
}

func postFiles(w http.ResponseWriter, r *http.Request) {
	contentRange, err := parseContentRange(r.Header.Get("Content-Range"))
	if err != nil {
		reply(w, http.StatusBadRequest, err.Error())
		return
	}

	if contentRange.Size == -1 {
		reply(w, http.StatusBadRequest, "Content-Range must indicate total file size.")
		return
	}

	if contentRange.End != -1 {
		reply(w, http.StatusNotImplemented, "File data in initial request.")
		return
	}

	contentType := r.Header.Get("Content-Type")
	if contentType == "" {
		contentType = "application/octet-stream"
	}

	id := uid()
	if err := initFile(id, contentRange.Size, contentType); err != nil {
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	// @TODO: Return X-Missing header

	w.Header().Set("Location", "/files/"+id)
	w.WriteHeader(http.StatusCreated)
}

func putFile(w http.ResponseWriter, r *http.Request, fileId string) {
	contentRange, err := parseContentRange(r.Header.Get("Content-Range"))
	if err != nil {
		reply(w, http.StatusBadRequest, err.Error())
		return
	}

	// @TODO: Check that file exists
	// @TODO: Make sure contentRange.Size matches file size

	if err := putFileChunk(fileId, contentRange.Start, contentRange.End, r.Body); err != nil {
		// @TODO: Could be a 404 as well
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	setFileRangeHeader(w, fileId)
}

func headFile(w http.ResponseWriter, r *http.Request, fileId string) {
	setFileRangeHeader(w, fileId)
}

func setFileRangeHeader(w http.ResponseWriter, fileId string) {
	chunks, err := getReceivedChunks(fileId)
	if err != nil {
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	received := ""
	for i, chunk := range chunks {
		received += fmt.Sprintf("%d-%d", chunk.Start, chunk.End)
		if i + 1 < len(chunks) {
			received += ","
		}
	}

	if received != "" {
		w.Header().Set("Range", "bytes="+received)
	}
}
<commit_msg>remove unused line<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"regexp"
)

var fileRoute = regexp.MustCompile("^/files/([^/]+)$")

func serveHttp() error {
	http.HandleFunc("/", route)

	addr := ":1080"
	log.Printf("serving clients at %s", addr)

	return http.ListenAndServe(addr, nil)
}

func route(w http.ResponseWriter, r *http.Request) {
	log.Printf("request: %s %s", r.Method, r.URL.RequestURI())

	w.Header().Set("Server", "tusd")

	if r.Method == "POST" && r.URL.Path == "/files" {
		postFiles(w, r)
	} else if match := fileRoute.FindStringSubmatch(r.URL.Path); match != nil {
		id := match[1]
		// WIP
		switch r.Method {
		case "HEAD":
			headFile(w, r, id)
		case "GET":
			reply(w, http.StatusNotImplemented, "File download")
		case "PUT":
			putFile(w, r, id)
		default:
			reply(w, http.StatusMethodNotAllowed, "Invalid http method")
		}
	} else {
		reply(w, http.StatusNotFound, "No matching route")
	}
}

func reply(w http.ResponseWriter, code int, message string) {
	w.WriteHeader(code)
	fmt.Fprintf(w, "%d - %s: %s\n", code, http.StatusText(code), message)
}

func postFiles(w http.ResponseWriter, r *http.Request) {
	contentRange, err := parseContentRange(r.Header.Get("Content-Range"))
	if err != nil {
		reply(w, http.StatusBadRequest, err.Error())
		return
	}

	if contentRange.Size == -1 {
		reply(w, http.StatusBadRequest, "Content-Range must indicate total file size.")
		return
	}

	if contentRange.End != -1 {
		reply(w, http.StatusNotImplemented, "File data in initial request.")
		return
	}

	contentType := r.Header.Get("Content-Type")
	if contentType == "" {
		contentType = "application/octet-stream"
	}

	id := uid()
	if err := initFile(id, contentRange.Size, contentType); err != nil {
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	// @TODO: Return X-Missing header

	w.Header().Set("Location", "/files/"+id)
	w.WriteHeader(http.StatusCreated)
}

func putFile(w http.ResponseWriter, r *http.Request, fileId string) {
	contentRange, err := parseContentRange(r.Header.Get("Content-Range"))
	if err != nil {
		reply(w, http.StatusBadRequest, err.Error())
		return
	}

	// @TODO: Check that file exists
	// @TODO: Make sure contentRange.Size matches file size

	if err := putFileChunk(fileId, contentRange.Start, contentRange.End, r.Body); err != nil {
		// @TODO: Could be a 404 as well
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	setFileRangeHeader(w, fileId)
}

func headFile(w http.ResponseWriter, r *http.Request, fileId string) {
	setFileRangeHeader(w, fileId)
}

func setFileRangeHeader(w http.ResponseWriter, fileId string) {
	chunks, err := getReceivedChunks(fileId)
	if err != nil {
		reply(w, http.StatusInternalServerError, err.Error())
		return
	}

	received := ""
	for i, chunk := range chunks {
		received += fmt.Sprintf("%d-%d", chunk.Start, chunk.End)
		if i+1 < len(chunks) {
			received += ","
		}
	}

	if received != "" {
		w.Header().Set("Range", "bytes="+received)
	}
}
<|endoftext|>


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

// This file contains the printf-checker.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/token"
	"strings"
	"unicode/utf8"
)

var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")

// printfList records the formatted-print functions. The value is the location
// of the format parameter. Names are lower-cased so the lookup is
// case insensitive.
var printfList = map[string]int{
	"errorf":  0,
	"fatalf":  0,
	"fprintf": 1,
	"panicf":  0,
	"printf":  0,
	"sprintf": 0,
}

// printList records the unformatted-print functions. The value is the location
// of the first parameter to be printed.  Names are lower-cased so the lookup is
// case insensitive.
var printList = map[string]int{
	"error":  0,
	"fatal":  0,
	"fprint": 1, "fprintln": 1,
	"panic": 0, "panicln": 0,
	"print": 0, "println": 0,
	"sprint": 0, "sprintln": 0,
}

// checkCall triggers the print-specific checks if the call invokes a print function.
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
	name := strings.ToLower(Name)
	if skip, ok := printfList[name]; ok {
		f.checkPrintf(call, Name, skip)
		return
	}
	if skip, ok := printList[name]; ok {
		f.checkPrint(call, Name, skip)
		return
	}
}

// checkPrintf checks a call to a formatted print routine such as Printf.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is (well, should be) the format argument.
func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
	if len(call.Args) <= skip {
		return
	}
	// Common case: literal is first argument.
	arg := call.Args[skip]
	lit, ok := arg.(*ast.BasicLit)
	if !ok {
		// Too hard to check.
		if *verbose {
			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
		}
		return
	}
	if lit.Kind == token.STRING {
		if !strings.Contains(lit.Value, "%") {
			if len(call.Args) > skip+1 {
				f.Badf(call.Pos(), "no formatting directive in %s call", name)
			}
			return
		}
	}
	// Hard part: check formats against args.
	// Trivial but useful test: count.
	numArgs := 0
	for i, w := 0, 0; i < len(lit.Value); i += w {
		w = 1
		if lit.Value[i] == '%' {
			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
			w = nbytes
			numArgs += nargs
		}
	}
	expect := len(call.Args) - (skip + 1)
	if numArgs != expect {
		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
	}
}

// parsePrintfVerb returns the number of bytes and number of arguments
// consumed by the Printf directive that begins s, including its percent sign
// and verb.
func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
	// There's guaranteed a percent sign.
	flags := make([]byte, 0, 5)
	nbytes = 1
	end := len(s)
	// There may be flags.
FlagLoop:
	for nbytes < end {
		switch s[nbytes] {
		case '#', '0', '+', '-', ' ':
			flags = append(flags, s[nbytes])
			nbytes++
		default:
			break FlagLoop
		}
	}
	getNum := func() {
		if nbytes < end && s[nbytes] == '*' {
			nbytes++
			nargs++
		} else {
			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
				nbytes++
			}
		}
	}
	// There may be a width.
	getNum()
	// If there's a period, there may be a precision.
	if nbytes < end && s[nbytes] == '.' {
		flags = append(flags, '.') // Treat precision as a flag.
		nbytes++
		getNum()
	}
	// Now a verb.
	c, w := utf8.DecodeRuneInString(s[nbytes:])
	nbytes += w
	if c != '%' {
		nargs++
		f.checkPrintfVerb(call, c, flags)
	}
	return
}

type printVerb struct {
	verb  rune
	flags string // known flags are all ASCII
}

// Common flag sets for printf verbs.
const (
	numFlag      = " -+.0"
	sharpNumFlag = " -+.0#"
	allFlags     = " -+.0#"
)

// printVerbs identifies which flags are known to printf for each verb.
// TODO: A type that implements Formatter may do what it wants, and vet
// will complain incorrectly.
var printVerbs = []printVerb{
	// '-' is a width modifier, always valid.
	// '.' is a precision for float, max width for strings.
	// '+' is required sign for numbers, Go format for %v.
	// '#' is alternate format for several verbs.
	// ' ' is spacer for numbers
	{'b', numFlag},
	{'c', "-"},
	{'d', numFlag},
	{'e', "-."},
	{'E', numFlag},
	{'f', numFlag},
	{'F', numFlag},
	{'g', numFlag},
	{'G', numFlag},
	{'o', sharpNumFlag},
	{'p', "-#"},
	{'q', "-+#."},
	{'s', "-."},
	{'t', "-"},
	{'T', "-"},
	{'U', "-#"},
	{'v', allFlags},
	{'x', sharpNumFlag},
	{'X', sharpNumFlag},
}

const printfVerbs = "bcdeEfFgGopqstTvxUX"

func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
	// Linear scan is fast enough for a small list.
	for _, v := range printVerbs {
		if v.verb == verb {
			for _, flag := range flags {
				if !strings.ContainsRune(v.flags, rune(flag)) {
					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
				}
			}
			return
		}
	}
	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}

// checkPrint checks a call to an unformatted print routine such as Println.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
	isLn := strings.HasSuffix(name, "ln")
	isF := strings.HasPrefix(name, "F")
	args := call.Args
	// check for Println(os.Stderr, ...)
	if skip == 0 && !isF && len(args) > 0 {
		if sel, ok := args[0].(*ast.SelectorExpr); ok {
			if x, ok := sel.X.(*ast.Ident); ok {
				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
					f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
				}
			}
		}
	}
	if len(args) <= skip {
		if *verbose && !isLn {
			f.Badf(call.Pos(), "no args in %s call", name)
		}
		return
	}
	arg := args[skip]
	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
		if strings.Contains(lit.Value, "%") {
			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
		}
	}
	if isLn {
		// The last item, if a string, should not have a newline.
		arg = args[len(call.Args)-1]
		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
			if strings.HasSuffix(lit.Value, `\n"`) {
				f.Badf(call.Pos(), "%s call ends with newline", name)
			}
		}
	}
}

// This function never executes, but it serves as a simple test for the program.
// Test with make test.
func BadFunctionUsedInTests() {
	fmt.Println()                      // not an error
	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
	fmt.Printf("%s%%%d", "hi", 3)      // correct
	fmt.Printf("%.*d", 3, 3)           // correct
	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
	printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("hi")                       // ok
	f := new(File)
	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
}

type BadTypeUsedInTests struct {
	X int "hello" // ERROR "struct field tag"
}

func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
}

type BadInterfaceUsedInTests interface {
	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
}

// printf is used by the test.
func printf(format string, args ...interface{}) {
	panic("don't call - testing only")
}
<commit_msg>cmd/vet: don't give error for Printf("%+5.2e", x)<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains the printf-checker.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/token"
	"strings"
	"unicode/utf8"
)

var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")

// printfList records the formatted-print functions. The value is the location
// of the format parameter. Names are lower-cased so the lookup is
// case insensitive.
var printfList = map[string]int{
	"errorf":  0,
	"fatalf":  0,
	"fprintf": 1,
	"panicf":  0,
	"printf":  0,
	"sprintf": 0,
}

// printList records the unformatted-print functions. The value is the location
// of the first parameter to be printed.  Names are lower-cased so the lookup is
// case insensitive.
var printList = map[string]int{
	"error":  0,
	"fatal":  0,
	"fprint": 1, "fprintln": 1,
	"panic": 0, "panicln": 0,
	"print": 0, "println": 0,
	"sprint": 0, "sprintln": 0,
}

// checkCall triggers the print-specific checks if the call invokes a print function.
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
	name := strings.ToLower(Name)
	if skip, ok := printfList[name]; ok {
		f.checkPrintf(call, Name, skip)
		return
	}
	if skip, ok := printList[name]; ok {
		f.checkPrint(call, Name, skip)
		return
	}
}

// checkPrintf checks a call to a formatted print routine such as Printf.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is (well, should be) the format argument.
func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) {
	if len(call.Args) <= skip {
		return
	}
	// Common case: literal is first argument.
	arg := call.Args[skip]
	lit, ok := arg.(*ast.BasicLit)
	if !ok {
		// Too hard to check.
		if *verbose {
			f.Warn(call.Pos(), "can't check non-literal format in call to", name)
		}
		return
	}
	if lit.Kind == token.STRING {
		if !strings.Contains(lit.Value, "%") {
			if len(call.Args) > skip+1 {
				f.Badf(call.Pos(), "no formatting directive in %s call", name)
			}
			return
		}
	}
	// Hard part: check formats against args.
	// Trivial but useful test: count.
	numArgs := 0
	for i, w := 0, 0; i < len(lit.Value); i += w {
		w = 1
		if lit.Value[i] == '%' {
			nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
			w = nbytes
			numArgs += nargs
		}
	}
	expect := len(call.Args) - (skip + 1)
	if numArgs != expect {
		f.Badf(call.Pos(), "wrong number of args in %s call: %d needed but %d args", name, numArgs, expect)
	}
}

// parsePrintfVerb returns the number of bytes and number of arguments
// consumed by the Printf directive that begins s, including its percent sign
// and verb.
func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
	// There's guaranteed a percent sign.
	flags := make([]byte, 0, 5)
	nbytes = 1
	end := len(s)
	// There may be flags.
FlagLoop:
	for nbytes < end {
		switch s[nbytes] {
		case '#', '0', '+', '-', ' ':
			flags = append(flags, s[nbytes])
			nbytes++
		default:
			break FlagLoop
		}
	}
	getNum := func() {
		if nbytes < end && s[nbytes] == '*' {
			nbytes++
			nargs++
		} else {
			for nbytes < end && '0' <= s[nbytes] && s[nbytes] <= '9' {
				nbytes++
			}
		}
	}
	// There may be a width.
	getNum()
	// If there's a period, there may be a precision.
	if nbytes < end && s[nbytes] == '.' {
		flags = append(flags, '.') // Treat precision as a flag.
		nbytes++
		getNum()
	}
	// Now a verb.
	c, w := utf8.DecodeRuneInString(s[nbytes:])
	nbytes += w
	if c != '%' {
		nargs++
		f.checkPrintfVerb(call, c, flags)
	}
	return
}

type printVerb struct {
	verb  rune
	flags string // known flags are all ASCII
}

// Common flag sets for printf verbs.
const (
	numFlag      = " -+.0"
	sharpNumFlag = " -+.0#"
	allFlags     = " -+.0#"
)

// printVerbs identifies which flags are known to printf for each verb.
// TODO: A type that implements Formatter may do what it wants, and vet
// will complain incorrectly.
var printVerbs = []printVerb{
	// '-' is a width modifier, always valid.
	// '.' is a precision for float, max width for strings.
	// '+' is required sign for numbers, Go format for %v.
	// '#' is alternate format for several verbs.
	// ' ' is spacer for numbers
	{'b', numFlag},
	{'c', "-"},
	{'d', numFlag},
	{'e', numFlag},
	{'E', numFlag},
	{'f', numFlag},
	{'F', numFlag},
	{'g', numFlag},
	{'G', numFlag},
	{'o', sharpNumFlag},
	{'p', "-#"},
	{'q', "-+#."},
	{'s', "-."},
	{'t', "-"},
	{'T', "-"},
	{'U', "-#"},
	{'v', allFlags},
	{'x', sharpNumFlag},
	{'X', sharpNumFlag},
}

const printfVerbs = "bcdeEfFgGopqstTvxUX"

func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
	// Linear scan is fast enough for a small list.
	for _, v := range printVerbs {
		if v.verb == verb {
			for _, flag := range flags {
				if !strings.ContainsRune(v.flags, rune(flag)) {
					f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
				}
			}
			return
		}
	}
	f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
}

// checkPrint checks a call to an unformatted print routine such as Println.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is the first argument to be printed.
func (f *File) checkPrint(call *ast.CallExpr, name string, skip int) {
	isLn := strings.HasSuffix(name, "ln")
	isF := strings.HasPrefix(name, "F")
	args := call.Args
	// check for Println(os.Stderr, ...)
	if skip == 0 && !isF && len(args) > 0 {
		if sel, ok := args[0].(*ast.SelectorExpr); ok {
			if x, ok := sel.X.(*ast.Ident); ok {
				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
					f.Warnf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name)
				}
			}
		}
	}
	if len(args) <= skip {
		if *verbose && !isLn {
			f.Badf(call.Pos(), "no args in %s call", name)
		}
		return
	}
	arg := args[skip]
	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
		if strings.Contains(lit.Value, "%") {
			f.Badf(call.Pos(), "possible formatting directive in %s call", name)
		}
	}
	if isLn {
		// The last item, if a string, should not have a newline.
		arg = args[len(call.Args)-1]
		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
			if strings.HasSuffix(lit.Value, `\n"`) {
				f.Badf(call.Pos(), "%s call ends with newline", name)
			}
		}
	}
}

// This function never executes, but it serves as a simple test for the program.
// Test with make test.
func BadFunctionUsedInTests() {
	fmt.Println()                      // not an error
	fmt.Println("%s", "hi")            // ERROR "possible formatting directive in Println call"
	fmt.Printf("%s", "hi", 3)          // ERROR "wrong number of args in Printf call"
	fmt.Printf("%s%%%d", "hi", 3)      // correct
	fmt.Printf("%.*d", 3, 3)           // correct
	fmt.Printf("%.*d", 3, 3, 3)        // ERROR "wrong number of args in Printf call"
	printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("now is the time", "buddy") // ERROR "no formatting directive"
	Printf("hi")                       // ok
	f := new(File)
	f.Warn(0, "%s", "hello", 3)  // ERROR "possible formatting directive in Warn call"
	f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
	f.Warnf(0, "%r", "hello")    // ERROR "unrecognized printf verb"
	f.Warnf(0, "%#s", "hello")   // ERROR "unrecognized printf flag"
}

type BadTypeUsedInTests struct {
	X int "hello" // ERROR "struct field tag"
}

func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
}

type BadInterfaceUsedInTests interface {
	ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
}

// printf is used by the test.
func printf(format string, args ...interface{}) {
	panic("don't call - testing only")
}
<|endoftext|>


<commit_before>package logrus

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"time"
)

// An entry is the final or intermediate Logrus logging entry. It contains all
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
// passed around as much as you wish to avoid field duplication.
type Entry struct {
	Logger *Logger

	// Contains all the fields set by the user.
	Data Fields

	// Time at which the log entry was created
	Time time.Time

	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
	Level Level

	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
	Message string
}

func NewEntry(logger *Logger) *Entry {
	return &Entry{
		Logger: logger,
		// Default is three fields, give a little extra room
		Data: make(Fields, 5),
	}
}

// Returns a reader for the entry, which is a proxy to the formatter.
func (entry *Entry) Reader() (*bytes.Buffer, error) {
	serialized, err := entry.Logger.Formatter.Format(entry)
	return bytes.NewBuffer(serialized), err
}

// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
	reader, err := entry.Reader()
	if err != nil {
		return "", err
	}

	return reader.String(), err
}

// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
	return entry.WithFields(Fields{key: value})
}

// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
	data := Fields{}
	for k, v := range entry.Data {
		data[k] = v
	}
	for k, v := range fields {
		data[k] = v
	}
	return &Entry{Logger: entry.Logger, Data: data}
}

func (entry Entry) log(level Level, msg string) {
	entry.Time = time.Now()
	entry.Level = level
	entry.Message = msg

	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
		entry.Logger.mu.Unlock()
	}

	reader, err := entry.Reader()
	if err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
		entry.Logger.mu.Unlock()
	}

	entry.Logger.mu.Lock()
	defer entry.Logger.mu.Unlock()

	_, err = io.Copy(entry.Logger.Out, reader)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
	}

	// To avoid Entry#log() returning a value that only would make sense for
	// panic() to use in Entry#Panic(), we avoid the allocation by checking
	// directly here.
	if level <= PanicLevel {
		panic(&entry)
	}
}

func (entry *Entry) Debug(args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.log(DebugLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Print(args ...interface{}) {
	entry.Info(args...)
}

func (entry *Entry) Info(args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.log(InfoLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warn(args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.log(WarnLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warning(args ...interface{}) {
	entry.Warn(args...)
}

func (entry *Entry) Error(args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.log(ErrorLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Fatal(args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.log(FatalLevel, fmt.Sprint(args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panic(args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.log(PanicLevel, fmt.Sprint(args...))
	}
	panic(fmt.Sprint(args...))
}

// Entry Printf family functions

func (entry *Entry) Debugf(format string, args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.Debug(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Infof(format string, args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.Info(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Printf(format string, args ...interface{}) {
	entry.Infof(format, args...)
}

func (entry *Entry) Warnf(format string, args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.Warn(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Warningf(format string, args ...interface{}) {
	entry.Warnf(format, args...)
}

func (entry *Entry) Errorf(format string, args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.Error(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Fatalf(format string, args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.Fatal(fmt.Sprintf(format, args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panicf(format string, args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.Panic(fmt.Sprintf(format, args...))
	}
}

// Entry Println family functions

func (entry *Entry) Debugln(args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.Debug(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Infoln(args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.Info(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Println(args ...interface{}) {
	entry.Infoln(args...)
}

func (entry *Entry) Warnln(args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.Warn(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Warningln(args ...interface{}) {
	entry.Warnln(args...)
}

func (entry *Entry) Errorln(args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.Error(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Fatalln(args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.Fatal(entry.sprintlnn(args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panicln(args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.Panic(entry.sprintlnn(args...))
	}
}

// Sprintlnn => Sprint no newline. This is to get the behavior of how
// fmt.Sprintln where spaces are always added between operands, regardless of
// their type. Instead of vendoring the Sprintln implementation to spare a
// string allocation, we do the simplest thing.
func (entry *Entry) sprintlnn(args ...interface{}) string {
	msg := fmt.Sprintln(args...)
	return msg[:len(msg)-1]
}
<commit_msg>Add comment to log function<commit_after>package logrus

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"time"
)

// An entry is the final or intermediate Logrus logging entry. It contains all
// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
// passed around as much as you wish to avoid field duplication.
type Entry struct {
	Logger *Logger

	// Contains all the fields set by the user.
	Data Fields

	// Time at which the log entry was created
	Time time.Time

	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
	Level Level

	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
	Message string
}

func NewEntry(logger *Logger) *Entry {
	return &Entry{
		Logger: logger,
		// Default is three fields, give a little extra room
		Data: make(Fields, 5),
	}
}

// Returns a reader for the entry, which is a proxy to the formatter.
func (entry *Entry) Reader() (*bytes.Buffer, error) {
	serialized, err := entry.Logger.Formatter.Format(entry)
	return bytes.NewBuffer(serialized), err
}

// Returns the string representation from the reader and ultimately the
// formatter.
func (entry *Entry) String() (string, error) {
	reader, err := entry.Reader()
	if err != nil {
		return "", err
	}

	return reader.String(), err
}

// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
	return entry.WithFields(Fields{key: value})
}

// Add a map of fields to the Entry.
func (entry *Entry) WithFields(fields Fields) *Entry {
	data := Fields{}
	for k, v := range entry.Data {
		data[k] = v
	}
	for k, v := range fields {
		data[k] = v
	}
	return &Entry{Logger: entry.Logger, Data: data}
}

// This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) {
	entry.Time = time.Now()
	entry.Level = level
	entry.Message = msg

	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
		entry.Logger.mu.Unlock()
	}

	reader, err := entry.Reader()
	if err != nil {
		entry.Logger.mu.Lock()
		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
		entry.Logger.mu.Unlock()
	}

	entry.Logger.mu.Lock()
	defer entry.Logger.mu.Unlock()

	_, err = io.Copy(entry.Logger.Out, reader)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
	}

	// To avoid Entry#log() returning a value that only would make sense for
	// panic() to use in Entry#Panic(), we avoid the allocation by checking
	// directly here.
	if level <= PanicLevel {
		panic(&entry)
	}
}

func (entry *Entry) Debug(args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.log(DebugLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Print(args ...interface{}) {
	entry.Info(args...)
}

func (entry *Entry) Info(args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.log(InfoLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warn(args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.log(WarnLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Warning(args ...interface{}) {
	entry.Warn(args...)
}

func (entry *Entry) Error(args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.log(ErrorLevel, fmt.Sprint(args...))
	}
}

func (entry *Entry) Fatal(args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.log(FatalLevel, fmt.Sprint(args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panic(args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.log(PanicLevel, fmt.Sprint(args...))
	}
	panic(fmt.Sprint(args...))
}

// Entry Printf family functions

func (entry *Entry) Debugf(format string, args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.Debug(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Infof(format string, args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.Info(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Printf(format string, args ...interface{}) {
	entry.Infof(format, args...)
}

func (entry *Entry) Warnf(format string, args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.Warn(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Warningf(format string, args ...interface{}) {
	entry.Warnf(format, args...)
}

func (entry *Entry) Errorf(format string, args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.Error(fmt.Sprintf(format, args...))
	}
}

func (entry *Entry) Fatalf(format string, args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.Fatal(fmt.Sprintf(format, args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panicf(format string, args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.Panic(fmt.Sprintf(format, args...))
	}
}

// Entry Println family functions

func (entry *Entry) Debugln(args ...interface{}) {
	if entry.Logger.Level >= DebugLevel {
		entry.Debug(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Infoln(args ...interface{}) {
	if entry.Logger.Level >= InfoLevel {
		entry.Info(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Println(args ...interface{}) {
	entry.Infoln(args...)
}

func (entry *Entry) Warnln(args ...interface{}) {
	if entry.Logger.Level >= WarnLevel {
		entry.Warn(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Warningln(args ...interface{}) {
	entry.Warnln(args...)
}

func (entry *Entry) Errorln(args ...interface{}) {
	if entry.Logger.Level >= ErrorLevel {
		entry.Error(entry.sprintlnn(args...))
	}
}

func (entry *Entry) Fatalln(args ...interface{}) {
	if entry.Logger.Level >= FatalLevel {
		entry.Fatal(entry.sprintlnn(args...))
	}
	os.Exit(1)
}

func (entry *Entry) Panicln(args ...interface{}) {
	if entry.Logger.Level >= PanicLevel {
		entry.Panic(entry.sprintlnn(args...))
	}
}

// Sprintlnn => Sprint no newline. This is to get the behavior of how
// fmt.Sprintln where spaces are always added between operands, regardless of
// their type. Instead of vendoring the Sprintln implementation to spare a
// string allocation, we do the simplest thing.
func (entry *Entry) sprintlnn(args ...interface{}) string {
	msg := fmt.Sprintln(args...)
	return msg[:len(msg)-1]
}
<|endoftext|>


<commit_before>package plugin

type Clone struct {
	Origin string `json:"origin"`
	Remote string `json:"remote"`
	Branch string `json:"branch"`
	Sha    string `json:"sha"`
	Ref    string `json:"ref"`
	Dir    string `json:"dir"`

	Netrc struct {
		Machine  string `json:"machine"`
		Login    string `json:"login"`
		Password string `json:"user"`
	}

	Keypair struct {
		Public  string `json:"public"`
		Private string `json:"private"`
	}
}

type User struct {
	Remote string `json:"remote"`
	Login  string `json:"login"`
	Name   string `json:"name"`
	Email  string `json:"email,omitempty"`
}

type Repo struct {
	Remote string `json:"remote"`
	Host   string `json:"host"`
	Owner  string `json:"owner"`
	Name   string `json:"name"`
	URL    string `json:"url"`
}

type Commit struct {
	Status      string `json:"status"`
	Started     int64  `json:"started_at"`
	Finished    int64  `json:"finished_at"`
	Duration    int64  `json:"duration"`
	Sha         string `json:"sha"`
	Branch      string `json:"branch"`
	PullRequest string `json:"pull_request"`
	Author      string `json:"author"`
	Gravatar    string `json:"gravatar"`
	Timestamp   string `json:"timestamp"`
	Message     string `json:"message"`
}

type Config struct {
	Image    string   `json:"image"`
	Env      []string `json:"env"`
	Script   []string `json:"script"`
	Branches []string `json:"branches"`
	Services []string `json:"services"`
}

type Links struct {
	Repo   string `json:"repo_url"`
	Commit string `json:"commit_url"`
}
<commit_msg>removed config type<commit_after>package plugin

type Clone struct {
	Origin string `json:"origin"`
	Remote string `json:"remote"`
	Branch string `json:"branch"`
	Sha    string `json:"sha"`
	Ref    string `json:"ref"`
	Dir    string `json:"dir"`

	Netrc struct {
		Machine  string `json:"machine"`
		Login    string `json:"login"`
		Password string `json:"user"`
	}

	Keypair struct {
		Public  string `json:"public"`
		Private string `json:"private"`
	}
}

type User struct {
	Remote string `json:"remote"`
	Login  string `json:"login"`
	Name   string `json:"name"`
	Email  string `json:"email,omitempty"`
}

type Repo struct {
	Remote string `json:"remote"`
	Host   string `json:"host"`
	Owner  string `json:"owner"`
	Name   string `json:"name"`
	URL    string `json:"url"`
}

type Commit struct {
	Status      string `json:"status"`
	Started     int64  `json:"started_at"`
	Finished    int64  `json:"finished_at"`
	Duration    int64  `json:"duration"`
	Sha         string `json:"sha"`
	Branch      string `json:"branch"`
	PullRequest string `json:"pull_request"`
	Author      string `json:"author"`
	Gravatar    string `json:"gravatar"`
	Timestamp   string `json:"timestamp"`
	Message     string `json:"message"`
}

type Links struct {
	Repo   string `json:"repo_url"`
	Commit string `json:"commit_url"`
}
<|endoftext|>


<commit_before>package flags

import (
	"fmt"
)

// ErrorType represents the type of error.
type ErrorType uint

const (
	// ErrUnknown indicates a generic error.
	ErrUnknown ErrorType = iota

	// ErrExpectedArgument indicates that an argument was expected.
	ErrExpectedArgument

	// ErrUnknownFlag indicates an unknown flag.
	ErrUnknownFlag

	// ErrUnknownGroup indicates an unknown group.
	ErrUnknownGroup

	// ErrMarshal indicates a marshalling error while converting values.
	ErrMarshal

	// ErrHelp indicates that the builtin help was shown (the error
	// contains the help message).
	ErrHelp

	// ErrNoArgumentForBool indicates that an argument was given for a
	// boolean flag (which don't not take any arguments).
	ErrNoArgumentForBool

	// ErrRequired indicates that a required flag was not provided.
	ErrRequired

	// ErrShortNameTooLong indicates that a short flag name was specified,
	// longer than one character.
	ErrShortNameTooLong

	// ErrDuplicatedFlag indicates that a short or long flag has been
	// defined more than once
	ErrDuplicatedFlag

	// ErrTag indicates an error while parsing flag tags.
	ErrTag
)

// String returns a string representation of the error type.
func (e ErrorType) String() string {
	switch e {
	case ErrUnknown:
		return "unknown"
	case ErrExpectedArgument:
		return "expected argument"
	case ErrUnknownFlag:
		return "unknown flag"
	case ErrUnknownGroup:
		return "unknown group"
	case ErrMarshal:
		return "marshal"
	case ErrHelp:
		return "help"
	case ErrNoArgumentForBool:
		return "no argument for bool"
	case ErrRequired:
		return "required"
	case ErrShortNameTooLong:
		return "short name too long"
	case ErrDuplicatedFlag:
		return "duplicated flag"
	case ErrTag:
		return "tag"
	}

	return "unknown"
}

// Error represents a parser error. The error returned from Parse is of this
// type. The error contains both a Type and Message.
type Error struct {
	// The type of error
	Type ErrorType

	// The error message
	Message string
}

// Error returns the error's message
func (e *Error) Error() string {
	return e.Message
}

func newError(tp ErrorType, message string) *Error {
	return &Error{
		Type:    tp,
		Message: message,
	}
}

func newErrorf(tp ErrorType, format string, args ...interface{}) *Error {
	return newError(tp, fmt.Sprintf(format, args...))
}

func wrapError(err error) *Error {
	ret, ok := err.(*Error)

	if !ok {
		return newError(ErrUnknown, err.Error())
	}

	return ret
}
<commit_msg>Remove error type to string<commit_after>package flags

import (
	"fmt"
)

// ErrorType represents the type of error.
type ErrorType uint

const (
	// ErrUnknown indicates a generic error.
	ErrUnknown ErrorType = iota

	// ErrExpectedArgument indicates that an argument was expected.
	ErrExpectedArgument

	// ErrUnknownFlag indicates an unknown flag.
	ErrUnknownFlag

	// ErrUnknownGroup indicates an unknown group.
	ErrUnknownGroup

	// ErrMarshal indicates a marshalling error while converting values.
	ErrMarshal

	// ErrHelp indicates that the builtin help was shown (the error
	// contains the help message).
	ErrHelp

	// ErrNoArgumentForBool indicates that an argument was given for a
	// boolean flag (which don't not take any arguments).
	ErrNoArgumentForBool

	// ErrRequired indicates that a required flag was not provided.
	ErrRequired

	// ErrShortNameTooLong indicates that a short flag name was specified,
	// longer than one character.
	ErrShortNameTooLong

	// ErrDuplicatedFlag indicates that a short or long flag has been
	// defined more than once
	ErrDuplicatedFlag

	// ErrTag indicates an error while parsing flag tags.
	ErrTag
)

// Error represents a parser error. The error returned from Parse is of this
// type. The error contains both a Type and Message.
type Error struct {
	// The type of error
	Type ErrorType

	// The error message
	Message string
}

// Error returns the error's message
func (e *Error) Error() string {
	return e.Message
}

func newError(tp ErrorType, message string) *Error {
	return &Error{
		Type:    tp,
		Message: message,
	}
}

func newErrorf(tp ErrorType, format string, args ...interface{}) *Error {
	return newError(tp, fmt.Sprintf(format, args...))
}

func wrapError(err error) *Error {
	ret, ok := err.(*Error)

	if !ok {
		return newError(ErrUnknown, err.Error())
	}

	return ret
}
<|endoftext|>


<commit_before>package couchbase

import "fmt"

type Error interface {
	KeyNotFound() bool
	KeyExists() bool
	Timeout() bool
	Temporary() bool
}

type clientError struct {
	message string
}

func (e clientError) Error() string {
	return e.message
}
func (e clientError) KeyNotFound() bool {
	return false
}
func (e clientError) KeyExists() bool {
	return false
}
func (e clientError) Timeout() bool {
	return false
}
func (e clientError) Temporary() bool {
	return false
}

type timeoutError struct {
}

func (e timeoutError) Error() string {
	return "The operation has timed out."
}
func (e timeoutError) KeyNotFound() bool {
	return false
}
func (e timeoutError) KeyExists() bool {
	return false
}
func (e timeoutError) Timeout() bool {
	return true
}
func (e timeoutError) Temporary() bool {
	return false
}

type memdError struct {
	code statusCode
}

func (e memdError) Error() string {
	switch e.code {
	case success:
		return "Success."
	case keyNotFound:
		return "Key not found."
	case keyExists:
		return "Key already exists."
	case tooBig:
		return "Document value was too large."
	case notStored:
		return "The document could not be stored."
	case badDelta:
		return "An invalid delta was passed."
	case notMyVBucket:
		return "Operation sent to incorrect server."
	case unknownCommand:
		return "An unknown command was received."
	case outOfMemory:
		return "The server is out of memory."
	case tmpFail:
		return "A temporary failure occurred.  Try again later."
	default:
		return fmt.Sprintf("An unknown error occurred (%d).", e.code)
	}
}
func (e memdError) KeyNotFound() bool {
	return e.code == keyNotFound
}
func (e memdError) KeyExists() bool {
	return e.code == keyExists
}
func (e memdError) Timeout() bool {
	return false
}
func (e memdError) Temporary() bool {
	return e.code == outOfMemory || e.code == tmpFail
}
<commit_msg>Woops.  Missed something.<commit_after>package couchbase

import "fmt"

type clientError struct {
	message string
}

func (e clientError) Error() string {
	return e.message
}
func (e clientError) KeyNotFound() bool {
	return false
}
func (e clientError) KeyExists() bool {
	return false
}
func (e clientError) Timeout() bool {
	return false
}
func (e clientError) Temporary() bool {
	return false
}

type timeoutError struct {
}

func (e timeoutError) Error() string {
	return "The operation has timed out."
}
func (e timeoutError) KeyNotFound() bool {
	return false
}
func (e timeoutError) KeyExists() bool {
	return false
}
func (e timeoutError) Timeout() bool {
	return true
}
func (e timeoutError) Temporary() bool {
	return false
}

type memdError struct {
	code statusCode
}

func (e memdError) Error() string {
	switch e.code {
	case success:
		return "Success."
	case keyNotFound:
		return "Key not found."
	case keyExists:
		return "Key already exists."
	case tooBig:
		return "Document value was too large."
	case notStored:
		return "The document could not be stored."
	case badDelta:
		return "An invalid delta was passed."
	case notMyVBucket:
		return "Operation sent to incorrect server."
	case unknownCommand:
		return "An unknown command was received."
	case outOfMemory:
		return "The server is out of memory."
	case tmpFail:
		return "A temporary failure occurred.  Try again later."
	default:
		return fmt.Sprintf("An unknown error occurred (%d).", e.code)
	}
}
func (e memdError) KeyNotFound() bool {
	return e.code == keyNotFound
}
func (e memdError) KeyExists() bool {
	return e.code == keyExists
}
func (e memdError) Timeout() bool {
	return false
}
func (e memdError) Temporary() bool {
	return e.code == outOfMemory || e.code == tmpFail
}
<|endoftext|>


<commit_before>package cli

import "fmt"

// ErrExitFailure represents errors that should immediately
// exit with failure status. All output to stdout or stderr
// should be written before a handler returns this value, as
// is the case for built in usage. It is the package user's
// responsibility to handle this error.
var ErrExitFailure = fmt.Errorf("1")

// ErrUsageNotFound represents the error that should be
// returned by Usage implementations to signal that the
// help topic is not found
var ErrUsageNotFound = fmt.Errorf("cli: usage not found")

// ErrFlagSyntax represents an error for bad arguments.
type ErrFlagSyntax string

// Error implements the error interface.
func (e ErrFlagSyntax) Error() string {
	return fmt.Sprintf("Flag '%s' is syntactically incorrect.", string(e))
}

// ErrUndefinedFlag represents an error for when an undefined flag is parsed.
type ErrUndefinedFlag string

// Error implements the error interface.
func (e ErrUndefinedFlag) Error() string {
	return fmt.Sprintf("Flag '%s' is undefined.", string(e))
}

// ErrRequiresArg represents an error for when an undefined flag is parsed.
type ErrRequiresArg string

// Error implements the error interface.
func (e ErrRequiresArg) Error() string {
	return fmt.Sprintf("Flag '%s' requires an argument.", string(e))
}
<commit_msg>Fix documentation string<commit_after>package cli

import "fmt"

// ErrExitFailure represents errors that should immediately
// exit with failure status. All output to stdout or stderr
// should be written before a handler returns this value, as
// is the case for built in usage. It is the package user's
// responsibility to handle this error.
var ErrExitFailure = fmt.Errorf("1")

// ErrUsageNotFound represents the error that should be
// returned by Usage implementations to signal that the
// help topic is not found.
var ErrUsageNotFound = fmt.Errorf("cli: usage not found")

// ErrFlagSyntax represents an error for bad arguments.
type ErrFlagSyntax string

// Error implements the error interface.
func (e ErrFlagSyntax) Error() string {
	return fmt.Sprintf("Flag '%s' is syntactically incorrect.", string(e))
}

// ErrUndefinedFlag represents an error for when an undefined flag is parsed.
type ErrUndefinedFlag string

// Error implements the error interface.
func (e ErrUndefinedFlag) Error() string {
	return fmt.Sprintf("Flag '%s' is undefined.", string(e))
}

// ErrRequiresArg represents an error for when an undefined flag is parsed.
type ErrRequiresArg string

// Error implements the error interface.
func (e ErrRequiresArg) Error() string {
	return fmt.Sprintf("Flag '%s' requires an argument.", string(e))
}
<|endoftext|>


<commit_before>package ucfg

import (
	"errors"
	"fmt"
	"reflect"
	"runtime/debug"
)

// Error type returned by all public functions in go-ucfg.
type Error interface {
	error

	// error class, one of ErrConfig, ErrImplementation, ErrUnknown
	Class() error

	// The internal reason error code like ErrMissing, ErrRequired,
	// ErrTypeMismatch and others.
	Reason() error

	// The error message.
	Message() string

	// [optional] path of config element error occurred for
	Path() string

	// [optional] stack trace
	Trace() string
}

type baseError struct {
	reason  error
	class   error
	message string
	path    string
}

type criticalError struct {
	baseError
	trace string
}

// Error Reasons
var (
	ErrMissing = errors.New("missing field")

	ErrCyclicReference = errors.New("cyclic reference detected")

	ErrDuplicateValidator = errors.New("validator already registered")

	ErrTypeNoArray = errors.New("field is no array")

	ErrTypeMismatch = errors.New("type mismatch")

	ErrKeyTypeNotString = errors.New("key must be a string")

	ErrIndexOutOfRange = errors.New("out of range index")

	ErrPointerRequired = errors.New("pointer required for unpacking configurations")

	ErrArraySizeMistach = errors.New("Array size mismatch")

	ErrExpectedObject = errors.New("expected object")

	ErrNilConfig = errors.New("config is nil")

	ErrNilValue = errors.New("nil value is invalid")

	ErrTODO = errors.New("TODO - implement me")

	ErrDuplicateKeey = errors.New("duplicate key")

	ErrOverflow = errors.New("integer overflow")

	ErrNegative = errors.New("negative value")

	ErrZeroValue = errors.New("zero value")

	ErrRequired = errors.New("missing required field")

	ErrEmpty = errors.New("empty field")
)

// Error Classes
var (
	ErrConfig         = errors.New("Configuration error")
	ErrImplementation = errors.New("Implementation error")
	ErrUnknown        = errors.New("Unspecified")
)

func (e baseError) Error() string { return e.Message() }
func (e baseError) Reason() error { return e.reason }
func (e baseError) Class() error  { return e.class }
func (e baseError) Trace() string { return "" }
func (e baseError) Path() string  { return e.path }

func (e baseError) Message() string {
	if e.message == "" {
		return e.reason.Error()
	}
	return e.message
}

func (e criticalError) Trace() string { return e.trace }

func (e criticalError) Error() string {
	return fmt.Sprintf("%s\nTrace:%v\n", e.baseError.Message(), e.trace)
}

func raiseErr(reason error, message string) Error {
	return baseError{
		reason:  reason,
		message: message,
		class:   ErrConfig,
	}
}

func raiseImplErr(reason error) Error {
	return baseError{
		reason: reason,
		class:  ErrImplementation,
	}
}

func raiseCritical(reason error, message string) Error {
	if message == "" {
		message = reason.Error()
	}
	if message != "" {
		message = fmt.Sprintf("(assert) %v", message)
	}
	return criticalError{
		baseError{reason, ErrImplementation, message, ""},
		string(debug.Stack()),
	}
}

func raisePathErr(reason error, meta *Meta, message, path string) Error {
	message = messagePath(reason, meta, message, path)
	return baseError{reason, ErrConfig, message, path}
}

func messageMeta(message string, meta *Meta) string {
	if meta == nil || meta.Source == "" {
		return message
	}
	return fmt.Sprintf("%v (source:'%v')", message, meta.Source)
}

func messagePath(reason error, meta *Meta, message, path string) string {
	if path == "" {
		path = "config"
	} else {
		path = fmt.Sprintf("'%v'", path)
	}

	if message == "" {
		message = reason.Error()
	}

	message = fmt.Sprintf("%v accessing %v", message, path)
	return messageMeta(message, meta)
}

func raiseDuplicateKey(cfg *Config, name string) Error {
	return raisePathErr(ErrDuplicateKeey, cfg.metadata, "", cfg.PathOf(name, "."))
}

func raiseCyclicErr(field string) Error {
	message := fmt.Sprintf("cyclic reference detected for key: '%s'", field)

	return baseError{
		reason:  ErrCyclicReference,
		class:   ErrConfig,
		message: message,
	}
}

func raiseMissing(c *Config, field string) Error {
	// error reading field from config, as missing in c
	return raiseMissingMsg(c, field, "")
}

func raiseMissingMsg(c *Config, field string, message string) Error {
	return raisePathErr(ErrMissing, c.metadata, message, c.PathOf(field, "."))
}

func raiseMissingArr(ctx context, meta *Meta, idx int) Error {
	message := fmt.Sprintf("no value in array at %v", idx)
	return raisePathErr(ErrMissing, meta, message, ctx.path("."))
}

func raiseIndexOutOfBounds(opts *options, value value, idx int) Error {
	reason := ErrIndexOutOfRange
	ctx := value.Context()
	len, _ := value.Len(opts)
	message := fmt.Sprintf("index '%v' out of range (length=%v)", idx, len)
	return raisePathErr(reason, value.meta(), message, ctx.path("."))
}

func raiseInvalidTopLevelType(v interface{}, meta *Meta) Error {
	// could be developers or user fault
	t := chaseTypePointers(chaseValue(reflect.ValueOf(v)).Type())
	message := fmt.Sprintf("type '%v' is not supported on top level of config, only dictionary or list", t)
	return raiseErr(ErrTypeMismatch, messageMeta(message, meta))
}

func raiseKeyInvalidTypeUnpack(t reflect.Type, from *Config) Error {
	// most likely developers fault
	ctx := from.ctx
	reason := ErrKeyTypeNotString
	message := fmt.Sprintf("string key required when unpacking into '%v'", t)
	return raiseCritical(reason, messagePath(reason, from.metadata, message, ctx.path(".")))
}

func raiseKeyInvalidTypeMerge(cfg *Config, t reflect.Type) Error {
	ctx := cfg.ctx
	reason := ErrKeyTypeNotString
	message := fmt.Sprintf("string key required when merging into '%v'", t)
	return raiseCritical(reason, messagePath(reason, cfg.metadata, message, ctx.path(".")))
}

func raiseSquashNeedsObject(cfg *Config, opts *options, f string, t reflect.Type) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("require map or struct when squash merging '%v' (%v)", f, t)

	return raiseCritical(reason, messagePath(reason, opts.meta, message, cfg.Path(".")))
}

func raiseInlineNeedsObject(cfg *Config, f string, t reflect.Type) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("require map or struct when inling '%v' (%v)", f, t)
	return raiseCritical(reason,
		messagePath(reason, cfg.metadata, message, cfg.Path(".")))
}

func raiseUnsupportedInputType(ctx context, meta *Meta, v reflect.Value) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("unspported input type (%v) with value '%#v'",
		v.Type(), v)

	return raiseCritical(reason, messagePath(reason, meta, message, ctx.path(".")))
}

func raiseNil(reason error) Error {
	// programmers error (passed unexpected nil pointer)
	return raiseCritical(reason, "")
}

func raisePointerRequired(v reflect.Value) Error {
	// developer did not pass pointer, unpack target is not settable
	return raiseCritical(ErrPointerRequired, "")
}

func raiseToTypeNotSupported(opts *options, v value, goT reflect.Type) Error {
	reason := ErrTypeMismatch
	t, _ := v.typ(opts)
	message := fmt.Sprintf("value of type '%v' not convertible into unsupported go type '%v'",
		t.name, goT)
	ctx := v.Context()

	return raiseCritical(reason, messagePath(reason, v.meta(), message, ctx.path(".")))
}

func raiseArraySize(ctx context, meta *Meta, n int, to int) Error {
	reason := ErrArraySizeMistach
	message := fmt.Sprintf("array of length %v does not meet required length %v",
		n, to)

	return raisePathErr(reason, meta, message, ctx.path("."))
}

func raiseConversion(opts *options, v value, err error, to string) Error {
	ctx := v.Context()
	path := ctx.path(".")
	t, _ := v.typ(opts)
	message := fmt.Sprintf("can not convert '%v' into '%v'", t.name, to)
	return raisePathErr(err, v.meta(), message, path)
}

func raiseExpectedObject(opts *options, v value) Error {
	ctx := v.Context()
	path := ctx.path(".")
	t, _ := v.typ(opts)
	message := fmt.Sprintf("required 'object', but found '%v' in field '%v'",
		t.name, path)

	return raiseErr(ErrExpectedObject, messageMeta(message, v.meta()))
}

func raiseInvalidDuration(v value, err error) Error {
	ctx := v.Context()
	path := ctx.path(".")
	return raisePathErr(err, v.meta(), "", path)
}

func raiseValidation(ctx context, meta *Meta, field string, err error) Error {
	path := ""
	if field == "" {
		path = ctx.path(".")
	} else {
		path = ctx.pathOf(field, ".")
	}
	return raiseErr(err, messagePath(err, meta, err.Error(), path))
}

func raiseInvalidRegexp(v value, err error) Error {
	ctx := v.Context()
	path := ctx.path(".")
	message := fmt.Sprintf("Failed to compile regular expression with '%v'", err)
	return raisePathErr(err, v.meta(), message, path)
}

func raiseParseSplice(ctx context, meta *Meta, err error) Error {
	message := fmt.Sprintf("%v parsing splice", err)
	return raisePathErr(err, meta, message, ctx.path("."))
}
<commit_msg>TYPO: Rename ErrDuplicateKeey to ErrDuplicateKey (#98)<commit_after>package ucfg

import (
	"errors"
	"fmt"
	"reflect"
	"runtime/debug"
)

// Error type returned by all public functions in go-ucfg.
type Error interface {
	error

	// error class, one of ErrConfig, ErrImplementation, ErrUnknown
	Class() error

	// The internal reason error code like ErrMissing, ErrRequired,
	// ErrTypeMismatch and others.
	Reason() error

	// The error message.
	Message() string

	// [optional] path of config element error occurred for
	Path() string

	// [optional] stack trace
	Trace() string
}

type baseError struct {
	reason  error
	class   error
	message string
	path    string
}

type criticalError struct {
	baseError
	trace string
}

// Error Reasons
var (
	ErrMissing = errors.New("missing field")

	ErrCyclicReference = errors.New("cyclic reference detected")

	ErrDuplicateValidator = errors.New("validator already registered")

	ErrTypeNoArray = errors.New("field is no array")

	ErrTypeMismatch = errors.New("type mismatch")

	ErrKeyTypeNotString = errors.New("key must be a string")

	ErrIndexOutOfRange = errors.New("out of range index")

	ErrPointerRequired = errors.New("pointer required for unpacking configurations")

	ErrArraySizeMistach = errors.New("Array size mismatch")

	ErrExpectedObject = errors.New("expected object")

	ErrNilConfig = errors.New("config is nil")

	ErrNilValue = errors.New("nil value is invalid")

	ErrTODO = errors.New("TODO - implement me")

	ErrDuplicateKey = errors.New("duplicate key")

	ErrOverflow = errors.New("integer overflow")

	ErrNegative = errors.New("negative value")

	ErrZeroValue = errors.New("zero value")

	ErrRequired = errors.New("missing required field")

	ErrEmpty = errors.New("empty field")
)

// Error Classes
var (
	ErrConfig         = errors.New("Configuration error")
	ErrImplementation = errors.New("Implementation error")
	ErrUnknown        = errors.New("Unspecified")
)

func (e baseError) Error() string { return e.Message() }
func (e baseError) Reason() error { return e.reason }
func (e baseError) Class() error  { return e.class }
func (e baseError) Trace() string { return "" }
func (e baseError) Path() string  { return e.path }

func (e baseError) Message() string {
	if e.message == "" {
		return e.reason.Error()
	}
	return e.message
}

func (e criticalError) Trace() string { return e.trace }

func (e criticalError) Error() string {
	return fmt.Sprintf("%s\nTrace:%v\n", e.baseError.Message(), e.trace)
}

func raiseErr(reason error, message string) Error {
	return baseError{
		reason:  reason,
		message: message,
		class:   ErrConfig,
	}
}

func raiseImplErr(reason error) Error {
	return baseError{
		reason: reason,
		class:  ErrImplementation,
	}
}

func raiseCritical(reason error, message string) Error {
	if message == "" {
		message = reason.Error()
	}
	if message != "" {
		message = fmt.Sprintf("(assert) %v", message)
	}
	return criticalError{
		baseError{reason, ErrImplementation, message, ""},
		string(debug.Stack()),
	}
}

func raisePathErr(reason error, meta *Meta, message, path string) Error {
	message = messagePath(reason, meta, message, path)
	return baseError{reason, ErrConfig, message, path}
}

func messageMeta(message string, meta *Meta) string {
	if meta == nil || meta.Source == "" {
		return message
	}
	return fmt.Sprintf("%v (source:'%v')", message, meta.Source)
}

func messagePath(reason error, meta *Meta, message, path string) string {
	if path == "" {
		path = "config"
	} else {
		path = fmt.Sprintf("'%v'", path)
	}

	if message == "" {
		message = reason.Error()
	}

	message = fmt.Sprintf("%v accessing %v", message, path)
	return messageMeta(message, meta)
}

func raiseDuplicateKey(cfg *Config, name string) Error {
	return raisePathErr(ErrDuplicateKey, cfg.metadata, "", cfg.PathOf(name, "."))
}

func raiseCyclicErr(field string) Error {
	message := fmt.Sprintf("cyclic reference detected for key: '%s'", field)

	return baseError{
		reason:  ErrCyclicReference,
		class:   ErrConfig,
		message: message,
	}
}

func raiseMissing(c *Config, field string) Error {
	// error reading field from config, as missing in c
	return raiseMissingMsg(c, field, "")
}

func raiseMissingMsg(c *Config, field string, message string) Error {
	return raisePathErr(ErrMissing, c.metadata, message, c.PathOf(field, "."))
}

func raiseMissingArr(ctx context, meta *Meta, idx int) Error {
	message := fmt.Sprintf("no value in array at %v", idx)
	return raisePathErr(ErrMissing, meta, message, ctx.path("."))
}

func raiseIndexOutOfBounds(opts *options, value value, idx int) Error {
	reason := ErrIndexOutOfRange
	ctx := value.Context()
	len, _ := value.Len(opts)
	message := fmt.Sprintf("index '%v' out of range (length=%v)", idx, len)
	return raisePathErr(reason, value.meta(), message, ctx.path("."))
}

func raiseInvalidTopLevelType(v interface{}, meta *Meta) Error {
	// could be developers or user fault
	t := chaseTypePointers(chaseValue(reflect.ValueOf(v)).Type())
	message := fmt.Sprintf("type '%v' is not supported on top level of config, only dictionary or list", t)
	return raiseErr(ErrTypeMismatch, messageMeta(message, meta))
}

func raiseKeyInvalidTypeUnpack(t reflect.Type, from *Config) Error {
	// most likely developers fault
	ctx := from.ctx
	reason := ErrKeyTypeNotString
	message := fmt.Sprintf("string key required when unpacking into '%v'", t)
	return raiseCritical(reason, messagePath(reason, from.metadata, message, ctx.path(".")))
}

func raiseKeyInvalidTypeMerge(cfg *Config, t reflect.Type) Error {
	ctx := cfg.ctx
	reason := ErrKeyTypeNotString
	message := fmt.Sprintf("string key required when merging into '%v'", t)
	return raiseCritical(reason, messagePath(reason, cfg.metadata, message, ctx.path(".")))
}

func raiseSquashNeedsObject(cfg *Config, opts *options, f string, t reflect.Type) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("require map or struct when squash merging '%v' (%v)", f, t)

	return raiseCritical(reason, messagePath(reason, opts.meta, message, cfg.Path(".")))
}

func raiseInlineNeedsObject(cfg *Config, f string, t reflect.Type) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("require map or struct when inling '%v' (%v)", f, t)
	return raiseCritical(reason,
		messagePath(reason, cfg.metadata, message, cfg.Path(".")))
}

func raiseUnsupportedInputType(ctx context, meta *Meta, v reflect.Value) Error {
	reason := ErrTypeMismatch
	message := fmt.Sprintf("unspported input type (%v) with value '%#v'",
		v.Type(), v)

	return raiseCritical(reason, messagePath(reason, meta, message, ctx.path(".")))
}

func raiseNil(reason error) Error {
	// programmers error (passed unexpected nil pointer)
	return raiseCritical(reason, "")
}

func raisePointerRequired(v reflect.Value) Error {
	// developer did not pass pointer, unpack target is not settable
	return raiseCritical(ErrPointerRequired, "")
}

func raiseToTypeNotSupported(opts *options, v value, goT reflect.Type) Error {
	reason := ErrTypeMismatch
	t, _ := v.typ(opts)
	message := fmt.Sprintf("value of type '%v' not convertible into unsupported go type '%v'",
		t.name, goT)
	ctx := v.Context()

	return raiseCritical(reason, messagePath(reason, v.meta(), message, ctx.path(".")))
}

func raiseArraySize(ctx context, meta *Meta, n int, to int) Error {
	reason := ErrArraySizeMistach
	message := fmt.Sprintf("array of length %v does not meet required length %v",
		n, to)

	return raisePathErr(reason, meta, message, ctx.path("."))
}

func raiseConversion(opts *options, v value, err error, to string) Error {
	ctx := v.Context()
	path := ctx.path(".")
	t, _ := v.typ(opts)
	message := fmt.Sprintf("can not convert '%v' into '%v'", t.name, to)
	return raisePathErr(err, v.meta(), message, path)
}

func raiseExpectedObject(opts *options, v value) Error {
	ctx := v.Context()
	path := ctx.path(".")
	t, _ := v.typ(opts)
	message := fmt.Sprintf("required 'object', but found '%v' in field '%v'",
		t.name, path)

	return raiseErr(ErrExpectedObject, messageMeta(message, v.meta()))
}

func raiseInvalidDuration(v value, err error) Error {
	ctx := v.Context()
	path := ctx.path(".")
	return raisePathErr(err, v.meta(), "", path)
}

func raiseValidation(ctx context, meta *Meta, field string, err error) Error {
	path := ""
	if field == "" {
		path = ctx.path(".")
	} else {
		path = ctx.pathOf(field, ".")
	}
	return raiseErr(err, messagePath(err, meta, err.Error(), path))
}

func raiseInvalidRegexp(v value, err error) Error {
	ctx := v.Context()
	path := ctx.path(".")
	message := fmt.Sprintf("Failed to compile regular expression with '%v'", err)
	return raisePathErr(err, v.meta(), message, path)
}

func raiseParseSplice(ctx context, meta *Meta, err error) Error {
	message := fmt.Sprintf("%v parsing splice", err)
	return raisePathErr(err, meta, message, ctx.path("."))
}
<|endoftext|>


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

// Package validator validates and normalizes email addresses and domain names.
package validator

import (
	"errors"
	"net"
	"regexp"
	"strings"
)

// Regular expression from WebCore's HTML5 email input: http://goo.gl/7SZbzj
var emailRegexp = regexp.MustCompile("(?i)" + // case insensitive
	"[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" + // local part
	"@" +
	"[a-z0-9-]+(\\.[a-z0-9-]+)*") // domain part

// IsValidEmail returns true if the given string is a valid email address.
//
// It uses a simple regular expression to check the domain validity.
func IsValidEmail(email string) bool {
	return emailRegexp.MatchString(email)
}

var ErrInvalidEmail = errors.New("invalid email address")

// fetchMXRecords fetches MX records for the domain of the given email.
func fetchMXRecords(email string) ([]*net.MX, error) {
	if !IsValidEmail(email) {
		return nil, ErrInvalidEmail
	}
	// Extract domain.
	_, domain, ok := splitEmail(email)
	if !ok {
		return nil, ErrInvalidEmail
	}
	if !IsValidDomain(domain) {
		return nil, ErrInvalidEmail
	}
	mx, err := net.LookupMX(domain)
	if err != nil {
		return nil, err
	}
	return mx, nil
}

// ValidateEmailByResolvingDomain validates email address by looking up MX
// records on its domain.
//
// This function can return various DNS errors, which may be temporary
// (e.g. caused by internet connection being offline) or permanent,
// e.g. the host doesn't exist or has no MX records.
//
// The function returns nil if email is valid and its domain can
// accept email messages (however this doesn't guarantee that a user
// with such email address exists on the host).
func ValidateEmailByResolvingDomain(email string) error {
	mx, err := fetchMXRecords(email)
	if err != nil {
		return err
	}
	if len(mx) == 0 {
		return ErrInvalidEmail
	}
	return nil
}

// splitEmail splits email address into local and domain parts.
// The last returned value is false if splitting fails.
func splitEmail(email string) (local string, domain string, ok bool) {
	parts := strings.Split(email, "@")
	if len(parts) < 2 {
		return
	}
	local = parts[0]
	domain = parts[1]
	// Check that the parts contain enough characters.
	if len(local) < 1 {
		return
	}
	if len(domain) < len("x.xx") {
		return
	}
	return local, domain, true
}

// NormalizeEmail returns a normalized email address.
// It returns an empty string if email is not valid.
func NormalizeEmail(email string) string {
	// Trim whitespace.
	email = strings.TrimSpace(email)
	// Make sure it is valid.
	if !IsValidEmail(email) {
		return ""
	}
	// Split email into parts.
	local, domain, ok := splitEmail(email)
	if !ok {
		return ""
	}
	// Remove trailing dot from domain.
	domain = strings.TrimRight(domain, ".")
	// Convert domain to lower case.
	domain = strings.ToLower(domain)
	// Combine and return the result.
	return local + "@" + domain
}
<commit_msg>Fix typo.<commit_after>// Copyright 2013 Dmitry Chestnykh. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package validator validates and normalizes email addresses and domain names.
package validator

import (
	"errors"
	"net"
	"regexp"
	"strings"
)

// Regular expression from WebCore's HTML5 email input: http://goo.gl/7SZbzj
var emailRegexp = regexp.MustCompile("(?i)" + // case insensitive
	"[a-z0-9!#$%&'*+/=?^_`{|}~.-]+" + // local part
	"@" +
	"[a-z0-9-]+(\\.[a-z0-9-]+)*") // domain part

// IsValidEmail returns true if the given string is a valid email address.
//
// It uses a simple regular expression to check the address validity.
func IsValidEmail(email string) bool {
	return emailRegexp.MatchString(email)
}

var ErrInvalidEmail = errors.New("invalid email address")

// fetchMXRecords fetches MX records for the domain of the given email.
func fetchMXRecords(email string) ([]*net.MX, error) {
	if !IsValidEmail(email) {
		return nil, ErrInvalidEmail
	}
	// Extract domain.
	_, domain, ok := splitEmail(email)
	if !ok {
		return nil, ErrInvalidEmail
	}
	if !IsValidDomain(domain) {
		return nil, ErrInvalidEmail
	}
	mx, err := net.LookupMX(domain)
	if err != nil {
		return nil, err
	}
	return mx, nil
}

// ValidateEmailByResolvingDomain validates email address by looking up MX
// records on its domain.
//
// This function can return various DNS errors, which may be temporary
// (e.g. caused by internet connection being offline) or permanent,
// e.g. the host doesn't exist or has no MX records.
//
// The function returns nil if email is valid and its domain can
// accept email messages (however this doesn't guarantee that a user
// with such email address exists on the host).
func ValidateEmailByResolvingDomain(email string) error {
	mx, err := fetchMXRecords(email)
	if err != nil {
		return err
	}
	if len(mx) == 0 {
		return ErrInvalidEmail
	}
	return nil
}

// splitEmail splits email address into local and domain parts.
// The last returned value is false if splitting fails.
func splitEmail(email string) (local string, domain string, ok bool) {
	parts := strings.Split(email, "@")
	if len(parts) < 2 {
		return
	}
	local = parts[0]
	domain = parts[1]
	// Check that the parts contain enough characters.
	if len(local) < 1 {
		return
	}
	if len(domain) < len("x.xx") {
		return
	}
	return local, domain, true
}

// NormalizeEmail returns a normalized email address.
// It returns an empty string if email is not valid.
func NormalizeEmail(email string) string {
	// Trim whitespace.
	email = strings.TrimSpace(email)
	// Make sure it is valid.
	if !IsValidEmail(email) {
		return ""
	}
	// Split email into parts.
	local, domain, ok := splitEmail(email)
	if !ok {
		return ""
	}
	// Remove trailing dot from domain.
	domain = strings.TrimRight(domain, ".")
	// Convert domain to lower case.
	domain = strings.ToLower(domain)
	// Combine and return the result.
	return local + "@" + domain
}
<|endoftext|>