<commit_before>// Copyright 2011 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 build gathers information about Go packages.
//
// Go Path
//
// The Go path is a list of directory trees containing Go source code.
// It is consulted to resolve imports that cannot be found in the standard
// Go tree. The default path is the value of the GOPATH environment
// variable, interpreted as a path list appropriate to the operating system
// (on Unix, the variable is a colon-separated string;
// on Windows, a semicolon-separated string;
// on Plan 9, a list).
//
// Each directory listed in the Go path must have a prescribed structure:
//
// The src/ directory holds source code. The path below 'src' determines
// the import path or executable name.
//
// The pkg/ directory holds installed package objects.
// As in the Go tree, each target operating system and
// architecture pair has its own subdirectory of pkg
// (pkg/GOOS_GOARCH).
//
// If DIR is a directory listed in the Go path, a package with
// source in DIR/src/foo/bar can be imported as "foo/bar" and
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
//
// The bin/ directory holds compiled commands.
// Each command is named for its source directory, but only
// using the final element, not the entire path. That is, the
// command with source in DIR/src/foo/quux is installed into
// DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
// so that you can add DIR/bin to your PATH to get at the
// installed commands.
//
// Here's an example directory layout:
//
//	GOPATH=/home/user/gocode
//
//	/home/user/gocode/
//	    src/
//	        foo/
//	            bar/               (go code in package bar)
//	                x.go
//	            quux/              (go code in package main)
//	                y.go
//	    bin/
//	        quux                   (installed command)
//	    pkg/
//	        linux_amd64/
//	            foo/
//	                bar.a          (installed package object)
//
// Build Constraints
//
// A build constraint, also known as a build tag, is a line comment that begins
//
//	// +build
//
// that lists the conditions under which a file should be included in the package.
// Constraints may appear in any kind of source file (not just Go), but
// they must appear near the top of the file, preceded
// only by blank lines and other line comments. These rules mean that in Go
// files a build constraint must appear before the package clause.
//
// To distinguish build constraints from package documentation, a series of
// build constraints must be followed by a blank line.
//
// A build constraint is evaluated as the OR of space-separated options;
// each option evaluates as the AND of its comma-separated terms;
// and each term is an alphanumeric word or, preceded by !, its negation.
// That is, the build constraint:
//
//	// +build linux,386 darwin,!cgo
//
// corresponds to the boolean formula:
//
//	(linux AND 386) OR (darwin AND (NOT cgo))
//
// A file may have multiple build constraints. The overall constraint is the AND
// of the individual constraints. That is, the build constraints:
//
//	// +build linux darwin
//	// +build 386
//
// corresponds to the boolean formula:
//
//	(linux OR darwin) AND 386
//
// During a particular build, the following words are satisfied:
//
//	- the target operating system, as spelled by runtime.GOOS
//	- the target architecture, as spelled by runtime.GOARCH
//	- the compiler being used, either "gc" or "gccgo"
//	- "cgo", if ctxt.CgoEnabled is true
//	- "go1.1", from Go version 1.1 onward
//	- "go1.2", from Go version 1.2 onward
//	- "go1.3", from Go version 1.3 onward
//	- "go1.4", from Go version 1.4 onward
//	- "go1.5", from Go version 1.5 onward
//	- "go1.6", from Go version 1.6 onward
//	- "go1.7", from Go version 1.7 onward
//	- "go1.8", from Go version 1.8 onward
//	- "go1.9", from Go version 1.9 onward
//	- "go1.10", from Go version 1.10 onward
//	- "go1.11", from Go version 1.11 onward
//	- "go1.12", from Go version 1.12 onward
//	- any additional words listed in ctxt.BuildTags
//
// There are no build tags for beta or minor releases. Programs that need the
// minor release number can call runtime.Version.
//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches any of the following patterns:
//	*_GOOS
// 	*_GOARCH
// 	*_GOOS_GOARCH
// (example: source_windows_amd64.go) where GOOS and GOARCH represent
// any known operating system and architecture values respectively, then
// the file is considered to have an implicit build constraint requiring
// those terms (in addition to any explicit constraints in the file).
//
// To keep a file from being considered for the build:
//
//	// +build ignore
//
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
//
// To build a file only when using cgo, and only on Linux and OS X:
//
//	// +build linux,cgo darwin,cgo
//
// Such a file is usually paired with another file implementing the
// default functionality for other systems, which in this case would
// carry the constraint:
//
//	// +build !linux,!darwin !cgo
//
// Naming a file dns_windows.go will cause it to be included only when
// building the package for Windows; similarly, math_386.s will be included
// only when building the package for 32-bit x86.
//
// Using GOOS=android matches build tags and files as for GOOS=linux
// in addition to android tags and files.
//
// Binary-Only Packages
//
// It is possible to distribute packages in binary form without including the
// source code used for compiling the package. To do this, the package must
// be distributed with a source file not excluded by build constraints and
// containing a "//go:binary-only-package" comment.
// Like a build constraint, this comment must appear near the top of the file,
// preceded only by blank lines and other line comments and with a blank line
// following the comment, to separate it from the package documentation.
// Unlike build constraints, this comment is only recognized in non-test
// Go source files.
//
// The minimal source code for a binary-only package is therefore:
//
//	//go:binary-only-package
//
//	package mypkg
//
// The source code may include additional Go code. That code is never compiled
// but will be processed by tools like godoc and might be useful as end-user
// documentation.
//
package build
<commit_msg>go/build: do not suggest runtime.Version in comment<commit_after>// Copyright 2011 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 build gathers information about Go packages.
//
// Go Path
//
// The Go path is a list of directory trees containing Go source code.
// It is consulted to resolve imports that cannot be found in the standard
// Go tree. The default path is the value of the GOPATH environment
// variable, interpreted as a path list appropriate to the operating system
// (on Unix, the variable is a colon-separated string;
// on Windows, a semicolon-separated string;
// on Plan 9, a list).
//
// Each directory listed in the Go path must have a prescribed structure:
//
// The src/ directory holds source code. The path below 'src' determines
// the import path or executable name.
//
// The pkg/ directory holds installed package objects.
// As in the Go tree, each target operating system and
// architecture pair has its own subdirectory of pkg
// (pkg/GOOS_GOARCH).
//
// If DIR is a directory listed in the Go path, a package with
// source in DIR/src/foo/bar can be imported as "foo/bar" and
// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a"
// (or, for gccgo, "DIR/pkg/gccgo/foo/libbar.a").
//
// The bin/ directory holds compiled commands.
// Each command is named for its source directory, but only
// using the final element, not the entire path. That is, the
// command with source in DIR/src/foo/quux is installed into
// DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
// so that you can add DIR/bin to your PATH to get at the
// installed commands.
//
// Here's an example directory layout:
//
//	GOPATH=/home/user/gocode
//
//	/home/user/gocode/
//	    src/
//	        foo/
//	            bar/               (go code in package bar)
//	                x.go
//	            quux/              (go code in package main)
//	                y.go
//	    bin/
//	        quux                   (installed command)
//	    pkg/
//	        linux_amd64/
//	            foo/
//	                bar.a          (installed package object)
//
// Build Constraints
//
// A build constraint, also known as a build tag, is a line comment that begins
//
//	// +build
//
// that lists the conditions under which a file should be included in the package.
// Constraints may appear in any kind of source file (not just Go), but
// they must appear near the top of the file, preceded
// only by blank lines and other line comments. These rules mean that in Go
// files a build constraint must appear before the package clause.
//
// To distinguish build constraints from package documentation, a series of
// build constraints must be followed by a blank line.
//
// A build constraint is evaluated as the OR of space-separated options;
// each option evaluates as the AND of its comma-separated terms;
// and each term is an alphanumeric word or, preceded by !, its negation.
// That is, the build constraint:
//
//	// +build linux,386 darwin,!cgo
//
// corresponds to the boolean formula:
//
//	(linux AND 386) OR (darwin AND (NOT cgo))
//
// A file may have multiple build constraints. The overall constraint is the AND
// of the individual constraints. That is, the build constraints:
//
//	// +build linux darwin
//	// +build 386
//
// corresponds to the boolean formula:
//
//	(linux OR darwin) AND 386
//
// During a particular build, the following words are satisfied:
//
//	- the target operating system, as spelled by runtime.GOOS
//	- the target architecture, as spelled by runtime.GOARCH
//	- the compiler being used, either "gc" or "gccgo"
//	- "cgo", if ctxt.CgoEnabled is true
//	- "go1.1", from Go version 1.1 onward
//	- "go1.2", from Go version 1.2 onward
//	- "go1.3", from Go version 1.3 onward
//	- "go1.4", from Go version 1.4 onward
//	- "go1.5", from Go version 1.5 onward
//	- "go1.6", from Go version 1.6 onward
//	- "go1.7", from Go version 1.7 onward
//	- "go1.8", from Go version 1.8 onward
//	- "go1.9", from Go version 1.9 onward
//	- "go1.10", from Go version 1.10 onward
//	- "go1.11", from Go version 1.11 onward
//	- "go1.12", from Go version 1.12 onward
//	- any additional words listed in ctxt.BuildTags
//
// There are no build tags for beta or minor releases.
//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches any of the following patterns:
//	*_GOOS
// 	*_GOARCH
// 	*_GOOS_GOARCH
// (example: source_windows_amd64.go) where GOOS and GOARCH represent
// any known operating system and architecture values respectively, then
// the file is considered to have an implicit build constraint requiring
// those terms (in addition to any explicit constraints in the file).
//
// To keep a file from being considered for the build:
//
//	// +build ignore
//
// (any other unsatisfied word will work as well, but ``ignore'' is conventional.)
//
// To build a file only when using cgo, and only on Linux and OS X:
//
//	// +build linux,cgo darwin,cgo
//
// Such a file is usually paired with another file implementing the
// default functionality for other systems, which in this case would
// carry the constraint:
//
//	// +build !linux,!darwin !cgo
//
// Naming a file dns_windows.go will cause it to be included only when
// building the package for Windows; similarly, math_386.s will be included
// only when building the package for 32-bit x86.
//
// Using GOOS=android matches build tags and files as for GOOS=linux
// in addition to android tags and files.
//
// Binary-Only Packages
//
// It is possible to distribute packages in binary form without including the
// source code used for compiling the package. To do this, the package must
// be distributed with a source file not excluded by build constraints and
// containing a "//go:binary-only-package" comment.
// Like a build constraint, this comment must appear near the top of the file,
// preceded only by blank lines and other line comments and with a blank line
// following the comment, to separate it from the package documentation.
// Unlike build constraints, this comment is only recognized in non-test
// Go source files.
//
// The minimal source code for a binary-only package is therefore:
//
//	//go:binary-only-package
//
//	package mypkg
//
// The source code may include additional Go code. That code is never compiled
// but will be processed by tools like godoc and might be useful as end-user
// documentation.
//
package build
<|endoftext|>


