<commit_before>package s3vfs

import (
	"bytes"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	pathpkg "path"
	"path/filepath"
	"time"

	"golang.org/x/tools/godoc/vfs"

	"strings"

	"github.com/sqs/s3"
	"github.com/sqs/s3/s3util"
	"sourcegraph.com/sourcegraph/rwvfs"
)

var DefaultS3Config = s3util.Config{
	Keys: &s3.Keys{
		AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
		SecretKey: os.Getenv("AWS_SECRET_KEY"),
	},
	Service: s3.DefaultService,
}

// S3 returns an implementation of FileSystem using the specified S3 bucket and
// config. If config is nil, DefaultS3Config is used.
//
// The bucket URL is the full URL to the bucket on Amazon S3, including the
// bucket name and AWS region (e.g.,
// https://s3-us-west-2.amazonaws.com/mybucket).
func S3(bucket *url.URL, config *s3util.Config) rwvfs.FileSystem {
	if config == nil {
		config = &DefaultS3Config
	}
	return &S3FS{bucket, config}
}

type S3FS struct {
	bucket *url.URL
	config *s3util.Config
}

func (fs *S3FS) String() string {
	return fmt.Sprintf("S3 filesystem at %s", fs.bucket)
}

func (fs *S3FS) url(path string) string {
	path = pathpkg.Join(fs.bucket.Path, path)
	return fs.bucket.ResolveReference(&url.URL{Path: path}).String()
}

func (fs *S3FS) Open(name string) (vfs.ReadSeekCloser, error) {
	return fs.open(name, "")
}

type rangeTransport struct {
	http.RoundTripper
	rangeVal string
}

func (t rangeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	req = cloneRequest(req)
	req.Header.Set("range", t.rangeVal)

	transport := t.RoundTripper
	if transport == nil {
		transport = http.DefaultTransport
	}

	resp, err := transport.RoundTrip(req)
	if resp != nil && resp.StatusCode == http.StatusPartialContent {
		resp.StatusCode = http.StatusOK
	}
	return resp, err
}

// cloneRequest returns a clone of the provided *http.Request. The clone is a
// shallow copy of the struct and its Header map.
func cloneRequest(r *http.Request) *http.Request {
	// shallow copy of the struct
	r2 := new(http.Request)
	*r2 = *r
	// deep copy of the Header
	r2.Header = make(http.Header)
	for k, s := range r.Header {
		r2.Header[k] = s
	}
	return r2
}

func (fs *S3FS) open(name string, rangeHeader string) (vfs.ReadSeekCloser, error) {
	cfg := fs.config
	if rangeHeader != "" {
		tmp := *cfg
		cfg = &tmp
		var existingTransport http.RoundTripper
		if cfg.Client != nil {
			existingTransport = cfg.Client.Transport
		}
		cfg.Client = &http.Client{Transport: rangeTransport{RoundTripper: existingTransport, rangeVal: rangeHeader}}
	}

	rdr, err := s3util.Open(fs.url(name), cfg)
	if err != nil {
		return nil, &os.PathError{Op: "open", Path: fs.url(name), Err: err}
	}

	b, err := ioutil.ReadAll(rdr)
	if err != nil {
		return nil, err
	}
	defer rdr.Close()
	return nopCloser{bytes.NewReader(b)}, nil
}

func (fs *S3FS) OpenFetcher(name string) (vfs.ReadSeekCloser, error) {
	return &explicitFetchFile{name: name, fs: fs, autofetch: true}, nil
}

type explicitFetchFile struct {
	name               string
	fs                 *S3FS
	startByte, endByte int64
	rc                 vfs.ReadSeekCloser
	autofetch          bool
}

var vlog = log.New(ioutil.Discard, "s3vfs: ", 0)

func (f *explicitFetchFile) Read(p []byte) (n int, err error) {
	ofs, err := f.Seek(0, 1) // get current offset
	if err != nil {
		return 0, err
	}
	if start, end := ofs, ofs+int64(len(p)); !f.isFetched(start, end) {
		if !f.autofetch {
			return 0, fmt.Errorf("s3vfs: range %d-%d not fetched (%d-%d fetched; offset %d)", start, end, f.startByte, f.endByte, ofs)
		}
		const x = 4 // overfetch factor (because network RTT >> network throughput)
		fetchEnd := end + (end-start)*x
		vlog.Printf("Autofetching range %d-%d because read of unfetched %d-%d attempted (%d bytes)", start, fetchEnd, start, end, len(p))
		if err := f.Fetch(start, fetchEnd); err != nil {
			return 0, err
		}
	}
	return f.rc.Read(p)
}

func (f *explicitFetchFile) isFetched(start, end int64) bool {
	return f.rc != nil && start <= end && start >= f.startByte && end <= f.endByte
}

func (f *explicitFetchFile) Fetch(start, end int64) error {
	if f.isFetched(start, end) {
		// Already prefetched.
		vlog.Printf("Already fetched %d-%d (fetched range is %d-%d)", start, end, f.startByte, f.endByte)
		return nil
	}

	// Close existing open reader (if any).
	if err := f.Close(); err != nil {
		return err
	}

	rng := fmt.Sprintf("bytes=%d-%d", start, end)
	var err error
	f.rc, err = f.fs.open(f.name, rng)
	if err == nil {
		f.startByte = start
		f.endByte = end
	}
	return err
}

var errRelOfs = errors.New("s3vfs: seek to offset relative to end of file is not supported")

func (f *explicitFetchFile) Seek(offset int64, whence int) (int64, error) {
	if f.rc == nil {
		return 0, errors.New("s3vfs: must call Fetch before Seek")
	}

	switch whence {
	case 0:
		offset -= f.startByte
	case 2:
		return 0, errRelOfs
	}
	n, err := f.rc.Seek(offset, whence)
	n += f.startByte
	return n, err
}

func (f *explicitFetchFile) Close() error {
	if f.rc != nil {
		err := f.rc.Close()
		f.rc = nil
		f.startByte = 0
		f.endByte = 0
		return err
	}
	return nil
}

func (fs *S3FS) ReadDir(path string) ([]os.FileInfo, error) {
	dir, err := s3util.NewFile(fs.url(path), fs.config)
	if err != nil {
		return nil, &os.PathError{Op: "readdir", Path: fs.url(path), Err: err}
	}

	fis, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}
	for i, fi := range fis {
		fis[i] = &fileInfo{
			name:    pathpkg.Base(fi.Name()),
			size:    fi.Size(),
			mode:    fi.Mode(),
			modTime: fi.ModTime(),
			sys:     fi.Sys(),
		}
	}
	return fis, nil
}

func (fs *S3FS) Lstat(name string) (os.FileInfo, error) {
	fi, err := fs.lstat(name)
	if err != nil {
		return nil, &os.PathError{Op: "lstat", Path: fs.url(name), Err: err}
	}
	return fi, nil
}

func (fs *S3FS) lstat(name string) (os.FileInfo, error) {
	name = strings.TrimPrefix(filepath.Clean(name), "/")

	if name == "." {
		return &fileInfo{
			name:    ".",
			size:    0,
			mode:    os.ModeDir,
			modTime: time.Time{},
		}, nil
	}

	client := fs.config.Client
	if client == nil {
		client = http.DefaultClient
	}

	q := make(url.Values)
	q.Set("prefix", name+"/")
	q.Set("max-keys", "1")
	u := fs.bucket.ResolveReference(&url.URL{RawQuery: q.Encode()})

	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	fs.config.Sign(req, *fs.config.Keys)
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		resp.Body.Close()
		return nil, newRespError(resp)
	}

	result := struct{ Contents []struct{ Key string } }{}
	if err := xml.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	if err := resp.Body.Close(); err != nil {
		return nil, err
	}

	// If Contents is non-empty, then this is a dir.
	if len(result.Contents) == 1 {
		return &fileInfo{
			name: name,
			size: 0,
			mode: os.ModeDir,
		}, nil
	}

	// Otherwise, see if a key exists here.
	req, err = http.NewRequest("HEAD", fs.url(name), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	fs.config.Sign(req, *fs.config.Keys)
	resp, err = client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusNotFound {
		return nil, os.ErrNotExist
	} else if resp.StatusCode != 200 {
		return nil, newRespError(resp)
	}
	t, _ := time.Parse(http.TimeFormat, resp.Header.Get("last-modified"))
	return &fileInfo{
		name:    name,
		size:    resp.ContentLength,
		mode:    0, // file
		modTime: t,
	}, nil
}

func (fs *S3FS) Stat(name string) (os.FileInfo, error) {
	return fs.Lstat(name)
}

// Create opens the file at path for writing, creating the file if it doesn't
// exist and truncating it otherwise.
func (fs *S3FS) Create(path string) (io.WriteCloser, error) {
	wc, err := s3util.Create(fs.url(path), nil, fs.config)
	if err != nil {
		return nil, &os.PathError{Op: "create", Path: fs.url(path), Err: err}
	}
	return wc, nil
}

