<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.

// Package os provides a platform-independent interface to operating system
// functionality.  The design is Unix-like.
// The os interface is intended to be uniform across all operating systems.
// Features not generally available appear in the system-specific package syscall.
package os

import (
	"io"
	"syscall"
)

// Name returns the name of the file as presented to Open.
func (file *File) Name() string { return file.name }

// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
var (
	Stdin  = NewFile(syscall.Stdin, "/dev/stdin")
	Stdout = NewFile(syscall.Stdout, "/dev/stdout")
	Stderr = NewFile(syscall.Stderr, "/dev/stderr")
)

// Flags to Open wrapping those of the underlying system. Not all flags
// may be implemented on a given system.
const (
	O_RDONLY   int = syscall.O_RDONLY   // open the file read-only.
	O_WRONLY   int = syscall.O_WRONLY   // open the file write-only.
	O_RDWR     int = syscall.O_RDWR     // open the file read-write.
	O_APPEND   int = syscall.O_APPEND   // append data to the file when writing.
	O_ASYNC    int = syscall.O_ASYNC    // generate a signal when I/O is available.
	O_CREATE   int = syscall.O_CREAT    // create a new file if none exists.
	O_EXCL     int = syscall.O_EXCL     // used with O_CREATE, file must not exist
	O_NOCTTY   int = syscall.O_NOCTTY   // do not make file the controlling tty.
	O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
	O_NDELAY   int = O_NONBLOCK         // synonym for O_NONBLOCK
	O_SYNC     int = syscall.O_SYNC     // open for synchronous I/O.
	O_TRUNC    int = syscall.O_TRUNC    // if possible, truncate file when opened.
)

// Seek whence values.
const (
	SEEK_SET int = 0 // seek relative to the origin of the file
	SEEK_CUR int = 1 // seek relative to the current offset
	SEEK_END int = 2 // seek relative to the end
)

// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
// EOF is signaled by a zero count with err set to io.EOF.
func (file *File) Read(b []byte) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	n, e := file.read(b)
	if n < 0 {
		n = 0
	}
	if n == 0 && len(b) > 0 && e == nil {
		return 0, io.EOF
	}
	if e != nil {
		err = &PathError{"read", file.name, e}
	}
	return n, err
}

// ReadAt reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// EOF is signaled by a zero count with err set to io.EOF.
// ReadAt always returns a non-nil error when n != len(b).
func (file *File) ReadAt(b []byte, off int64) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	for len(b) > 0 {
		m, e := file.pread(b, off)
		if m == 0 && e == nil {
			return n, io.EOF
		}
		if e != nil {
			err = &PathError{"read", file.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
// Write returns a non-nil error when n != len(b).
func (file *File) Write(b []byte) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	n, e := file.write(b)
	if n < 0 {
		n = 0
	}

	epipecheck(file, e)

	if e != nil {
		err = &PathError{"write", file.name, e}
	}
	return n, err
}

// WriteAt writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
// WriteAt returns a non-nil error when n != len(b).
func (file *File) WriteAt(b []byte, off int64) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	for len(b) > 0 {
		m, e := file.pwrite(b, off)
		if e != nil {
			err = &PathError{"write", file.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (file *File) Seek(offset int64, whence int) (ret int64, err error) {
	r, e := file.seek(offset, whence)
	if e == nil && file.dirinfo != nil && r != 0 {
		e = syscall.EISDIR
	}
	if e != nil {
		return 0, &PathError{"seek", file.name, e}
	}
	return r, nil
}

// WriteString is like Write, but writes the contents of string s rather than
// an array of bytes.
func (file *File) WriteString(s string) (ret int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	return file.Write([]byte(s))
}

// Mkdir creates a new directory with the specified name and permission bits.
// It returns an error, if any.
func Mkdir(name string, perm uint32) error {
	e := syscall.Mkdir(name, perm)
	if e != nil {
		return &PathError{"mkdir", name, e}
	}
	return nil
}

// Chdir changes the current working directory to the named directory.
func Chdir(dir string) error {
	if e := syscall.Chdir(dir); e != nil {
		return &PathError{"chdir", dir, e}
	}
	return nil
}

// Chdir changes the current working directory to the file,
// which must be a directory.
func (f *File) Chdir() error {
	if e := syscall.Fchdir(f.fd); e != nil {
		return &PathError{"chdir", f.name, e}
	}
	return nil
}

// Open opens the named file for reading.  If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// It returns the File and an error, if any.
func Open(name string) (file *File, err error) {
	return OpenFile(name, O_RDONLY, 0)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// It returns the File and an error, if any.
func Create(name string) (file *File, err error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
<commit_msg>os: make ReadAt comment clearer<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.

// Package os provides a platform-independent interface to operating system
// functionality.  The design is Unix-like.
// The os interface is intended to be uniform across all operating systems.
// Features not generally available appear in the system-specific package syscall.
package os

import (
	"io"
	"syscall"
)

// Name returns the name of the file as presented to Open.
func (file *File) Name() string { return file.name }

// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
var (
	Stdin  = NewFile(syscall.Stdin, "/dev/stdin")
	Stdout = NewFile(syscall.Stdout, "/dev/stdout")
	Stderr = NewFile(syscall.Stderr, "/dev/stderr")
)

// Flags to Open wrapping those of the underlying system. Not all flags
// may be implemented on a given system.
const (
	O_RDONLY   int = syscall.O_RDONLY   // open the file read-only.
	O_WRONLY   int = syscall.O_WRONLY   // open the file write-only.
	O_RDWR     int = syscall.O_RDWR     // open the file read-write.
	O_APPEND   int = syscall.O_APPEND   // append data to the file when writing.
	O_ASYNC    int = syscall.O_ASYNC    // generate a signal when I/O is available.
	O_CREATE   int = syscall.O_CREAT    // create a new file if none exists.
	O_EXCL     int = syscall.O_EXCL     // used with O_CREATE, file must not exist
	O_NOCTTY   int = syscall.O_NOCTTY   // do not make file the controlling tty.
	O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
	O_NDELAY   int = O_NONBLOCK         // synonym for O_NONBLOCK
	O_SYNC     int = syscall.O_SYNC     // open for synchronous I/O.
	O_TRUNC    int = syscall.O_TRUNC    // if possible, truncate file when opened.
)

// Seek whence values.
const (
	SEEK_SET int = 0 // seek relative to the origin of the file
	SEEK_CUR int = 1 // seek relative to the current offset
	SEEK_END int = 2 // seek relative to the end
)

// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and an error, if any.
// EOF is signaled by a zero count with err set to io.EOF.
func (file *File) Read(b []byte) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	n, e := file.read(b)
	if n < 0 {
		n = 0
	}
	if n == 0 && len(b) > 0 && e == nil {
		return 0, io.EOF
	}
	if e != nil {
		err = &PathError{"read", file.name, e}
	}
	return n, err
}

// ReadAt reads len(b) bytes from the File starting at byte offset off.
// It returns the number of bytes read and the error, if any.
// ReadAt always returns a non-nil error when n < len(b).
// At end of file, that error is io.EOF.
func (file *File) ReadAt(b []byte, off int64) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	for len(b) > 0 {
		m, e := file.pread(b, off)
		if m == 0 && e == nil {
			return n, io.EOF
		}
		if e != nil {
			err = &PathError{"read", file.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
// Write returns a non-nil error when n != len(b).
func (file *File) Write(b []byte) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	n, e := file.write(b)
	if n < 0 {
		n = 0
	}

	epipecheck(file, e)

	if e != nil {
		err = &PathError{"write", file.name, e}
	}
	return n, err
}

// WriteAt writes len(b) bytes to the File starting at byte offset off.
// It returns the number of bytes written and an error, if any.
// WriteAt returns a non-nil error when n != len(b).
func (file *File) WriteAt(b []byte, off int64) (n int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	for len(b) > 0 {
		m, e := file.pwrite(b, off)
		if e != nil {
			err = &PathError{"write", file.name, e}
			break
		}
		n += m
		b = b[m:]
		off += int64(m)
	}
	return
}

// Seek sets the offset for the next Read or Write on file to offset, interpreted
// according to whence: 0 means relative to the origin of the file, 1 means
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
func (file *File) Seek(offset int64, whence int) (ret int64, err error) {
	r, e := file.seek(offset, whence)
	if e == nil && file.dirinfo != nil && r != 0 {
		e = syscall.EISDIR
	}
	if e != nil {
		return 0, &PathError{"seek", file.name, e}
	}
	return r, nil
}

// WriteString is like Write, but writes the contents of string s rather than
// an array of bytes.
func (file *File) WriteString(s string) (ret int, err error) {
	if file == nil {
		return 0, EINVAL
	}
	return file.Write([]byte(s))
}

// Mkdir creates a new directory with the specified name and permission bits.
// It returns an error, if any.
func Mkdir(name string, perm uint32) error {
	e := syscall.Mkdir(name, perm)
	if e != nil {
		return &PathError{"mkdir", name, e}
	}
	return nil
}

// Chdir changes the current working directory to the named directory.
func Chdir(dir string) error {
	if e := syscall.Chdir(dir); e != nil {
		return &PathError{"chdir", dir, e}
	}
	return nil
}

// Chdir changes the current working directory to the file,
// which must be a directory.
func (f *File) Chdir() error {
	if e := syscall.Fchdir(f.fd); e != nil {
		return &PathError{"chdir", f.name, e}
	}
	return nil
}

// Open opens the named file for reading.  If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// It returns the File and an error, if any.
func Open(name string) (file *File, err error) {
	return OpenFile(name, O_RDONLY, 0)
}

// Create creates the named file mode 0666 (before umask), truncating
// it if it already exists.  If successful, methods on the returned
// File can be used for I/O; the associated file descriptor has mode
// O_RDWR.
// It returns the File and an error, if any.
func Create(name string) (file *File, err error) {
	return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
<|endoftext|>


<commit_before><commit_msg>adding skeleton to file<commit_after><|endoftext|>


<commit_before>// Package structs contains various utilities functions to work with structs.
package structs

import "reflect"

var (
	// DefaultTagName is the default tag name for struct fields which provides
	// a more granular to tweak certain structs. Lookup the necessary functions
	// for more info.
	DefaultTagName = "structs" // struct's field default tag name
)

// Struct encapsulates a struct type to provide several high level functions
// around the struct.
type Struct struct {
	raw   interface{}
	value reflect.Value
}

// New returns a new *Struct with the struct s. It panics if the s's kind is
// not struct.
func New(s interface{}) *Struct {
	return &Struct{
		raw:   s,
		value: strctVal(s),
	}
}

// Map converts the given struct to a map[string]interface{}, where the keys
// of the map are the field names and the values of the map the associated
// values of the fields. The default key string is the struct field name but
// can be changed in the struct field's tag value. The "structs" key in the
// struct's field tag value is the key name. Example:
//
//   // Field appears in map as key "myName".
//   Name string `structs:"myName"`
//
// A value with the content of "-" ignores that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields will be neglected.
func (s *Struct) Map() map[string]interface{} {
	out := make(map[string]interface{})

	fields := s.structFields()

	for _, field := range fields {
		name := field.Name
		val := s.value.FieldByName(name)

		var finalVal interface{}

		tagName, tagOpts := parseTag(field.Tag.Get(DefaultTagName))
		if tagName != "" {
			name = tagName
		}

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			// look out for embedded structs, and convert them to a
			// map[string]interface{} too
			finalVal = Map(val.Interface())
		} else {

			finalVal = val.Interface()
		}

		out[name] = finalVal
	}

	return out
}

// Values converts the given s struct's field values to a []interface{}.  A
// struct tag with the content of "-" ignores the that particular field.
// Example:
//
//   // Field is ignored by this package.
//   Field int `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected.
func (s *Struct) Values() []interface{} {
	fields := s.structFields()

	var t []interface{}

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			// look out for embedded structs, and convert them to a
			// []interface{} to be added to the final values slice
			for _, embeddedVal := range Values(val.Interface()) {
				t = append(t, embeddedVal)
			}
		} else {
			t = append(t, val.Interface())
		}
	}

	return t
}

// Fields returns a slice of Fields. A struct tag with the content of "-"
// ignores the checking of that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// It panics if s's kind is not struct.
func (s *Struct) Fields() []*Field {
	return getFields(s.value)
}

func getFields(v reflect.Value) []*Field {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	t := v.Type()

	var fields []*Field

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)

		if tag := field.Tag.Get(DefaultTagName); tag == "-" {
			continue
		}

		f := &Field{
			field: field,
			value: v.FieldByName(field.Name),
		}

		fields = append(fields, f)

	}

	return fields
}

// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. It panics if the field is not found.
func (s *Struct) Field(name string) *Field {
	f, ok := s.FieldOk(name)
	if !ok {
		panic("field not found")
	}

	return f
}

// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. The boolean returns true if the field
// was found.
func (s *Struct) FieldOk(name string) (*Field, bool) {
	t := s.value.Type()

	field, ok := t.FieldByName(name)
	if !ok {
		return nil, false
	}

	return &Field{
		field: field,
		value: s.value.FieldByName(name),
	}, true
}

// IsZero returns true if all fields in a struct is a zero value (not
// initialized) A struct tag with the content of "-" ignores the checking of
// that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected. It panics if s's kind is not struct.
func (s *Struct) IsZero() bool {
	fields := s.structFields()

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			ok := IsZero(val.Interface())
			if !ok {
				return false
			}

			continue
		}

		// zero value of the given field, such as "" for string, 0 for int
		zero := reflect.Zero(val.Type()).Interface()

		//  current value of the given field
		current := val.Interface()

		if !reflect.DeepEqual(current, zero) {
			return false
		}
	}

	return true
}

// HasZero returns true if a field in a struct is not initialized (zero value).
// A struct tag with the content of "-" ignores the checking of that particular
// field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected. It panics if s's kind is not struct.
func (s *Struct) HasZero() bool {
	fields := s.structFields()

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			ok := HasZero(val.Interface())
			if ok {
				return true
			}

			continue
		}

		// zero value of the given field, such as "" for string, 0 for int
		zero := reflect.Zero(val.Type()).Interface()

		//  current value of the given field
		current := val.Interface()

		if reflect.DeepEqual(current, zero) {
			return true
		}
	}

	return false
}