<commit_before>package http

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

var fileUrlMatcher = regexp.MustCompile("^/([a-z0-9]{32})$")

// HandlerConfig holds the configuration for a tus Handler.
type HandlerConfig struct {
	// Dir points to a filesystem path used by tus to store uploaded and partial
	// files. Will be created if does not exist yet. Required.
	Dir string

	// MaxSize defines how many bytes may be stored inside Dir. Exceeding this
	// limit will cause the oldest upload files to be deleted until enough space
	// is available again. Required.
	MaxSize int64

	// BasePath defines the url path used for handling uploads, e.g. "/files/".
	// Must contain a trailling "/". Requests not matching this base path will
	// cause a 404, so make sure you dispatch only appropriate requests to the
	// handler. Required.
	BasePath string
}

// NewHandler returns an initialized Handler. An error may occur if the
// config.Dir is not writable.
func NewHandler(config HandlerConfig) (*Handler, error) {
	// Ensure the data store directory exists
	if err := os.MkdirAll(config.Dir, 0777); err != nil {
		return nil, err
	}

	errChan := make(chan error)

	return &Handler{
		store:     newDataStore(config.Dir, config.MaxSize),
		config:    config,
		Error:     errChan,
		sendError: errChan,
	}, nil
}

// Handler is a http.Handler that implements tus resumable upload protocol.
type Handler struct {
	store  *dataStore
	config HandlerConfig

	// Error provides error events for logging purposes.
	Error <-chan error
	// same chan as Error, used for sending.
	sendError chan<- error
}

// ServeHTTP processes an incoming request according to the tus protocol.
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Verify that url matches BasePath
	absPath := r.URL.Path
	if !strings.HasPrefix(absPath, h.config.BasePath) {
		err := errors.New("unknown url: " + absPath + " - does not match BasePath: " + h.config.BasePath)
		h.err(err, w, http.StatusNotFound)
		return
	}

	// example relPath results: "/", "/f81d4fae7dec11d0a76500a0c91e6bf6", etc.
	relPath := absPath[len(h.config.BasePath)-1:]

	// file creation request
	if relPath == "/" {
		if r.Method == "POST" {
			h.createFile(w, r)
			return
		}

		// handle invalid method
		w.Header().Set("Allow", "POST")
		err := errors.New(r.Method + " used against file creation url. Only POST is allowed.")
		h.err(err, w, http.StatusMethodNotAllowed)
		return
	}

	if matches := fileUrlMatcher.FindStringSubmatch(relPath); matches != nil {
		id := matches[1]
		if r.Method == "PATCH" {
			h.patchFile(w, r, id)
			return
		} else if r.Method == "HEAD" {
			h.headFile(w, r, id)
			return
		}

		// handle invalid method
		allowed := "HEAD,PATCH"
		w.Header().Set("Allow", allowed)
		err := errors.New(r.Method + " used against file creation url. Allowed: " + allowed)
		h.err(err, w, http.StatusMethodNotAllowed)
		return
	}

	// handle unknown url
	err := errors.New("unknown url: " + absPath + " - does not match file pattern")
	h.err(err, w, http.StatusNotFound)
}

func (h *Handler) createFile(w http.ResponseWriter, r *http.Request) {
	id := uid()

	finalLength, err := getPositiveIntHeader(r, "Final-Length")
	if err != nil {
		h.err(err, w, http.StatusBadRequest)
		return
	}

	// @TODO: Define meta data extension and implement it here
	// @TODO: Make max finalLength configurable, reply with error if exceeded.
	// 			  This should go into the protocol as well.
	if err := h.store.CreateFile(id, finalLength, nil); err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

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

func (h *Handler) patchFile(w http.ResponseWriter, r *http.Request, id string) {
	offset, err := getPositiveIntHeader(r, "Offset")
	if err != nil {
		h.err(err, w, http.StatusBadRequest)
		return
	}

	info, err := h.store.GetInfo(id)
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	if offset > info.Offset {
		err = fmt.Errorf("Offset: %d exceeds current offset: %d", offset, info.Offset)
		h.err(err, w, http.StatusForbidden)
		return
	}

	// @TODO Test offset < current offset

	err = h.store.WriteFileChunk(id, offset, r.Body)
	if err != nil {
		// @TODO handle 404 properly (goes for all h.err calls)
		h.err(err, w, http.StatusInternalServerError)
		return
	}
}

func (h *Handler) headFile(w http.ResponseWriter, r *http.Request, id string) {
	info, err := h.store.GetInfo(id)
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	w.Header().Set("Offset", fmt.Sprintf("%d", info.Offset))
}

func getPositiveIntHeader(r *http.Request, key string) (int64, error) {
	val := r.Header.Get(key)
	if val == "" {
		return 0, errors.New(key+" header must not be empty")
	}

	intVal, err := strconv.ParseInt(val, 10, 64)
	if err != nil {
		return 0, errors.New("invalid " + key + " header: " + err.Error())
	} else if intVal < 0 {
		return 0, errors.New(key + " header must be > 0")
	}
	return intVal, nil
}

// absUrl turn a relPath (e.g. "/foo") into an absolute url (e.g.
// "http://example.com/foo").
//
// @TODO: Look at r.TLS to determine the url scheme.
// @TODO: Make url prefix user configurable (optional) to deal with reverse
// 				proxies. This could be done by turning BasePath into BaseURL that
//				that could be relative or absolute.
func (h *Handler) absUrl(r *http.Request, relPath string) string {
	return "http://" + r.Host + path.Clean(h.config.BasePath+relPath)
}

// err sends a http error response and publishes to the Error channel.
func (h *Handler) err(err error, w http.ResponseWriter, status int) {
	w.WriteHeader(status)
	io.WriteString(w, err.Error()+"\n")

	// non-blocking send
	select {
	case h.sendError <- err:
	default:
	}
}
<commit_msg>implementing GET file<commit_after>package http

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
)

var fileUrlMatcher = regexp.MustCompile("^/([a-z0-9]{32})$")

// HandlerConfig holds the configuration for a tus Handler.
type HandlerConfig struct {
	// Dir points to a filesystem path used by tus to store uploaded and partial
	// files. Will be created if does not exist yet. Required.
	Dir string

	// MaxSize defines how many bytes may be stored inside Dir. Exceeding this
	// limit will cause the oldest upload files to be deleted until enough space
	// is available again. Required.
	MaxSize int64

	// BasePath defines the url path used for handling uploads, e.g. "/files/".
	// Must contain a trailling "/". Requests not matching this base path will
	// cause a 404, so make sure you dispatch only appropriate requests to the
	// handler. Required.
	BasePath string
}

// NewHandler returns an initialized Handler. An error may occur if the
// config.Dir is not writable.
func NewHandler(config HandlerConfig) (*Handler, error) {
	// Ensure the data store directory exists
	if err := os.MkdirAll(config.Dir, 0777); err != nil {
		return nil, err
	}

	errChan := make(chan error)

	return &Handler{
		store:     newDataStore(config.Dir, config.MaxSize),
		config:    config,
		Error:     errChan,
		sendError: errChan,
	}, nil
}

// Handler is a http.Handler that implements tus resumable upload protocol.
type Handler struct {
	store  *dataStore
	config HandlerConfig

	// Error provides error events for logging purposes.
	Error <-chan error
	// same chan as Error, used for sending.
	sendError chan<- error
}

// ServeHTTP processes an incoming request according to the tus protocol.
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Verify that url matches BasePath
	absPath := r.URL.Path
	if !strings.HasPrefix(absPath, h.config.BasePath) {
		err := errors.New("unknown url: " + absPath + " - does not match BasePath: " + h.config.BasePath)
		h.err(err, w, http.StatusNotFound)
		return
	}

	// example relPath results: "/", "/f81d4fae7dec11d0a76500a0c91e6bf6", etc.
	relPath := absPath[len(h.config.BasePath)-1:]

	// file creation request
	if relPath == "/" {
		if r.Method == "POST" {
			h.createFile(w, r)
			return
		}

		// handle invalid method
		w.Header().Set("Allow", "POST")
		err := errors.New(r.Method + " used against file creation url. Only POST is allowed.")
		h.err(err, w, http.StatusMethodNotAllowed)
		return
	}

	if matches := fileUrlMatcher.FindStringSubmatch(relPath); matches != nil {
		id := matches[1]
		if r.Method == "PATCH" {
			h.patchFile(w, r, id)
			return
		} else if r.Method == "HEAD" {
			h.headFile(w, r, id)
			return
		} else if r.Method == "GET" {
			h.getFile(w, r, id)
			return
		}

		// handle invalid method
		allowed := "HEAD,PATCH"
		w.Header().Set("Allow", allowed)
		err := errors.New(r.Method + " used against file creation url. Allowed: " + allowed)
		h.err(err, w, http.StatusMethodNotAllowed)
		return
	}

	// handle unknown url
	err := errors.New("unknown url: " + absPath + " - does not match file pattern")
	h.err(err, w, http.StatusNotFound)
}