func (fs *S3FS) Mkdir(name string) error {
	// S3 doesn't have directories.
	return nil
}

// MkdirAll implements rwvfs.MkdirAllOverrider.
func (fs *S3FS) MkdirAll(name string) error {
	// S3 doesn't have directories.
	return nil
}

func (fs *S3FS) Remove(name string) (err error) {
	var rdr io.ReadCloser
	rdr, err = s3util.Delete(fs.url(name), fs.config)
	defer func() {
		if rdr != nil {
			err2 := rdr.Close()
			if err == nil {
				err = err2
			}
		}
	}()
	return err
}

type nopCloser struct {
	io.ReadSeeker
}

func (nc nopCloser) Close() error { return nil }

type fileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	sys     interface{}
}

func (f *fileInfo) Name() string       { return f.name }
func (f *fileInfo) Size() int64        { return f.size }
func (f *fileInfo) Mode() os.FileMode  { return f.mode }
func (f *fileInfo) ModTime() time.Time { return f.modTime }
func (f *fileInfo) IsDir() bool        { return f.mode&os.ModeDir != 0 }
func (f *fileInfo) Sys() interface{}   { return f.sys }

type respError struct {
	r *http.Response
	b bytes.Buffer
}

func newRespError(r *http.Response) *respError {
	e := new(respError)
	e.r = r
	io.Copy(&e.b, r.Body)
	r.Body.Close()
	return e
}

func (e *respError) Error() string {
	return fmt.Sprintf(
		"unwanted http status %d: %q",
		e.r.StatusCode,
		e.b.String(),
	)
}
<commit_msg>check Close error<commit_after>package s3vfs

import (
	"bytes"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	pathpkg "path"
	"path/filepath"
	"time"

	"golang.org/x/tools/godoc/vfs"

	"strings"

	"github.com/sqs/s3"
	"github.com/sqs/s3/s3util"
	"sourcegraph.com/sourcegraph/rwvfs"
)

var DefaultS3Config = s3util.Config{
	Keys: &s3.Keys{
		AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
		SecretKey: os.Getenv("AWS_SECRET_KEY"),
	},
	Service: s3.DefaultService,
}

// S3 returns an implementation of FileSystem using the specified S3 bucket and
// config. If config is nil, DefaultS3Config is used.
//
// The bucket URL is the full URL to the bucket on Amazon S3, including the
// bucket name and AWS region (e.g.,
// https://s3-us-west-2.amazonaws.com/mybucket).
func S3(bucket *url.URL, config *s3util.Config) rwvfs.FileSystem {
	if config == nil {
		config = &DefaultS3Config
	}
	return &S3FS{bucket, config}
}

type S3FS struct {
	bucket *url.URL
	config *s3util.Config
}

func (fs *S3FS) String() string {
	return fmt.Sprintf("S3 filesystem at %s", fs.bucket)
}

func (fs *S3FS) url(path string) string {
	path = pathpkg.Join(fs.bucket.Path, path)
	return fs.bucket.ResolveReference(&url.URL{Path: path}).String()
}

func (fs *S3FS) Open(name string) (vfs.ReadSeekCloser, error) {
	return fs.open(name, "")
}

type rangeTransport struct {
	http.RoundTripper
	rangeVal string
}

func (t rangeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	req = cloneRequest(req)
	req.Header.Set("range", t.rangeVal)

	transport := t.RoundTripper
	if transport == nil {
		transport = http.DefaultTransport
	}

	resp, err := transport.RoundTrip(req)
	if resp != nil && resp.StatusCode == http.StatusPartialContent {
		resp.StatusCode = http.StatusOK
	}
	return resp, err
}

// cloneRequest returns a clone of the provided *http.Request. The clone is a
// shallow copy of the struct and its Header map.
func cloneRequest(r *http.Request) *http.Request {
	// shallow copy of the struct
	r2 := new(http.Request)
	*r2 = *r
	// deep copy of the Header
	r2.Header = make(http.Header)
	for k, s := range r.Header {
		r2.Header[k] = s
	}
	return r2
}

func (fs *S3FS) open(name string, rangeHeader string) (f vfs.ReadSeekCloser, err error) {
	cfg := fs.config
	if rangeHeader != "" {
		tmp := *cfg
		cfg = &tmp
		var existingTransport http.RoundTripper
		if cfg.Client != nil {
			existingTransport = cfg.Client.Transport
		}
		cfg.Client = &http.Client{Transport: rangeTransport{RoundTripper: existingTransport, rangeVal: rangeHeader}}
	}

	rdr, err := s3util.Open(fs.url(name), cfg)
	if err != nil {
		return nil, &os.PathError{Op: "open", Path: fs.url(name), Err: err}
	}

	b, err := ioutil.ReadAll(rdr)
	if err != nil {
		return nil, err
	}
	defer func() {
		err2 := rdr.Close()
		if err == nil {
			err = err2
		}
	}()
	return nopCloser{bytes.NewReader(b)}, nil
}

func (fs *S3FS) OpenFetcher(name string) (vfs.ReadSeekCloser, error) {
	return &explicitFetchFile{name: name, fs: fs, autofetch: true}, nil
}

type explicitFetchFile struct {
	name               string
	fs                 *S3FS
	startByte, endByte int64
	rc                 vfs.ReadSeekCloser
	autofetch          bool
}

var vlog = log.New(ioutil.Discard, "s3vfs: ", 0)

func (f *explicitFetchFile) Read(p []byte) (n int, err error) {
	ofs, err := f.Seek(0, 1) // get current offset
	if err != nil {
		return 0, err
	}
	if start, end := ofs, ofs+int64(len(p)); !f.isFetched(start, end) {
		if !f.autofetch {
			return 0, fmt.Errorf("s3vfs: range %d-%d not fetched (%d-%d fetched; offset %d)", start, end, f.startByte, f.endByte, ofs)
		}
		const x = 4 // overfetch factor (because network RTT >> network throughput)
		fetchEnd := end + (end-start)*x
		vlog.Printf("Autofetching range %d-%d because read of unfetched %d-%d attempted (%d bytes)", start, fetchEnd, start, end, len(p))
		if err := f.Fetch(start, fetchEnd); err != nil {
			return 0, err
		}
	}
	return f.rc.Read(p)
}

func (f *explicitFetchFile) isFetched(start, end int64) bool {
	return f.rc != nil && start <= end && start >= f.startByte && end <= f.endByte
}

func (f *explicitFetchFile) Fetch(start, end int64) error {
	if f.isFetched(start, end) {
		// Already prefetched.
		vlog.Printf("Already fetched %d-%d (fetched range is %d-%d)", start, end, f.startByte, f.endByte)
		return nil
	}

	// Close existing open reader (if any).
	if err := f.Close(); err != nil {
		return err
	}

	rng := fmt.Sprintf("bytes=%d-%d", start, end)
	var err error
	f.rc, err = f.fs.open(f.name, rng)
	if err == nil {
		f.startByte = start
		f.endByte = end
	}
	return err
}

var errRelOfs = errors.New("s3vfs: seek to offset relative to end of file is not supported")

func (f *explicitFetchFile) Seek(offset int64, whence int) (int64, error) {
	if f.rc == nil {
		return 0, errors.New("s3vfs: must call Fetch before Seek")
	}

	switch whence {
	case 0:
		offset -= f.startByte
	case 2:
		return 0, errRelOfs
	}
	n, err := f.rc.Seek(offset, whence)
	n += f.startByte
	return n, err
}

func (f *explicitFetchFile) Close() error {
	if f.rc != nil {
		err := f.rc.Close()
		f.rc = nil
		f.startByte = 0
		f.endByte = 0
		return err
	}
	return nil
}

func (fs *S3FS) ReadDir(path string) ([]os.FileInfo, error) {
	dir, err := s3util.NewFile(fs.url(path), fs.config)
	if err != nil {
		return nil, &os.PathError{Op: "readdir", Path: fs.url(path), Err: err}
	}

	fis, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}
	for i, fi := range fis {
		fis[i] = &fileInfo{
			name:    pathpkg.Base(fi.Name()),
			size:    fi.Size(),
			mode:    fi.Mode(),
			modTime: fi.ModTime(),
			sys:     fi.Sys(),
		}
	}
	return fis, nil
}

func (fs *S3FS) Lstat(name string) (os.FileInfo, error) {
	fi, err := fs.lstat(name)
	if err != nil {
		return nil, &os.PathError{Op: "lstat", Path: fs.url(name), Err: err}
	}
	return fi, nil
}