// Name returns the structs's type name within its package. For more info refer
// to Name() function.
func (s *Struct) Name() string {
	return s.value.Type().Name()
}

// structFields returns the exported struct fields for a given s struct. This
// is a convenient helper method to avoid duplicate code in some of the
// functions.
func (s *Struct) structFields() []reflect.StructField {
	t := s.value.Type()

	var f []reflect.StructField

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		// we can't access the value of unexported fields
		if field.PkgPath != "" {
			continue
		}

		// don't check if it's omitted
		if tag := field.Tag.Get(DefaultTagName); tag == "-" {
			continue
		}

		f = append(f, field)
	}

	return f
}

func strctVal(s interface{}) reflect.Value {
	v := reflect.ValueOf(s)

	// if pointer get the underlying element≤
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct {
		panic("not struct")
	}

	return v
}

// Map converts the given struct to a map[string]interface{}. For more info
// refer to Struct types Map() method. It panics if s's kind is not struct.
func Map(s interface{}) map[string]interface{} {
	return New(s).Map()
}

// Values converts the given struct to a []interface{}. For more info refer to
// Struct types Values() method.  It panics if s's kind is not struct.
func Values(s interface{}) []interface{} {
	return New(s).Values()
}

// Fields returns a slice of *Field. For more info refer to Struct types
// Fields() method.  It panics if s's kind is not struct.
func Fields(s interface{}) []*Field {
	return New(s).Fields()
}

// IsZero returns true if all fields is equal to a zero value. For more info
// refer to Struct types IsZero() method.  It panics if s's kind is not struct.
func IsZero(s interface{}) bool {
	return New(s).IsZero()
}

// HasZero returns true if any field is equal to a zero value. For more info
// refer to Struct types HasZero() method.  It panics if s's kind is not struct.
func HasZero(s interface{}) bool {
	return New(s).HasZero()
}

// IsStruct returns true if the given variable is a struct or a pointer to
// struct.
func IsStruct(s interface{}) bool {
	t := reflect.TypeOf(s)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	return t.Kind() == reflect.Struct
}

// Name returns the structs's type name within its package. It returns an
// empty string for unnamed types. It panics if s's kind is not struct.
func Name(s interface{}) string {
	return New(s).Name()
}
<commit_msg>structs: add omitempty tag option<commit_after>// Package structs contains various utilities functions to work with structs.
package structs

import "reflect"

var (
	// DefaultTagName is the default tag name for struct fields which provides
	// a more granular to tweak certain structs. Lookup the necessary functions
	// for more info.
	DefaultTagName = "structs" // struct's field default tag name
)

// Struct encapsulates a struct type to provide several high level functions
// around the struct.
type Struct struct {
	raw   interface{}
	value reflect.Value
}

// New returns a new *Struct with the struct s. It panics if the s's kind is
// not struct.
func New(s interface{}) *Struct {
	return &Struct{
		raw:   s,
		value: strctVal(s),
	}
}

// Map converts the given struct to a map[string]interface{}, where the keys
// of the map are the field names and the values of the map the associated
// values of the fields. The default key string is the struct field name but
// can be changed in the struct field's tag value. The "structs" key in the
// struct's field tag value is the key name. Example:
//
//   // Field appears in map as key "myName".
//   Name string `structs:"myName"`
//
// A tag value with the content of "-" ignores that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A tag value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// A tag value with the option of "omitempty" ignores that particular field if
// the field value is empty. Example:
//
//   // Field appears in map as key "myName", but the field is
//   // skipped if empty.
//   Field string `structs:"myName,omitempty"`
//
//   // Field appears in map as key "Field" (the default), but
//   // the field is skipped if empty.
//   Field string `structs:",omitempty"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields will be neglected.
func (s *Struct) Map() map[string]interface{} {
	out := make(map[string]interface{})

	fields := s.structFields()

	for _, field := range fields {
		name := field.Name
		val := s.value.FieldByName(name)

		var finalVal interface{}

		tagName, tagOpts := parseTag(field.Tag.Get(DefaultTagName))
		if tagName != "" {
			name = tagName
		}

		// if the value is a zero value do not include
		if tagOpts.Has("omitempty") {
			zero := reflect.Zero(val.Type()).Interface()
			current := val.Interface()

			if reflect.DeepEqual(current, zero) {
				continue
			}
		}

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			// look out for embedded structs, and convert them to a
			// map[string]interface{} too
			finalVal = Map(val.Interface())
		} else {

			finalVal = val.Interface()
		}

		out[name] = finalVal
	}

	return out
}

// Values converts the given s struct's field values to a []interface{}.  A
// struct tag with the content of "-" ignores the that particular field.
// Example:
//
//   // Field is ignored by this package.
//   Field int `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected.
func (s *Struct) Values() []interface{} {
	fields := s.structFields()

	var t []interface{}

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			// look out for embedded structs, and convert them to a
			// []interface{} to be added to the final values slice
			for _, embeddedVal := range Values(val.Interface()) {
				t = append(t, embeddedVal)
			}
		} else {
			t = append(t, val.Interface())
		}
	}

	return t
}