func (h *Handler) createFile(w http.ResponseWriter, r *http.Request) {
	id := uid()

	finalLength, err := getPositiveIntHeader(r, "Final-Length")
	if err != nil {
		h.err(err, w, http.StatusBadRequest)
		return
	}

	// @TODO: Define meta data extension and implement it here
	// @TODO: Make max finalLength configurable, reply with error if exceeded.
	// 			  This should go into the protocol as well.
	if err := h.store.CreateFile(id, finalLength, nil); err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

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

func (h *Handler) patchFile(w http.ResponseWriter, r *http.Request, id string) {
	offset, err := getPositiveIntHeader(r, "Offset")
	if err != nil {
		h.err(err, w, http.StatusBadRequest)
		return
	}

	info, err := h.store.GetInfo(id)
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	if offset > info.Offset {
		err = fmt.Errorf("Offset: %d exceeds current offset: %d", offset, info.Offset)
		h.err(err, w, http.StatusForbidden)
		return
	}

	// @TODO Test offset < current offset

	err = h.store.WriteFileChunk(id, offset, r.Body)
	if err != nil {
		// @TODO handle 404 properly (goes for all h.err calls)
		h.err(err, w, http.StatusInternalServerError)
		return
	}
}

func (h *Handler) headFile(w http.ResponseWriter, r *http.Request, id string) {
	info, err := h.store.GetInfo(id)
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	w.Header().Set("Offset", fmt.Sprintf("%d", info.Offset))
}

// GET requests on files aren't part of the protocol yet,
// but it is implemented here anyway for the demo. It still lacks the meta data
// extension in order to send the proper content type header.
func (h *Handler) getFile(w http.ResponseWriter, r *http.Request, fileId string) {
	info, err := h.store.GetInfo(fileId)
	if os.IsNotExist(err) {
		h.err(err, w, http.StatusNotFound)
		return
	}
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	data, err := h.store.ReadFile(fileId)
	if os.IsNotExist(err) {
		h.err(err, w, http.StatusNotFound)
		return
	}
	if err != nil {
		h.err(err, w, http.StatusInternalServerError)
		return
	}

	defer data.Close()

	w.Header().Set("Offset", strconv.FormatInt(info.Offset, 10))

	// @TODO: Once the meta extension is done, send the proper content type here
	//w.Header().Set("Content-Type", info.Meta.ContentType)

	w.Header().Set("Content-Length", strconv.FormatInt(info.FinalLength, 10))

	if _, err := io.CopyN(w, data, info.FinalLength); err != nil {
		return
	}
}

func getPositiveIntHeader(r *http.Request, key string) (int64, error) {
	val := r.Header.Get(key)
	if val == "" {
		return 0, errors.New(key + " header must not be empty")
	}

	intVal, err := strconv.ParseInt(val, 10, 64)
	if err != nil {
		return 0, errors.New("invalid " + key + " header: " + err.Error())
	} else if intVal < 0 {
		return 0, errors.New(key + " header must be > 0")
	}
	return intVal, nil
}

// absUrl turn a relPath (e.g. "/foo") into an absolute url (e.g.
// "http://example.com/foo").
//
// @TODO: Look at r.TLS to determine the url scheme.
// @TODO: Make url prefix user configurable (optional) to deal with reverse
// 				proxies. This could be done by turning BasePath into BaseURL that
//				that could be relative or absolute.
func (h *Handler) absUrl(r *http.Request, relPath string) string {
	return "http://" + r.Host + path.Clean(h.config.BasePath+relPath)
}

// err sends a http error response and publishes to the Error channel.
func (h *Handler) err(err error, w http.ResponseWriter, status int) {
	w.WriteHeader(status)
	io.WriteString(w, err.Error()+"\n")

	// non-blocking send
	select {
	case h.sendError <- err:
	default:
	}
}
<|endoftext|>


<commit_before>package extensions

import (
	"fmt"

	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/pagination"
)

// GetResult temporarily stores the result of a Get call.
// Use its Extract() method to interpret it as an Extension.
type GetResult struct {
	gophercloud.CommonResult
}

// Extract interprets a GetResult as an Extension.
func (r GetResult) Extract() (*Extension, error) {
	if r.Err != nil {
		return nil, r.Err
	}

	var res struct {
		Extension *Extension `json:"extension"`
	}

	err := mapstructure.Decode(r.Resp, &res)
	if err != nil {
		return nil, fmt.Errorf("Error decoding OpenStack extension: %v", err)
	}

	return res.Extension, nil
}

// Extension is a struct that represents an OpenStack extension.
type Extension struct {
	Updated     string        `json:"updated"`
	Name        string        `json:"name"`
	Links       []interface{} `json:"links"`
	Namespace   string        `json:"namespace"`
	Alias       string        `json:"alias"`
	Description string        `json:"description"`
}

// ExtensionPage is the page returned by a pager when traversing over a collection of extensions.
type ExtensionPage struct {
	pagination.SinglePageBase
}

// IsEmpty checks whether an ExtensionPage struct is empty.
func (r ExtensionPage) IsEmpty() (bool, error) {
	is, err := ExtractExtensions(r)
	if err != nil {
		return true, err
	}
	return len(is) == 0, nil
}

// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
// elements into a slice of Extension structs.
// In other words, a generic collection is mapped into a relevant slice.
func ExtractExtensions(page pagination.Page) ([]Extension, error) {
	var resp struct {
		Extensions []Extension `mapstructure:"extensions"`
	}

	err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)
	if err != nil {
		return nil, err
	}

	return resp.Extensions, nil
}
<commit_msg>Removing unnecessary conditionals from common exts<commit_after>package extensions

import (
	"github.com/mitchellh/mapstructure"
	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/pagination"
)

// GetResult temporarily stores the result of a Get call.
// Use its Extract() method to interpret it as an Extension.
type GetResult struct {
	gophercloud.CommonResult
}

// Extract interprets a GetResult as an Extension.
func (r GetResult) Extract() (*Extension, error) {
	if r.Err != nil {
		return nil, r.Err
	}

	var res struct {
		Extension *Extension `json:"extension"`
	}

	err := mapstructure.Decode(r.Resp, &res)

	return res.Extension, err
}

// Extension is a struct that represents an OpenStack extension.
type Extension struct {
	Updated     string        `json:"updated"`
	Name        string        `json:"name"`
	Links       []interface{} `json:"links"`
	Namespace   string        `json:"namespace"`
	Alias       string        `json:"alias"`
	Description string        `json:"description"`
}

// ExtensionPage is the page returned by a pager when traversing over a collection of extensions.
type ExtensionPage struct {
	pagination.SinglePageBase
}

// IsEmpty checks whether an ExtensionPage struct is empty.
func (r ExtensionPage) IsEmpty() (bool, error) {
	is, err := ExtractExtensions(r)
	if err != nil {
		return true, err
	}
	return len(is) == 0, nil
}

// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
// elements into a slice of Extension structs.
// In other words, a generic collection is mapped into a relevant slice.
func ExtractExtensions(page pagination.Page) ([]Extension, error) {
	var resp struct {
		Extensions []Extension `mapstructure:"extensions"`
	}

	err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)

	return resp.Extensions, err
}
<|endoftext|>


<commit_before>package osxkeychain

import (
	"github.com/docker/docker-credential-helpers/credentials"
	"testing"
)

func TestOSXKeychainHelper(t *testing.T) {
	creds := &credentials.Credentials{
		ServerURL: "https://foobar.docker.io:2376/v1",
		Username:  "foobar",
		Secret:    "foobarbaz",
	}
	creds1 := &credentials.Credentials{
		ServerURL: "https://foobar.docker.io:2376/v2",
		Username:  "foobarbaz",
		Secret:    "foobar",
	}
	helper := Osxkeychain{}
	if err := helper.Add(creds); err != nil {
		t.Fatal(err)
	}

	username, secret, err := helper.Get(creds.ServerURL)
	if err != nil {
		t.Fatal(err)
	}

	if username != "foobar" {
		t.Fatalf("expected %s, got %s\n", "foobar", username)
	}

	if secret != "foobarbaz" {
		t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
	}

	paths, accts, err := helper.List()
	if err != nil || len(paths) == 0 || len(accts) == 0 {
		t.Fatal(err)
	}

	if err := helper.Delete(creds.ServerURL); err != nil {
		t.Fatal(err)
	}

	helper.Add(creds1)
	defer helper.Delete(creds1.ServerURL)
	newpaths, newaccts, err := helper.List()
	if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 {
		t.Fatal(err)
	}
}

func TestMissingCredentials(t *testing.T) {
	helper := Osxkeychain{}
	_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
	if !credentials.IsErrCredentialsNotFound(err) {
		t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
	}
}
<commit_msg>fixed a bug in the test for osx<commit_after>package osxkeychain

import (
	"github.com/docker/docker-credential-helpers/credentials"
	"testing"
)

func TestOSXKeychainHelper(t *testing.T) {
	creds := &credentials.Credentials{
		ServerURL: "https://foobar.docker.io:2376/v1",
		Username:  "foobar",
		Secret:    "foobarbaz",
	}
	creds1 := &credentials.Credentials{
		ServerURL: "https://foobar.docker.io:2376/v2",
		Username:  "foobarbaz",
		Secret:    "foobar",
	}
	helper := Osxkeychain{}
	if err := helper.Add(creds); err != nil {
		t.Fatal(err)
	}

	username, secret, err := helper.Get(creds.ServerURL)
	if err != nil {
		t.Fatal(err)
	}

	if username != "foobar" {
		t.Fatalf("expected %s, got %s\n", "foobar", username)
	}

	if secret != "foobarbaz" {
		t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
	}

	paths, accts, err := helper.List()
	if err != nil || len(paths) == 0 || len(accts) == 0 {
		t.Fatal(err)
	}

	helper.Add(creds1)
	defer helper.Delete(creds1.ServerURL)
	newpaths, newaccts, err := helper.List()
	if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 {
		if(err == nil) {
			t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), nil)
		}
		t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error())
	}

	if err := helper.Delete(creds.ServerURL); err != nil {
		t.Fatal(err)
	}
}