func (fs *S3FS) lstat(name string) (os.FileInfo, error) {
	name = strings.TrimPrefix(filepath.Clean(name), "/")

	if name == "." {
		return &fileInfo{
			name:    ".",
			size:    0,
			mode:    os.ModeDir,
			modTime: time.Time{},
		}, nil
	}

	client := fs.config.Client
	if client == nil {
		client = http.DefaultClient
	}

	q := make(url.Values)
	q.Set("prefix", name+"/")
	q.Set("max-keys", "1")
	u := fs.bucket.ResolveReference(&url.URL{RawQuery: q.Encode()})

	req, err := http.NewRequest("GET", u.String(), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	fs.config.Sign(req, *fs.config.Keys)
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		resp.Body.Close()
		return nil, newRespError(resp)
	}

	result := struct{ Contents []struct{ Key string } }{}
	if err := xml.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	if err := resp.Body.Close(); err != nil {
		return nil, err
	}

	// If Contents is non-empty, then this is a dir.
	if len(result.Contents) == 1 {
		return &fileInfo{
			name: name,
			size: 0,
			mode: os.ModeDir,
		}, nil
	}

	// Otherwise, see if a key exists here.
	req, err = http.NewRequest("HEAD", fs.url(name), nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	fs.config.Sign(req, *fs.config.Keys)
	resp, err = client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusNotFound {
		return nil, os.ErrNotExist
	} else if resp.StatusCode != 200 {
		return nil, newRespError(resp)
	}
	t, _ := time.Parse(http.TimeFormat, resp.Header.Get("last-modified"))
	return &fileInfo{
		name:    name,
		size:    resp.ContentLength,
		mode:    0, // file
		modTime: t,
	}, nil
}

func (fs *S3FS) Stat(name string) (os.FileInfo, error) {
	return fs.Lstat(name)
}

// Create opens the file at path for writing, creating the file if it doesn't
// exist and truncating it otherwise.
func (fs *S3FS) Create(path string) (io.WriteCloser, error) {
	wc, err := s3util.Create(fs.url(path), nil, fs.config)
	if err != nil {
		return nil, &os.PathError{Op: "create", Path: fs.url(path), Err: err}
	}
	return wc, nil
}

func (fs *S3FS) Mkdir(name string) error {
	// S3 doesn't have directories.
	return nil
}

// MkdirAll implements rwvfs.MkdirAllOverrider.
func (fs *S3FS) MkdirAll(name string) error {
	// S3 doesn't have directories.
	return nil
}

func (fs *S3FS) Remove(name string) (err error) {
	var rdr io.ReadCloser
	rdr, err = s3util.Delete(fs.url(name), fs.config)
	defer func() {
		if rdr != nil {
			err2 := rdr.Close()
			if err == nil {
				err = err2
			}
		}
	}()
	return err
}

type nopCloser struct {
	io.ReadSeeker
}

func (nc nopCloser) Close() error { return nil }

type fileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	sys     interface{}
}

func (f *fileInfo) Name() string       { return f.name }
func (f *fileInfo) Size() int64        { return f.size }
func (f *fileInfo) Mode() os.FileMode  { return f.mode }
func (f *fileInfo) ModTime() time.Time { return f.modTime }
func (f *fileInfo) IsDir() bool        { return f.mode&os.ModeDir != 0 }
func (f *fileInfo) Sys() interface{}   { return f.sys }

type respError struct {
	r *http.Response
	b bytes.Buffer
}

func newRespError(r *http.Response) *respError {
	e := new(respError)
	e.r = r
	io.Copy(&e.b, r.Body)
	r.Body.Close()
	return e
}

func (e *respError) Error() string {
	return fmt.Sprintf(
		"unwanted http status %d: %q",
		e.r.StatusCode,
		e.b.String(),
	)
}
<|endoftext|>


<commit_before>package schema

import (
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/mapstructure"
)

// DiffFieldReader reads fields out of a diff structures.
//
// It also requires access to a Reader that reads fields from the structure
// that the diff was derived from. This is usually the state. This is required
// because a diff on its own doesn't have complete data about non-primitive
// objects such as maps, lists and sets.
//
// The Source MUST be the data that the diff was derived from. If it isn't,
// the behavior of this struct is undefined.
//
// Reading fields from a DiffFieldReader is identical to reading from
// Source except the diff will be applied to the end result.
//
// The "Exists" field on the result will be set to true if the complete
// field exists whether its from the source, diff, or a combination of both.
// It cannot be determined whether a retrieved value is composed of
// diff elements.
type DiffFieldReader struct {
	Diff   *terraform.InstanceDiff
	Source FieldReader
	Schema map[string]*Schema
}

func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
	schemaList := addrToSchema(address, r.Schema)
	if len(schemaList) == 0 {
		return FieldReadResult{}, nil
	}

	schema := schemaList[len(schemaList)-1]
	switch schema.Type {
	case TypeBool, TypeInt, TypeFloat, TypeString:
		return r.readPrimitive(address, schema)
	case TypeList:
		return r.readList(address, schema)
	case TypeMap:
		return r.readMap(address, schema)
	case TypeSet:
		return r.readSet(address, schema)
	case typeObject:
		return readObjectField(r, address, schema.Elem.(map[string]*Schema))
	default:
		panic(fmt.Sprintf("Unknown type: %#v", schema.Type))
	}
}

func (r *DiffFieldReader) readMap(
	address []string, schema *Schema) (FieldReadResult, error) {
	result := make(map[string]interface{})
	resultSet := false

	// First read the map from the underlying source
	source, err := r.Source.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}
	if source.Exists {
		result = source.Value.(map[string]interface{})
		resultSet = true
	}

	// Next, read all the elements we have in our diff, and apply
	// the diff to our result.
	prefix := strings.Join(address, ".") + "."
	for k, v := range r.Diff.Attributes {
		if !strings.HasPrefix(k, prefix) {
			continue
		}
		if strings.HasPrefix(k, prefix+"%") {
			// Ignore the count field
			continue
		}

		resultSet = true

		k = k[len(prefix):]
		if v.NewRemoved {
			delete(result, k)
			continue
		}

		result[k] = v.New
	}

	var resultVal interface{}
	if resultSet {
		resultVal = result
	}

	return FieldReadResult{
		Value:  resultVal,
		Exists: resultSet,
	}, nil
}

func (r *DiffFieldReader) readPrimitive(
	address []string, schema *Schema) (FieldReadResult, error) {
	result, err := r.Source.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}

	attrD, ok := r.Diff.Attributes[strings.Join(address, ".")]
	if !ok {
		return result, nil
	}

	var resultVal string
	if !attrD.NewComputed {
		resultVal = attrD.New
		if attrD.NewExtra != nil {
			result.ValueProcessed = resultVal
			if err := mapstructure.WeakDecode(attrD.NewExtra, &resultVal); err != nil {
				return FieldReadResult{}, err
			}
		}
	}

	result.Computed = attrD.NewComputed
	result.Exists = true
	result.Value, err = stringToPrimitive(resultVal, false, schema)
	if err != nil {
		return FieldReadResult{}, err
	}

	return result, nil
}

func (r *DiffFieldReader) readList(
	address []string, schema *Schema) (FieldReadResult, error) {
	prefix := strings.Join(address, ".") + "."

	addrPadded := make([]string, len(address)+1)
	copy(addrPadded, address)

	// Get the number of elements in the list
	addrPadded[len(addrPadded)-1] = "#"
	countResult, err := r.readPrimitive(addrPadded, &Schema{Type: TypeInt})
	if err != nil {
		return FieldReadResult{}, err
	}
	if !countResult.Exists {
		// No count, means we have no list
		countResult.Value = 0
	}
	// If we have an empty list, then return an empty list
	if countResult.Computed || countResult.Value.(int) == 0 {
		return FieldReadResult{
			Value:    []interface{}{},
			Exists:   countResult.Exists,
			Computed: countResult.Computed,
		}, nil
	}

	// Bail out if diff doesn't contain the given field at all
	// This has to be a separate loop because we're only
	// iterating over raw list items (list.idx).
	// Other fields (list.idx.*) are left for other read* methods
	// which can deal with these fields appropriately.
	diffContainsField := false
	for k, _ := range r.Diff.Attributes {
		if strings.HasPrefix(k, address[0]+".") {
			diffContainsField = true
		}
	}
	if !diffContainsField {
		return FieldReadResult{
			Value:  []interface{}{},
			Exists: false,
		}, nil
	}

	// Create the list that will be our result
	list := []interface{}{}

	// Go through the diff and find all the list items
	// We are not iterating over the diff directly as some indexes
	// may be missing and we expect the whole list to be returned.
	for i := 0; i < countResult.Value.(int); i++ {
		idx := strconv.Itoa(i)
		addrString := prefix + idx

		d, ok := r.Diff.Attributes[addrString]
		if ok && d.NewRemoved {
			// If the field is being removed, we ignore it
			continue
		}

		addrPadded[len(addrPadded)-1] = idx
		raw, err := r.ReadField(addrPadded)
		if err != nil {
			return FieldReadResult{}, err
		}
		if !raw.Exists {
			// This should never happen, because by the time the data
			// gets to the FieldReaders, all the defaults should be set by
			// Schema.
			panic("missing field in set: " + addrString + "." + idx)
		}
		list = append(list, raw.Value)
	}

	// Determine if the list "exists". It exists if there are items or if
	// the diff explicitly wanted it empty.
	exists := len(list) > 0
	if !exists {
		// We could check if the diff value is "0" here but I think the
		// existence of "#" on its own is enough to show it existed. This
		// protects us in the future from the zero value changing from
		// "0" to "" breaking us (if that were to happen).
		if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
			exists = true
		}
	}

	return FieldReadResult{
		Value:  list,
		Exists: exists,
	}, nil
}