// Fields returns a slice of Fields. A struct tag with the content of "-"
// ignores the checking of that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// It panics if s's kind is not struct.
func (s *Struct) Fields() []*Field {
	return getFields(s.value)
}

func getFields(v reflect.Value) []*Field {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	t := v.Type()

	var fields []*Field

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)

		if tag := field.Tag.Get(DefaultTagName); tag == "-" {
			continue
		}

		f := &Field{
			field: field,
			value: v.FieldByName(field.Name),
		}

		fields = append(fields, f)

	}

	return fields
}

// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. It panics if the field is not found.
func (s *Struct) Field(name string) *Field {
	f, ok := s.FieldOk(name)
	if !ok {
		panic("field not found")
	}

	return f
}

// Field returns a new Field struct that provides several high level functions
// around a single struct field entitiy. The boolean returns true if the field
// was found.
func (s *Struct) FieldOk(name string) (*Field, bool) {
	t := s.value.Type()

	field, ok := t.FieldByName(name)
	if !ok {
		return nil, false
	}

	return &Field{
		field: field,
		value: s.value.FieldByName(name),
	}, true
}

// IsZero returns true if all fields in a struct is a zero value (not
// initialized) A struct tag with the content of "-" ignores the checking of
// that particular field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected. It panics if s's kind is not struct.
func (s *Struct) IsZero() bool {
	fields := s.structFields()

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			ok := IsZero(val.Interface())
			if !ok {
				return false
			}

			continue
		}

		// zero value of the given field, such as "" for string, 0 for int
		zero := reflect.Zero(val.Type()).Interface()

		//  current value of the given field
		current := val.Interface()

		if !reflect.DeepEqual(current, zero) {
			return false
		}
	}

	return true
}

// HasZero returns true if a field in a struct is not initialized (zero value).
// A struct tag with the content of "-" ignores the checking of that particular
// field. Example:
//
//   // Field is ignored by this package.
//   Field bool `structs:"-"`
//
// A value with the option of "omitnested" stops iterating further if the type
// is a struct. Example:
//
//   // Field is not processed further by this package.
//   Field time.Time     `structs:"myName,omitnested"`
//   Field *http.Request `structs:",omitnested"`
//
// Note that only exported fields of a struct can be accessed, non exported
// fields  will be neglected. It panics if s's kind is not struct.
func (s *Struct) HasZero() bool {
	fields := s.structFields()

	for _, field := range fields {
		val := s.value.FieldByName(field.Name)

		_, tagOpts := parseTag(field.Tag.Get(DefaultTagName))

		if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") {
			ok := HasZero(val.Interface())
			if ok {
				return true
			}

			continue
		}

		// zero value of the given field, such as "" for string, 0 for int
		zero := reflect.Zero(val.Type()).Interface()

		//  current value of the given field
		current := val.Interface()

		if reflect.DeepEqual(current, zero) {
			return true
		}
	}

	return false
}

// Name returns the structs's type name within its package. For more info refer
// to Name() function.
func (s *Struct) Name() string {
	return s.value.Type().Name()
}

// structFields returns the exported struct fields for a given s struct. This
// is a convenient helper method to avoid duplicate code in some of the
// functions.
func (s *Struct) structFields() []reflect.StructField {
	t := s.value.Type()

	var f []reflect.StructField

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		// we can't access the value of unexported fields
		if field.PkgPath != "" {
			continue
		}

		// don't check if it's omitted
		if tag := field.Tag.Get(DefaultTagName); tag == "-" {
			continue
		}

		f = append(f, field)
	}

	return f
}

func strctVal(s interface{}) reflect.Value {
	v := reflect.ValueOf(s)

	// if pointer get the underlying element≤
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	if v.Kind() != reflect.Struct {
		panic("not struct")
	}

	return v
}

// Map converts the given struct to a map[string]interface{}. For more info
// refer to Struct types Map() method. It panics if s's kind is not struct.
func Map(s interface{}) map[string]interface{} {
	return New(s).Map()
}

// Values converts the given struct to a []interface{}. For more info refer to
// Struct types Values() method.  It panics if s's kind is not struct.
func Values(s interface{}) []interface{} {
	return New(s).Values()
}

// Fields returns a slice of *Field. For more info refer to Struct types
// Fields() method.  It panics if s's kind is not struct.
func Fields(s interface{}) []*Field {
	return New(s).Fields()
}

// IsZero returns true if all fields is equal to a zero value. For more info
// refer to Struct types IsZero() method.  It panics if s's kind is not struct.
func IsZero(s interface{}) bool {
	return New(s).IsZero()
}

// HasZero returns true if any field is equal to a zero value. For more info
// refer to Struct types HasZero() method.  It panics if s's kind is not struct.
func HasZero(s interface{}) bool {
	return New(s).HasZero()
}

// IsStruct returns true if the given variable is a struct or a pointer to
// struct.
func IsStruct(s interface{}) bool {
	t := reflect.TypeOf(s)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	return t.Kind() == reflect.Struct
}

// Name returns the structs's type name within its package. It returns an
// empty string for unnamed types. It panics if s's kind is not struct.
func Name(s interface{}) string {
	return New(s).Name()
}
<|endoftext|>


<commit_before>package couchdb

import (
	"fmt"
)

// http://docs.couchdb.org/en/latest/intro/api.html#server
type Server struct {
	Couchdb string
	Uuid    string
	Vendor  struct {
		Version string
		Name    string
	}
	Version string
}

// http://docs.couchdb.org/en/latest/api/database/common.html#get--db
type DatabaseInfo struct {
	DbName             string `json:"db_name"`
	DocCount           int    `json:"doc_count"`
	DocDelCount        int    `json:"doc_del_count"`
	UpdateSeq          int    `json:"update_seq"`
	PurgeSeq           int    `json:"purge_seq"`
	CompactRunning     bool   `json:"compact_running"`
	DiskSize           int    `json:"disk_size"`
	DataSize           int    `json:"data_size"`
	InstanceStartTime  string `json:"instance_start_time"`
	DiskFormatVersion  int    `json:"disk_format_version"`
	CommittedUpdateSeq int    `json:"committed_update_seq"`
}

type DatabaseResponse struct {
	Ok bool
}

type Error struct {
	Method     string
	Url        string
	StatusCode int
	Type       string `json:"error"`
	Reason     string
}

func (e *Error) Error() string {
	return fmt.Sprintf("CouchDB - %s %s, Status Code: %d, Error: %s, Reason: %s", e.Method, e.Url, e.StatusCode, e.Type, e.Reason)
}