func TestMissingCredentials(t *testing.T) {
	helper := Osxkeychain{}
	_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
	if !credentials.IsErrCredentialsNotFound(err) {
		t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package fever // import "miniflux.app/fever"

import (
	"context"
	"net/http"

	"miniflux.app/http/request"
	"miniflux.app/http/response/json"
	"miniflux.app/logger"
	"miniflux.app/storage"
)

type middleware struct {
	store *storage.Storage
}

func newMiddleware(s *storage.Storage) *middleware {
	return &middleware{s}
}

func (m *middleware) serve(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		apiKey := r.FormValue("api_key")
		if apiKey == "" {
			logger.Info("[Fever] No API key provided")
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		user, err := m.store.UserByFeverToken(apiKey)
		if err != nil {
			logger.Error("[Fever] %v", err)
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		if user == nil {
			logger.Info("[Fever] No user found with this API key")
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		logger.Info("[Fever] User #%d is authenticated with user agent %q", user.ID, r.UserAgent())
		m.store.SetLastLogin(user.ID)

		ctx := r.Context()
		ctx = context.WithValue(ctx, request.UserIDContextKey, user.ID)
		ctx = context.WithValue(ctx, request.UserTimezoneContextKey, user.Timezone)
		ctx = context.WithValue(ctx, request.IsAdminUserContextKey, user.IsAdmin)
		ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)

		next.ServeHTTP(w, r.WithContext(ctx))
	})
}
<commit_msg>Fever API: add client IP in middleware logs<commit_after>// Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.

package fever // import "miniflux.app/fever"

import (
	"context"
	"net/http"

	"miniflux.app/http/request"
	"miniflux.app/http/response/json"
	"miniflux.app/logger"
	"miniflux.app/storage"
)

type middleware struct {
	store *storage.Storage
}

func newMiddleware(s *storage.Storage) *middleware {
	return &middleware{s}
}

func (m *middleware) serve(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		clientIP := request.ClientIP(r)
		apiKey := r.FormValue("api_key")
		if apiKey == "" {
			logger.Info("[Fever] [ClientIP=%s] No API key provided", clientIP)
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		user, err := m.store.UserByFeverToken(apiKey)
		if err != nil {
			logger.Error("[Fever] %v", err)
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		if user == nil {
			logger.Info("[Fever] [ClientIP=%s] No user found with this API key", clientIP)
			json.OK(w, r, newAuthFailureResponse())
			return
		}

		logger.Info("[Fever] [ClientIP=%s] User #%d is authenticated with user agent %q", clientIP, user.ID, r.UserAgent())
		m.store.SetLastLogin(user.ID)

		ctx := r.Context()
		ctx = context.WithValue(ctx, request.UserIDContextKey, user.ID)
		ctx = context.WithValue(ctx, request.UserTimezoneContextKey, user.Timezone)
		ctx = context.WithValue(ctx, request.IsAdminUserContextKey, user.IsAdmin)
		ctx = context.WithValue(ctx, request.IsAuthenticatedContextKey, true)

		next.ServeHTTP(w, r.WithContext(ctx))
	})
}
<|endoftext|>


<commit_before>package sync

import (
	"io"
	"sync"

	ds "github.com/jbenet/go-datastore"
	dsq "github.com/jbenet/go-datastore/query"
)

// MutexDatastore contains a child datastire and a mutex.
// used for coarse sync
type MutexDatastore struct {
	sync.RWMutex

	child ds.Datastore
}

// MutexWrap constructs a datastore with a coarse lock around
// the entire datastore, for every single operation
func MutexWrap(d ds.Datastore) *MutexDatastore {
	return &MutexDatastore{child: d}
}

// Children implements Shim
func (d *MutexDatastore) Children() []ds.Datastore {
	return []ds.Datastore{d.child}
}

// IsThreadSafe implements ThreadSafeDatastore
func (d *MutexDatastore) IsThreadSafe() {}

// Put implements Datastore.Put
func (d *MutexDatastore) Put(key ds.Key, value interface{}) (err error) {
	d.Lock()
	defer d.Unlock()
	return d.child.Put(key, value)
}

// Get implements Datastore.Get
func (d *MutexDatastore) Get(key ds.Key) (value interface{}, err error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Get(key)
}

// Has implements Datastore.Has
func (d *MutexDatastore) Has(key ds.Key) (exists bool, err error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Has(key)
}

// Delete implements Datastore.Delete
func (d *MutexDatastore) Delete(key ds.Key) (err error) {
	d.Lock()
	defer d.Unlock()
	return d.child.Delete(key)
}

// KeyList implements Datastore.KeyList
func (d *MutexDatastore) Query(q dsq.Query) (dsq.Results, error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Query(q)
}

func (d *MutexDatastore) Batch() (ds.Batch, error) {
	d.RLock()
	defer d.RUnlock()
	bds, ok := d.child.(ds.Batching)
	if !ok {
		return nil, ds.ErrBatchUnsupported
	}

	b, err := bds.Batch()
	if err != nil {
		return nil, err
	}
	return &syncBatch{
		batch: b,
	}, nil
}

func (d *MutexDatastore) Close() error {
	d.RWMutex.Lock()
	defer d.RWMutex.Unlock()
	if c, ok := d.child.(io.Closer); ok {
		return c.Close()
	}
	return nil
}

type syncBatch struct {
	lk    sync.Mutex
	batch ds.Batch
}

func (b *syncBatch) Put(key ds.Key, val interface{}) error {
	b.lk.Lock()
	defer b.lk.Unlock()
	return b.batch.Put(key, val)
}

func (b *syncBatch) Delete(key ds.Key) error {
	b.lk.Lock()
	defer b.lk.Unlock()
	return b.batch.Delete(key)
}

func (b *syncBatch) Commit() error {
	b.lk.Lock()
	defer b.lk.Unlock()
	return b.batch.Commit()
}
<commit_msg>fix locking in syncbatch<commit_after>package sync

import (
	"io"
	"sync"

	ds "github.com/jbenet/go-datastore"
	dsq "github.com/jbenet/go-datastore/query"
)

// MutexDatastore contains a child datastire and a mutex.
// used for coarse sync
type MutexDatastore struct {
	sync.RWMutex

	child ds.Datastore
}

// MutexWrap constructs a datastore with a coarse lock around
// the entire datastore, for every single operation
func MutexWrap(d ds.Datastore) *MutexDatastore {
	return &MutexDatastore{child: d}
}

// Children implements Shim
func (d *MutexDatastore) Children() []ds.Datastore {
	return []ds.Datastore{d.child}
}

// IsThreadSafe implements ThreadSafeDatastore
func (d *MutexDatastore) IsThreadSafe() {}

// Put implements Datastore.Put
func (d *MutexDatastore) Put(key ds.Key, value interface{}) (err error) {
	d.Lock()
	defer d.Unlock()
	return d.child.Put(key, value)
}

// Get implements Datastore.Get
func (d *MutexDatastore) Get(key ds.Key) (value interface{}, err error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Get(key)
}

// Has implements Datastore.Has
func (d *MutexDatastore) Has(key ds.Key) (exists bool, err error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Has(key)
}

// Delete implements Datastore.Delete
func (d *MutexDatastore) Delete(key ds.Key) (err error) {
	d.Lock()
	defer d.Unlock()
	return d.child.Delete(key)
}

// KeyList implements Datastore.KeyList
func (d *MutexDatastore) Query(q dsq.Query) (dsq.Results, error) {
	d.RLock()
	defer d.RUnlock()
	return d.child.Query(q)
}

func (d *MutexDatastore) Batch() (ds.Batch, error) {
	d.RLock()
	defer d.RUnlock()
	bds, ok := d.child.(ds.Batching)
	if !ok {
		return nil, ds.ErrBatchUnsupported
	}

	b, err := bds.Batch()
	if err != nil {
		return nil, err
	}
	return &syncBatch{
		batch: b,
	}, nil
}

func (d *MutexDatastore) Close() error {
	d.RWMutex.Lock()
	defer d.RWMutex.Unlock()
	if c, ok := d.child.(io.Closer); ok {
		return c.Close()
	}
	return nil
}

type syncBatch struct {
	batch ds.Batch
	mds   *MutexDatastore
}

func (b *syncBatch) Put(key ds.Key, val interface{}) error {
	b.mds.Lock()
	defer b.mds.Unlock()
	return b.batch.Put(key, val)
}

func (b *syncBatch) Delete(key ds.Key) error {
	b.mds.Lock()
	defer b.mds.Unlock()
	return b.batch.Delete(key)
}

func (b *syncBatch) Commit() error {
	b.mds.Lock()
	defer b.mds.Unlock()
	return b.batch.Commit()
}
<|endoftext|>


<commit_before>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type ContainerChanges struct {
	Path string
	Kind int
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Stats struct {
	Read    time.Time `json:"read"`
	Network struct {
		RxBytes   uint64 `json:"rx_bytes"`
		RxPackets uint64 `json:"rx_packets"`
		RxErrors  uint64 `json:"rx_errors"`
		RxDropped uint64 `json:"rx_dropped"`
		TxBytes   uint64 `json:"tx_bytes"`
		TxPackets uint64 `json:"tx_packets"`
		TxErrors  uint64 `json:"tx_errors"`
		TxDropped uint64 `json:"tx_dropped"`
	}

	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}
<commit_msg>Add Labels map field to ContainerConfig<commit_after>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Labels          map[string]string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type ContainerChanges struct {
	Path string
	Kind int
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Stats struct {
	Read    time.Time `json:"read"`
	Network struct {
		RxBytes   uint64 `json:"rx_bytes"`
		RxPackets uint64 `json:"rx_packets"`
		RxErrors  uint64 `json:"rx_errors"`
		RxDropped uint64 `json:"rx_dropped"`
		TxBytes   uint64 `json:"tx_bytes"`
		TxPackets uint64 `json:"tx_packets"`
		TxErrors  uint64 `json:"tx_errors"`
		TxDropped uint64 `json:"tx_dropped"`
	}

	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}
<|endoftext|>


<commit_before>package btsync_api

type Folder struct {
  Dir      string `json:"dir"`
  Secret   string `json:"secret"`
  Size     int64  `json:"size"`
  Type     string `json:"type"`
  Files    int64  `json:"files"`
  Error    int    `json:"error"`
  Indexing int    `json:"indexing"`
}

type File struct {
  HavePieces  int    `json:"have_pieces"`
  Name        string `json:"name"`
  Size        int64  `json:"size"`
  State       string `json:"state"`
  TotalPieces string `json:"total_pieces"`
  Type        string `json:"type"`
  Download    int    `json:"download"`
}

type Peer struct {
  Id         string `json:"id"`
  Connection string `json:"connection"`
  Name       string `json:"name"`
  Synced     int    `json:"synced"`
  Download   int64  `json:"download"`
  Upload     int64  `json:"upload"`
}

type Preferences struct {
  DeviceName                 string `json:"device_name"`
  DiskLowPriority            bool   `json:"disk_low_priority"`
  DownloadLimit              int    `json:"download_limit"`
  FolderRescanInterval       int    `json:"folder_rescan_interval"`
  LANEncryptData             bool   `json:"lan_encrypt_data"`
  LANUseTCP                  bool   `json:"lan_use_tcp"`
  Lang                       int    `json:"lang"`
  ListeningPort              int    `json:"listening_port"`
  MaxFileSizeDiffForPatching int64  `json:"max_file_size_diff_for_patching"`
  MaxFileSizeForVersioning   int64  `json:"max_file_size_for_versioning"`
  RateLimitLocalPeers        bool   `json:"rate_limit_local_peers"`
  ReadPoolSize               int64  `json:"read_pool_size"`
  SyncMaxTimeDiff            int64  `json:"sync_max_time_diff"`
  SyncTrashTTL               int64  `json:"sync_trash_ttl"`
  UploadLimit                int64  `json:"upload_limit"`
  UseUPnP                    int    `json:"use_upnp"`
  WritePoolSize              int    `json:"write_pool_size"`
}

type FolderPreferences struct {
  SearchLAN      int `json:"search_lan"`
  SelectiveSync  int `json:"selective_sync"`
  UseDHT         int `json:"use_dht"`
  UseHosts       int `json:"use_hosts"`
  UseRelayServer int `json:"use_relay_server"`
  UseSyncTrash   int `json:"use_sync_trash"`
  UseTracker     int `json:"use_tracker"`
}

type Response struct {
  Error   int    `json:"error"`
  Message string `json:"message"`
}

type GetFoldersResponse []Folder

type GetFilesResponse []File

type SetFilePrefsResponse []File

type GetFolderPeersResponse []Peer

type GetSecretsResponse struct {
  ReadOnly   string `json:"read_only"`
  ReadWrite  string `json:"read_write"`
  Encryption string `json:"encryption"`
}

type GetFolderPrefsResponse FolderPreferences
type SetFolderPrefsResponse FolderPreferences

type GetFolderHostsResponse []string

type GetPreferencesResponse Preferences

type GetOSResponse struct {
  Name string `json:"os"`
}

type GetVersionResponse struct {
  Version string `json:"version"`
}

type GetSpeedResponse struct {
  Download int64 `json:"download"`
  Upload   int64 `json:"upload"`
}
<commit_msg>Fix incorrect type for total_pieces property in File struct. Should be int and not string.<commit_after>package btsync_api

type Folder struct {
  Dir      string `json:"dir"`
  Secret   string `json:"secret"`
  Size     int64  `json:"size"`
  Type     string `json:"type"`
  Files    int64  `json:"files"`
  Error    int    `json:"error"`
  Indexing int    `json:"indexing"`
}

type File struct {
  HavePieces  int    `json:"have_pieces"`
  Name        string `json:"name"`
  Size        int64  `json:"size"`
  State       string `json:"state"`
  TotalPieces int    `json:"total_pieces"`
  Type        string `json:"type"`
  Download    int    `json:"download"`
}

type Peer struct {
  Id         string `json:"id"`
  Connection string `json:"connection"`
  Name       string `json:"name"`
  Synced     int    `json:"synced"`
  Download   int64  `json:"download"`
  Upload     int64  `json:"upload"`
}

type Preferences struct {
  DeviceName                 string `json:"device_name"`
  DiskLowPriority            bool   `json:"disk_low_priority"`
  DownloadLimit              int    `json:"download_limit"`
  FolderRescanInterval       int    `json:"folder_rescan_interval"`
  LANEncryptData             bool   `json:"lan_encrypt_data"`
  LANUseTCP                  bool   `json:"lan_use_tcp"`
  Lang                       int    `json:"lang"`
  ListeningPort              int    `json:"listening_port"`
  MaxFileSizeDiffForPatching int64  `json:"max_file_size_diff_for_patching"`
  MaxFileSizeForVersioning   int64  `json:"max_file_size_for_versioning"`
  RateLimitLocalPeers        bool   `json:"rate_limit_local_peers"`
  ReadPoolSize               int64  `json:"read_pool_size"`
  SyncMaxTimeDiff            int64  `json:"sync_max_time_diff"`
  SyncTrashTTL               int64  `json:"sync_trash_ttl"`
  UploadLimit                int64  `json:"upload_limit"`
  UseUPnP                    int    `json:"use_upnp"`
  WritePoolSize              int    `json:"write_pool_size"`
}

type FolderPreferences struct {
  SearchLAN      int `json:"search_lan"`
  SelectiveSync  int `json:"selective_sync"`
  UseDHT         int `json:"use_dht"`
  UseHosts       int `json:"use_hosts"`
  UseRelayServer int `json:"use_relay_server"`
  UseSyncTrash   int `json:"use_sync_trash"`
  UseTracker     int `json:"use_tracker"`
}

type Response struct {
  Error   int    `json:"error"`
  Message string `json:"message"`
}

type GetFoldersResponse []Folder

type GetFilesResponse []File

type SetFilePrefsResponse []File

type GetFolderPeersResponse []Peer

type GetSecretsResponse struct {
  ReadOnly   string `json:"read_only"`
  ReadWrite  string `json:"read_write"`
  Encryption string `json:"encryption"`
}

type GetFolderPrefsResponse FolderPreferences
type SetFolderPrefsResponse FolderPreferences

type GetFolderHostsResponse []string

type GetPreferencesResponse Preferences

type GetOSResponse struct {
  Name string `json:"os"`
}

type GetVersionResponse struct {
  Version string `json:"version"`
}

type GetSpeedResponse struct {
  Download int64 `json:"download"`
  Upload   int64 `json:"upload"`
}
<|endoftext|>


<commit_before>package form

import (
	"regexp"
	"strconv"
	"strings"
	"time"
)

// Bool is a bool that implements Parser
type Bool struct {
	Data *bool
}

// Parse is an implementation of Parser
func (b Bool) Parse(d []string) error {
	switch strings.ToLower(d[0]) {
	case "on", "yes", "y":
		*b.Data = true
	case "off", "no", "n":
		*b.Data = false
	default:
		c, err := strconv.ParseBool(d[0])
		*b.Data = c
		return err
	}
	return nil
}

// Int is an int that implements Parser
type Int struct {
	Data *int
}

// Parse is an implementation of Parser
func (i Int) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 0)
	*i.Data = int(n)
	return err
}

// Int8 is an int8 that implements Parser
type Int8 struct {
	Data *int8
}

// Parse is an implementation of Parser
func (i Int8) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 8)
	*i.Data = int8(n)
	return err
}