func (r *DiffFieldReader) readSet(
	address []string, schema *Schema) (FieldReadResult, error) {
	prefix := strings.Join(address, ".") + "."

	// Create the set that will be our result
	set := schema.ZeroValue().(*Set)

	// Check if we're supposed to remove it
	v, ok := r.Diff.Attributes[prefix+"#"]
	if ok && v.New == "0" {
		// I'm not entirely sure what's the point of
		// returning empty set w/ Exists: true
		return FieldReadResult{
			Value:  set,
			Exists: true,
		}, nil
	}

	// Compose list of all keys (diff + source)
	var keys []string

	// Add keys from diff
	diffContainsField := false
	for k, _ := range r.Diff.Attributes {
		if strings.HasPrefix(k, address[0]+".") {
			diffContainsField = true
		}
		keys = append(keys, k)
	}
	// Bail out if diff doesn't contain the given field at all
	if !diffContainsField {
		return FieldReadResult{
			Value:  set,
			Exists: false,
		}, nil
	}
	// Add keys from source
	sourceResult, err := r.Source.ReadField(address)
	if err == nil && sourceResult.Exists {
		sourceSet := sourceResult.Value.(*Set)
		sourceMap := sourceSet.Map()

		for k, _ := range sourceMap {
			key := prefix + k
			_, ok := r.Diff.Attributes[key]
			if !ok {
				keys = append(keys, key)
			}
		}
	}

	// Keep the order consistent for hashing functions
	sort.Strings(keys)

	// Go through the map and find all the set items
	// We are not iterating over the diff directly as some indexes
	// may be missing and we expect the whole set to be returned.
	for _, k := range keys {
		d, ok := r.Diff.Attributes[k]
		if ok && d.NewRemoved {
			// If the field is being removed, we ignore it
			continue
		}
		if !strings.HasPrefix(k, prefix) {
			continue
		}
		if strings.HasSuffix(k, "#") {
			// Ignore any count field
			continue
		}

		// Split the key, since it might be a sub-object like "idx.field"
		parts := strings.Split(k[len(prefix):], ".")
		idx := parts[0]

		raw, err := r.ReadField(append(address, idx))
		if err != nil {
			return FieldReadResult{}, err
		}
		if !raw.Exists {
			// This shouldn't happen because we just verified it does exist
			panic("missing field in set: " + k + "." + idx)
		}

		set.Add(raw.Value)
	}

	// Determine if the set "exists". It exists if there are items or if
	// the diff explicitly wanted it empty.
	exists := set.Len() > 0
	if !exists {
		// We could check if the diff value is "0" here but I think the
		// existence of "#" on its own is enough to show it existed. This
		// protects us in the future from the zero value changing from
		// "0" to "" breaking us (if that were to happen).
		if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
			exists = true
		}
	}

	return FieldReadResult{
		Value:  set,
		Exists: exists,
	}, nil
}
<commit_msg>Improve naming convention (resultSet -> exists)<commit_after>package schema

import (
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/mapstructure"
)

// DiffFieldReader reads fields out of a diff structures.
//
// It also requires access to a Reader that reads fields from the structure
// that the diff was derived from. This is usually the state. This is required
// because a diff on its own doesn't have complete data about non-primitive
// objects such as maps, lists and sets.
//
// The Source MUST be the data that the diff was derived from. If it isn't,
// the behavior of this struct is undefined.
//
// Reading fields from a DiffFieldReader is identical to reading from
// Source except the diff will be applied to the end result.
//
// The "Exists" field on the result will be set to true if the complete
// field exists whether its from the source, diff, or a combination of both.
// It cannot be determined whether a retrieved value is composed of
// diff elements.
type DiffFieldReader struct {
	Diff   *terraform.InstanceDiff
	Source FieldReader
	Schema map[string]*Schema
}

func (r *DiffFieldReader) ReadField(address []string) (FieldReadResult, error) {
	schemaList := addrToSchema(address, r.Schema)
	if len(schemaList) == 0 {
		return FieldReadResult{}, nil
	}

	schema := schemaList[len(schemaList)-1]
	switch schema.Type {
	case TypeBool, TypeInt, TypeFloat, TypeString:
		return r.readPrimitive(address, schema)
	case TypeList:
		return r.readList(address, schema)
	case TypeMap:
		return r.readMap(address, schema)
	case TypeSet:
		return r.readSet(address, schema)
	case typeObject:
		return readObjectField(r, address, schema.Elem.(map[string]*Schema))
	default:
		panic(fmt.Sprintf("Unknown type: %#v", schema.Type))
	}
}

func (r *DiffFieldReader) readMap(
	address []string, schema *Schema) (FieldReadResult, error) {
	result := make(map[string]interface{})
	exists := false

	// First read the map from the underlying source
	source, err := r.Source.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}
	if source.Exists {
		result = source.Value.(map[string]interface{})
		exists = true
	}

	// Next, read all the elements we have in our diff, and apply
	// the diff to our result.
	prefix := strings.Join(address, ".") + "."
	for k, v := range r.Diff.Attributes {
		if !strings.HasPrefix(k, prefix) {
			continue
		}
		if strings.HasPrefix(k, prefix+"%") {
			// Ignore the count field
			continue
		}

		exists = true

		k = k[len(prefix):]
		if v.NewRemoved {
			delete(result, k)
			continue
		}

		result[k] = v.New
	}

	var resultVal interface{}
	if exists {
		resultVal = result
	}

	return FieldReadResult{
		Value:  resultVal,
		Exists: exists,
	}, nil
}

func (r *DiffFieldReader) readPrimitive(
	address []string, schema *Schema) (FieldReadResult, error) {
	result, err := r.Source.ReadField(address)
	if err != nil {
		return FieldReadResult{}, err
	}

	attrD, ok := r.Diff.Attributes[strings.Join(address, ".")]
	if !ok {
		return result, nil
	}

	var resultVal string
	if !attrD.NewComputed {
		resultVal = attrD.New
		if attrD.NewExtra != nil {
			result.ValueProcessed = resultVal
			if err := mapstructure.WeakDecode(attrD.NewExtra, &resultVal); err != nil {
				return FieldReadResult{}, err
			}
		}
	}

	result.Computed = attrD.NewComputed
	result.Exists = true
	result.Value, err = stringToPrimitive(resultVal, false, schema)
	if err != nil {
		return FieldReadResult{}, err
	}

	return result, nil
}

func (r *DiffFieldReader) readList(
	address []string, schema *Schema) (FieldReadResult, error) {
	prefix := strings.Join(address, ".") + "."

	addrPadded := make([]string, len(address)+1)
	copy(addrPadded, address)

	// Get the number of elements in the list
	addrPadded[len(addrPadded)-1] = "#"
	countResult, err := r.readPrimitive(addrPadded, &Schema{Type: TypeInt})
	if err != nil {
		return FieldReadResult{}, err
	}
	if !countResult.Exists {
		// No count, means we have no list
		countResult.Value = 0
	}
	// If we have an empty list, then return an empty list
	if countResult.Computed || countResult.Value.(int) == 0 {
		return FieldReadResult{
			Value:    []interface{}{},
			Exists:   countResult.Exists,
			Computed: countResult.Computed,
		}, nil
	}

	// Bail out if diff doesn't contain the given field at all
	// This has to be a separate loop because we're only
	// iterating over raw list items (list.idx).
	// Other fields (list.idx.*) are left for other read* methods
	// which can deal with these fields appropriately.
	diffContainsField := false
	for k, _ := range r.Diff.Attributes {
		if strings.HasPrefix(k, address[0]+".") {
			diffContainsField = true
		}
	}
	if !diffContainsField {
		return FieldReadResult{
			Value:  []interface{}{},
			Exists: false,
		}, nil
	}

	// Create the list that will be our result
	list := []interface{}{}

	// Go through the diff and find all the list items
	// We are not iterating over the diff directly as some indexes
	// may be missing and we expect the whole list to be returned.
	for i := 0; i < countResult.Value.(int); i++ {
		idx := strconv.Itoa(i)
		addrString := prefix + idx

		d, ok := r.Diff.Attributes[addrString]
		if ok && d.NewRemoved {
			// If the field is being removed, we ignore it
			continue
		}

		addrPadded[len(addrPadded)-1] = idx
		raw, err := r.ReadField(addrPadded)
		if err != nil {
			return FieldReadResult{}, err
		}
		if !raw.Exists {
			// This should never happen, because by the time the data
			// gets to the FieldReaders, all the defaults should be set by
			// Schema.
			panic("missing field in set: " + addrString + "." + idx)
		}
		list = append(list, raw.Value)
	}

	// Determine if the list "exists". It exists if there are items or if
	// the diff explicitly wanted it empty.
	exists := len(list) > 0
	if !exists {
		// We could check if the diff value is "0" here but I think the
		// existence of "#" on its own is enough to show it existed. This
		// protects us in the future from the zero value changing from
		// "0" to "" breaking us (if that were to happen).
		if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
			exists = true
		}
	}

	return FieldReadResult{
		Value:  list,
		Exists: exists,
	}, nil
}