type Document struct {
	Id          string                `json:"_id,omitempty"`
	Rev         string                `json:"_rev,omitempty"`
	Attachments map[string]Attachment `json:"_attachments,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments
type Attachment struct {
	Follows     bool   `json:"follows"`
	ContentType string `json:"content_type"`
	Length      int64  `json:"length"`
}

type CouchDoc interface {
	GetDocument() *Document
}

type DocumentResponse struct {
	Ok  bool
	Id  string
	Rev string
}

// http://docs.couchdb.org/en/latest/api/server/common.html#active-tasks
type Task struct {
	ChangesDone  int `json:"changes_done"`
	Database     string
	Pid          string
	Progress     int
	StartedOn    int `json:"started_on"`
	Status       string
	Task         string
	TotalChanges int `json:"total_changes"`
	Type         string
	UpdatedOn    string `json:"updated_on"`
}

type QueryParameters struct {
	Conflicts       bool   `url:"conflicts,omitempty"`
	Descending      bool   `url:"descending,omitempty"`
	EndKey          string `url:"endkey,comma,omitempty"`
	EndKeyDocId     string `url:"end_key_doc_id,omitempty"`
	Group           bool   `url:"group,omitempty"`
	GroupLevel      int    `url:"group_level,omitempty"`
	IncludeDocs     bool   `url:"include_docs,omitempty"`
	Attachments     bool   `url:"attachments,omitempty"`
	AttEncodingInfo bool   `url:"att_encoding_info,omitempty"`
	InclusiveEnd    bool   `url:"inclusive_end,omitempty"`
	Key             string `url:"key,omitempty"`
	Limit           int    `url:"limit,omitempty"`
	Reduce          bool   `url:"reduce,omitempty"`
	Skip            int    `url:"skip,omitempty"`
	Stale           string `url:"stale,omitempty"`
	StartKey        string `url:"startkey,comma,omitempty"`
	StartKeyDocId   string `url:"startkey_docid,omitempty"`
	UpdateSeq       bool   `url:"update_seq,omitempty"`
}

type ViewResponse struct {
	Offset    int   `json:"offset,omitempty"`
	Rows      []Row `json:"rows,omitempty"`
	TotalRows int   `json:"total_rows,omitempty"`
	UpdateSeq int   `json:"update_seq,omitempty"`
}

type Row struct {
	Id    string                 `json:"id"`
	Key   interface{}            `json:"key"`
	Value interface{}            `json:"value,omitempty"`
	Doc   map[string]interface{} `json:"doc,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_bulk_docs
type BulkDoc struct {
	AllOrNothing bool          `json:"all_or_nothing,omitempty"`
	Docs         []interface{} `json:"docs"`
	NewEdits     bool          `json:"new_edits,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication
type Credentials struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type PostSessionResponse struct {
	Ok    bool
	Name  string
	Roles []string
}

type User struct {
	Document
	DerivedKey     string   `json:"derived_key,omitempty"`
	Name           string   `json:"name,omitempty"`
	Roles          []string `json:"roles"`
	Password       string   `json:"password,omitempty"`     // plain text password when creating the user
	PasswordSha    string   `json:"password_sha,omitempty"` // hashed password when requesting user information
	PasswordScheme string   `json:"password_scheme,omitempty"`
	Salt           string   `json:"salt,omitempty"`
	Type           string   `json:"type,omitempty"`
	Iterations     int      `json:"iterations,omitempty"`
}

func (user User) GetDocument() *Document {
	return &user.Document
}

func NewUser(name, password string, roles []string) User {
	user := User{
		Document: Document{
			Id: "org.couchdb.user:" + name,
		},
		DerivedKey:     "",
		Name:           name,
		Roles:          roles,
		Password:       password,
		PasswordSha:    "",
		PasswordScheme: "",
		Salt:           "",
		Type:           "user",
	}
	return user
}

type GetSessionResponse struct {
	Info struct {
		Authenticated          string   `json:"authenticated"`
		AuthenticationDb       string   `json:"authentication_db"`
		AuthenticationHandlers []string `json:"authentication_handlers"`
	} `json:"info"`
	Ok          bool `json:"ok"`
	UserContext struct {
		Db    string   `json:"db"`
		Name  string   `json:"name"`
		Roles []string `json:"roles"`
	} `json:"userCtx"`
}
<commit_msg>add advanced design document features<commit_after>package couchdb

import (
	"fmt"
	"strings"
)

// http://docs.couchdb.org/en/latest/intro/api.html#server
type Server struct {
	Couchdb string
	Uuid    string
	Vendor  struct {
		Version string
		Name    string
	}
	Version string
}

// http://docs.couchdb.org/en/latest/api/database/common.html#get--db
type DatabaseInfo struct {
	DbName             string `json:"db_name"`
	DocCount           int    `json:"doc_count"`
	DocDelCount        int    `json:"doc_del_count"`
	UpdateSeq          int    `json:"update_seq"`
	PurgeSeq           int    `json:"purge_seq"`
	CompactRunning     bool   `json:"compact_running"`
	DiskSize           int    `json:"disk_size"`
	DataSize           int    `json:"data_size"`
	InstanceStartTime  string `json:"instance_start_time"`
	DiskFormatVersion  int    `json:"disk_format_version"`
	CommittedUpdateSeq int    `json:"committed_update_seq"`
}

type DatabaseResponse struct {
	Ok bool
}

type Error struct {
	Method     string
	Url        string
	StatusCode int
	Type       string `json:"error"`
	Reason     string
}

func (e *Error) Error() string {
	return fmt.Sprintf("CouchDB - %s %s, Status Code: %d, Error: %s, Reason: %s", e.Method, e.Url, e.StatusCode, e.Type, e.Reason)
}

type Document struct {
	Id          string                `json:"_id,omitempty"`
	Rev         string                `json:"_rev,omitempty"`
	Attachments map[string]Attachment `json:"_attachments,omitempty"`
}

func (d Document) GetDocument() *Document {
	return &d
}

type DesignDocument struct {
	Document
	Language string                        `json:"language,omitempty"`
	Views    map[string]DesignDocumentView `json:"views,omitempty"`
}

func (dd DesignDocument) Name() string {
	return strings.TrimPrefix(dd.Id, "_design/")
}

type DesignDocumentView struct {
	Map    string `json:"map,omitempty"`
	Reduce string `json:"reduce,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments
type Attachment struct {
	Follows     bool   `json:"follows"`
	ContentType string `json:"content_type"`
	Length      int64  `json:"length"`
}

type CouchDoc interface {
	GetDocument() *Document
}

type DocumentResponse struct {
	Ok  bool
	Id  string
	Rev string
}

// http://docs.couchdb.org/en/latest/api/server/common.html#active-tasks
type Task struct {
	ChangesDone  int `json:"changes_done"`
	Database     string
	Pid          string
	Progress     int
	StartedOn    int `json:"started_on"`
	Status       string
	Task         string
	TotalChanges int `json:"total_changes"`
	Type         string
	UpdatedOn    string `json:"updated_on"`
}

type QueryParameters struct {
	Conflicts       bool   `url:"conflicts,omitempty"`
	Descending      bool   `url:"descending,omitempty"`
	EndKey          string `url:"endkey,comma,omitempty"`
	EndKeyDocId     string `url:"end_key_doc_id,omitempty"`
	Group           bool   `url:"group,omitempty"`
	GroupLevel      int    `url:"group_level,omitempty"`
	IncludeDocs     bool   `url:"include_docs,omitempty"`
	Attachments     bool   `url:"attachments,omitempty"`
	AttEncodingInfo bool   `url:"att_encoding_info,omitempty"`
	InclusiveEnd    bool   `url:"inclusive_end,omitempty"`
	Key             string `url:"key,omitempty"`
	Limit           int    `url:"limit,omitempty"`
	Reduce          bool   `url:"reduce,omitempty"`
	Skip            int    `url:"skip,omitempty"`
	Stale           string `url:"stale,omitempty"`
	StartKey        string `url:"startkey,comma,omitempty"`
	StartKeyDocId   string `url:"startkey_docid,omitempty"`
	UpdateSeq       bool   `url:"update_seq,omitempty"`
}

type ViewResponse struct {
	Offset    int   `json:"offset,omitempty"`
	Rows      []Row `json:"rows,omitempty"`
	TotalRows int   `json:"total_rows,omitempty"`
	UpdateSeq int   `json:"update_seq,omitempty"`
}

type Row struct {
	Id    string                 `json:"id"`
	Key   interface{}            `json:"key"`
	Value interface{}            `json:"value,omitempty"`
	Doc   map[string]interface{} `json:"doc,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_bulk_docs
type BulkDoc struct {
	AllOrNothing bool          `json:"all_or_nothing,omitempty"`
	Docs         []interface{} `json:"docs"`
	NewEdits     bool          `json:"new_edits,omitempty"`
}

// http://docs.couchdb.org/en/latest/api/server/authn.html#cookie-authentication
type Credentials struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type PostSessionResponse struct {
	Ok    bool
	Name  string
	Roles []string
}

type User struct {
	Document
	DerivedKey     string   `json:"derived_key,omitempty"`
	Name           string   `json:"name,omitempty"`
	Roles          []string `json:"roles"`
	Password       string   `json:"password,omitempty"`     // plain text password when creating the user
	PasswordSha    string   `json:"password_sha,omitempty"` // hashed password when requesting user information
	PasswordScheme string   `json:"password_scheme,omitempty"`
	Salt           string   `json:"salt,omitempty"`
	Type           string   `json:"type,omitempty"`
	Iterations     int      `json:"iterations,omitempty"`
}

func NewUser(name, password string, roles []string) User {
	user := User{
		Document: Document{
			Id: "org.couchdb.user:" + name,
		},
		DerivedKey:     "",
		Name:           name,
		Roles:          roles,
		Password:       password,
		PasswordSha:    "",
		PasswordScheme: "",
		Salt:           "",
		Type:           "user",
	}
	return user
}

type GetSessionResponse struct {
	Info struct {
		Authenticated          string   `json:"authenticated"`
		AuthenticationDb       string   `json:"authentication_db"`
		AuthenticationHandlers []string `json:"authentication_handlers"`
	} `json:"info"`
	Ok          bool `json:"ok"`
	UserContext struct {
		Db    string   `json:"db"`
		Name  string   `json:"name"`
		Roles []string `json:"roles"`
	} `json:"userCtx"`
}
<|endoftext|>


<commit_before>package stripe

// SubscriptionItemPriceDataRecurringParams is a structure representing the parameters to create
// an inline recurring price for a subscription item.
type SubscriptionItemPriceDataRecurringParams struct {
	AggregateUsage  *string `form:"aggregate_usage"`
	Interval        *string `form:"interval"`
	IntervalCount   *int64  `form:"interval_count"`
	TrialPeriodDays *int64  `form:"trial_period_days"`
	UsageType       *string `form:"usage_type"`
}

// SubscriptionItemPriceDataParams is a structure representing the parameters to create an inline
// price for a subscription item.
type SubscriptionItemPriceDataParams struct {
	Currency          *string                                   `form:"currency"`
	Product           *string                                   `form:"product"`
	Recurring         *SubscriptionItemPriceDataRecurringParams `form:"recurring"`
	UnitAmount        *int64                                    `form:"unit_amount"`
	UnitAmountDecimal *float64                                  `form:"unit_amount_decimal,high_precision"`
}

// SubscriptionItemParams is the set of parameters that can be used when creating or updating a subscription item.
// For more details see https://stripe.com/docs/api#create_subscription_item and https://stripe.com/docs/api#update_subscription_item.
type SubscriptionItemParams struct {
	Params            `form:"*"`
	ID                *string                                  `form:"-"` // Handled in URL
	BillingThresholds *SubscriptionItemBillingThresholdsParams `form:"billing_thresholds"`
	ClearUsage        *bool                                    `form:"clear_usage"`
	PaymentBehavior   *string                                  `form:"payment_behavior"`
	Plan              *string                                  `form:"plan"`
	Price             *string                                  `form:"price"`
	PriceData         *SubscriptionItemPriceDataParams         `form:"price_data"`
	Prorate           *bool                                    `form:"prorate"`
	ProrationDate     *int64                                   `form:"proration_date"`
	ProrationBehavior *string                                  `form:"proration_behavior"`
	Quantity          *int64                                   `form:"quantity"`
	Subscription      *string                                  `form:"subscription"`
	TaxRates          []*string                                `form:"tax_rates"`

	// The following parameters are only supported on updates
	OffSession *bool `form:"off_session"`
}

// SubscriptionItemBillingThresholdsParams is a structure representing the parameters allowed to
// control billing thresholds for a subscription item.
type SubscriptionItemBillingThresholdsParams struct {
	UsageGTE *int64 `form:"usage_gte"`
}

// SubscriptionItemListParams is the set of parameters that can be used when listing invoice items.
// For more details see https://stripe.com/docs/api#list_invoiceitems.
type SubscriptionItemListParams struct {
	ListParams   `form:"*"`
	Subscription *string `form:"subscription"`
}

// SubscriptionItem is the resource representing a Stripe subscription item.
// For more details see https://stripe.com/docs/api#subscription_items.
type SubscriptionItem struct {
	APIResource
	BillingThresholds SubscriptionItemBillingThresholds `json:"billing_thresholds"`
	Created           int64                             `json:"created"`
	Deleted           bool                              `json:"deleted"`
	ID                string                            `json:"id"`
	Metadata          map[string]string                 `json:"metadata"`
	Plan              *Plan                             `json:"plan"`
	Price             *Price                            `json:"price"`
	Quantity          int64                             `json:"quantity"`
	Subscription      string                            `json:"subscription"`
	TaxRates          []*TaxRate                        `json:"tax_rates"`
}

// SubscriptionItemBillingThresholds is a structure representing the billing thresholds for a
// subscription item.
type SubscriptionItemBillingThresholds struct {
	UsageGTE int64 `form:"usage_gte"`
}

// SubscriptionItemList is a list of invoice items as retrieved from a list endpoint.
type SubscriptionItemList struct {
	APIResource
	ListMeta
	Data []*SubscriptionItem `json:"data"`
}
<commit_msg>Fix parameters supported in `Recurring` for `PriceData` across the API<commit_after>package stripe

// SubscriptionItemPriceDataRecurringParams is a structure representing the parameters to create
// an inline recurring price for a subscription item.
type SubscriptionItemPriceDataRecurringParams struct {
	Interval      *string `form:"interval"`
	IntervalCount *int64  `form:"interval_count"`
}

// SubscriptionItemPriceDataParams is a structure representing the parameters to create an inline
// price for a subscription item.
type SubscriptionItemPriceDataParams struct {
	Currency          *string                                   `form:"currency"`
	Product           *string                                   `form:"product"`
	Recurring         *SubscriptionItemPriceDataRecurringParams `form:"recurring"`
	UnitAmount        *int64                                    `form:"unit_amount"`
	UnitAmountDecimal *float64                                  `form:"unit_amount_decimal,high_precision"`
}

// SubscriptionItemParams is the set of parameters that can be used when creating or updating a subscription item.
// For more details see https://stripe.com/docs/api#create_subscription_item and https://stripe.com/docs/api#update_subscription_item.
type SubscriptionItemParams struct {
	Params            `form:"*"`
	ID                *string                                  `form:"-"` // Handled in URL
	BillingThresholds *SubscriptionItemBillingThresholdsParams `form:"billing_thresholds"`
	ClearUsage        *bool                                    `form:"clear_usage"`
	PaymentBehavior   *string                                  `form:"payment_behavior"`
	Plan              *string                                  `form:"plan"`
	Price             *string                                  `form:"price"`
	PriceData         *SubscriptionItemPriceDataParams         `form:"price_data"`
	Prorate           *bool                                    `form:"prorate"`
	ProrationDate     *int64                                   `form:"proration_date"`
	ProrationBehavior *string                                  `form:"proration_behavior"`
	Quantity          *int64                                   `form:"quantity"`
	Subscription      *string                                  `form:"subscription"`
	TaxRates          []*string                                `form:"tax_rates"`

	// The following parameters are only supported on updates
	OffSession *bool `form:"off_session"`
}

// SubscriptionItemBillingThresholdsParams is a structure representing the parameters allowed to
// control billing thresholds for a subscription item.
type SubscriptionItemBillingThresholdsParams struct {
	UsageGTE *int64 `form:"usage_gte"`
}

// SubscriptionItemListParams is the set of parameters that can be used when listing invoice items.
// For more details see https://stripe.com/docs/api#list_invoiceitems.
type SubscriptionItemListParams struct {
	ListParams   `form:"*"`
	Subscription *string `form:"subscription"`
}

// SubscriptionItem is the resource representing a Stripe subscription item.
// For more details see https://stripe.com/docs/api#subscription_items.
type SubscriptionItem struct {
	APIResource
	BillingThresholds SubscriptionItemBillingThresholds `json:"billing_thresholds"`
	Created           int64                             `json:"created"`
	Deleted           bool                              `json:"deleted"`
	ID                string                            `json:"id"`
	Metadata          map[string]string                 `json:"metadata"`
	Plan              *Plan                             `json:"plan"`
	Price             *Price                            `json:"price"`
	Quantity          int64                             `json:"quantity"`
	Subscription      string                            `json:"subscription"`
	TaxRates          []*TaxRate                        `json:"tax_rates"`
}

// SubscriptionItemBillingThresholds is a structure representing the billing thresholds for a
// subscription item.
type SubscriptionItemBillingThresholds struct {
	UsageGTE int64 `form:"usage_gte"`
}

// SubscriptionItemList is a list of invoice items as retrieved from a list endpoint.
type SubscriptionItemList struct {
	APIResource
	ListMeta
	Data []*SubscriptionItem `json:"data"`
}
<|endoftext|>


<commit_before>/**
What about https://stackoverflow.com/questions/20932078/where-are-the-project-files-stored-in-a-git-repository-git-folder
*/

package main

import (
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"

	"github.com/gorilla/mux"
	"github.com/libgit2/git2go"
)

type SuchGit struct {
	RepoRoot string
	Tpl      *template.Template
	Router   *mux.Router
}

func NewSuchGit(repoRoot string) *SuchGit {
	sg := new(SuchGit)
	sg.RepoRoot = repoRoot
	sg.Setup()
	return sg
}

func (sg *SuchGit) Setup() {
	var err error
	sg.Tpl, err = template.ParseFiles(
		"_templates/header.html",
		"_templates/footer.html",
		"_templates/error.html",
		"_templates/tree.html",
		"_templates/repos.html",
		"_templates/repo.html")
	if err != nil {
		panic(err)
	}

	sg.Router = mux.NewRouter()
	sg.Router.HandleFunc("/", sg.HandleIndex)
	sg.Router.HandleFunc("/{repo}/tree/{ref}/{folder}", sg.HandleTree)
	sg.Router.HandleFunc("/{repo}/tree/{ref}", sg.HandleTree) // defaults to tree=/
	sg.Router.HandleFunc("/{repo}/tree/", sg.HandleTree)      // defaults to ref=head
	sg.Router.HandleFunc("/{repo}", sg.HandleTree)            // same as above
	sg.Router.HandleFunc("/{repo}/blob/{ref}/{file}", sg.HandleBlob)
	sg.Router.HandleFunc("/{repo}/blob/{file}", sg.HandleBlob) // defaults to ref=head
	sg.Router.HandleFunc("/{repo}/commits/{ref}", sg.HandleCommits)
	sg.Router.HandleFunc("/{repo}/commits", sg.HandleCommits) // defaults to ref=head
	sg.Router.HandleFunc("/{repo}/commit/{ref}", sg.HandleCommit)
	sg.Router.HandleFunc("/{repo}/commit", sg.HandleCommit) // defaults to ref=head
}

func (sg *SuchGit) ShowError(w http.ResponseWriter, err error) {
	err_ := sg.Tpl.ExecuteTemplate(w, "error.html", err)
	if err_ != nil {
		fmt.Fprintf(w, "Error: %s", err_)
		fmt.Fprintf(w, "From Error: %s", err)
	}
}

func (sg *SuchGit) ListRepositories() []string {
	repos, err := filepath.Glob(filepath.Join(sg.RepoRoot, "*.git"))
	if err != nil {
		return make([]string, 0)
	}
	for i, repo := range repos {
		repos[i] = filepath.Base(repo)
	}
	return repos
}

func (sg *SuchGit) HandleIndex(w http.ResponseWriter, r *http.Request) {
	repos := sg.ListRepositories()
	err := sg.Tpl.ExecuteTemplate(w, "repos.html", repos)
	if err != nil {
		fmt.Fprintf(w, "Error: %s", err)
	}
}

func (sg *SuchGit) HandleTree(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	repoName := vars["repo"]
	refName, set := vars["ref"]
	if !set {
		refName = "master"
	}
	folderName, set := vars["folder"]
	if !set {
		folderName = ""
	}

	repo, err := git.OpenRepository(filepath.Join(sg.RepoRoot, repoName))
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	ref, err := repo.DwimReference(refName)
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	oid := ref.Target()
	commit, err := repo.LookupCommit(oid)
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	folder, err := commit.Tree()
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	if folderName != "" {
		folderEntry, err := folder.EntryByPath(folderName)
		if err != nil {
			sg.ShowError(w, err)
			return
		}
		oid = folderEntry.Id
		folder, err = repo.LookupTree(oid)
		if err != nil {
			sg.ShowError(w, err)
			return
		}
	}

	count := folder.EntryCount()
	files := make([]string, 0, count)
	for i := uint64(0); i < count; i++ {
		files = append(files, folder.EntryByIndex(i).Name)
	}

	resp := TreeResponse{RepositoryResponse{repoName, refName, make([]string, 0), commit}, folderName, files}
	err = sg.Tpl.ExecuteTemplate(w, "tree.html", resp)
	if err != nil {
		sg.ShowError(w, err)
	}
}

func (sg *SuchGit) HandleBlob(w http.ResponseWriter, r *http.Request) {}

func (sg *SuchGit) HandleCommits(w http.ResponseWriter, r *http.Request) {}

func (sg *SuchGit) HandleCommit(w http.ResponseWriter, r *http.Request) {}
<commit_msg>Some testing.<commit_after>/**
What about https://stackoverflow.com/questions/20932078/where-are-the-project-files-stored-in-a-git-repository-git-folder
*/

package main

import (
	"fmt"
	"html/template"
	"net/http"
	"path/filepath"

	"github.com/gorilla/mux"
	"github.com/libgit2/git2go"
)

type SuchGit struct {
	RepoRoot string
	Tpl      *template.Template
	Router   *mux.Router
}

func NewSuchGit(repoRoot string) *SuchGit {
	sg := new(SuchGit)
	sg.RepoRoot = repoRoot
	sg.Setup()
	return sg
}

func (sg *SuchGit) Setup() {
	var err error
	sg.Tpl, err = template.ParseFiles(
		"_templates/header.html",
		"_templates/footer.html",
		"_templates/error.html",
		"_templates/tree.html",
		"_templates/repos.html",
		"_templates/repo.html")
	if err != nil {
		panic(err)
	}

	sg.Router = mux.NewRouter()
	sg.Router.HandleFunc("/", sg.HandleIndex)
	sg.Router.HandleFunc("/{repo}/tree/{ref}/{folder}", sg.HandleTree)
	sg.Router.HandleFunc("/{repo}/tree/{ref}", sg.HandleTree) // defaults to tree=/
	sg.Router.HandleFunc("/{repo}/tree/", sg.HandleTree)      // defaults to ref=head
	sg.Router.HandleFunc("/{repo}", sg.HandleTree)            // same as above
	sg.Router.HandleFunc("/{repo}/blob/{ref}/{file}", sg.HandleBlob)
	sg.Router.HandleFunc("/{repo}/blob/{file}", sg.HandleBlob) // defaults to ref=head
	sg.Router.HandleFunc("/{repo}/commits/{ref}", sg.HandleCommits)
	sg.Router.HandleFunc("/{repo}/commits", sg.HandleCommits) // defaults to ref=head
	sg.Router.HandleFunc("/{repo}/commit/{ref}", sg.HandleCommit)
	sg.Router.HandleFunc("/{repo}/commit", sg.HandleCommit) // defaults to ref=head
	// --- TESTING ---
	sg.Router.HandleFunc("/test/{repo}/file/{commit}/{filename}", sg.TestFileHandler)
	sg.Router.HandleFunc("/test/{repo}/diff/{id1}/{id2}", sg.TestDiffHandler)
	sg.Router.HandleFunc("/test/{repo}/{ref}", sg.TestHandler)
	sg.Router.HandleFunc("/test/{repo}", sg.TestHandler)
}

func (sg *SuchGit) ShowError(w http.ResponseWriter, err error) {
	err_ := sg.Tpl.ExecuteTemplate(w, "error.html", err)
	if err_ != nil {
		fmt.Fprintf(w, "Error: %s", err_)
		fmt.Fprintf(w, "From Error: %s", err)
	}
}

func (sg *SuchGit) ListRepositories() []string {
	repos, err := filepath.Glob(filepath.Join(sg.RepoRoot, "*.git"))
	if err != nil {
		return make([]string, 0)
	}
	for i, repo := range repos {
		repos[i] = filepath.Base(repo)
	}
	return repos
}

func (sg *SuchGit) HandleIndex(w http.ResponseWriter, r *http.Request) {
	repos := sg.ListRepositories()
	err := sg.Tpl.ExecuteTemplate(w, "repos.html", repos)
	if err != nil {
		fmt.Fprintf(w, "Error: %s", err)
	}
}

func (sg *SuchGit) HandleTree(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	repoName := vars["repo"]
	refName, set := vars["ref"]
	if !set {
		refName = "master"
	}
	folderName, set := vars["folder"]
	if !set {
		folderName = ""
	}

	repo, err := git.OpenRepository(filepath.Join(sg.RepoRoot, repoName))
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	ref, err := repo.DwimReference(refName)
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	oid := ref.Target()
	commit, err := repo.LookupCommit(oid)
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	folder, err := commit.Tree()
	if err != nil {
		sg.ShowError(w, err)
		return
	}

	if folderName != "" {
		folderEntry, err := folder.EntryByPath(folderName)
		if err != nil {
			sg.ShowError(w, err)
			return
		}
		oid = folderEntry.Id
		folder, err = repo.LookupTree(oid)
		if err != nil {
			sg.ShowError(w, err)
			return
		}
	}

	count := folder.EntryCount()
	files := make([]string, 0, count)
	for i := uint64(0); i < count; i++ {
		files = append(files, folder.EntryByIndex(i).Name)
	}

	resp := TreeResponse{RepositoryResponse{repoName, refName, make([]string, 0), commit}, folderName, files}
	err = sg.Tpl.ExecuteTemplate(w, "tree.html", resp)
	if err != nil {
		sg.ShowError(w, err)
	}
}

func (sg *SuchGit) HandleBlob(w http.ResponseWriter, r *http.Request) {}

func (sg *SuchGit) HandleCommits(w http.ResponseWriter, r *http.Request) {}

func (sg *SuchGit) HandleCommit(w http.ResponseWriter, r *http.Request) {}

func (sg *SuchGit) TestHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	repoName := vars["repo"]
	repo, err := git.OpenRepository(filepath.Join(sg.RepoRoot, repoName+".git"))
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}

	refName, refSet := vars["ref"]
	if refSet {
		ref, err := repo.DwimReference(refName)
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		fmt.Fprintf(w, "%s (%s)\n", ref.Shorthand(), ref.Name())
		oid := ref.Target()
		commit, err := repo.LookupCommit(oid)
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		for ; commit.ParentCount() > 0; commit = commit.Parent(0) {
			fmt.Fprintf(w, "[%s]\n%s\n\n", commit.Id().String(), commit.Message())
		}
	} else {
		refit, err := repo.NewReferenceIterator()
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		head, err := repo.Head()
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		for {
			ref, err := refit.Next()
			if err != nil {
				break // end of iterator
			}
			if ref.Name() == head.Name() {
				fmt.Fprintf(w, "*")
			} else {
				fmt.Fprintf(w, " ")
			}
			if ref.IsBranch() {
				fmt.Fprintf(w, "[Branch]")
			} else if ref.IsTag() {
				fmt.Fprintf(w, "[Tag]   ")
			} else if ref.IsRemote() {
				fmt.Fprintf(w, "[Remote]")
			} else {
				fmt.Fprintf(w, "--------")
			}
			fmt.Fprintf(w, " %25s (%s)\n", ref.Shorthand(), ref.Name())
		}

	}
}

func (sg *SuchGit) TestDiffHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	repoName := vars["repo"]
	repo, err := git.OpenRepository(filepath.Join(sg.RepoRoot, repoName+".git"))
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}

	id1, err := git.NewOid(vars["id1"])
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	commit1, err := repo.LookupCommit(id1)
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	tree1, err := commit1.Tree()
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	//id2, err := git.NewOid(vars["id2"])
	//if err != nil {
	//	fmt.Fprintf(w, "Error: %s\n", err)
	//	return
	//}
	//commit2, err := repo.LookupCommit(id2)
	//if err != nil {
	//	fmt.Fprintf(w, "Error: %s\n", err)
	//	return
	//}
	//tree2, err := commit2.Tree()
	//if err != nil {
	//	fmt.Fprintf(w, "Error: %s\n", err)
	//	return
	//}
	defaultDiffOptions, err := git.DefaultDiffOptions()
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	diff, err := repo.DiffTreeToTree(nil, tree1, &defaultDiffOptions)
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	deltas, err := diff.NumDeltas()
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	for i := 0; i < deltas; i++ {
		patch, err := diff.Patch(i)
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		patchString, err := patch.String()
		if err != nil {
			fmt.Fprintf(w, "Error: %s\n", err)
			return
		}
		fmt.Fprintf(w, "%s\n", patchString)
	}
}

func (sg *SuchGit) TestFileHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	repoName := vars["repo"]
	repo, err := git.OpenRepository(filepath.Join(sg.RepoRoot, repoName+".git"))
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}

	id1, err := git.NewOid(vars["commit"])
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	commit1, err := repo.LookupCommit(id1)
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	tree1, err := commit1.Tree()
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	fileEntry, err := tree1.EntryByPath(vars["filename"])
	if err != nil {
		fmt.Fprintf(w, "Error: %s\n", err)
		return
	}
	if fileEntry.Type != git.ObjectBlob {
		fmt.Fprintf(w, "File has to be blob!\n")
		return
	}
	oid := fileEntry.Id
	file, err := repo.LookupBlob(oid)
	if err != nil {
		fmt.Fprintf(w, "326 Error: %s\n", err)
		return
	}
	fmt.Fprintf(w, "<pre>%s</pre>\n", file.Contents())
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 Intel Corporation
//
// 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 main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	hyper "github.com/clearcontainers/agent/api"
	goudev "github.com/jochenvg/go-udev"
	"github.com/sirupsen/logrus"
)

const mountPerm = os.FileMode(0755)
const devPath = "/dev"

// bindMount bind mounts a source in to a destination, with the recursive
// flag if needed.
func bindMount(source, destination string, recursive bool) error {
	flags := syscall.MS_BIND

	if recursive == true {
		flags |= syscall.MS_REC
	}

	return mount(source, destination, "bind", flags)
}

// mount mounts a source in to a destination. This will do some bookkeeping:
// * evaluate all symlinks
// * ensure the source exists
func mount(source, destination, fsType string, flags int) error {
	var options string
	if fsType == "xfs" {
		options = "nouuid"
	}

	absSource, err := filepath.EvalSymlinks(source)
	if err != nil {
		return fmt.Errorf("Could not resolve symlink for source %v", source)
	}

	if err := ensureDestinationExists(absSource, destination, fsType); err != nil {
		return fmt.Errorf("Could not create destination mount point: %v: %v", destination, err)
	}

	if err := syscall.Mount(absSource, destination, fsType, uintptr(flags), options); err != nil {
		return fmt.Errorf("Could not bind mount %v to %v: %v", absSource, destination, err)
	}

	return nil
}

// ensureDestinationExists will recursively create a given mountpoint. If directories
// are created, their permissions are initialized to mountPerm
func ensureDestinationExists(source, destination string, fsType string) error {
	fileInfo, err := os.Stat(source)
	if err != nil {
		return fmt.Errorf("could not stat source location: %v", source)
	}

	targetPathParent, _ := filepath.Split(destination)
	if err := os.MkdirAll(targetPathParent, mountPerm); err != nil {
		return fmt.Errorf("could not create parent directory: %v", targetPathParent)
	}

	if fsType != "bind" || fileInfo.IsDir() {
		if err := os.Mkdir(destination, mountPerm); !os.IsExist(err) {
			return err
		}
	} else {
		file, err := os.OpenFile(destination, os.O_CREATE, mountPerm)
		if err != nil {
			return err
		}

		file.Close()
	}
	return nil
}

func mountShareDir(tag string) error {
	if tag == "" {
		return fmt.Errorf("Invalid mount tag, should not be empty")
	}

	if err := os.MkdirAll(mountShareDirDest, os.FileMode(0755)); err != nil {
		return err
	}

	return syscall.Mount(tag, mountShareDirDest, type9pFs, syscall.MS_MGC_VAL|syscall.MS_NODEV, "trans=virtio")
}

func unmountShareDir() error {
	if err := syscall.Unmount(mountShareDirDest, 0); err != nil {
		return err
	}

	return os.RemoveAll(containerMountDest)
}

var (
	// Here in "0:0", the first number is the SCSI host number, while the second number is always 0.
	scsiHostChannel = "/0:0:"

	scsiDiskPrefix = "/sys/class/scsi_disk" + scsiHostChannel

	scsiDiskSuffix = "/device/block"
)

func waitForBlockDevice(deviceName string, isSCSIAddr bool) error {
	var path string

	if isSCSIAddr {
		path = filepath.Join(scsiDiskPrefix+deviceName, scsiDiskSuffix)
	} else {
		path = filepath.Join(devPath, deviceName)
	}

	if _, err := os.Stat(path); err == nil {
		return nil
	}

	u := goudev.Udev{}

	// Create a monitor listening on a NetLink socket.
	monitor := u.NewMonitorFromNetlink("udev")

	// Add filter to watch for just block devices.
	if err := monitor.FilterAddMatchSubsystemDevtype("block", "disk"); err != nil {
		return err
	}

	// Create done signal channel for signalling epoll loop on the monitor socket.
	done := make(chan struct{})

	// Create channel to signal when desired udev event has been received.
	doneListening := make(chan bool)

	// Start monitor goroutine.
	ch, _ := monitor.DeviceChan(done)

	go func() {
		fieldLogger := agentLog.WithField("device", deviceName)

		fieldLogger.Info("Started listening for udev events for block device hotplug")

		// Check if the device already exists.
		if _, err := os.Stat(path); err == nil {
			fieldLogger.Info("Device already hotplugged, quit listening")
		} else {

			for d := range ch {
				fieldLogger = fieldLogger.WithFields(logrus.Fields{
					"udev-path":  d.Syspath(),
					"dev-path":   d.Devpath(),
					"udev-event": d.Action(),
				})

				fieldLogger.Info("got udev event")

				if isSCSIAddr && d.Action() == "add" && strings.Contains(d.Devpath(), scsiHostChannel+deviceName+"/block") {
					fieldLogger.Info("SCSI hotplug event received")
					break
				} else if d.Action() == "add" && filepath.Base(d.Devpath()) == deviceName {
					fieldLogger.Info("Block hotplug event received")
					break
				}
			}
		}
		close(doneListening)
	}()

	select {
	case <-doneListening:
		close(done)
	case <-time.After(time.Duration(1) * time.Second):
		close(done)
		return fmt.Errorf("Timed out waiting for device %s", deviceName)
	}

	return nil
}

var scsiHostPath = "/sys/class/scsi_host"

// scanSCSIBus scans SCSI bus for the given SCSI address(SCSI-Id and LUN)
func scanSCSIBus(scsiAddr string) error {
	files, err := ioutil.ReadDir(scsiHostPath)
	if err != nil {
		return err
	}

	tokens := strings.Split(scsiAddr, ":")
	if len(tokens) != 2 {
		return fmt.Errorf("Unexpected format for SCSI Address : %s, expect SCSIID:LUN", scsiAddr)
	}

	// Scan scsi host passing in the channel, SCSI id and LUN, channel is always 0
	scanData := []byte(fmt.Sprintf("0 %s %s", tokens[0], tokens[1]))

	for _, file := range files {
		host := file.Name()
		scanPath := filepath.Join(scsiHostPath, host, "scan")
		if err := ioutil.WriteFile(scanPath, scanData, 0200); err != nil {
			return err
		}
	}

	return nil
}

// findSCSIDisk finds the SCSI disk name associated with the given SCSI address.
// This approach eliminates the need to predict the disk name on the host side,
// but we do need to rescan SCSI bus for this.
func findSCSIDisk(scsiAddr string) (string, error) {
	scsiPath := filepath.Join(scsiDiskPrefix+scsiAddr, scsiDiskSuffix)

	files, err := ioutil.ReadDir(scsiPath)
	if err != nil {
		return "", err
	}

	l := len(files)

	if l == 0 || l > 1 {
		return "", fmt.Errorf("Expecting a single SCSI device, found %v", files)
	}

	return files[0].Name(), nil
}

// getSCSIDisk scans the SCSI bus for the SCSI address provided, waits for the SCSI disk
// to become available and returns the device name associated with the disk.
func getSCSIDisk(scsiAddr string) (string, error) {
	if err := scanSCSIBus(scsiAddr); err != nil {
		return "", err
	}

	// Check if disk is available, and find the disk name for the SCSI address
	scsiDiskName, err := findSCSIDisk(scsiAddr)

	if err == nil {
		if err = waitForBlockDevice(scsiDiskName, false); err != nil {
			return "", err
		}
	} else {
		// If device node is not found, wait for udev event for the scsi disk,
		// with the format "0:SCSIId:LUN/block"

		if err := waitForBlockDevice(scsiAddr, true); err != nil {
			return "", err
		}

		scsiDiskName, err = findSCSIDisk(scsiAddr)
		if err != nil {
			return "", err
		}
	}
	return filepath.Join(devPath, scsiDiskName), nil
}

func mountContainerRootFs(payload hyper.NewContainer) (string, error) {
	dest := filepath.Join(containerMountDest, payload.ID, "root")
	if err := os.MkdirAll(dest, os.FileMode(0755)); err != nil {
		return "", err
	}

	var source string
	var err error

	if payload.FsType != "" {
		// If SCSI adddress is provided, use that to find SCSI disk
		if payload.SCSIAddr != "" {
			source, err = getSCSIDisk(payload.SCSIAddr)
			if err != nil {
				return "", err
			}
		} else {
			source = filepath.Join(devPath, payload.Image)
			if err := waitForBlockDevice(payload.Image, false); err != nil {
				return "", err
			}
		}

		if err := mount(source, dest, payload.FsType, 0); err != nil {
			return "", fmt.Errorf("Mount rootfs command failed: %s", err)
		}
	} else {
		source = filepath.Join(mountShareDirDest, payload.Image)
		if err := bindMount(source, dest, false); err != nil {
			return "", err
		}
	}

	mountingPath := filepath.Join(dest, payload.RootFs)
	if err := bindMount(mountingPath, mountingPath, true); err != nil {
		return "", err
	}

	return mountingPath, nil
}

func unmountContainerRootFs(containerID, mountingPath string) error {
	if err := syscall.Unmount(mountingPath, 0); err != nil {
		return err
	}

	containerPath := filepath.Join(containerMountDest, containerID, "root")
	if err := syscall.Unmount(containerPath, 0); err != nil {
		return err
	}

	return os.RemoveAll(containerPath)
}

func ioctl(fd uintptr, flag, data uintptr) error {
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, flag, data); err != 0 {
		return err
	}

	return nil
}
<commit_msg>mount: Use 9p2000.L version when mounting 9p filesystem<commit_after>//
// Copyright (c) 2017 Intel Corporation
//
// 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 main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	hyper "github.com/clearcontainers/agent/api"
	goudev "github.com/jochenvg/go-udev"
	"github.com/sirupsen/logrus"
)

const mountPerm = os.FileMode(0755)
const devPath = "/dev"
const mntOptions9p = "trans=virtio,version=9p2000.L"

// bindMount bind mounts a source in to a destination, with the recursive
// flag if needed.
func bindMount(source, destination string, recursive bool) error {
	flags := syscall.MS_BIND

	if recursive == true {
		flags |= syscall.MS_REC
	}

	return mount(source, destination, "bind", flags)
}

// mount mounts a source in to a destination. This will do some bookkeeping:
// * evaluate all symlinks
// * ensure the source exists
func mount(source, destination, fsType string, flags int) error {
	var options string
	if fsType == "xfs" {
		options = "nouuid"
	}

	absSource, err := filepath.EvalSymlinks(source)
	if err != nil {
		return fmt.Errorf("Could not resolve symlink for source %v", source)
	}

	if err := ensureDestinationExists(absSource, destination, fsType); err != nil {
		return fmt.Errorf("Could not create destination mount point: %v: %v", destination, err)
	}

	if err := syscall.Mount(absSource, destination, fsType, uintptr(flags), options); err != nil {
		return fmt.Errorf("Could not bind mount %v to %v: %v", absSource, destination, err)
	}

	return nil
}

// ensureDestinationExists will recursively create a given mountpoint. If directories
// are created, their permissions are initialized to mountPerm
func ensureDestinationExists(source, destination string, fsType string) error {
	fileInfo, err := os.Stat(source)
	if err != nil {
		return fmt.Errorf("could not stat source location: %v", source)
	}

	targetPathParent, _ := filepath.Split(destination)
	if err := os.MkdirAll(targetPathParent, mountPerm); err != nil {
		return fmt.Errorf("could not create parent directory: %v", targetPathParent)
	}

	if fsType != "bind" || fileInfo.IsDir() {
		if err := os.Mkdir(destination, mountPerm); !os.IsExist(err) {
			return err
		}
	} else {
		file, err := os.OpenFile(destination, os.O_CREATE, mountPerm)
		if err != nil {
			return err
		}

		file.Close()
	}
	return nil
}

func mountShareDir(tag string) error {
	if tag == "" {
		return fmt.Errorf("Invalid mount tag, should not be empty")
	}

	if err := os.MkdirAll(mountShareDirDest, os.FileMode(0755)); err != nil {
		return err
	}

	return syscall.Mount(tag, mountShareDirDest, type9pFs, syscall.MS_MGC_VAL|syscall.MS_NODEV, mntOptions9p)
}

func unmountShareDir() error {
	if err := syscall.Unmount(mountShareDirDest, 0); err != nil {
		return err
	}

	return os.RemoveAll(containerMountDest)
}

var (
	// Here in "0:0", the first number is the SCSI host number, while the second number is always 0.
	scsiHostChannel = "/0:0:"

	scsiDiskPrefix = "/sys/class/scsi_disk" + scsiHostChannel

	scsiDiskSuffix = "/device/block"
)

func waitForBlockDevice(deviceName string, isSCSIAddr bool) error {
	var path string

	if isSCSIAddr {
		path = filepath.Join(scsiDiskPrefix+deviceName, scsiDiskSuffix)
	} else {
		path = filepath.Join(devPath, deviceName)
	}

	if _, err := os.Stat(path); err == nil {
		return nil
	}

	u := goudev.Udev{}

	// Create a monitor listening on a NetLink socket.
	monitor := u.NewMonitorFromNetlink("udev")

	// Add filter to watch for just block devices.
	if err := monitor.FilterAddMatchSubsystemDevtype("block", "disk"); err != nil {
		return err
	}

	// Create done signal channel for signalling epoll loop on the monitor socket.
	done := make(chan struct{})

	// Create channel to signal when desired udev event has been received.
	doneListening := make(chan bool)

	// Start monitor goroutine.
	ch, _ := monitor.DeviceChan(done)

	go func() {
		fieldLogger := agentLog.WithField("device", deviceName)

		fieldLogger.Info("Started listening for udev events for block device hotplug")

		// Check if the device already exists.
		if _, err := os.Stat(path); err == nil {
			fieldLogger.Info("Device already hotplugged, quit listening")
		} else {

			for d := range ch {
				fieldLogger = fieldLogger.WithFields(logrus.Fields{
					"udev-path":  d.Syspath(),
					"dev-path":   d.Devpath(),
					"udev-event": d.Action(),
				})

				fieldLogger.Info("got udev event")

				if isSCSIAddr && d.Action() == "add" && strings.Contains(d.Devpath(), scsiHostChannel+deviceName+"/block") {
					fieldLogger.Info("SCSI hotplug event received")
					break
				} else if d.Action() == "add" && filepath.Base(d.Devpath()) == deviceName {
					fieldLogger.Info("Block hotplug event received")
					break
				}
			}
		}
		close(doneListening)
	}()

	select {
	case <-doneListening:
		close(done)
	case <-time.After(time.Duration(1) * time.Second):
		close(done)
		return fmt.Errorf("Timed out waiting for device %s", deviceName)
	}

	return nil
}

var scsiHostPath = "/sys/class/scsi_host"

// scanSCSIBus scans SCSI bus for the given SCSI address(SCSI-Id and LUN)
func scanSCSIBus(scsiAddr string) error {
	files, err := ioutil.ReadDir(scsiHostPath)
	if err != nil {
		return err
	}

	tokens := strings.Split(scsiAddr, ":")
	if len(tokens) != 2 {
		return fmt.Errorf("Unexpected format for SCSI Address : %s, expect SCSIID:LUN", scsiAddr)
	}

	// Scan scsi host passing in the channel, SCSI id and LUN, channel is always 0
	scanData := []byte(fmt.Sprintf("0 %s %s", tokens[0], tokens[1]))

	for _, file := range files {
		host := file.Name()
		scanPath := filepath.Join(scsiHostPath, host, "scan")
		if err := ioutil.WriteFile(scanPath, scanData, 0200); err != nil {
			return err
		}
	}

	return nil
}

// findSCSIDisk finds the SCSI disk name associated with the given SCSI address.
// This approach eliminates the need to predict the disk name on the host side,
// but we do need to rescan SCSI bus for this.
func findSCSIDisk(scsiAddr string) (string, error) {
	scsiPath := filepath.Join(scsiDiskPrefix+scsiAddr, scsiDiskSuffix)

	files, err := ioutil.ReadDir(scsiPath)
	if err != nil {
		return "", err
	}

	l := len(files)

	if l == 0 || l > 1 {
		return "", fmt.Errorf("Expecting a single SCSI device, found %v", files)
	}

	return files[0].Name(), nil
}

// getSCSIDisk scans the SCSI bus for the SCSI address provided, waits for the SCSI disk
// to become available and returns the device name associated with the disk.
func getSCSIDisk(scsiAddr string) (string, error) {
	if err := scanSCSIBus(scsiAddr); err != nil {
		return "", err
	}

	// Check if disk is available, and find the disk name for the SCSI address
	scsiDiskName, err := findSCSIDisk(scsiAddr)

	if err == nil {
		if err = waitForBlockDevice(scsiDiskName, false); err != nil {
			return "", err
		}
	} else {
		// If device node is not found, wait for udev event for the scsi disk,
		// with the format "0:SCSIId:LUN/block"

		if err := waitForBlockDevice(scsiAddr, true); err != nil {
			return "", err
		}

		scsiDiskName, err = findSCSIDisk(scsiAddr)
		if err != nil {
			return "", err
		}
	}
	return filepath.Join(devPath, scsiDiskName), nil
}

func mountContainerRootFs(payload hyper.NewContainer) (string, error) {
	dest := filepath.Join(containerMountDest, payload.ID, "root")
	if err := os.MkdirAll(dest, os.FileMode(0755)); err != nil {
		return "", err
	}

	var source string
	var err error

	if payload.FsType != "" {
		// If SCSI adddress is provided, use that to find SCSI disk
		if payload.SCSIAddr != "" {
			source, err = getSCSIDisk(payload.SCSIAddr)
			if err != nil {
				return "", err
			}
		} else {
			source = filepath.Join(devPath, payload.Image)
			if err := waitForBlockDevice(payload.Image, false); err != nil {
				return "", err
			}
		}

		if err := mount(source, dest, payload.FsType, 0); err != nil {
			return "", fmt.Errorf("Mount rootfs command failed: %s", err)
		}
	} else {
		source = filepath.Join(mountShareDirDest, payload.Image)
		if err := bindMount(source, dest, false); err != nil {
			return "", err
		}
	}

	mountingPath := filepath.Join(dest, payload.RootFs)
	if err := bindMount(mountingPath, mountingPath, true); err != nil {
		return "", err
	}

	return mountingPath, nil
}

func unmountContainerRootFs(containerID, mountingPath string) error {
	if err := syscall.Unmount(mountingPath, 0); err != nil {
		return err
	}

	containerPath := filepath.Join(containerMountDest, containerID, "root")
	if err := syscall.Unmount(containerPath, 0); err != nil {
		return err
	}

	return os.RemoveAll(containerPath)
}

func ioctl(fd uintptr, flag, data uintptr) error {
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, flag, data); err != 0 {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package render

import (
	"bytes"
	"os"
	"os/exec"
	"strconv"
	"time"
)

func Image(url, filePath string, height, width int) (string, string, error) {
	cmd := exec.Command("/usr/local/bin/wkhtmltoimage", "--height", strconv.Itoa(height), "--width", strconv.Itoa(width), url, filePath)
	var stdOut bytes.Buffer
	var stdErr bytes.Buffer
	cmd.Stdout = &stdOut
	cmd.Stderr = &stdErr

	start := time.Now()
	err := cmd.Run()

	elapsed := time.Now().Sub(start)

	f, err := os.Create("/home/ubuntu/repos/marktai.com/upload/timings.txt")
	if err != nil {
		return stdOut.String(), stdErr.String(), err
	}

	defer f.Close()

	line := url + " took " + elapsed.String()

	_, _ = f.WriteString(line)
	return stdOut.String(), stdErr.String(), err
}
<commit_msg>changed create to open<commit_after>package render

import (
	"bytes"
	"os"
	"os/exec"
	"strconv"
	"time"
)

func Image(url, filePath string, height, width int) (string, string, error) {
	cmd := exec.Command("/usr/local/bin/wkhtmltoimage", "--height", strconv.Itoa(height), "--width", strconv.Itoa(width), url, filePath)
	var stdOut bytes.Buffer
	var stdErr bytes.Buffer
	cmd.Stdout = &stdOut
	cmd.Stderr = &stdErr

	start := time.Now()
	err := cmd.Run()

	elapsed := time.Now().Sub(start)

	f, err := os.Open("/home/ubuntu/repos/marktai.com/upload/timings.txt")
	if err != nil {
		return stdOut.String(), stdErr.String(), err
	}

	defer f.Close()

	line := url + " took " + elapsed.String()

	_, _ = f.WriteString(line)
	return stdOut.String(), stdErr.String(), err
}
<|endoftext|>