// Int16 is an int16 that implements Parser
type Int16 struct {
	Data *int16
}

// Parse is an implementation of Parser
func (i Int16) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 16)
	*i.Data = int16(n)
	return err
}

// Int32 is an int32 that implements Parser
type Int32 struct {
	Data *int32
}

// Parse is an implementation of Parser
func (i Int32) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 32)
	*i.Data = int32(n)
	return err
}

// Int64 is an int64 that implements Parser
type Int64 struct {
	Data *int64
}

// Parse is an implementation of Parser
func (i Int64) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 64)
	*i.Data = n
	return err
}

// IntBetween is an implementation of Parser that allows a signed integer
// between the Min and Max (inclusively)
type IntBetween struct {
	Parser
	Min, Max int64
}

// Parse is an implementation of Parser
func (i IntBetween) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 64)
	if err != nil {
		return err
	}
	if n >= i.Min && n <= i.Max {
		return i.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// Uint is a uint that implements Parser
type Uint struct {
	Data *uint
}

// Parse is an implementation of Parser
func (u Uint) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 0)
	*u.Data = uint(n)
	return err
}

// Uint8 is a uint8 that implements Parser
type Uint8 struct {
	Data *uint8
}

// Parse is an implementation of Parser
func (u Uint8) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 8)
	*u.Data = uint8(n)
	return err
}

// Uint16 is a uint16 that implements Parser
type Uint16 struct {
	Data *uint16
}

// Parse is an implementation of Parser
func (u Uint16) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 16)
	*u.Data = uint16(n)
	return err
}

// Uint32 is a uint32 that implements Parser
type Uint32 struct {
	Data *uint32
}

// Parse is an implementation of Parser
func (u Uint32) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 32)
	*u.Data = uint32(n)
	return err
}