func (r *DiffFieldReader) readSet(
	address []string, schema *Schema) (FieldReadResult, error) {
	prefix := strings.Join(address, ".") + "."

	// Create the set that will be our result
	set := schema.ZeroValue().(*Set)

	// Check if we're supposed to remove it
	v, ok := r.Diff.Attributes[prefix+"#"]
	if ok && v.New == "0" {
		// I'm not entirely sure what's the point of
		// returning empty set w/ Exists: true
		return FieldReadResult{
			Value:  set,
			Exists: true,
		}, nil
	}

	// Compose list of all keys (diff + source)
	var keys []string

	// Add keys from diff
	diffContainsField := false
	for k, _ := range r.Diff.Attributes {
		if strings.HasPrefix(k, address[0]+".") {
			diffContainsField = true
		}
		keys = append(keys, k)
	}
	// Bail out if diff doesn't contain the given field at all
	if !diffContainsField {
		return FieldReadResult{
			Value:  set,
			Exists: false,
		}, nil
	}
	// Add keys from source
	sourceResult, err := r.Source.ReadField(address)
	if err == nil && sourceResult.Exists {
		sourceSet := sourceResult.Value.(*Set)
		sourceMap := sourceSet.Map()

		for k, _ := range sourceMap {
			key := prefix + k
			_, ok := r.Diff.Attributes[key]
			if !ok {
				keys = append(keys, key)
			}
		}
	}

	// Keep the order consistent for hashing functions
	sort.Strings(keys)

	// Go through the map and find all the set items
	// We are not iterating over the diff directly as some indexes
	// may be missing and we expect the whole set to be returned.
	for _, k := range keys {
		d, ok := r.Diff.Attributes[k]
		if ok && d.NewRemoved {
			// If the field is being removed, we ignore it
			continue
		}
		if !strings.HasPrefix(k, prefix) {
			continue
		}
		if strings.HasSuffix(k, "#") {
			// Ignore any count field
			continue
		}

		// Split the key, since it might be a sub-object like "idx.field"
		parts := strings.Split(k[len(prefix):], ".")
		idx := parts[0]

		raw, err := r.ReadField(append(address, idx))
		if err != nil {
			return FieldReadResult{}, err
		}
		if !raw.Exists {
			// This shouldn't happen because we just verified it does exist
			panic("missing field in set: " + k + "." + idx)
		}

		set.Add(raw.Value)
	}

	// Determine if the set "exists". It exists if there are items or if
	// the diff explicitly wanted it empty.
	exists := set.Len() > 0
	if !exists {
		// We could check if the diff value is "0" here but I think the
		// existence of "#" on its own is enough to show it existed. This
		// protects us in the future from the zero value changing from
		// "0" to "" breaking us (if that were to happen).
		if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
			exists = true
		}
	}

	return FieldReadResult{
		Value:  set,
		Exists: exists,
	}, nil
}
<|endoftext|>


<commit_before>package client

import (
	"io"
	"net"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/events"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/image"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/api/types/swarm"
	volumetypes "github.com/docker/docker/api/types/volume"
	"golang.org/x/net/context"
)

// CommonAPIClient is the common methods between stable and experimental versions of APIClient.
type CommonAPIClient interface {
	ConfigAPIClient
	ContainerAPIClient
	DistributionAPIClient
	ImageAPIClient
	NodeAPIClient
	NetworkAPIClient
	PluginAPIClient
	ServiceAPIClient
	SwarmAPIClient
	SecretAPIClient
	SystemAPIClient
	VolumeAPIClient
	ClientVersion() string
	DaemonHost() string
	ServerVersion(ctx context.Context) (types.Version, error)
	NegotiateAPIVersion(ctx context.Context)
	NegotiateAPIVersionPing(types.Ping)
	DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
}

// ContainerAPIClient defines API client methods for the containers
type ContainerAPIClient interface {
	ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
	ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error)
	ContainerDiff(ctx context.Context, container string) ([]container.ContainerChangeResponseItem, error)
	ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
	ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error)
	ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
	ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
	ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
	ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
	ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
	ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
	ContainerKill(ctx context.Context, container, signal string) error
	ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
	ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	ContainerPause(ctx context.Context, container string) error
	ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
	ContainerRename(ctx context.Context, container, newContainerName string) error
	ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
	ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error
	ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
	ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error)
	ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
	ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
	ContainerTop(ctx context.Context, container string, arguments []string) (container.ContainerTopOKBody, error)
	ContainerUnpause(ctx context.Context, container string) error
	ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error)
	ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error)
	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
	ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
}

// DistributionAPIClient defines API client methods for the registry
type DistributionAPIClient interface {
	DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error)
}

// ImageAPIClient defines API client methods for the images
type ImageAPIClient interface {
	ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
	BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error)
	ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
	ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
	ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error)
	ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error)
	ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
	ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
	ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
	ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error)
	ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
	ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
	ImageTag(ctx context.Context, image, ref string) error
	ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error)
}

// NetworkAPIClient defines API client methods for the networks
type NetworkAPIClient interface {
	NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
	NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
	NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
	NetworkInspect(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, error)
	NetworkInspectWithRaw(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error)
	NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
	NetworkRemove(ctx context.Context, networkID string) error
	NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error)
}

// NodeAPIClient defines API client methods for the nodes
type NodeAPIClient interface {
	NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error)
	NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
	NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error
	NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error
}

// PluginAPIClient defines API client methods for the plugins
type PluginAPIClient interface {
	PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error)
	PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error
	PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error
	PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error
	PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error)
	PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error)
	PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error)
	PluginSet(ctx context.Context, name string, args []string) error
	PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error)
	PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error
}

// ServiceAPIClient defines API client methods for the services
type ServiceAPIClient interface {
	ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error)
	ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
	ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
	ServiceRemove(ctx context.Context, serviceID string) error
	ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
	ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
	TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
}

// SwarmAPIClient defines API client methods for the swarm
type SwarmAPIClient interface {
	SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
	SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error)
	SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error
	SwarmLeave(ctx context.Context, force bool) error
	SwarmInspect(ctx context.Context) (swarm.Swarm, error)
	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error
}

// SystemAPIClient defines API client methods for the system
type SystemAPIClient interface {
	Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error)
	Info(ctx context.Context) (types.Info, error)
	RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error)
	DiskUsage(ctx context.Context) (types.DiskUsage, error)
	Ping(ctx context.Context) (types.Ping, error)
}

// VolumeAPIClient defines API client methods for the volumes
type VolumeAPIClient interface {
	VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error)
	VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
	VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
	VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error)
	VolumeRemove(ctx context.Context, volumeID string, force bool) error
	VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
}

// SecretAPIClient defines API client methods for secrets
type SecretAPIClient interface {
	SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error)
	SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error)
	SecretRemove(ctx context.Context, id string) error
	SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error)
	SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error
}

// ConfigAPIClient defines API client methods for configs
type ConfigAPIClient interface {
	ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error)
	ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error)
	ConfigRemove(ctx context.Context, id string) error
	ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error)
	ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error
}
<commit_msg>Alias container and network packages to stop name clashes<commit_after>package client

import (
	"io"
	"net"
	"time"

	"github.com/docker/docker/api/types"
	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/events"
	"github.com/docker/docker/api/types/filters"
	"github.com/docker/docker/api/types/image"
	networktypes "github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/registry"
	"github.com/docker/docker/api/types/swarm"
	volumetypes "github.com/docker/docker/api/types/volume"
	"golang.org/x/net/context"
)

// CommonAPIClient is the common methods between stable and experimental versions of APIClient.
type CommonAPIClient interface {
	ConfigAPIClient
	ContainerAPIClient
	DistributionAPIClient
	ImageAPIClient
	NodeAPIClient
	NetworkAPIClient
	PluginAPIClient
	ServiceAPIClient
	SwarmAPIClient
	SecretAPIClient
	SystemAPIClient
	VolumeAPIClient
	ClientVersion() string
	DaemonHost() string
	ServerVersion(ctx context.Context) (types.Version, error)
	NegotiateAPIVersion(ctx context.Context)
	NegotiateAPIVersionPing(types.Ping)
	DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
}