// Uint64 is a uint64 that implements Parser
type Uint64 struct {
	Data *uint64
}

// Parse is an implementation of Parser
func (u Uint64) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 64)
	*u.Data = n
	return err
}

// UintBetween is an implementation of Parser that allows an unsigned integer
// between the Min and Max (inclusively)
type UintBetween struct {
	Parser
	Min, Max uint64
}

// Parse is an implementation of Parser
func (u UintBetween) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 64)
	if err != nil {
		return err
	}
	if n >= u.Min && n <= u.Max {
		return u.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// Float32 is a float32 that implements Parser
type Float32 struct {
	Data *float32
}

// Parse is an implementation of Parser
func (f Float32) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 32)
	*f.Data = float32(n)
	return err
}

// Float64 is a float64 that implements Parser
type Float64 struct {
	Data *float64
}

// Parse is an implementation of Parser
func (f Float64) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 64)
	*f.Data = n
	return err
}

// FloatBetween is an implementation of Parser that allows a float between the
// Min and Max (inclusively)
type FloatBetween struct {
	Parser
	Min, Max float64
}

// Parse is an implementation of Parser
func (f FloatBetween) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 64)
	if err != nil {
		return err
	}
	if n >= f.Min && n <= f.Max {
		return f.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// String is a string that implements Parser
type String struct {
	Data *string
}

// Parse is an implementation of Parser
func (s String) Parse(d []string) error {
	*s.Data = d[0]
	return nil
}

// RegexString is an implementation of Parser that matches a string again the
// given regular expression
type RegexString struct {
	Data  *string
	Regex *regexp.Regexp
}

// Parse is an implementation of Parser
func (r RegexString) Parse(d []string) error {
	if r.Regex.MatchString(d[0]) {
		*r.Data = d[0]
		return nil
	}
	return NoRegexMatch(d[0])
}

type RequiredString String

func (r RequiredString) Parse(d []string) error {
	if d[0] == "" {
		return Empty{}
	}
	*r.Data = d[0]
	return nil
}

var formats = [...]string{
	time.ANSIC,
	time.Kitchen,
	time.RFC1123,
	time.RFC1123Z,
	time.RFC3339,
	time.RFC3339Nano,
	time.RFC822,
	time.RFC822Z,
	time.RFC850,
	time.RubyDate,
	time.Stamp,
	time.StampNano,
	time.StampMicro,
	time.StampMilli,
	time.UnixDate,
	"2/1/06 15:04:05",
	"2/1/2006 15:04:05",
	"02/01/06 15:04:05",
	"02/01/2006 15:04:05",
	"2/1/06 15:04",
	"2/1/2006 15:04",
	"02/01/06 15:04",
	"02/01/2006 15:04",
	"15:04:05 2/1/06",
	"15:04:05 2/1/2006",
	"15:04:05 02/01/06",
	"15:04:05 02/01/2006",
	"15:04 2/1/06",
	"15:04 2/1/2006",
	"15:04 02/01/06",
	"15:04 02/01/2006",
	"2-1-06 15:04:05",
	"2-1-2006 15:04:05",
	"02-01-06 15:04:05",
	"02-01-2006 15:04:05",
	"2-1-06 15:04",
	"2-1-2006 15:04",
	"02-01-06 15:04",
	"02-01-2006 15:04",
	"15:04:05 2-1-06",
	"15:04:05 2-1-2006",
	"15:04:05 02-01-06",
	"15:04:05 02-01-2006",
	"15:04 2-1-06",
	"15:04 2-1-2006",
	"15:04 02-01-06",
	"15:04 02-01-2006",
}

// Time is a time.Time that implements Parser
type Time struct {
	Data *time.Time
}

// Parse is an implementation of Parser
func (t Time) Parse(d []string) error {
	for _, format := range formats {
		pt, err := time.Parse(format, d[0])
		if err == nil {
			*t.Data = pt
			return nil
		}
	}
	return UnknownFormat(d[0])
}

// TimeFormat is like a Time except that it allows a specific format to be
// specified
type TimeFormat struct {
	Data   *time.Time
	Format string
}

// Parse is an implementation of Parser
func (t TimeFormat) Parse(d []string) error {
	pt, err := time.Parse(t.Format, d[0])
	if err != nil {
		*t.Data = pt
	}
	return err
}

// Errors

// OutsideBounds is an error returned from a Parser when the parsed value falls
// outside of the range given as an acceptable value
type OutsideBounds string

func (OutsideBounds) Error() string {
	return "value received was outside of specified bounds"
}

// NoRegexMatch is an error returned from RegexString.Parse when the given
// string does not match the given regular expression
type NoRegexMatch string

func (NoRegexMatch) Error() string {
	return "string did not match given regular expression"
}

// Empty is returned when a field contains only an empty string and that is not
// allowed
type Empty struct{}

func (Empty) Error() string {
	return "field is empty"
}

// UnknownFormat is an error returned from Time.Parse when it cannot determine
// the time format of the given string
type UnknownFormat string

func (UnknownFormat) Error() string {
	return "unknown time format"
}
<commit_msg>Added Single type<commit_after>package form

import (
	"regexp"
	"strconv"
	"strings"
	"time"
)

// Bool is a bool that implements Parser
type Bool struct {
	Data *bool
}

// Parse is an implementation of Parser
func (b Bool) Parse(d []string) error {
	switch strings.ToLower(d[0]) {
	case "on", "yes", "y":
		*b.Data = true
	case "off", "no", "n":
		*b.Data = false
	default:
		c, err := strconv.ParseBool(d[0])
		*b.Data = c
		return err
	}
	return nil
}

// Int is an int that implements Parser
type Int struct {
	Data *int
}

// Parse is an implementation of Parser
func (i Int) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 0)
	*i.Data = int(n)
	return err
}

// Int8 is an int8 that implements Parser
type Int8 struct {
	Data *int8
}

// Parse is an implementation of Parser
func (i Int8) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 8)
	*i.Data = int8(n)
	return err
}

// Int16 is an int16 that implements Parser
type Int16 struct {
	Data *int16
}

// Parse is an implementation of Parser
func (i Int16) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 16)
	*i.Data = int16(n)
	return err
}

// Int32 is an int32 that implements Parser
type Int32 struct {
	Data *int32
}

// Parse is an implementation of Parser
func (i Int32) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 32)
	*i.Data = int32(n)
	return err
}

// Int64 is an int64 that implements Parser
type Int64 struct {
	Data *int64
}

// Parse is an implementation of Parser
func (i Int64) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 64)
	*i.Data = n
	return err
}

// IntBetween is an implementation of Parser that allows a signed integer
// between the Min and Max (inclusively)
type IntBetween struct {
	Parser
	Min, Max int64
}

// Parse is an implementation of Parser
func (i IntBetween) Parse(d []string) error {
	n, err := strconv.ParseInt(d[0], 10, 64)
	if err != nil {
		return err
	}
	if n >= i.Min && n <= i.Max {
		return i.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// Uint is a uint that implements Parser
type Uint struct {
	Data *uint
}

// Parse is an implementation of Parser
func (u Uint) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 0)
	*u.Data = uint(n)
	return err
}

// Uint8 is a uint8 that implements Parser
type Uint8 struct {
	Data *uint8
}

// Parse is an implementation of Parser
func (u Uint8) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 8)
	*u.Data = uint8(n)
	return err
}

// Uint16 is a uint16 that implements Parser
type Uint16 struct {
	Data *uint16
}

// Parse is an implementation of Parser
func (u Uint16) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 16)
	*u.Data = uint16(n)
	return err
}

// Uint32 is a uint32 that implements Parser
type Uint32 struct {
	Data *uint32
}

// Parse is an implementation of Parser
func (u Uint32) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 32)
	*u.Data = uint32(n)
	return err
}

// Uint64 is a uint64 that implements Parser
type Uint64 struct {
	Data *uint64
}

// Parse is an implementation of Parser
func (u Uint64) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 64)
	*u.Data = n
	return err
}

// UintBetween is an implementation of Parser that allows an unsigned integer
// between the Min and Max (inclusively)
type UintBetween struct {
	Parser
	Min, Max uint64
}

// Parse is an implementation of Parser
func (u UintBetween) Parse(d []string) error {
	n, err := strconv.ParseUint(d[0], 10, 64)
	if err != nil {
		return err
	}
	if n >= u.Min && n <= u.Max {
		return u.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// Float32 is a float32 that implements Parser
type Float32 struct {
	Data *float32
}

// Parse is an implementation of Parser
func (f Float32) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 32)
	*f.Data = float32(n)
	return err
}

// Float64 is a float64 that implements Parser
type Float64 struct {
	Data *float64
}

// Parse is an implementation of Parser
func (f Float64) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 64)
	*f.Data = n
	return err
}

// FloatBetween is an implementation of Parser that allows a float between the
// Min and Max (inclusively)
type FloatBetween struct {
	Parser
	Min, Max float64
}

// Parse is an implementation of Parser
func (f FloatBetween) Parse(d []string) error {
	n, err := strconv.ParseFloat(d[0], 64)
	if err != nil {
		return err
	}
	if n >= f.Min && n <= f.Max {
		return f.Parser.Parse(d)
	}
	return OutsideBounds(d[0])
}

// String is a string that implements Parser
type String struct {
	Data *string
}

// Parse is an implementation of Parser
func (s String) Parse(d []string) error {
	*s.Data = d[0]
	return nil
}

// RegexString is an implementation of Parser that matches a string again the
// given regular expression
type RegexString struct {
	Data  *string
	Regex *regexp.Regexp
}

// Parse is an implementation of Parser
func (r RegexString) Parse(d []string) error {
	if r.Regex.MatchString(d[0]) {
		*r.Data = d[0]
		return nil
	}
	return NoRegexMatch(d[0])
}