// ContainerAPIClient defines API client methods for the containers
type ContainerAPIClient interface {
	ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
	ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
	ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, containerName string) (containertypes.ContainerCreateCreatedBody, error)
	ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, error)
	ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
	ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error)
	ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
	ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
	ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
	ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
	ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
	ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
	ContainerKill(ctx context.Context, container, signal string) error
	ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
	ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	ContainerPause(ctx context.Context, container string) error
	ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
	ContainerRename(ctx context.Context, container, newContainerName string) error
	ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
	ContainerRestart(ctx context.Context, container string, timeout *time.Duration) error
	ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
	ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error)
	ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error
	ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
	ContainerTop(ctx context.Context, container string, arguments []string) (containertypes.ContainerTopOKBody, error)
	ContainerUnpause(ctx context.Context, container string) error
	ContainerUpdate(ctx context.Context, container string, updateConfig containertypes.UpdateConfig) (containertypes.ContainerUpdateOKBody, error)
	ContainerWait(ctx context.Context, container string, condition containertypes.WaitCondition) (<-chan containertypes.ContainerWaitOKBody, <-chan error)
	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
	ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error)
}

// DistributionAPIClient defines API client methods for the registry
type DistributionAPIClient interface {
	DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error)
}

// ImageAPIClient defines API client methods for the images
type ImageAPIClient interface {
	ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
	BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error)
	ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
	ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
	ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
	ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error)
	ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error)
	ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
	ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
	ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
	ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error)
	ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
	ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
	ImageTag(ctx context.Context, image, ref string) error
	ImagesPrune(ctx context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error)
}

// NetworkAPIClient defines API client methods for the networks
type NetworkAPIClient interface {
	NetworkConnect(ctx context.Context, network, container string, config *networktypes.EndpointSettings) error
	NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
	NetworkDisconnect(ctx context.Context, network, container string, force bool) error
	NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error)
	NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error)
	NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
	NetworkRemove(ctx context.Context, network string) error
	NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error)
}

// NodeAPIClient defines API client methods for the nodes
type NodeAPIClient interface {
	NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error)
	NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error)
	NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error
	NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error
}

// PluginAPIClient defines API client methods for the plugins
type PluginAPIClient interface {
	PluginList(ctx context.Context, filter filters.Args) (types.PluginsListResponse, error)
	PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error
	PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error
	PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error
	PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error)
	PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error)
	PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error)
	PluginSet(ctx context.Context, name string, args []string) error
	PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error)
	PluginCreate(ctx context.Context, createContext io.Reader, options types.PluginCreateOptions) error
}

// ServiceAPIClient defines API client methods for the services
type ServiceAPIClient interface {
	ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error)
	ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
	ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
	ServiceRemove(ctx context.Context, serviceID string) error
	ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
	ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	TaskLogs(ctx context.Context, taskID string, options types.ContainerLogsOptions) (io.ReadCloser, error)
	TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error)
	TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error)
}

// SwarmAPIClient defines API client methods for the swarm
type SwarmAPIClient interface {
	SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error)
	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
	SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error)
	SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error
	SwarmLeave(ctx context.Context, force bool) error
	SwarmInspect(ctx context.Context) (swarm.Swarm, error)
	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error
}

// SystemAPIClient defines API client methods for the system
type SystemAPIClient interface {
	Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error)
	Info(ctx context.Context) (types.Info, error)
	RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error)
	DiskUsage(ctx context.Context) (types.DiskUsage, error)
	Ping(ctx context.Context) (types.Ping, error)
}

// VolumeAPIClient defines API client methods for the volumes
type VolumeAPIClient interface {
	VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error)
	VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
	VolumeInspectWithRaw(ctx context.Context, volumeID string) (types.Volume, []byte, error)
	VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error)
	VolumeRemove(ctx context.Context, volumeID string, force bool) error
	VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
}

// SecretAPIClient defines API client methods for secrets
type SecretAPIClient interface {
	SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error)
	SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error)
	SecretRemove(ctx context.Context, id string) error
	SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error)
	SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error
}

// ConfigAPIClient defines API client methods for configs
type ConfigAPIClient interface {
	ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error)
	ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error)
	ConfigRemove(ctx context.Context, id string) error
	ConfigInspectWithRaw(ctx context.Context, name string) (swarm.Config, []byte, error)
	ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 trivago GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package router

import (
	"github.com/trivago/gollum/core"
)

// Broadcast router plugin
//
// The "Broadcast" plugin relays all messages sent to [Stream] to all
// produces connected to [Stream].
//
// With the default options, this plugin has no practical effect. Using
// the Filters and TimeoutMs options, it is possible to restrict and control
// the messages being passed.
//
// Configuration example:
//
// # Generate junk messages
// JunkGenerator:
//   Type: "consumer.Profiler"
//   Message: "%20s"
//   Streams: "junkstream"
//   Characters: "abcdefghijklmZ"
//   KeepRunning: true
//   Runs: 10000
//   Batches: 3000000
//   DelayMs: 500
// # Filter out messsages including 'Z' and broadcast them
// JunkRouterBroad:
//   Type: "router.Broadcast"
//   Stream: "junkstream"
//   Filters:
//     - JunkRegexp:
//         Type: "filter.RegExp"
//         Expression: "Z"
// # Produce filtered messages from 'junkstream' to stdout
// JunkPrinter00:
//   Type: "producer.Console"
//   Streams: "junkstream"
//   Modulators:
//     - "format.Envelope":
//         Prefix: "[junkdist_00] "
// # Produce filtered messages from 'junkstream' to stdout
// JunkPrinter01:
//   Type: "producer.Console"
//   Streams: "junkstream"
//   Modulators:
//     - "format.Envelope":
//         Prefix: "[junkdist_01] "
//
type Broadcast struct {
	core.SimpleRouter `gollumdoc:"embed_type"`
}

func init() {
	core.TypeRegistry.Register(Broadcast{})
}

// Configure initializes this distributor with values from a plugin config.
func (router *Broadcast) Configure(conf core.PluginConfigReader) {
}

// Start the router
func (router *Broadcast) Start() error {
	return nil
}

// Enqueue enques a message to the router
func (router *Broadcast) Enqueue(msg *core.Message) error {
	producers := router.GetProducers()
	if len(producers) == 0 {
		return core.NewModulateResultError(
			"Router %s: no producers configured", router.GetID())
	}

	timeout := router.GetTimeout()
	lastProdIdx := len(producers) - 1
	for _, prod := range producers[:lastProdIdx] {
		prod.Enqueue(msg.Clone(), timeout)
	}

	// Cloning is a rather expensive operation, so skip cloning for the last
	// message (not required)
	producers[lastProdIdx].Enqueue(msg, timeout)
	return nil
}
<commit_msg>update plugin docs for router.broadcast<commit_after>// Copyright 2015-2017 trivago GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package router

import (
	"github.com/trivago/gollum/core"
)

// Broadcast router
//
// This router implements the default behavior of routing all messages to all
// producers registered to the configured stream.
//
// Examples
//
//  rateLimiter:
//    Type: router.Broadcast
//    Stream: errorlogs
//    Filters:
//      - filter.Rate:
//        MessagesPerSec: 200
type Broadcast struct {
	core.SimpleRouter `gollumdoc:"embed_type"`
}

func init() {
	core.TypeRegistry.Register(Broadcast{})
}

// Configure initializes this distributor with values from a plugin config.
func (router *Broadcast) Configure(conf core.PluginConfigReader) {
}

// Start the router
func (router *Broadcast) Start() error {
	return nil
}

// Enqueue enques a message to the router
func (router *Broadcast) Enqueue(msg *core.Message) error {
	producers := router.GetProducers()
	if len(producers) == 0 {
		return core.NewModulateResultError(
			"Router %s: no producers configured", router.GetID())
	}

	timeout := router.GetTimeout()
	lastProdIdx := len(producers) - 1
	for _, prod := range producers[:lastProdIdx] {
		prod.Enqueue(msg.Clone(), timeout)
	}

	// Cloning is a rather expensive operation, so skip cloning for the last
	// message (not required)
	producers[lastProdIdx].Enqueue(msg, timeout)
	return nil
}
<|endoftext|>


<commit_before>// +-------------------------------------------------------------------------
// | Copyright (C) 2016 Yunify, Inc.
// +-------------------------------------------------------------------------
// | Licensed under the Apache License, Version 2.0 (the "License");
// | you may not use this work except in compliance with the License.
// | You may obtain a copy of the License in the LICENSE file, or at:
// |
// | http://www.apache.org/licenses/LICENSE-2.0
// |
// | Unless required by applicable law or agreed to in writing, software
// | distributed under the License is distributed on an "AS IS" BASIS,
// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// | See the License for the specific language governing permissions and
// | limitations under the License.
// +-------------------------------------------------------------------------

package constants

// Version number string.
const Version = "0.2.12"
<commit_msg>Bump to version v0.2.13<commit_after>// +-------------------------------------------------------------------------
// | Copyright (C) 2016 Yunify, Inc.
// +-------------------------------------------------------------------------
// | Licensed under the Apache License, Version 2.0 (the "License");
// | you may not use this work except in compliance with the License.
// | You may obtain a copy of the License in the LICENSE file, or at:
// |
// | http://www.apache.org/licenses/LICENSE-2.0
// |
// | Unless required by applicable law or agreed to in writing, software
// | distributed under the License is distributed on an "AS IS" BASIS,
// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// | See the License for the specific language governing permissions and
// | limitations under the License.
// +-------------------------------------------------------------------------

package constants

// Version number string.
const Version = "0.2.13"
<|endoftext|>


<commit_before>// Copyright 2009 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.

// A synthetic filesystem emulating a persistent cloning interface
// from Plan 9. Reading the /clone file creates new entries in the filesystem
// each containing unique information/data. Clone files remember what it written
// to them. Removing a clone file does what is expected.

package main

import (
	"code.google.com/p/go9p/p"
	"code.google.com/p/go9p/p/srv"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"
)

type ClFile struct {
	srv.File
	created string
	id      int
	data    []byte
}

type Clone struct {
	srv.File
	clones int
}

var addr = flag.String("addr", ":5640", "network address")
var debug = flag.Bool("d", false, "print debug messages")

var root *srv.File

func (cl *ClFile) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
	var b []byte
	if len(cl.data) == 0 {
		str := strconv.Itoa(cl.id) + " created on:" + cl.created
		b = []byte(str)
	} else {
		b = cl.data
	}
	n := len(b)
	if offset >= uint64(n) {
		return 0, nil
	}

	b = b[int(offset):n]
	n -= int(offset)
	if len(buf) < n {
		n = len(buf)
	}

	copy(buf[offset:int(offset)+n], b[offset:])
	return n, nil
}

func (cl *ClFile) Write(fid *srv.FFid, data []byte, offset uint64) (int, error) {
	n := uint64(len(cl.data))
	nlen := offset + uint64(len(data))
	if nlen > n {
		ndata := make([]byte, nlen)
		copy(ndata, cl.data[0:n])
		cl.data = ndata
	}

	copy(cl.data[offset:], data[offset:])
	return len(data), nil
}

func (cl *ClFile) Remove(fid *srv.FFid) error {
	log.Println("Remove")
	return nil
}

func (cl *Clone) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
	// we only allow a single read from us, change the offset and we're done
	if offset > uint64(0) {
		return 0, nil
	}

	cl.clones += 1
	ncl := new(ClFile)
	ncl.id = cl.clones
	ncl.created = time.Now().String()
	name := strconv.Itoa(ncl.id)

	err := ncl.Add(root, name, p.OsUsers.Uid2User(os.Geteuid()), nil, 0666, ncl)
	if err != nil {
		return 0, &p.Error{"can not create file", 0}
	}

	b := []byte(name)
	if len(buf) < len(b) {
		// cleanup
		ncl.File.Remove()
		return 0, &p.Error{"not enough buffer space for result", 0}
	}

	copy(buf, b)
	return len(b), nil
}

func main() {
	var err error
	var cl *Clone
	var s *srv.Fsrv

	flag.Parse()
	user := p.OsUsers.Uid2User(os.Geteuid())
	root = new(srv.File)
	err = root.Add(nil, "/", user, nil, p.DMDIR|0777, nil)
	if err != nil {
		goto error
	}

	cl = new(Clone)
	err = cl.Add(root, "clone", p.OsUsers.Uid2User(os.Geteuid()), nil, 0444, cl)
	if err != nil {
		goto error
	}

	s = srv.NewFileSrv(root)
	s.Dotu = true

	if *debug {
		s.Debuglevel = 1
	}

	s.Start(s)
	err = s.StartNetListener("tcp", *addr)
	if err != nil {
		goto error
	}
	return

error:
	log.Println(fmt.Sprintf("Error: %s", err))
}
<commit_msg>Implement Wstat for clonefs.<commit_after>// Copyright 2009 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.

// A synthetic filesystem emulating a persistent cloning interface
// from Plan 9. Reading the /clone file creates new entries in the filesystem
// each containing unique information/data. Clone files remember what it written
// to them. Removing a clone file does what is expected.

package main

import (
	"code.google.com/p/go9p/p"
	"code.google.com/p/go9p/p/srv"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"
)

type ClFile struct {
	srv.File
	created string
	id      int
	data    []byte
}

type Clone struct {
	srv.File
	clones int
}

var addr = flag.String("addr", ":5640", "network address")
var debug = flag.Bool("d", false, "print debug messages")

var root *srv.File

func (cl *ClFile) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
	var b []byte
	if len(cl.data) == 0 {
		str := strconv.Itoa(cl.id) + " created on:" + cl.created
		b = []byte(str)
	} else {
		b = cl.data
	}
	n := len(b)
	if offset >= uint64(n) {
		return 0, nil
	}

	b = b[int(offset):n]
	n -= int(offset)
	if len(buf) < n {
		n = len(buf)
	}

	copy(buf[offset:int(offset)+n], b[offset:])
	return n, nil
}

func (cl *ClFile) Write(fid *srv.FFid, data []byte, offset uint64) (int, error) {
	n := uint64(len(cl.data))
	nlen := offset + uint64(len(data))
	if nlen > n {
		ndata := make([]byte, nlen)
		copy(ndata, cl.data[0:n])
		cl.data = ndata
	}

	copy(cl.data[offset:], data[offset:])
	return len(data), nil
}

func (cl *ClFile) Wstat(fid *srv.FFid, dir *p.Dir) error {
	return nil
}

func (cl *ClFile) Remove(fid *srv.FFid) error {
	return nil
}

func (cl *Clone) Read(fid *srv.FFid, buf []byte, offset uint64) (int, error) {
	// we only allow a single read from us, change the offset and we're done
	if offset > uint64(0) {
		return 0, nil
	}

	cl.clones += 1
	ncl := new(ClFile)
	ncl.id = cl.clones
	ncl.created = time.Now().String()
	name := strconv.Itoa(ncl.id)

	err := ncl.Add(root, name, p.OsUsers.Uid2User(os.Geteuid()), nil, 0666, ncl)
	if err != nil {
		return 0, &p.Error{"can not create file", 0}
	}

	b := []byte(name)
	if len(buf) < len(b) {
		// cleanup
		ncl.File.Remove()
		return 0, &p.Error{"not enough buffer space for result", 0}
	}

	copy(buf, b)
	return len(b), nil
}

func main() {
	var err error
	var cl *Clone
	var s *srv.Fsrv

	flag.Parse()
	user := p.OsUsers.Uid2User(os.Geteuid())
	root = new(srv.File)
	err = root.Add(nil, "/", user, nil, p.DMDIR|0777, nil)
	if err != nil {
		goto error
	}

	cl = new(Clone)
	err = cl.Add(root, "clone", p.OsUsers.Uid2User(os.Geteuid()), nil, 0444, cl)
	if err != nil {
		goto error
	}

	s = srv.NewFileSrv(root)
	s.Dotu = true

	if *debug {
		s.Debuglevel = 1
	}

	s.Start(s)
	err = s.StartNetListener("tcp", *addr)
	if err != nil {
		goto error
	}
	return

error:
	log.Println(fmt.Sprintf("Error: %s", err))
}
<|endoftext|>


<commit_before>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package hugolib

import (
	"testing"

	"github.com/stretchr/testify/require"
)

// Just some simple test of the embedded templates to avoid
// https://github.com/gohugoio/hugo/issues/4757 and similar.
func TestEmbeddedTemplates(t *testing.T) {
	t.Parallel()

	assert := require.New(t)
	assert.True(true)

	home := []string{"index.html", `
GA:
{{ template "_internal/google_analytics.html" . }}

GA async:

{{ template "_internal/google_analytics_async.html" . }}

Disqus:

{{ template "_internal/disqus.html" . }}

`}

	b := newTestSitesBuilder(t)
	b.WithSimpleConfigFile().WithTemplatesAdded(home...)

	b.Build(BuildCfg{})

	// Gheck GA regular and async
	b.AssertFileContent("public/index.html",
		"'anonymizeIp', true",
		"'script','https://www.google-analytics.com/analytics.js','ga');\n\tga('create', 'ga_id', 'auto')",
		"<script async src='https://www.google-analytics.com/analytics.js'>")

	// Disqus
	b.AssertFileContent("public/index.html", "\"disqus_shortname\" + '.disqus.com/embed.js';")
}
<commit_msg>hugolib: Disable racy test<commit_after>// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package hugolib