type RequiredString String

func (r RequiredString) Parse(d []string) error {
	if d[0] == "" {
		return Empty{}
	}
	*r.Data = d[0]
	return nil
}

var formats = [...]string{
	time.ANSIC,
	time.Kitchen,
	time.RFC1123,
	time.RFC1123Z,
	time.RFC3339,
	time.RFC3339Nano,
	time.RFC822,
	time.RFC822Z,
	time.RFC850,
	time.RubyDate,
	time.Stamp,
	time.StampNano,
	time.StampMicro,
	time.StampMilli,
	time.UnixDate,
	"2/1/06 15:04:05",
	"2/1/2006 15:04:05",
	"02/01/06 15:04:05",
	"02/01/2006 15:04:05",
	"2/1/06 15:04",
	"2/1/2006 15:04",
	"02/01/06 15:04",
	"02/01/2006 15:04",
	"15:04:05 2/1/06",
	"15:04:05 2/1/2006",
	"15:04:05 02/01/06",
	"15:04:05 02/01/2006",
	"15:04 2/1/06",
	"15:04 2/1/2006",
	"15:04 02/01/06",
	"15:04 02/01/2006",
	"2-1-06 15:04:05",
	"2-1-2006 15:04:05",
	"02-01-06 15:04:05",
	"02-01-2006 15:04:05",
	"2-1-06 15:04",
	"2-1-2006 15:04",
	"02-01-06 15:04",
	"02-01-2006 15:04",
	"15:04:05 2-1-06",
	"15:04:05 2-1-2006",
	"15:04:05 02-01-06",
	"15:04:05 02-01-2006",
	"15:04 2-1-06",
	"15:04 2-1-2006",
	"15:04 02-01-06",
	"15:04 02-01-2006",
}

// Time is a time.Time that implements Parser
type Time struct {
	Data *time.Time
}

// Parse is an implementation of Parser
func (t Time) Parse(d []string) error {
	for _, format := range formats {
		pt, err := time.Parse(format, d[0])
		if err == nil {
			*t.Data = pt
			return nil
		}
	}
	return UnknownFormat(d[0])
}

// TimeFormat is like a Time except that it allows a specific format to be
// specified
type TimeFormat struct {
	Data   *time.Time
	Format string
}

// Parse is an implementation of Parser
func (t TimeFormat) Parse(d []string) error {
	pt, err := time.Parse(t.Format, d[0])
	if err != nil {
		*t.Data = pt
	}
	return err
}

type Single struct {
	Name string
	Parser
}

func (s Single) ParserList() ParserList {
	return ParserList{
		s.Name: s,
	}
}

// Errors

// OutsideBounds is an error returned from a Parser when the parsed value falls
// outside of the range given as an acceptable value
type OutsideBounds string

func (OutsideBounds) Error() string {
	return "value received was outside of specified bounds"
}

// NoRegexMatch is an error returned from RegexString.Parse when the given
// string does not match the given regular expression
type NoRegexMatch string

func (NoRegexMatch) Error() string {
	return "string did not match given regular expression"
}

// Empty is returned when a field contains only an empty string and that is not
// allowed
type Empty struct{}

func (Empty) Error() string {
	return "field is empty"
}

// UnknownFormat is an error returned from Time.Parse when it cannot determine
// the time format of the given string
type UnknownFormat string

func (UnknownFormat) Error() string {
	return "unknown time format"
}
<|endoftext|>


<commit_before>package astgen

import (
	"fmt"
)

type Kind int

const (
	LEXICAL = Kind(iota)
	STRUCT
	OPTION
	ENUM
)

type Type interface {
	Common() *TypeBase
	Processed() bool
	SetProcessed()
	ResetProcessed()
}

type TypeBase struct {
	Name      string

	processed bool
}

func (t *TypeBase) Common() *TypeBase {
	return t
}

func (t *TypeBase) Processed() bool {
	return t.processed
}

func (t *TypeBase) SetProcessed() {
	t.processed = true
}

func (t *TypeBase) ResetProcessed() {
	t.processed = false
}

type LexicalType struct {
	TypeBase
}

type OptionType struct {
	TypeBase

	Options []string
}

type EnumType struct {
	TypeBase

	EnumTokens []EnumToken
}

type EnumToken struct {
	Name string
	String string
}

type StructType struct {
	TypeBase

	Productions []Production
	Members []StructMember
}

type StructMember struct {
	Name             string
	Nullable         bool
	Array            bool
	ArrayTerminator  *Production
	ArraySeparator   *Production
	ArrayMinLength   int
	Type             string
}

type Production struct {
	Tokens []Token
}

type Token struct {
	VarRef string
	Token  string
}

type LangDef struct {
	Types map[string]Type
}

func (t *StructType) MemberByName(name string) *StructMember {
	for i := range t.Members {
		if t.Members[i].Name == name {
			return &t.Members[i]
		}
	}
	return nil
}

func (p *Production) MemberPos(name string) int {
	for i := range p.Tokens {
		if p.Tokens[i].VarRef == name {
			return i + 1
		}
	}
	return -1
}

func (def *LangDef) SanityCheck() (e error) {
	for _, t := range def.Types {
		switch tt := t.(type) {
		case *StructType:
			// TODO: Check for duplicity.
			for _, memb := range tt.Members {
				_, ok := def.Types[memb.Type]
				if !ok {
					return fmt.Errorf("Undefined type '%s'.", memb.Type)
				}
			}
		case *LexicalType:
			// Nothing needed.
		case *EnumType:
			// TODO: Check for duplicity.
		case *OptionType:
			for _, subtype := range tt.Options {
				_, ok := def.Types[subtype]
				if !ok {
					return fmt.Errorf("Undefined type '%s'.", subtype)
				}
			}
		default:
			return fmt.Errorf("Internal error in SanityCheck().")
		}
	}

	return nil
}

/*

var file []byte
var types = make(map[string]Type)

func to_uppercase(b byte) byte {
	if b >= 'a' && b <= 'z' {
		return b - 'a' + 'A'
	} else {
		return b
	}
}

func to_upperstring(s string) string {
	buf := []byte(s)
	buf2 := make([]byte, len(buf))

	for i := range buf {
		buf2[i] = to_uppercase(buf[i])
	}

	return string(buf2)
}

func token_symbol(token string) string {
	tok := []byte(token)

	if is_letter(tok[0]) {
		return to_upperstring(token)
	}

	if len(tok) == 1 {
		if tok[0] == '\'' {
			return "\"'\""
		}
		return "'" + string(tok) + "'"
	}

	ret := sym_name(tok[0])

	for i := 1; i < len(tok); i++ {
		ret += "_"
		ret += sym_name(tok[i])
	}

	return ret
}

func ResetProcessed() {
	for k := range types {
		types[k].ResetProcessed()
	}
}

func ConcreteTypes(opt string) []string {
	ResetProcessed()

	opts := []string{opt}
	result := []string{}

	types[opt].SetProcessed()

	for len(opts) > 0 {
		o := types[opts[0]].(*OptionType)
		opts = opts[1:]

		for i := range o.Options {
			t := types[o.Options[i]]
			if t.Processed() {
				continue
			}
			t.SetProcessed()

			switch t.(type) {
			case *LexType:
				panic("bad definition")
			case *StructType:
				result = append(result, t.Common().Name)
			case *OptionType:
				opts = append(opts, t.Common().Name)
			}
		}
	}

	return result
}*/
<commit_msg>Add LangDef::ConcreteTypes().<commit_after>package astgen

import (
	"fmt"
)

type Kind int

const (
	LEXICAL = Kind(iota)
	STRUCT
	OPTION
	ENUM
)

type Type interface {
	Common() *TypeBase
	Processed() bool
	SetProcessed()
	ResetProcessed()
}

type TypeBase struct {
	Name      string

	processed bool
}

func (t *TypeBase) Common() *TypeBase {
	return t
}

func (t *TypeBase) Processed() bool {
	return t.processed
}

func (t *TypeBase) SetProcessed() {
	t.processed = true
}

func (t *TypeBase) ResetProcessed() {
	t.processed = false
}

type LexicalType struct {
	TypeBase
}

type OptionType struct {
	TypeBase

	Options []string
}

type EnumType struct {
	TypeBase

	EnumTokens []EnumToken
}

type EnumToken struct {
	Name string
	String string
}

type StructType struct {
	TypeBase

	Productions []Production
	Members []StructMember
}

type StructMember struct {
	Name             string
	Nullable         bool
	Array            bool
	ArrayTerminator  *Production
	ArraySeparator   *Production
	ArrayMinLength   int
	Type             string
}

type Production struct {
	Tokens []Token
}

type Token struct {
	VarRef string
	Token  string
}

type LangDef struct {
	Types map[string]Type
}

func (t *StructType) MemberByName(name string) *StructMember {
	for i := range t.Members {
		if t.Members[i].Name == name {
			return &t.Members[i]
		}
	}
	return nil
}

func (p *Production) MemberPos(name string) int {
	for i := range p.Tokens {
		if p.Tokens[i].VarRef == name {
			return i + 1
		}
	}
	return -1
}

func (def *LangDef) SanityCheck() (e error) {
	for _, t := range def.Types {
		switch tt := t.(type) {
		case *StructType:
			// TODO: Check for duplicity.
			for _, memb := range tt.Members {
				_, ok := def.Types[memb.Type]
				if !ok {
					return fmt.Errorf("Undefined type '%s'.", memb.Type)
				}
			}
		case *LexicalType:
			// Nothing needed.
		case *EnumType:
			// TODO: Check for duplicity.
		case *OptionType:
			for _, subtype := range tt.Options {
				_, ok := def.Types[subtype]
				if !ok {
					return fmt.Errorf("Undefined type '%s'.", subtype)
				}
			}
		default:
			return fmt.Errorf("Internal error in SanityCheck().")
		}
	}

	return nil
}