import (
	"testing"

	"github.com/stretchr/testify/require"
)

// Just some simple test of the embedded templates to avoid
// https://github.com/gohugoio/hugo/issues/4757 and similar.
// TODO(bep) fix me https://github.com/gohugoio/hugo/issues/5926
func _TestEmbeddedTemplates(t *testing.T) {
	t.Parallel()

	assert := require.New(t)
	assert.True(true)

	home := []string{"index.html", `
GA:
{{ template "_internal/google_analytics.html" . }}

GA async:

{{ template "_internal/google_analytics_async.html" . }}

Disqus:

{{ template "_internal/disqus.html" . }}

`}

	b := newTestSitesBuilder(t)
	b.WithSimpleConfigFile().WithTemplatesAdded(home...)

	b.Build(BuildCfg{})

	// Gheck GA regular and async
	b.AssertFileContent("public/index.html",
		"'anonymizeIp', true",
		"'script','https://www.google-analytics.com/analytics.js','ga');\n\tga('create', 'ga_id', 'auto')",
		"<script async src='https://www.google-analytics.com/analytics.js'>")

	// Disqus
	b.AssertFileContent("public/index.html", "\"disqus_shortname\" + '.disqus.com/embed.js';")
}
<|endoftext|>


<commit_before>// +build ignore

// Cross compile rclone - in go because I hate bash ;-)

package main

import (
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"
)

var (
	// Flags
	debug    = flag.Bool("d", false, "Print commands instead of running them.")
	parallel = flag.Int("parallel", runtime.NumCPU(), "Number of commands to run in parallel.")
)

// GOOS/GOARCH pairs we build for
var osarches = []string{
	"windows/386",
	"windows/amd64",
	"darwin/386",
	"darwin/amd64",
	"linux/386",
	"linux/amd64",
	"linux/arm",
	"linux/arm64",
	"linux/mips",
	"linux/mipsle",
	"freebsd/386",
	"freebsd/amd64",
	"freebsd/arm",
	"netbsd/386",
	"netbsd/amd64",
	"netbsd/arm",
	"openbsd/386",
	"openbsd/amd64",
	"plan9/386",
	"plan9/amd64",
	"solaris/amd64",
}

// runEnv - run a shell command with env
func runEnv(args, env []string) {
	if *debug {
		args = append([]string{"echo"}, args...)
	}
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if env != nil {
		cmd.Env = append(os.Environ(), env...)
	}
	err := cmd.Run()
	if err != nil {
		log.Fatalf("Failed to run %v: %v", args, err)
	}
}

// run a shell command
func run(args ...string) {
	runEnv(args, nil)
}

// build the binary in dir
func compileArch(version, goos, goarch, dir string) {
	log.Printf("Compiling %s/%s", goos, goarch)
	output := filepath.Join(dir, "rclone")
	err := os.MkdirAll(dir, 0777)
	if err != nil {
		log.Fatalf("Failed to mkdir: %v", err)
	}
	args := []string{
		"go", "build",
		"--ldflags", "-s -X github.com/ncw/rclone/fs.Version=" + version,
		"-i",
		"-o", output,
		"..",
	}
	env := []string{
		"GOOS=" + goos,
		"GOARCH=" + goarch,
		"CGO_ENABLED=0",
	}
	runEnv(args, env)
	// Now build the zip
	run("cp", "-a", "../MANUAL.txt", filepath.Join(dir, "README.txt"))
	run("cp", "-a", "../MANUAL.html", filepath.Join(dir, "README.html"))
	run("cp", "-a", "../rclone.1", dir)
	zip := dir + ".zip"
	run("zip", "-r9", zip, dir)
	currentZip := strings.Replace(zip, "-"+version, "-current", 1)
	run("ln", zip, currentZip)
	run("rm", "-rf", dir)
	log.Printf("Done compiling %s/%s", goos, goarch)
}

func compile(version string) {
	start := time.Now()
	wg := new(sync.WaitGroup)
	run := make(chan func(), *parallel)
	for i := 0; i < *parallel; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for f := range run {
				f()
			}
		}()
	}
	for _, osarch := range osarches {
		parts := strings.Split(osarch, "/")
		if len(parts) != 2 {
			log.Fatalf("Bad osarch %q", osarch)
		}
		goos, goarch := parts[0], parts[1]
		userGoos := goos
		if goos == "darwin" {
			userGoos = "osx"
		}
		dir := filepath.Join("rclone-" + version + "-" + userGoos + "-" + goarch)
		run <- func() {
			compileArch(version, goos, goarch, dir)
		}
	}
	close(run)
	wg.Wait()
	log.Printf("Compiled %d arches in %v", len(osarches), time.Since(start))
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) != 1 {
		log.Fatalf("Syntax: %s <version>", os.Args[0])
	}
	version := args[0]
	run("rm", "-rf", "build")
	run("mkdir", "build")
	err := os.Chdir("build")
	if err != nil {
		log.Fatalf("Couldn't cd into build dir: %v", err)
	}
	compile(version)
}
<commit_msg>cross-compile: add missing .exe suffix to windows binaries<commit_after>// +build ignore

// Cross compile rclone - in go because I hate bash ;-)

package main

import (
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"time"
)

var (
	// Flags
	debug    = flag.Bool("d", false, "Print commands instead of running them.")
	parallel = flag.Int("parallel", runtime.NumCPU(), "Number of commands to run in parallel.")
)

// GOOS/GOARCH pairs we build for
var osarches = []string{
	"windows/386",
	"windows/amd64",
	"darwin/386",
	"darwin/amd64",
	"linux/386",
	"linux/amd64",
	"linux/arm",
	"linux/arm64",
	"linux/mips",
	"linux/mipsle",
	"freebsd/386",
	"freebsd/amd64",
	"freebsd/arm",
	"netbsd/386",
	"netbsd/amd64",
	"netbsd/arm",
	"openbsd/386",
	"openbsd/amd64",
	"plan9/386",
	"plan9/amd64",
	"solaris/amd64",
}

// runEnv - run a shell command with env
func runEnv(args, env []string) {
	if *debug {
		args = append([]string{"echo"}, args...)
	}
	cmd := exec.Command(args[0], args[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if env != nil {
		cmd.Env = append(os.Environ(), env...)
	}
	err := cmd.Run()
	if err != nil {
		log.Fatalf("Failed to run %v: %v", args, err)
	}
}

// run a shell command
func run(args ...string) {
	runEnv(args, nil)
}

// build the binary in dir
func compileArch(version, goos, goarch, dir string) {
	log.Printf("Compiling %s/%s", goos, goarch)
	output := filepath.Join(dir, "rclone")
	if goos == "windows" {
		output += ".exe"
	}
	err := os.MkdirAll(dir, 0777)
	if err != nil {
		log.Fatalf("Failed to mkdir: %v", err)
	}
	args := []string{
		"go", "build",
		"--ldflags", "-s -X github.com/ncw/rclone/fs.Version=" + version,
		"-i",
		"-o", output,
		"..",
	}
	env := []string{
		"GOOS=" + goos,
		"GOARCH=" + goarch,
		"CGO_ENABLED=0",
	}
	runEnv(args, env)
	// Now build the zip
	run("cp", "-a", "../MANUAL.txt", filepath.Join(dir, "README.txt"))
	run("cp", "-a", "../MANUAL.html", filepath.Join(dir, "README.html"))
	run("cp", "-a", "../rclone.1", dir)
	zip := dir + ".zip"
	run("zip", "-r9", zip, dir)
	currentZip := strings.Replace(zip, "-"+version, "-current", 1)
	run("ln", zip, currentZip)
	run("rm", "-rf", dir)
	log.Printf("Done compiling %s/%s", goos, goarch)
}

func compile(version string) {
	start := time.Now()
	wg := new(sync.WaitGroup)
	run := make(chan func(), *parallel)
	for i := 0; i < *parallel; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for f := range run {
				f()
			}
		}()
	}
	for _, osarch := range osarches {
		parts := strings.Split(osarch, "/")
		if len(parts) != 2 {
			log.Fatalf("Bad osarch %q", osarch)
		}
		goos, goarch := parts[0], parts[1]
		userGoos := goos
		if goos == "darwin" {
			userGoos = "osx"
		}
		dir := filepath.Join("rclone-" + version + "-" + userGoos + "-" + goarch)
		run <- func() {
			compileArch(version, goos, goarch, dir)
		}
	}
	close(run)
	wg.Wait()
	log.Printf("Compiled %d arches in %v", len(osarches), time.Since(start))
}

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) != 1 {
		log.Fatalf("Syntax: %s <version>", os.Args[0])
	}
	version := args[0]
	run("rm", "-rf", "build")
	run("mkdir", "build")
	err := os.Chdir("build")
	if err != nil {
		log.Fatalf("Couldn't cd into build dir: %v", err)
	}
	compile(version)
}
<|endoftext|>