func (def *LangDef) ConcreteTypes(opt string) []string {
	processed := make(map[string]bool)

	opts := []string{opt}
	result := []string{}

	processed[opt] = true

	for len(opts) > 0 {
		o := def.Types[opts[0]].(*OptionType)
		opts = opts[1:]

		for _, op := range o.Options {
			if processed[op] {
				continue
			}

			processed[op] = true

			t := def.Types[op]

			switch t.(type) {
			case *LexicalType, *EnumType:
				panic("bad definition")
			case *StructType:
				result = append(result, t.Common().Name)
			case *OptionType:
				opts = append(opts, t.Common().Name)
			}
		}
	}

	return result
}

/*

var file []byte
var types = make(map[string]Type)

func to_uppercase(b byte) byte {
	if b >= 'a' && b <= 'z' {
		return b - 'a' + 'A'
	} else {
		return b
	}
}

func to_upperstring(s string) string {
	buf := []byte(s)
	buf2 := make([]byte, len(buf))

	for i := range buf {
		buf2[i] = to_uppercase(buf[i])
	}

	return string(buf2)
}

func token_symbol(token string) string {
	tok := []byte(token)

	if is_letter(tok[0]) {
		return to_upperstring(token)
	}

	if len(tok) == 1 {
		if tok[0] == '\'' {
			return "\"'\""
		}
		return "'" + string(tok) + "'"
	}

	ret := sym_name(tok[0])

	for i := 1; i < len(tok); i++ {
		ret += "_"
		ret += sym_name(tok[i])
	}

	return ret
}

func ResetProcessed() {
	for k := range types {
		types[k].ResetProcessed()
	}
}

*/
<|endoftext|>


<commit_before>package lockgate

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/atsaki/lockgate/cli"
)

func getKeys(x interface{}) []string {

	v := reflect.ValueOf(x)
	n := v.Type().NumField()
	keys := make([]string, n, n)

	for i := 0; i < n; i++ {
		var key string
		if v.Type().Field(i).Tag.Get("json") != "" {
			key = v.Type().Field(i).Tag.Get("json")
		} else {
			key = v.Type().Field(i).Name
		}
		keys[i] = key
	}
	sort.Strings(keys)

	return keys
}

func getFieldByTag(v reflect.Value, tag string) reflect.Value {

	if v.Kind() != reflect.Struct {
		log.Fatal("v's Kind must be struct")
	}

	for i := 0; i < v.Type().NumField(); i++ {
		field := v.Type().Field(i)
		if field.Tag.Get("json") == tag {
			return v.FieldByName(field.Name)
		}
	}
	return reflect.Value{}
}

type TabWriter struct {
	separator byte
	writer    *tabwriter.Writer
	minwidth  int
	tabwidth  int
	padding   int
	padchar   byte
	header    bool
	keys      []string
}

func (tw *TabWriter) Print(xs interface{}) {

	vs := reflect.ValueOf(xs)

	if vs.Kind() != reflect.Slice {
		log.Println("xs's Kind must be slice")
		return
	}

	if vs.Len() == 0 {
		return
	}

	if vs.Index(0).Kind() != reflect.Struct {
		log.Println("Elements of xs must be struct")
		return
	}

	keys := tw.keys
	if len(keys) == 0 && vs.Len() > 0 {
		log.Println("keys is not specified. use keys of first item.")
		keys = getKeys(vs.Index(0).Interface())
		if len(keys) > 0 {
			// move id column to left side
			var i int
			var k string
			for i, k = range keys {
				if k == "id" {
					break
				}
			}
			keys = append(append(keys[i:i+1], keys[0:i]...), keys[i+1:]...)
		}
	}
	log.Println("keys", keys)

	if tw.header {
		fmt.Fprintln(tw.writer, strings.Join(keys, string(tw.separator)))
	}
	for i := 0; i < vs.Len(); i++ {
		s := ""
		for _, key := range keys {

			field := getFieldByTag(vs.Index(i), key)
			if field.IsValid() {
				// check if filed is Marshaler (Especially cloudstack.Null*).
				p := reflect.New(field.Type())
				p.Elem().Set(field)
				marshaler, ok := p.Interface().(json.Marshaler)
				if ok {
					var v interface{}
					var b []byte
					var err error

					b, err = marshaler.MarshalJSON()
					if err != nil {
						log.Println("Failed to marshal.", marshaler)
					}
					err = json.Unmarshal(b, &v)
					if err != nil {
						log.Println("Failed to unmarshal.", string(b))
					}
					s += fmt.Sprint(v)
				} else {
					s += fmt.Sprint(field.Interface())
				}
			}
			s += string(tw.separator)
		}
		fmt.Fprintln(tw.writer, s)
	}
	tw.writer.Flush()
}

func GetTabWriter(c *cli.Context) *TabWriter {

	profile := GetProfile(c)
	config, err := LoadConfig(profile)
	if err != nil {
		log.Println(err)
		log.Fatal(err)
	}

	keys := []string{}
	if c.App.Flag("keys").String() != "" {
		keys = strings.Split(c.App.Flag("keys").String(), ",")
		for i := range keys {
			keys[i] = strings.TrimSpace(keys[i])
		}
	} else {
		command, ok := config.Commands[c.CommandName]
		if ok {
			keys = command.Keys
		} else {
			log.Println("Unable to get keys from config: " + c.Command.Name)
		}
	}

	tw := TabWriter{
		separator: '\t',
		writer:    new(tabwriter.Writer),
		minwidth:  0,
		tabwidth:  8,
		padding:   0,
		header:    !c.App.Flag("no-header").Bool(),
		keys:      keys,
	}

	tw.writer.Init(os.Stdout, tw.minwidth, tw.tabwidth, tw.padding,
		tw.separator, 0)
	return &tw
}
<commit_msg>change padding from 0 to 1<commit_after>package lockgate

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/atsaki/lockgate/cli"
)

func getKeys(x interface{}) []string {

	v := reflect.ValueOf(x)
	n := v.Type().NumField()
	keys := make([]string, n, n)

	for i := 0; i < n; i++ {
		var key string
		if v.Type().Field(i).Tag.Get("json") != "" {
			key = v.Type().Field(i).Tag.Get("json")
		} else {
			key = v.Type().Field(i).Name
		}
		keys[i] = key
	}
	sort.Strings(keys)

	return keys
}

func getFieldByTag(v reflect.Value, tag string) reflect.Value {

	if v.Kind() != reflect.Struct {
		log.Fatal("v's Kind must be struct")
	}

	for i := 0; i < v.Type().NumField(); i++ {
		field := v.Type().Field(i)
		if field.Tag.Get("json") == tag {
			return v.FieldByName(field.Name)
		}
	}
	return reflect.Value{}
}

type TabWriter struct {
	separator byte
	writer    *tabwriter.Writer
	minwidth  int
	tabwidth  int
	padding   int
	padchar   byte
	header    bool
	keys      []string
}

func (tw *TabWriter) Print(xs interface{}) {

	vs := reflect.ValueOf(xs)

	if vs.Kind() != reflect.Slice {
		log.Println("xs's Kind must be slice")
		return
	}

	if vs.Len() == 0 {
		return
	}

	if vs.Index(0).Kind() != reflect.Struct {
		log.Println("Elements of xs must be struct")
		return
	}

	keys := tw.keys
	if len(keys) == 0 && vs.Len() > 0 {
		log.Println("keys is not specified. use keys of first item.")
		keys = getKeys(vs.Index(0).Interface())
		if len(keys) > 0 {
			// move id column to left side
			var i int
			var k string
			for i, k = range keys {
				if k == "id" {
					break
				}
			}
			keys = append(append(keys[i:i+1], keys[0:i]...), keys[i+1:]...)
		}
	}
	log.Println("keys", keys)

	if tw.header {
		fmt.Fprintln(tw.writer, strings.Join(keys, string(tw.separator)))
	}
	for i := 0; i < vs.Len(); i++ {
		s := ""
		for _, key := range keys {

			field := getFieldByTag(vs.Index(i), key)
			if field.IsValid() {
				// check if filed is Marshaler (Especially cloudstack.Null*).
				p := reflect.New(field.Type())
				p.Elem().Set(field)
				marshaler, ok := p.Interface().(json.Marshaler)
				if ok {
					var v interface{}
					var b []byte
					var err error

					b, err = marshaler.MarshalJSON()
					if err != nil {
						log.Println("Failed to marshal.", marshaler)
					}
					err = json.Unmarshal(b, &v)
					if err != nil {
						log.Println("Failed to unmarshal.", string(b))
					}
					s += fmt.Sprint(v)
				} else {
					s += fmt.Sprint(field.Interface())
				}
			}
			s += string(tw.separator)
		}
		fmt.Fprintln(tw.writer, s)
	}
	tw.writer.Flush()
}

func GetTabWriter(c *cli.Context) *TabWriter {

	profile := GetProfile(c)
	config, err := LoadConfig(profile)
	if err != nil {
		log.Println(err)
		log.Fatal(err)
	}

	keys := []string{}
	if c.App.Flag("keys").String() != "" {
		keys = strings.Split(c.App.Flag("keys").String(), ",")
		for i := range keys {
			keys[i] = strings.TrimSpace(keys[i])
		}
	} else {
		command, ok := config.Commands[c.CommandName]
		if ok {
			keys = command.Keys
		} else {
			log.Println("Unable to get keys from config: " + c.Command.Name)
		}
	}

	tw := TabWriter{
		separator: '\t',
		writer:    new(tabwriter.Writer),
		minwidth:  0,
		tabwidth:  8,
		padding:   1,
		header:    !c.App.Flag("no-header").Bool(),
		keys:      keys,
	}

	tw.writer.Init(os.Stdout, tw.minwidth, tw.tabwidth, tw.padding,
		tw.separator, 0)
	return &tw
}
<|endoftext|>