<commit_before>package bucketizer

import (
	"errors"
	"fmt"
	"io/ioutil"
	"sort"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/service/s3"
)

//Bucket handler for a S3 bucket
type Bucket struct {
	Client *s3.S3
	Bucket string
	ACL    string
	Creds  Credentials
}

// Credentials represents a pair of AWS credentials
type Credentials struct {
	AccessKey       string
	SecretAccessKey string
}

// Object in a S3 bucket
type Object struct {
	Key          string
	LastModified time.Time
	Data         []byte
}

func (p Object) String() string {
	return fmt.Sprintf("%s; %s", p.LastModified, p.Key)
}

// ByLastModified implements sort.Interface for []Object based on
// the LastModified field. Sort is descending
type ByLastModified []Object

func (a ByLastModified) Len() int           { return len(a) }
func (a ByLastModified) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByLastModified) Less(i, j int) bool { return a[i].LastModified.After(a[j].LastModified) }

// New creates a new connection to a S3 bucket using the provided credentials.
func New(bucket, accessKey, secretAccessKey string) (*Bucket, error) {

	creds := credentials.NewStaticCredentials(accessKey, secretAccessKey, "")

	newS3 := s3.New(&aws.Config{
		Region:      aws.String("eu-west-1"),
		Credentials: creds,
	})

	return &Bucket{Client: newS3, Bucket: bucket, ACL: "private"}, nil
}

//Test tests the connection to the bucket using the provided credentials
func (s *Bucket) Test() error {

	params := &s3.HeadBucketInput{
		Bucket: aws.String(s.Bucket), // Required
	}

	_, err := s.Client.HeadBucket(params)

	if err != nil {
		return err
	}

	return nil
}

//List all objects in a bucket
func (s *Bucket) List() (obj []Object, err error) {

	var resp *s3.ListObjectsOutput
	var currentKey string

	for {

		params := &s3.ListObjectsInput{
			Bucket:  aws.String(s.Bucket), // Required
			MaxKeys: aws.Int64(1000),
			Marker:  aws.String(currentKey),
		}
		resp, err = s.Client.ListObjects(params)

		for i := 0; i < len(resp.Contents); i++ {
			currentKey = *resp.Contents[i].Key
			obj = append(obj, Object{Key: *resp.Contents[i].Key, LastModified: *resp.Contents[i].LastModified})
		}

		if err != nil {
			// Print the error, cast err to awserr.Error to get the Code and
			// Message from an error.
			fmt.Println(err.Error())
			return nil, err
		}

		if !*resp.IsTruncated {
			break
		}
	}

	sort.Sort(ByLastModified(obj))

	return obj, nil
}

// Get data of an S3 object
func (s *Bucket) Get(key string) (o *Object, err error) {

	params := &s3.GetObjectInput{
		Bucket:          aws.String(s.Bucket),  // Required
		Key:             aws.String("/" + key), // Required
		ResponseExpires: aws.Time(time.Now()),
	}
	resp, err := s.Client.GetObject(params)

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			// Generic AWS Error with Code, Message, and original error (if any)
			if reqErr, ok := err.(awserr.RequestFailure); ok {
				// A service error occurred
				errMsg := fmt.Sprintf("%s %d %s", reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID())

				return nil, errors.New(errMsg)
			}

			errMsg := fmt.Sprintf("%s %s %s", awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
			return nil, errors.New(errMsg)

		}

		// This case should never be hit, the SDK should always return an
		// error which satisfies the awserr.Error interface.
		return nil, errors.New(err.Error())

	}

	buf, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		return nil, err
	}

	return &Object{Key: key, LastModified: *resp.LastModified, Data: buf}, nil
}

//Put stores an object into an S3 bucket
func (s *Bucket) Put(o *Object) error {

	/*	params := &s3.PutObjectInput{
			Bucket:      aws.String(s.Bucket),    // Required
			Key:         aws.String("/" + o.Key), // Required
			ACL:         aws.String(s.ACL),
			Body:        bytes.NewReader(o.Data),
			ContentType: aws.String("application/json"),
		}
		_, err := s.Client.PutObject(params)
	*/

	fmt.Println("Debug: S3 PUT temp disabled")

	var err error

	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok {
			// Generic AWS Error with Code, Message, and original error (if any)
			if reqErr, ok := err.(awserr.RequestFailure); ok {
				// A service error occurred
				errMsg := fmt.Sprintf("%s %d %s", reqErr.Message(), reqErr.StatusCode(), reqErr.RequestID())

				return errors.New(errMsg)
			}

			errMsg := fmt.Sprintf("%s %s %s", awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
			return errors.New(errMsg)

		}

		// This case should never be hit, the SDK should always return an
		// error which satisfies the awserr.Error interface.
		return errors.New(err.Error())

	}

	return nil
}
<commit_msg>updated readme<commit_after><|endoftext|>


<commit_before>package sp

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

const (
	apiURL = "https://api.spotify.com"
)

type Spotify struct {
	Client http.Client
}

// FloatString takes a string and converts it to a float64.
// The API returns strings for some things that one would expect
// to be numbers (for example, popularity))
type FloatString string

func (f *FloatString) UnmarshalJSON(i interface{}) float64 {
	s := i.(string)
	n, err := strconv.ParseFloat(s, 64)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

// IntString is the same as FloatString, but for integers.
type IntString string

func (f *IntString) UnmarshalJSON(i interface{}) int64 {
	s := i.(string)
	n, err := strconv.ParseInt(s, 10, 0)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

type ExternalID struct {
	Type string
	ID   IntString
}

type Artist struct {
	Href       string
	Name       string
	Popularity FloatString `json:"popularity,omitempty"`
}

type Album struct {
	Name         string
	Released     string       `json:"released,omitempty"`
	Popularity   FloatString  `json:"popularity,omitempty"`
	ExternalIDs  []ExternalID `json:"external-ids"`
	Length       float64      `json:"length,omitempty"`
	Href         string
	Artists      []Artist `json:"artists,omitempty"`
	Availability struct {
		Territories string
	}
}

type Info struct {
	NumResults int `json:"num_results"`
	Limit      int
	Offset     int
	Query      string
	Type       string
	Page       int
}

type SearchAlbumsResponse struct {
	Info   Info
	Albums struct {
		Items []Album
	}
}

type SearchArtistsResponse struct {
	Info    Info
	Artists []Artist
}

type Track struct {
	Album        Album
	Name         string
	ExternalIDs  []ExternalID `json:"external-ids"`
	Popularity   FloatString
	Explicit     bool `json:"explicit,omitempty"`
	Length       float64
	Href         string
	Artists      []Artist
	TrackNumber  IntString `json:"track-number"`
	Availability struct {
		Territories string
	} `json:"availability,omitempty"`
}

type SearchTracksResponse struct {
	Info   Info
	Tracks []Track
}

type LookupArtistResponse struct {
	Info struct {
		Type string
	}
	Artist Artist
}

type LookupTrackResponse struct {
	Info struct {
		Type string
	}
	Track Track
}

type LookupAlbumResponse struct {
	Info struct {
		Type string
	}
	Album struct {
		ArtistID    string `json:"artist-id"`
		Name        string
		Artist      string
		ExternalIDs []struct {
			Type string
			ID   string
		} `json:"external-ids"`
		Released string
		Tracks   []struct {
			Available bool
			Href      string
			Artists   []struct {
				Href string
				Name string
			}
			Name string
		}
	}
}

func (r *Spotify) getRequest(params map[string]string, endpoint string) ([]byte, error) {
	v := url.Values{}
	for key, val := range params {
		v.Set(key, val)
	}
	u := apiURL + endpoint + "?" + v.Encode()
	resp, err := r.Client.Get(u)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (r *Spotify) SearchAlbums(q string) (SearchAlbumsResponse, error) {
	p := map[string]string{"q": q, "type": "album"}
	e := "/v1/search"
	resp, err := r.getRequest(p, e)
	var s SearchAlbumsResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) SearchArtists(q string) (SearchArtistsResponse, error) {
	p := map[string]string{"q": q}
	e := "/search/1/artist.json"
	resp, err := r.getRequest(p, e)
	var s SearchArtistsResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) SearchTracks(q string) (SearchTracksResponse, error) {
	p := map[string]string{"q": q}
	e := "/search/1/track.json"
	resp, err := r.getRequest(p, e)
	var s SearchTracksResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) LookupArtist(uri string) (LookupArtistResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupArtistResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}

func (r *Spotify) LookupAlbum(uri string) (LookupAlbumResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupAlbumResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}

func (r *Spotify) LookupTrack(uri string) (LookupTrackResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupTrackResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}
<commit_msg>add images to album struct<commit_after>package sp

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strconv"
)

const (
	apiURL = "https://api.spotify.com"
)

type Spotify struct {
	Client *http.Client
}

// FloatString takes a string and converts it to a float64.
// The API returns strings for some things that one would expect
// to be numbers (for example, popularity))
type FloatString string

func (f *FloatString) UnmarshalJSON(i interface{}) float64 {
	s := i.(string)
	n, err := strconv.ParseFloat(s, 64)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

// IntString is the same as FloatString, but for integers.
type IntString string

func (f *IntString) UnmarshalJSON(i interface{}) int64 {
	s := i.(string)
	n, err := strconv.ParseInt(s, 10, 0)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

type Image struct {
	Height int
	URL    string
	Width  int
}

type ExternalID struct {
	Type string
	ID   IntString
}

type Artist struct {
	Href       string
	Name       string
	Popularity FloatString `json:"popularity,omitempty"`
}

type Album struct {
	Name         string
	Released     string        `json:"released,omitempty"`
	Popularity   FloatString   `json:"popularity,omitempty"`
	ExternalURLs []ExternalURL `json:"external_urls"`
	Length       float64       `json:"length,omitempty"`
	Href         string
	Artists      []Artist `json:"artists,omitempty"`
	Availability struct {
		Territories string
	}
	Images []Image
}

type Info struct {
	NumResults int `json:"num_results"`
	Limit      int
	Offset     int
	Query      string
	Type       string
	Page       int
}

type SearchAlbumsResponse struct {
	Info   Info
	Albums struct {
		Items []Album
	}
}

type SearchArtistsResponse struct {
	Info    Info
	Artists []Artist
}

type Track struct {
	Album        Album
	Name         string
	ExternalIDs  []ExternalID `json:"external-ids"`
	Popularity   FloatString
	Explicit     bool `json:"explicit,omitempty"`
	Length       float64
	Href         string
	Artists      []Artist
	TrackNumber  IntString `json:"track-number"`
	Availability struct {
		Territories string
	} `json:"availability,omitempty"`
}

type SearchTracksResponse struct {
	Info   Info
	Tracks []Track
}

type LookupArtistResponse struct {
	Info struct {
		Type string
	}
	Artist Artist
}

type LookupTrackResponse struct {
	Info struct {
		Type string
	}
	Track Track
}

type LookupAlbumResponse struct {
	Info struct {
		Type string
	}
	Album struct {
		ArtistID    string `json:"artist-id"`
		Name        string
		Artist      string
		ExternalIDs []struct {
			Type string
			ID   string
		} `json:"external-ids"`
		Released string
		Tracks   []struct {
			Available bool
			Href      string
			Artists   []struct {
				Href string
				Name string
			}
			Name string
		}
	}
}

func (r *Spotify) getRequest(params map[string]string, endpoint string) ([]byte, error) {
	v := url.Values{}
	for key, val := range params {
		v.Set(key, val)
	}
	u := apiURL + endpoint + "?" + v.Encode()
	resp, err := r.Client.Get(u)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

func (r *Spotify) SearchAlbums(q string) (SearchAlbumsResponse, error) {
	p := map[string]string{"q": q, "type": "album"}
	e := "/v1/search"
	resp, err := r.getRequest(p, e)
	var s SearchAlbumsResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) SearchArtists(q string) (SearchArtistsResponse, error) {
	p := map[string]string{"q": q}
	e := "/search/1/artist.json"
	resp, err := r.getRequest(p, e)
	var s SearchArtistsResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) SearchTracks(q string) (SearchTracksResponse, error) {
	p := map[string]string{"q": q}
	e := "/search/1/track.json"
	resp, err := r.getRequest(p, e)
	var s SearchTracksResponse
	if err != nil {
		return s, err
	}
	err = json.Unmarshal(resp, &s)
	if err != nil {
		return s, err
	}
	return s, nil
}

func (r *Spotify) LookupArtist(uri string) (LookupArtistResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupArtistResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}

func (r *Spotify) LookupAlbum(uri string) (LookupAlbumResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupAlbumResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}

func (r *Spotify) LookupTrack(uri string) (LookupTrackResponse, error) {
	p := map[string]string{"uri": uri}
	e := "/lookup/1/.json"
	resp, err := r.getRequest(p, e)
	var l LookupTrackResponse
	if err != nil {
		return l, err
	}
	err = json.Unmarshal(resp, &l)
	if err != nil {
		return l, err
	}
	return l, nil
}
<|endoftext|>


<commit_before>package pg

import (
	"context"
	"errors"
	"io"
	"sync"
	"sync/atomic"

	"github.com/go-pg/pg/v9/internal"
	"github.com/go-pg/pg/v9/internal/pool"
	"github.com/go-pg/pg/v9/orm"
)

var errTxDone = errors.New("pg: transaction has already been committed or rolled back")

// Tx is an in-progress database transaction. It is safe for concurrent use
// by multiple goroutines.
//
// A transaction must end with a call to Commit or Rollback.
//
// After a call to Commit or Rollback, all operations on the transaction fail
// with ErrTxDone.
//
// The statements prepared for a transaction by calling the transaction's
// Prepare or Stmt methods are closed by the call to Commit or Rollback.
type Tx struct {
	db  *baseDB
	ctx context.Context

	stmtsMu sync.Mutex
	stmts   []*Stmt

	_closed int32
}

var _ orm.DB = (*Tx)(nil)

// Context returns the context.Context of the transaction
func (tx *Tx) Context() context.Context {
	return tx.ctx
}

// Begin starts a transaction. Most callers should use RunInTransaction instead.
func (db *baseDB) Begin() (*Tx, error) {
	tx := &Tx{
		db:  db.withPool(pool.NewSingleConnPool(db.pool)),
		ctx: db.db.Context(),
	}

	err := tx.begin(tx.ctx)
	if err != nil {
		tx.close()
		return nil, err
	}

	return tx, nil
}

// RunInTransaction runs a function in a transaction. If function
// returns an error transaction is rollbacked, otherwise transaction
// is committed.
func (db *baseDB) RunInTransaction(fn func(*Tx) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	return tx.RunInTransaction(fn)
}

// Begin returns current transaction. It does not start new transaction.
func (tx *Tx) Begin() (*Tx, error) {
	return tx, nil
}

// RunInTransaction runs a function in the transaction. If function
// returns an error transaction is rollbacked, otherwise transaction
// is committed.
func (tx *Tx) RunInTransaction(fn func(*Tx) error) error {
	defer func() {
		if err := recover(); err != nil {
			_ = tx.Rollback()
			panic(err)
		}
	}()
	if err := fn(tx); err != nil {
		_ = tx.Rollback()
		return err
	}
	return tx.Commit()
}

func (tx *Tx) withConn(c context.Context, fn func(context.Context, *pool.Conn) error) error {
	err := tx.db.withConn(c, fn)
	if err == pool.ErrClosed {
		return errTxDone
	}
	return err
}

// Stmt returns a transaction-specific prepared statement
// from an existing statement.
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
	stmt, err := tx.Prepare(stmt.q)
	if err != nil {
		return &Stmt{stickyErr: err}
	}
	return stmt
}

// Prepare creates a prepared statement for use within a transaction.
//
// The returned statement operates within the transaction and can no longer
// be used once the transaction has been committed or rolled back.
//
// To use an existing prepared statement on this transaction, see Tx.Stmt.
func (tx *Tx) Prepare(q string) (*Stmt, error) {
	tx.stmtsMu.Lock()
	defer tx.stmtsMu.Unlock()

	stmt, err := prepareStmt(tx.db, q)
	if err != nil {
		return nil, err
	}
	tx.stmts = append(tx.stmts, stmt)

	return stmt, nil
}

// Exec is an alias for DB.Exec.
func (tx *Tx) Exec(query interface{}, params ...interface{}) (Result, error) {
	return tx.exec(tx.ctx, query, params...)
}

// ExecContext acts like Exec but additionally receives a context
func (tx *Tx) ExecContext(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	return tx.exec(c, query, params...)
}

func (tx *Tx) exec(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	c, evt, err := tx.db.beforeQuery(c, tx, nil, query, params)
	if err != nil {
		return nil, err
	}

	var res Result
	lastErr := tx.withConn(c, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.simpleQuery(c, cn, query, params...)
		return err
	})

	if err := tx.db.afterQuery(c, evt, res, lastErr); err != nil {
		return nil, err
	}
	return res, lastErr
}

// ExecOne is an alias for DB.ExecOne.
func (tx *Tx) ExecOne(query interface{}, params ...interface{}) (Result, error) {
	return tx.execOne(tx.ctx, query, params...)
}

// ExecOneContext acts like ExecOne but additionally receives a context
func (tx *Tx) ExecOneContext(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	return tx.execOne(c, query, params...)
}

func (tx *Tx) execOne(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	res, err := tx.ExecContext(c, query, params...)
	if err != nil {
		return nil, err
	}

	if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
		return nil, err
	}
	return res, nil
}

// Query is an alias for DB.Query.
func (tx *Tx) Query(model interface{}, query interface{}, params ...interface{}) (Result, error) {
	return tx.query(tx.ctx, model, query, params...)
}

// QueryContext acts like Query but additionally receives a context
func (tx *Tx) QueryContext(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	return tx.query(c, model, query, params...)
}

func (tx *Tx) query(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	c, evt, err := tx.db.beforeQuery(c, tx, model, query, params)
	if err != nil {
		return nil, err
	}

	var res *result
	lastErr := tx.withConn(c, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.simpleQueryData(c, cn, model, query, params...)
		return err
	})

	if err := tx.db.afterQuery(c, evt, res, lastErr); err != nil {
		return nil, err
	}
	return res, lastErr
}

// QueryOne is an alias for DB.QueryOne.
func (tx *Tx) QueryOne(model interface{}, query interface{}, params ...interface{}) (Result, error) {
	return tx.queryOne(tx.ctx, model, query, params...)
}

// QueryOneContext acts like QueryOne but additionally receives a context
func (tx *Tx) QueryOneContext(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	return tx.queryOne(c, model, query, params...)
}

func (tx *Tx) queryOne(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	mod, err := orm.NewModel(model)
	if err != nil {
		return nil, err
	}

	res, err := tx.QueryContext(c, mod, query, params...)
	if err != nil {
		return nil, err
	}

	if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
		return nil, err
	}
	return res, nil
}

// Model is an alias for DB.Model.
func (tx *Tx) Model(model ...interface{}) *orm.Query {
	return orm.NewQuery(tx, model...)
}

// ModelContext acts like Model but additionally receives a context
func (tx *Tx) ModelContext(c context.Context, model ...interface{}) *orm.Query {
	return orm.NewQueryContext(c, tx, model...)
}

// Select is an alias for DB.Select.
func (tx *Tx) Select(model interface{}) error {
	return orm.Select(tx, model)
}

// Insert is an alias for DB.Insert.
func (tx *Tx) Insert(model ...interface{}) error {
	return orm.Insert(tx, model...)
}

// Update is an alias for DB.Update.
func (tx *Tx) Update(model interface{}) error {
	return orm.Update(tx, model)
}

// Delete is an alias for DB.Delete.
func (tx *Tx) Delete(model interface{}) error {
	return orm.Delete(tx, model)
}

// ForceDelete forces the deletion of the model with deleted_at column.
func (tx *Tx) ForceDelete(model interface{}) error {
	return orm.ForceDelete(tx, model)
}

// CreateTable is an alias for DB.CreateTable.
func (tx *Tx) CreateTable(model interface{}, opt *orm.CreateTableOptions) error {
	return orm.CreateTable(tx, model, opt)
}

// DropTable is an alias for DB.DropTable.
func (tx *Tx) DropTable(model interface{}, opt *orm.DropTableOptions) error {
	return orm.DropTable(tx, model, opt)
}

// CopyFrom is an alias for DB.CopyFrom.
func (tx *Tx) CopyFrom(r io.Reader, query interface{}, params ...interface{}) (res Result, err error) {
	err = tx.withConn(tx.ctx, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.copyFrom(c, cn, r, query, params...)
		return err
	})
	return res, err
}

// CopyTo is an alias for DB.CopyTo.
func (tx *Tx) CopyTo(w io.Writer, query interface{}, params ...interface{}) (res Result, err error) {
	err = tx.withConn(tx.ctx, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.copyTo(c, cn, w, query, params...)
		return err
	})
	return res, err
}

// Formatter is an alias for DB.Formatter
func (tx *Tx) Formatter() orm.QueryFormatter {
	return tx.db.Formatter()
}

func (tx *Tx) begin(ctx context.Context) error {
	var lastErr error
	for attempt := 0; attempt <= tx.db.opt.MaxRetries; attempt++ {
		if attempt > 0 {
			if err := internal.Sleep(ctx, tx.db.retryBackoff(attempt-1)); err != nil {
				return err
			}

			err := tx.db.pool.(*pool.SingleConnPool).Reset()
			if err != nil {
				return err
			}
		}

		_, lastErr = tx.ExecContext(ctx, "BEGIN")
		if !tx.db.shouldRetry(lastErr) {
			break
		}
	}
	return lastErr
}

// Commit commits the transaction.
func (tx *Tx) Commit() error {
	_, err := tx.Exec("COMMIT")
	tx.close()
	return err
}

// Rollback aborts the transaction.
func (tx *Tx) Rollback() error {
	_, err := tx.Exec("ROLLBACK")
	tx.close()
	return err
}

// Close calls Rollback if the tx has not already beed committed or rolled back.
func (tx *Tx) Close() error {
	if tx.closed() {
		return nil
	}
	return tx.Rollback()
}

func (tx *Tx) close() {
	if !atomic.CompareAndSwapInt32(&tx._closed, 0, 1) {
		return
	}

	tx.stmtsMu.Lock()
	defer tx.stmtsMu.Unlock()

	for _, stmt := range tx.stmts {
		_ = stmt.Close()
	}
	tx.stmts = nil
	_ = tx.db.Close()
}

func (tx *Tx) closed() bool {
	return atomic.LoadInt32(&tx._closed) == 0
}
<commit_msg>tx: fix closed<commit_after>package pg

import (
	"context"
	"errors"
	"io"
	"sync"
	"sync/atomic"

	"github.com/go-pg/pg/v9/internal"
	"github.com/go-pg/pg/v9/internal/pool"
	"github.com/go-pg/pg/v9/orm"
)

var errTxDone = errors.New("pg: transaction has already been committed or rolled back")

// Tx is an in-progress database transaction. It is safe for concurrent use
// by multiple goroutines.
//
// A transaction must end with a call to Commit or Rollback.
//
// After a call to Commit or Rollback, all operations on the transaction fail
// with ErrTxDone.
//
// The statements prepared for a transaction by calling the transaction's
// Prepare or Stmt methods are closed by the call to Commit or Rollback.
type Tx struct {
	db  *baseDB
	ctx context.Context

	stmtsMu sync.Mutex
	stmts   []*Stmt

	_closed int32
}

var _ orm.DB = (*Tx)(nil)

// Context returns the context.Context of the transaction
func (tx *Tx) Context() context.Context {
	return tx.ctx
}

// Begin starts a transaction. Most callers should use RunInTransaction instead.
func (db *baseDB) Begin() (*Tx, error) {
	tx := &Tx{
		db:  db.withPool(pool.NewSingleConnPool(db.pool)),
		ctx: db.db.Context(),
	}

	err := tx.begin(tx.ctx)
	if err != nil {
		tx.close()
		return nil, err
	}

	return tx, nil
}

// RunInTransaction runs a function in a transaction. If function
// returns an error transaction is rollbacked, otherwise transaction
// is committed.
func (db *baseDB) RunInTransaction(fn func(*Tx) error) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	return tx.RunInTransaction(fn)
}

// Begin returns current transaction. It does not start new transaction.
func (tx *Tx) Begin() (*Tx, error) {
	return tx, nil
}

// RunInTransaction runs a function in the transaction. If function
// returns an error transaction is rollbacked, otherwise transaction
// is committed.
func (tx *Tx) RunInTransaction(fn func(*Tx) error) error {
	defer func() {
		if err := recover(); err != nil {
			_ = tx.Rollback()
			panic(err)
		}
	}()
	if err := fn(tx); err != nil {
		_ = tx.Rollback()
		return err
	}
	return tx.Commit()
}

func (tx *Tx) withConn(c context.Context, fn func(context.Context, *pool.Conn) error) error {
	err := tx.db.withConn(c, fn)
	if err == pool.ErrClosed {
		return errTxDone
	}
	return err
}

// Stmt returns a transaction-specific prepared statement
// from an existing statement.
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
	stmt, err := tx.Prepare(stmt.q)
	if err != nil {
		return &Stmt{stickyErr: err}
	}
	return stmt
}

// Prepare creates a prepared statement for use within a transaction.
//
// The returned statement operates within the transaction and can no longer
// be used once the transaction has been committed or rolled back.
//
// To use an existing prepared statement on this transaction, see Tx.Stmt.
func (tx *Tx) Prepare(q string) (*Stmt, error) {
	tx.stmtsMu.Lock()
	defer tx.stmtsMu.Unlock()

	stmt, err := prepareStmt(tx.db, q)
	if err != nil {
		return nil, err
	}
	tx.stmts = append(tx.stmts, stmt)

	return stmt, nil
}

// Exec is an alias for DB.Exec.
func (tx *Tx) Exec(query interface{}, params ...interface{}) (Result, error) {
	return tx.exec(tx.ctx, query, params...)
}

// ExecContext acts like Exec but additionally receives a context
func (tx *Tx) ExecContext(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	return tx.exec(c, query, params...)
}

func (tx *Tx) exec(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	c, evt, err := tx.db.beforeQuery(c, tx, nil, query, params)
	if err != nil {
		return nil, err
	}

	var res Result
	lastErr := tx.withConn(c, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.simpleQuery(c, cn, query, params...)
		return err
	})

	if err := tx.db.afterQuery(c, evt, res, lastErr); err != nil {
		return nil, err
	}
	return res, lastErr
}

// ExecOne is an alias for DB.ExecOne.
func (tx *Tx) ExecOne(query interface{}, params ...interface{}) (Result, error) {
	return tx.execOne(tx.ctx, query, params...)
}

// ExecOneContext acts like ExecOne but additionally receives a context
func (tx *Tx) ExecOneContext(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	return tx.execOne(c, query, params...)
}

func (tx *Tx) execOne(c context.Context, query interface{}, params ...interface{}) (Result, error) {
	res, err := tx.ExecContext(c, query, params...)
	if err != nil {
		return nil, err
	}

	if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
		return nil, err
	}
	return res, nil
}

// Query is an alias for DB.Query.
func (tx *Tx) Query(model interface{}, query interface{}, params ...interface{}) (Result, error) {
	return tx.query(tx.ctx, model, query, params...)
}

// QueryContext acts like Query but additionally receives a context
func (tx *Tx) QueryContext(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	return tx.query(c, model, query, params...)
}

func (tx *Tx) query(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	c, evt, err := tx.db.beforeQuery(c, tx, model, query, params)
	if err != nil {
		return nil, err
	}

	var res *result
	lastErr := tx.withConn(c, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.simpleQueryData(c, cn, model, query, params...)
		return err
	})

	if err := tx.db.afterQuery(c, evt, res, lastErr); err != nil {
		return nil, err
	}
	return res, lastErr
}

// QueryOne is an alias for DB.QueryOne.
func (tx *Tx) QueryOne(model interface{}, query interface{}, params ...interface{}) (Result, error) {
	return tx.queryOne(tx.ctx, model, query, params...)
}

// QueryOneContext acts like QueryOne but additionally receives a context
func (tx *Tx) QueryOneContext(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	return tx.queryOne(c, model, query, params...)
}

func (tx *Tx) queryOne(
	c context.Context,
	model interface{},
	query interface{},
	params ...interface{},
) (Result, error) {
	mod, err := orm.NewModel(model)
	if err != nil {
		return nil, err
	}

	res, err := tx.QueryContext(c, mod, query, params...)
	if err != nil {
		return nil, err
	}

	if err := internal.AssertOneRow(res.RowsAffected()); err != nil {
		return nil, err
	}
	return res, nil
}

// Model is an alias for DB.Model.
func (tx *Tx) Model(model ...interface{}) *orm.Query {
	return orm.NewQuery(tx, model...)
}

// ModelContext acts like Model but additionally receives a context
func (tx *Tx) ModelContext(c context.Context, model ...interface{}) *orm.Query {
	return orm.NewQueryContext(c, tx, model...)
}

// Select is an alias for DB.Select.
func (tx *Tx) Select(model interface{}) error {
	return orm.Select(tx, model)
}

// Insert is an alias for DB.Insert.
func (tx *Tx) Insert(model ...interface{}) error {
	return orm.Insert(tx, model...)
}

// Update is an alias for DB.Update.
func (tx *Tx) Update(model interface{}) error {
	return orm.Update(tx, model)
}

// Delete is an alias for DB.Delete.
func (tx *Tx) Delete(model interface{}) error {
	return orm.Delete(tx, model)
}

// ForceDelete forces the deletion of the model with deleted_at column.
func (tx *Tx) ForceDelete(model interface{}) error {
	return orm.ForceDelete(tx, model)
}

// CreateTable is an alias for DB.CreateTable.
func (tx *Tx) CreateTable(model interface{}, opt *orm.CreateTableOptions) error {
	return orm.CreateTable(tx, model, opt)
}

// DropTable is an alias for DB.DropTable.
func (tx *Tx) DropTable(model interface{}, opt *orm.DropTableOptions) error {
	return orm.DropTable(tx, model, opt)
}

// CopyFrom is an alias for DB.CopyFrom.
func (tx *Tx) CopyFrom(r io.Reader, query interface{}, params ...interface{}) (res Result, err error) {
	err = tx.withConn(tx.ctx, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.copyFrom(c, cn, r, query, params...)
		return err
	})
	return res, err
}

// CopyTo is an alias for DB.CopyTo.
func (tx *Tx) CopyTo(w io.Writer, query interface{}, params ...interface{}) (res Result, err error) {
	err = tx.withConn(tx.ctx, func(c context.Context, cn *pool.Conn) error {
		res, err = tx.db.copyTo(c, cn, w, query, params...)
		return err
	})
	return res, err
}

// Formatter is an alias for DB.Formatter
func (tx *Tx) Formatter() orm.QueryFormatter {
	return tx.db.Formatter()
}

func (tx *Tx) begin(ctx context.Context) error {
	var lastErr error
	for attempt := 0; attempt <= tx.db.opt.MaxRetries; attempt++ {
		if attempt > 0 {
			if err := internal.Sleep(ctx, tx.db.retryBackoff(attempt-1)); err != nil {
				return err
			}

			err := tx.db.pool.(*pool.SingleConnPool).Reset()
			if err != nil {
				return err
			}
		}

		_, lastErr = tx.ExecContext(ctx, "BEGIN")
		if !tx.db.shouldRetry(lastErr) {
			break
		}
	}
	return lastErr
}

// Commit commits the transaction.
func (tx *Tx) Commit() error {
	_, err := tx.Exec("COMMIT")
	tx.close()
	return err
}

// Rollback aborts the transaction.
func (tx *Tx) Rollback() error {
	_, err := tx.Exec("ROLLBACK")
	tx.close()
	return err
}

// Close calls Rollback if the tx has not already beed committed or rolled back.
func (tx *Tx) Close() error {
	if tx.closed() {
		return nil
	}
	return tx.Rollback()
}

func (tx *Tx) close() {
	if !atomic.CompareAndSwapInt32(&tx._closed, 0, 1) {
		return
	}

	tx.stmtsMu.Lock()
	defer tx.stmtsMu.Unlock()

	for _, stmt := range tx.stmts {
		_ = stmt.Close()
	}
	tx.stmts = nil
	_ = tx.db.Close()
}

func (tx *Tx) closed() bool {
	return atomic.LoadInt32(&tx._closed) == 1
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

func main() {
	db, err := sql.Open("sqlite3", "diary.db")
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, words TEXT)")
	if err != nil {
		panic(err)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		now := time.Now()
		days := daysOfMonth(now)
		annotatedDays, err := annotateDays(db, days)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}

		words := ""
		rows, err := db.Query("SELECT words FROM entries WHERE date = ?", now.Format("2006-01-02"))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
		defer rows.Close()

		if rows.Next() {
			err = rows.Scan(&words)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			}
		}

		err = indexTmpl.Execute(w, map[string]interface{}{
			"Title": "900 words",

			"Now":  now,
			"Days": annotatedDays,

			"Words": words,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		words, ok := entry["words"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("missing field 'words'"))
			return
		}

		now := time.Now()
		_, err = db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?)", now.Format("2006-01-02"), words)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}

{{ $day.Date.Day }}

			{{ end }}

{{ .Now.Format "Monday, January 2, 2006" }}

				<textarea id="editor">{{ .Words }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	if rows.Next() {
		err = rows.Scan(&day)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = 1

			if rows.Next() {
				err = rows.Scan(&day)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<commit_msg>Make the number of words configurable<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"os"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

var settings struct {
	DailyTarget int
}

func init() {
	flag.IntVar(&settings.DailyTarget, "target", 900, "The number of words to write daily")
}

func main() {
	flag.Parse()

	db, err := sql.Open("sqlite3", "diary.db")
	if err != nil {
		panic(err)
	}

	_, err = db.Exec("CREATE TABLE IF NOT EXISTS entries (date TEXT PRIMARY KEY, words TEXT)")
	if err != nil {
		panic(err)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		now := time.Now()
		days := daysOfMonth(now)
		annotatedDays, err := annotateDays(db, days)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}

		words := ""
		rows, err := db.Query("SELECT words FROM entries WHERE date = ?", now.Format("2006-01-02"))
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
		defer rows.Close()

		if rows.Next() {
			err = rows.Scan(&words)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %s\n", err)
			}
		}

		err = indexTmpl.Execute(w, map[string]interface{}{
			"Title": fmt.Sprintf("%d words", settings.DailyTarget),

			"Now":  now,
			"Days": annotatedDays,

			"Words": words,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.HandleFunc("/save", func(w http.ResponseWriter, req *http.Request) {
		var entry map[string]string
		dec := json.NewDecoder(req.Body)
		err := dec.Decode(&entry)
		if err != nil {
			respondWithError(w, http.StatusBadRequest, err)
			return
		}

		words, ok := entry["words"]
		if !ok {
			respondWithError(w, http.StatusBadRequest, fmt.Errorf("missing field 'words'"))
			return
		}

		now := time.Now()
		_, err = db.Exec("INSERT OR REPLACE INTO entries VALUES (?, ?)", now.Format("2006-01-02"), words)
		if err != nil {
			respondWithError(w, http.StatusInternalServerError, fmt.Errorf("%s", http.StatusText(http.StatusInternalServerError)))
			return
		}

		enc := json.NewEncoder(w)
		err = enc.Encode(map[string]string{"message": "saved post", "time": now.Format(time.RFC3339)})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		}
	})

	http.ListenAndServe("localhost:12345", nil)
}

func respondWithError(w http.ResponseWriter, status int, err error) {
	res := map[string]string{"error": err.Error()}
	out, err := json.Marshal(res)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "{\"error\": %q}", http.StatusText(http.StatusInternalServerError))
		return
	}
	w.WriteHeader(status)
	w.Write(out)
}

var indexTmpl = template.Must(template.New("index").Parse(`<!doctype html>

		<meta charset="utf-8" />
		<title>{{ .Title }}</title>

{{ .Title }}

			{{ $now := .Now }}
			{{ range $day := .Days -}}

{{ $day.Date.Day }}

			{{ end }}

{{ .Now.Format "Monday, January 2, 2006" }}

				<textarea id="editor">{{ .Words }}</textarea>

					0 words

				Made with <3 by strange adventures.  —  /about

`))

func daysOfMonth(t time.Time) []time.Time {
	s := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
	e := s.AddDate(0, 1, 0)
	ts := make([]time.Time, 0, 31)
	for s.Before(e) {
		ts = append(ts, s)
		s = s.AddDate(0, 0, 1)
	}
	return ts
}

type Day struct {
	Date  time.Time
	Words int
}

func (d Day) Classes(now time.Time) string {
	var classes string
	if d.Date.Before(now) {
		classes = "past"
	} else {
		classes = "future"
	}

	if d.Words >= 1 {
		classes += " written"
	}

	return classes
}

func annotateDays(db *sql.DB, days []time.Time) ([]Day, error) {
	rows, err := db.Query("SELECT date FROM entries WHERE date >= ? AND date <= ?", days[0].Format("2006-01-02"), days[len(days)-1].Format("2006-01-02"))
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var day string
	if rows.Next() {
		err = rows.Scan(&day)
		if err != nil {
			return nil, err
		}
	}

	annotatedDays := make([]Day, len(days))
	for i, t := range days {
		d := Day{Date: t, Words: 0}

		if t.Format("2006-01-02") == day {
			d.Words = 1

			if rows.Next() {
				err = rows.Scan(&day)
				if err != nil {
					return nil, err
				}
			}
		}

		annotatedDays[i] = d
	}

	return annotatedDays, nil
}
<|endoftext|>


<commit_before>package tabio

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strconv"
	"strings"
)

// RecordReader implement reading of tabular data, in plain text format, where
// records are separated by a "record separator" (RS) ASCII and UNICODE control
// character and fields are separated by a "unit separator" (US) ASCII and UNICODE
// control character.
//
// (RS = 30. US = 31)
//
// *RecordReader has intentionally been made to include the methods of *sql.Rows.
//
// Because of this, if desired, a *RecordReader can be conceptually "converted"
// into a *sql.Rows by using the "github.com/reiver/go-shunt" package's shunt.Rows
// func.
type RecordReader struct {
	reader io.ReadCloser
	runeReader io.RuneReader

	buffer bytes.Buffer
	err error

	cachedColumns []string

	closed bool
}

// NewRecordReader returns a new *RecordReader, reading from the io.ReadCloser r.
func NewRecordReader(r io.ReadCloser) *RecordReader {
	runeReader, ok := r.(io.RuneReader)
	if !ok {
		runeReader = bufio.NewReader(r)
	}

	rr := RecordReader{
		reader:     r,
		runeReader: runeReader,
	}

	if !rr.Next() {
		return &rr
	}

	cachedColumns, err := rr.Fields()
	if nil != err {
		rr.err = err
		return &rr
	}

	rr.cachedColumns = cachedColumns

	return &rr
}

// Close closes the *RecordReader, preventing further iteration.
//
// If Next returns false then the *RecordReader is closed automatically.
//
// Close is idempotent and does not affect the result of Err.
//
// The first time Close is called it will in turn call Close on the wrapped io.ReadCloser that way passed to NewRecordReader.
func (rr *RecordReader) Close() error {
	if nil == rr {
		return errNilReceiver
	}

	if rr.closed {
		return nil
	}

	if err := rr.reader.Close(); nil != err {
		return err
	}

	rr.closed = true

	return nil
}

// MustClose is like Close, except it panic()s if there is an error.
func (rr *RecordReader) MustClose() {
	if err := rr.Close(); nil != err {
		panic(err)
	}
}

// Columns returns the column names.
//
// Columns returns an error if the *RecordReader is closed.
func (rr *RecordReader) Columns() ([]string, error) {
	if nil == rr {
		return nil, errNilReceiver
	}

	if rr.closed {
		return nil, errClosed
	}

	cachedColumns := rr.cachedColumns
	if nil == cachedColumns {
		return []string{}, nil
	}

//@TODO: Should we return a copy of this instead?
	return cachedColumns, nil
}

// MustColumns is like Columns, except it panic()s if there is an error.
func (rr *RecordReader) MustColumns() []string {
	cols, err := rr.Columns()
	if nil != err {
		panic(err)
	}

	return cols
}

// Error return an err, if an error occurred when calling Next.
//
// Usually Err is called after getting back a false result from a call to Next.
func (rr *RecordReader) Err() error {
	return rr.err
}

// Fields returns the field values.
//
// Fields returns an error if the *RecordReader is closed.
func (rr *RecordReader) Fields() ([]string, error) {
	const US = "\x1f" // Unit Separator

	if nil == rr {
		return nil, errNilReceiver
	}

	if rr.closed {
		return nil, errClosed
	}

	return strings.Split(rr.buffer.String(), US), nil
}

// MustFields is like Fields, except it panic()s if there is an error.
func (rr *RecordReader) MustFields() []string {
	fields, err := rr.Fields()
	if nil != err {
		panic(err)
	}

	return fields
}

// Next prepares the next record for reading with the Fields, Scan or Unmarshal methods.
//
// It returns true if it was successful.
//
// It returns false if there is no next record or if an error occurred while trying to prepare it.
//
// Err should be consulted to be able to tell the difference between the two cases.
//
// Every call to Fields, Scan, and Unmarshal, even the first one, must be preceded by a call to Next.
func (rr *RecordReader) Next() bool {

	const RS rune = 30 // Record Separator

	if nil == rr {
		panic(errNilReceiver)
	}

	if rr.closed {
		return false
	}

	if nil != rr.err {
		return false
	}

	runeReader := rr.runeReader
	if nil == runeReader {
		panic(errInternalError)
	}

	rr.buffer.Reset()

	var r rune
	var err error
	for {
		r, _, err = runeReader.ReadRune()
		if io.EOF == err {
			next := 0 < rr.buffer.Len()
			if !next {
				rr.Close()
			}

			return next
		}
		if nil != err {
			rr.err = err
			rr.Close()
			return false
		}

		if RS == r {
			return true
		}

		rr.buffer.WriteRune(r)
	}
}

// Scan copies the fields in the current record into the values pointed at by dest.
//
// The number of values in dest must be the same as the number of columns in *RecordReader.
func (rr *RecordReader) Scan(dest ...interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	lenColumns := 0
	if cachedColumns := rr.cachedColumns; nil != cachedColumns {
		lenColumns = len(cachedColumns)
	}

	if lenDest := len(dest); lenColumns != lenDest {
		return internalWrongNumberOfArgumentsComplainer{expected: uint(lenColumns), actual: uint(lenDest) }
	}

//@TODO: Do this better.
	fields, err := rr.Fields()
	if nil != err {
		return err
	}
	for i, _ := range dest {
//@TODO: need to handle converions... probably.
		switch dest[i].(type) {
		case *float32:
			f32, err := strconv.ParseFloat(fields[i], 32)
			if nil != err {
				return err
			}

			dest[i] = &f32
		case *float64:
			f64, err := strconv.ParseFloat(fields[i], 64)
			if nil != err {
				return err
			}

			dest[i] = &f64
		case *string:
			dest[i] = &fields[i]
		default:
			return internalUnsupportedScanComplainer{
				srcType:  fmt.Sprintf("%T", &fields[i]),
				destType: fmt.Sprintf("%T", dest[i]),
			}
		}
	}

	return nil
}

// MustScan is like Scan, except it panic()s if there is an error.
func (rr *RecordReader) MustScan(dest ...interface{}) {
	if err := rr.Scan(dest...); nil != err {
		panic(err)
	}
}

func (rr *RecordReader) Unmarshal(target interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	switch x:= target.(type) {
	case RecordUnmarshaler:
		bs := rr.buffer.Bytes()

		if err := x.UnmarshalRecord(bs); nil != err {
			return err
		}
	default:
panic("//@TODO TODO TODO TODO TODO")

	}

	return nil
}

// MustUnmarshal is like Unmarshal, except it panic()s if there is an error.
func (rr *RecordReader) MustUnmarshal(target interface{}) {
	if err := rr.Unmarshal(target); nil != err {
		panic(err)
	}
}
<commit_msg>made Err handle nil receiver.<commit_after>package tabio

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strconv"
	"strings"
)

// RecordReader implement reading of tabular data, in plain text format, where
// records are separated by a "record separator" (RS) ASCII and UNICODE control
// character and fields are separated by a "unit separator" (US) ASCII and UNICODE
// control character.
//
// (RS = 30. US = 31)
//
// *RecordReader has intentionally been made to include the methods of *sql.Rows.
//
// Because of this, if desired, a *RecordReader can be conceptually "converted"
// into a *sql.Rows by using the "github.com/reiver/go-shunt" package's shunt.Rows
// func.
type RecordReader struct {
	reader io.ReadCloser
	runeReader io.RuneReader

	buffer bytes.Buffer
	err error

	cachedColumns []string

	closed bool
}

// NewRecordReader returns a new *RecordReader, reading from the io.ReadCloser r.
func NewRecordReader(r io.ReadCloser) *RecordReader {
	runeReader, ok := r.(io.RuneReader)
	if !ok {
		runeReader = bufio.NewReader(r)
	}

	rr := RecordReader{
		reader:     r,
		runeReader: runeReader,
	}

	if !rr.Next() {
		return &rr
	}

	cachedColumns, err := rr.Fields()
	if nil != err {
		rr.err = err
		return &rr
	}

	rr.cachedColumns = cachedColumns

	return &rr
}

// Close closes the *RecordReader, preventing further iteration.
//
// If Next returns false then the *RecordReader is closed automatically.
//
// Close is idempotent and does not affect the result of Err.
//
// The first time Close is called it will in turn call Close on the wrapped io.ReadCloser that way passed to NewRecordReader.
func (rr *RecordReader) Close() error {
	if nil == rr {
		return errNilReceiver
	}

	if rr.closed {
		return nil
	}

	if err := rr.reader.Close(); nil != err {
		return err
	}

	rr.closed = true

	return nil
}

// MustClose is like Close, except it panic()s if there is an error.
func (rr *RecordReader) MustClose() {
	if err := rr.Close(); nil != err {
		panic(err)
	}
}

// Columns returns the column names.
//
// Columns returns an error if the *RecordReader is closed.
func (rr *RecordReader) Columns() ([]string, error) {
	if nil == rr {
		return nil, errNilReceiver
	}

	if rr.closed {
		return nil, errClosed
	}

	cachedColumns := rr.cachedColumns
	if nil == cachedColumns {
		return []string{}, nil
	}

//@TODO: Should we return a copy of this instead?
	return cachedColumns, nil
}

// MustColumns is like Columns, except it panic()s if there is an error.
func (rr *RecordReader) MustColumns() []string {
	cols, err := rr.Columns()
	if nil != err {
		panic(err)
	}

	return cols
}

// Error return an err, if an error occurred when calling Next.
//
// Usually Err is called after getting back a false result from a call to Next.
func (rr *RecordReader) Err() error {
	if nil == rr {
		return errNilReceiver
	}

	return rr.err
}

// Fields returns the field values.
//
// Fields returns an error if the *RecordReader is closed.
func (rr *RecordReader) Fields() ([]string, error) {
	const US = "\x1f" // Unit Separator

	if nil == rr {
		return nil, errNilReceiver
	}

	if rr.closed {
		return nil, errClosed
	}

	return strings.Split(rr.buffer.String(), US), nil
}

// MustFields is like Fields, except it panic()s if there is an error.
func (rr *RecordReader) MustFields() []string {
	fields, err := rr.Fields()
	if nil != err {
		panic(err)
	}

	return fields
}

// Next prepares the next record for reading with the Fields, Scan or Unmarshal methods.
//
// It returns true if it was successful.
//
// It returns false if there is no next record or if an error occurred while trying to prepare it.
//
// Err should be consulted to be able to tell the difference between the two cases.
//
// Every call to Fields, Scan, and Unmarshal, even the first one, must be preceded by a call to Next.
func (rr *RecordReader) Next() bool {

	const RS rune = 30 // Record Separator

	if nil == rr {
		panic(errNilReceiver)
	}

	if rr.closed {
		return false
	}

	if nil != rr.err {
		return false
	}

	runeReader := rr.runeReader
	if nil == runeReader {
		panic(errInternalError)
	}

	rr.buffer.Reset()

	var r rune
	var err error
	for {
		r, _, err = runeReader.ReadRune()
		if io.EOF == err {
			next := 0 < rr.buffer.Len()
			if !next {
				rr.Close()
			}

			return next
		}
		if nil != err {
			rr.err = err
			rr.Close()
			return false
		}

		if RS == r {
			return true
		}

		rr.buffer.WriteRune(r)
	}
}

// Scan copies the fields in the current record into the values pointed at by dest.
//
// The number of values in dest must be the same as the number of columns in *RecordReader.
func (rr *RecordReader) Scan(dest ...interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	lenColumns := 0
	if cachedColumns := rr.cachedColumns; nil != cachedColumns {
		lenColumns = len(cachedColumns)
	}

	if lenDest := len(dest); lenColumns != lenDest {
		return internalWrongNumberOfArgumentsComplainer{expected: uint(lenColumns), actual: uint(lenDest) }
	}

//@TODO: Do this better.
	fields, err := rr.Fields()
	if nil != err {
		return err
	}
	for i, _ := range dest {
//@TODO: need to handle converions... probably.
		switch dest[i].(type) {
		case *float32:
			f32, err := strconv.ParseFloat(fields[i], 32)
			if nil != err {
				return err
			}

			dest[i] = &f32
		case *float64:
			f64, err := strconv.ParseFloat(fields[i], 64)
			if nil != err {
				return err
			}

			dest[i] = &f64
		case *string:
			dest[i] = &fields[i]
		default:
			return internalUnsupportedScanComplainer{
				srcType:  fmt.Sprintf("%T", &fields[i]),
				destType: fmt.Sprintf("%T", dest[i]),
			}
		}
	}

	return nil
}

// MustScan is like Scan, except it panic()s if there is an error.
func (rr *RecordReader) MustScan(dest ...interface{}) {
	if err := rr.Scan(dest...); nil != err {
		panic(err)
	}
}

func (rr *RecordReader) Unmarshal(target interface{}) error {
	if nil == rr {
		return errNilReceiver
	}

	switch x:= target.(type) {
	case RecordUnmarshaler:
		bs := rr.buffer.Bytes()

		if err := x.UnmarshalRecord(bs); nil != err {
			return err
		}
	default:
panic("//@TODO TODO TODO TODO TODO")

	}

	return nil
}

// MustUnmarshal is like Unmarshal, except it panic()s if there is an error.
func (rr *RecordReader) MustUnmarshal(target interface{}) {
	if err := rr.Unmarshal(target); nil != err {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package hexa

import (
	"sync"
)

// Experimental api...
type ThreadGroup struct {
	cnt sync.WaitGroup
}

// func NewThreadGroup() *ThreadGroup {
// 	return &ThreadGroup{
// 		cnt: sync.WaitGroup{},
// 	}
// }

func (__ *ThreadGroup) SpawnService(stopCtx *ContextStop, ch <-chan interface{}, f func(interface{}) error) {
	__.cnt.Add(1)
	go func() {
		defer __.cnt.Done()
	loop:
		for {
			select {
			// break loop when client calls Close() method.
			case <-stopCtx.InDoneNotify():
				break loop

			// do some parallel work in service.
			case d := <-ch:
				err := f(d)
				if err != nil {
					stopCtx.InBreak(err)
					continue
				}
			}
		}
	}()
}

func (__ *ThreadGroup) Done(stopCtx *ContextStop, f func()) {
	__.cnt.Wait()
	f()
	stopCtx.InClose()
}
<commit_msg>push test<commit_after>package hexa

import (
	"sync"
)

// Experimental api...
type ThreadGroup struct {
	cnt sync.WaitGroup
}

func (__ *ThreadGroup) SpawnService(stopCtx *ContextStop, ch <-chan interface{}, f func(interface{}) error) {
	__.cnt.Add(1)
	go func() {
		defer __.cnt.Done()
	loop:
		for {
			select {
			// break loop when client calls Close() method.
			case <-stopCtx.InDoneNotify():
				break loop

			// do some parallel work in service.
			case d := <-ch:
				err := f(d)
				if err != nil {
					stopCtx.InBreak(err)
					continue
				}
			}
		}
	}()
}

func (__ *ThreadGroup) Done(stopCtx *ContextStop, f func()) {
	__.cnt.Wait()
	f()
	stopCtx.InClose()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
)

// Token identifies the type of lex items.
type Token int

const (
	// EOF represents the end of file
	EOF Token = iota
	// Error represents an error
	Error
	// Assign represents the assignment '='
	Assign
	// Number represents a simple number
	Number
	// Operator an operator such as '+' '-' '*'
	Operator
	// Asterix the multiplication operator
	Asterix
	// Space represents space separation between tokens
	Space
	// Identifier represent an identifier such as a var name
	Identifier
)

// eof rune to treat EOF like any other character
var eof = rune(0)

func isWhitespace(r rune) bool {
	return r == ' ' || r == '\t' || r == 'n'
}

func isLetter(r rune) bool {
	return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z')
}

func isDigit(r rune) bool {
	return (r >= '0' && r <= '9')
}

// Scanner represents a lexical scanner
type Scanner struct {
	r *bufio.Reader
}

// NewScanner returns a new instance of Scanner.
func NewScanner(r io.Reader) *Scanner {
	return &Scanner{r: bufio.NewReader(r)}
}

// read reads the next rune from the bufferred reader.
// Returns the rune(0) if an error occurs (or io.EOF is returned)
func (s *Scanner) read() rune {
	r, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return r
}

func (s *Scanner) unread() { _ = s.r.UnreadRune() }

// Scan retusn the next token and literal value.
func (s *Scanner) Scan() (t Token, lit string) {
	// read the next rune.
	r := s.read()

	// if we see whitespace then consume all contiguous whitespace.
	// if we see a letter then consume as an identifier keyword word.
	if isWhitespace(r) {
		s.unread()
		return s.scanWhitespace()
	} else if isLetter(r) {
		s.unread()
		return s.scanIdentifier()
	}

	switch r {
	case eof:
		return EOF, ""
	case '*':
		return Asterix, string(r)
	}
	return Error, string(r)
}

// scanWhitespace consumes the current rune and all contiguous whitespace.
func (s *Scanner) scanWhitespace() (t Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent whitespace character into the bufer.
	// non whitespace characters and EOF will cause the loop to exit.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isWhitespace(r) {
			s.unread()
			break
		} else {
			buf.WriteRune(r)
		}
	}
	return Space, buf.String()
}

func (s *Scanner) scanIdentifier() (t Token, lit string) {
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	for {
		if r := s.read(); r == eof {
			break
		} else if !isLetter(r) && !isDigit(r) && r != '_' {
			s.unread()
			break
		} else {
			_, _ = buf.WriteRune(r)
		}
	}
	return Identifier, buf.String()
}

// Parser represents a parser
type Parser struct {
	s   *Scanner
	buf struct {
		t   Token  // last read token
		lit string // last read literal
		n   int    // buffer size (max=1)
	}
}

// NewParser returns a new instance of Parser.
func NewParser(r io.Reader) *Parser {
	return &Parser{s: NewScanner(r)}
}

// scan returns the next token from the underlying scanner.
// if a token has been unscanned then read that instead.
func (p *Parser) scan() (t Token, lit string) {
	// if we have a token on the buffer, then return it
	if p.buf.n != 0 {
		p.buf.n = 0
		return p.buf.t, p.buf.lit
	}
	// otherwise read the next token from the scanner
	t, lit = p.s.Scan()

	// save it to the buffer in case we unscan later.
	p.buf.t, p.buf.lit = t, lit
	return
}

// unscan pushes the previously read token back onto the buffer.
func (p *Parser) unscan() { p.buf.n = 1 }

// scanIgnoreWhitespace scans the next non-whitespace token.
func (p *Parser) scanIgnoreWhitespace() (t Token, lit string) {
	t, lit = p.scan()
	if t == Space {
		t, lit = p.scan()
	}
	return
}

// Statement represents a code statement a = 2.
type Statement struct {
	Left  string
	Rigth string
}

// Parser parse a assign statement a = b
func (p *Parser) Parser() (*Statement, error) {
	stmt := &Statement{}

	// Next we should loop over all our comma-delimited fields.
	// Read a field.
	tok, lit := p.scanIgnoreWhitespace()
	if tok != Identifier && tok != Asterix {
		return nil, fmt.Errorf("found %q, expected left", lit)
	}
	stmt.Left = lit

	// Next we should see the "=" keyword.
	if tok, lit := p.scanIgnoreWhitespace(); tok != Assign {
		return nil, fmt.Errorf("found %q, expected FROM", lit)
	}

	// Finally we should read the left var/number name.
	tok, lit = p.scanIgnoreWhitespace()
	if tok != Identifier {
		return nil, fmt.Errorf("found %q, expected identifier name", lit)
	}
	stmt.Rigth = lit

	// Return the successfully parsed statement.
	return stmt, nil
}

func main() {
	fmt.Println("hello, world")
}
<commit_msg>add assign case to scanner<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"strings"
)

// Token identifies the type of lex items.
type Token int

const (
	// EOF represents the end of file
	EOF Token = iota
	// Error represents an error
	Error
	// Assign represents the assignment '='
	Assign
	// Number represents a simple number
	Number
	// Operator an operator such as '+' '-' '*'
	Operator
	// Asterix the multiplication operator
	Asterix
	// Space represents space separation between tokens
	Space
	// Identifier represent an identifier such as a var name
	Identifier
)

// eof rune to treat EOF like any other character
var eof = rune(0)

func isWhitespace(r rune) bool {
	return r == ' ' || r == '\t' || r == 'n'
}

func isLetter(r rune) bool {
	return (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z')
}

func isDigit(r rune) bool {
	return (r >= '0' && r <= '9')
}

// Scanner represents a lexical scanner
type Scanner struct {
	r *bufio.Reader
}

// NewScanner returns a new instance of Scanner.
func NewScanner(r io.Reader) *Scanner {
	return &Scanner{r: bufio.NewReader(r)}
}

// read reads the next rune from the bufferred reader.
// Returns the rune(0) if an error occurs (or io.EOF is returned)
func (s *Scanner) read() rune {
	r, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return r
}

func (s *Scanner) unread() { _ = s.r.UnreadRune() }

// Scan retusn the next token and literal value.
func (s *Scanner) Scan() (t Token, lit string) {
	// read the next rune.
	r := s.read()

	// if we see whitespace then consume all contiguous whitespace.
	// if we see a letter then consume as an identifier keyword word.
	if isWhitespace(r) {
		s.unread()
		return s.scanWhitespace()
	} else if isLetter(r) {
		s.unread()
		return s.scanIdentifier()
	}

	switch r {
	case eof:
		return EOF, ""
	case '*':
		return Asterix, string(r)
	case '=':
		return Assign, string(r)
	}
	return Error, string(r)
}

// scanWhitespace consumes the current rune and all contiguous whitespace.
func (s *Scanner) scanWhitespace() (t Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent whitespace character into the bufer.
	// non whitespace characters and EOF will cause the loop to exit.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isWhitespace(r) {
			s.unread()
			break
		} else {
			buf.WriteRune(r)
		}
	}
	return Space, buf.String()
}

func (s *Scanner) scanIdentifier() (t Token, lit string) {
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	for {
		if r := s.read(); r == eof {
			break
		} else if !isLetter(r) && !isDigit(r) && r != '_' {
			s.unread()
			break
		} else {
			_, _ = buf.WriteRune(r)
		}
	}
	return Identifier, buf.String()
}

// Parser represents a parser
type Parser struct {
	s   *Scanner
	buf struct {
		t   Token  // last read token
		lit string // last read literal
		n   int    // buffer size (max=1)
	}
}

// NewParser returns a new instance of Parser.
func NewParser(r io.Reader) *Parser {
	return &Parser{s: NewScanner(r)}
}

// scan returns the next token from the underlying scanner.
// if a token has been unscanned then read that instead.
func (p *Parser) scan() (t Token, lit string) {
	// if we have a token on the buffer, then return it
	if p.buf.n != 0 {
		p.buf.n = 0
		return p.buf.t, p.buf.lit
	}
	// otherwise read the next token from the scanner
	t, lit = p.s.Scan()

	// save it to the buffer in case we unscan later.
	p.buf.t, p.buf.lit = t, lit
	return
}

// unscan pushes the previously read token back onto the buffer.
func (p *Parser) unscan() { p.buf.n = 1 }

// scanIgnoreWhitespace scans the next non-whitespace token.
func (p *Parser) scanIgnoreWhitespace() (t Token, lit string) {
	t, lit = p.scan()
	if t == Space {
		t, lit = p.scan()
	}
	return
}

// Statement represents a code statement a = 2.
type Statement struct {
	Left  string
	Rigth string
}

// Parse parse a assign statement a = b
func (p *Parser) Parse() (*Statement, error) {
	stmt := &Statement{}

	// Next we should loop over all our comma-delimited fields.
	// Read a field.
	tok, lit := p.scanIgnoreWhitespace()
	if tok != Identifier {
		return nil, fmt.Errorf("found %q, expected left", lit)
	}
	stmt.Left = lit

	// Next we should see the "=" keyword.
	if tok, lit := p.scanIgnoreWhitespace(); tok != Assign {
		return nil, fmt.Errorf("found %q, expected FROM", lit)
	}

	// Finally we should read the left var/number name.
	tok, lit = p.scanIgnoreWhitespace()
	if tok != Identifier {
		return nil, fmt.Errorf("found %q, expected identifier name", lit)
	}
	stmt.Rigth = lit

	// Return the successfully parsed statement.
	return stmt, nil
}

func main() {
	fmt.Println("hello, world")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"text/tabwriter"

	"github.com/coreos/updateservicectl/Godeps/_workspace/src/code.google.com/p/go-uuid/uuid"
	"github.com/coreos/updateservicectl/client/update/v1"
)

var (
	appFlags struct {
		appId       StringFlag
		label       StringFlag
		description StringFlag
	}

	cmdApp = &Command{
		Name:    "app",
		Summary: "Manage applications.",
		Subcommands: []*Command{
			cmdAppCreate,
			cmdAppList,
			cmdAppUpdate,
			cmdAppDelete,
		},
	}
	cmdAppCreate = &Command{
		Name:        "app create",
		Usage:       "[OPTION]...",
		Description: `Create a new application.`,
		Run:         appCreate,
	}
	cmdAppList = &Command{
		Name:        "app list",
		Description: `List all of the apps that exist including their label, token and update state.`,
		Run:         appList,
	}
	cmdAppUpdate = &Command{
		Name:        "app update",
		Usage:       "[OPTION]...",
		Description: `Update an app's label or description.`,
		Run:         appUpdate,
	}
	cmdAppDelete = &Command{
		Name:        "app delete",
		Usage:       "[OPTION]...",
		Description: `Delete an app.`,
		Run:         appDelete,
	}
)

func init() {
	cmdAppCreate.Flags.Var(&appFlags.appId, "app-id", "Application UUID. If not provided, one will be randomly generated.")
	cmdAppCreate.Flags.Var(&appFlags.label, "label", "New application label.")
	cmdAppCreate.Flags.Var(&appFlags.description, "description", "New application description.")

	cmdAppUpdate.Flags.Var(&appFlags.appId, "app-id", "Application ID to update.")
	cmdAppUpdate.Flags.Var(&appFlags.label, "label", "Set application label.")
	cmdAppUpdate.Flags.Var(&appFlags.description, "description", "Set application description.")

	cmdAppDelete.Flags.Var(&appFlags.appId, "app-id", "Application ID to delete.")
}

func formatApp(app *update.App) string {
	return fmt.Sprintf("%s\t%s\t%s\n", app.Id, app.Label, app.Description)
}

func appList(args []string, service *update.Service, out *tabwriter.Writer) int {
	listCall := service.App.List()
	list, err := listCall.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprintln(out, "Id\tLabel\tDescription")
	for _, app := range list.Items {
		fmt.Fprintf(out, "%s", formatApp(app))
	}

	out.Flush()
	return OK
}

func appCreate(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil {
		appFlags.appId.Set(uuid.New())
	}

	appReq := &update.AppInsertReq{
		Id:          appFlags.appId.String(),
		Label:       appFlags.label.String(),
		Description: appFlags.description.String(),
	}
	call := service.App.Insert(appReq)
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK

}

func appUpdate(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil || appFlags.label.Get() == nil || appFlags.description.Get() == nil {
		return ERROR_USAGE
	}

	appReq := &update.AppUpdateReq{Label: appFlags.label.String(), Description: appFlags.description.String()}
	call := service.App.Update(appFlags.appId.String(), appReq)
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK

}

func appDelete(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil {
		return ERROR_USAGE
	}

	call := service.App.Delete(appFlags.appId.String())
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK
}
<commit_msg>app: Add headers to app subcommands<commit_after>package main

import (
	"fmt"
	"log"
	"text/tabwriter"

	"github.com/coreos/updateservicectl/Godeps/_workspace/src/code.google.com/p/go-uuid/uuid"
	"github.com/coreos/updateservicectl/client/update/v1"
)

var (
	appFlags struct {
		appId       StringFlag
		label       StringFlag
		description StringFlag
	}

	cmdApp = &Command{
		Name:    "app",
		Summary: "Manage applications.",
		Subcommands: []*Command{
			cmdAppCreate,
			cmdAppList,
			cmdAppUpdate,
			cmdAppDelete,
		},
	}
	cmdAppCreate = &Command{
		Name:        "app create",
		Usage:       "[OPTION]...",
		Description: `Create a new application.`,
		Run:         appCreate,
	}
	cmdAppList = &Command{
		Name:        "app list",
		Description: `List all of the apps that exist including their label, token and update state.`,
		Run:         appList,
	}
	cmdAppUpdate = &Command{
		Name:        "app update",
		Usage:       "[OPTION]...",
		Description: `Update an app's label or description.`,
		Run:         appUpdate,
	}
	cmdAppDelete = &Command{
		Name:        "app delete",
		Usage:       "[OPTION]...",
		Description: `Delete an app.`,
		Run:         appDelete,
	}
)

func init() {
	cmdAppCreate.Flags.Var(&appFlags.appId, "app-id", "Application UUID. If not provided, one will be randomly generated.")
	cmdAppCreate.Flags.Var(&appFlags.label, "label", "New application label.")
	cmdAppCreate.Flags.Var(&appFlags.description, "description", "New application description.")

	cmdAppUpdate.Flags.Var(&appFlags.appId, "app-id", "Application ID to update.")
	cmdAppUpdate.Flags.Var(&appFlags.label, "label", "Set application label.")
	cmdAppUpdate.Flags.Var(&appFlags.description, "description", "Set application description.")

	cmdAppDelete.Flags.Var(&appFlags.appId, "app-id", "Application ID to delete.")
}

const appHeader = "Id\tLabel\tDescription\n"

func formatApp(app *update.App) string {
	return fmt.Sprintf("%s\t%s\t%s\n", app.Id, app.Label, app.Description)
}

func appList(args []string, service *update.Service, out *tabwriter.Writer) int {
	listCall := service.App.List()
	list, err := listCall.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprint(out, appHeader)
	for _, app := range list.Items {
		fmt.Fprintf(out, "%s", formatApp(app))
	}

	out.Flush()
	return OK
}

func appCreate(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil {
		appFlags.appId.Set(uuid.New())
	}

	appReq := &update.AppInsertReq{
		Id:          appFlags.appId.String(),
		Label:       appFlags.label.String(),
		Description: appFlags.description.String(),
	}
	call := service.App.Insert(appReq)
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprint(out, appHeader)
	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK

}

func appUpdate(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil || appFlags.label.Get() == nil || appFlags.description.Get() == nil {
		return ERROR_USAGE
	}

	appReq := &update.AppUpdateReq{Label: appFlags.label.String(), Description: appFlags.description.String()}
	call := service.App.Update(appFlags.appId.String(), appReq)
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprint(out, appHeader)
	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK

}

func appDelete(args []string, service *update.Service, out *tabwriter.Writer) int {
	if appFlags.appId.Get() == nil {
		return ERROR_USAGE
	}

	call := service.App.Delete(appFlags.appId.String())
	app, err := call.Do()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Fprint(out, appHeader)
	fmt.Fprintf(out, "%s", formatApp(app))

	out.Flush()
	return OK
}
<|endoftext|>


<commit_before>package scroll

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gorilla/mux"
	"github.com/mailgun/log"
	"github.com/mailgun/manners"
	"github.com/mailgun/metrics"

	"github.com/mailgun/scroll/vulcan"
	"github.com/mailgun/scroll/vulcan/middleware"
)

const (
	// Suggested result set limit for APIs that may return many entries (e.g. paging).
	DefaultLimit int = 100

	// Suggested max allowed result set limit for APIs that may return many entries (e.g. paging).
	MaxLimit int = 10000

	// Suggested max allowed amount of entries that batch APIs can accept (e.g. batch uploads).
	MaxBatchSize int = 1000

	// Interval between Vulcand heartbeats (if the app if configured to register in it).
	defaultRegisterInterval time.Duration = 2 * time.Second
)

// Represents an app.
type App struct {
	Config   AppConfig
	router   *mux.Router
	registry *vulcan.Registry
	stats    *appStats
}

// Represents a configuration object an app is created with.
type AppConfig struct {
	// name of the app being created
	Name string

	// IP/port the app will bind to
	ListenIP   string
	ListenPort int

	// optional router to use
	Router *mux.Router

	// hostnames of the public and protected API entrypoints used for vulcan registration
	PublicAPIHost    string
	ProtectedAPIHost string
	ProtectedAPIURL  string

	// whether to register the app's endpoint and handlers in vulcan
	Register bool

	// metrics service used for emitting the app's real-time metrics
	Client metrics.Client
}

// Create a new app.
func NewApp() *App {
	return NewAppWithConfig(AppConfig{})
}

// Create a new app with the provided configuration.
func NewAppWithConfig(config AppConfig) *App {
	var reg *vulcan.Registry
	if config.Register != false {
		reg = vulcan.NewRegistry(vulcan.Config{
			PublicAPIHost:    config.PublicAPIHost,
			ProtectedAPIHost: config.ProtectedAPIHost,
		})
	}

	router := config.Router
	if router == nil {
		router = mux.NewRouter()
	}

	return &App{
		Config:   config,
		router:   router,
		registry: reg,
		stats:    newAppStats(config.Client),
	}
}

// Register a handler function.
//
// If vulcan registration is enabled in the both app config and handler spec,
// the handler will be registered in the local etcd instance.
func (app *App) AddHandler(spec Spec) error {
	var handler http.HandlerFunc

	// make a handler depending on the function provided in the spec
	if spec.RawHandler != nil {
		handler = spec.RawHandler
	} else if spec.Handler != nil {
		handler = MakeHandler(app, spec.Handler, spec)
	} else if spec.HandlerWithBody != nil {
		handler = MakeHandlerWithBody(app, spec.HandlerWithBody, spec)
	} else {
		return fmt.Errorf("the spec does not provide a handler function: %v", spec)
	}

	// register the handler in the router
	route := app.router.HandleFunc(spec.Path, handler).Methods(spec.Methods...)
	if len(spec.Headers) != 0 {
		route.Headers(spec.Headers...)
	}

	// vulcan registration
	if app.registry != nil && spec.Register != false {
		app.registerLocation(spec.Methods, spec.Path, spec.Scopes, spec.Middlewares)
	}

	return nil
}

// GetHandler returns HTTP compatible Handler interface.
func (app *App) GetHandler() http.Handler {
	return app.router
}

// SetNotFoundHandler sets the handler for the case when URL can not be matched by the router.
func (app *App) SetNotFoundHandler(fn http.HandlerFunc) {
	app.router.NotFoundHandler = fn
}

// IsPublicRequest determines whether the provided request came through the public HTTP endpoint.
func (app *App) IsPublicRequest(request *http.Request) bool {
	return request.Host == app.Config.PublicAPIHost
}

// Start the app on the configured host/port.
//
// If vulcan registration is enabled in the app config, starts a goroutine that
// will be registering the app's endpoint once every minute in the local etcd
// instance.
//
// Supports graceful shutdown on 'kill' and 'int' signals.
func (app *App) Run() error {
	http.Handle("/", app.router)

	if app.registry != nil {
		go func() {
			// heartbeat can be stopped/resumed on USR1 signal
			heartbeatChan := make(chan os.Signal, 1)
			signal.Notify(heartbeatChan, syscall.SIGUSR1)

			for {
				select {
				// this will proceed to the "default" without blocking if there is no signal
				case s := <-heartbeatChan:
					log.Infof("Got signal: %v, pausing heartbeat", s)
					// now it blocks until another signal comes
					<-heartbeatChan
					log.Infof("Resuming heartbeat")
				default:
					app.registerEndpoint()
					time.Sleep(defaultRegisterInterval)
				}
			}
		}()
	}

	// listen for a shutdown signal
	go func() {
		exitChan := make(chan os.Signal, 1)
		signal.Notify(exitChan, os.Interrupt, os.Kill)
		s := <-exitChan
		log.Infof("Got shutdown signal: %v", s)
		manners.Close()
	}()

	return manners.ListenAndServe(
		fmt.Sprintf("%v:%v", app.Config.ListenIP, app.Config.ListenPort), nil)
}

// registerEndpoint is a helper for registering the app's endpoint in vulcan.
func (app *App) registerEndpoint() {
	endpoint, err := vulcan.NewEndpoint(app.Config.Name, app.Config.ListenIP, app.Config.ListenPort)
	if err != nil {
		log.Errorf("Failed to create an endpoint: %v", err)
		return
	}

	if err := app.registry.RegisterEndpoint(endpoint); err != nil {
		log.Errorf("Failed to register an endpoint: %v %v", endpoint, err)
		return
	}

	log.Infof("Registered: %v", endpoint)
}

// registerLocation is a helper for registering handlers in vulcan.
func (app *App) registerLocation(methods []string, path string, scopes []Scope, middlewares []middleware.Middleware) {
	for _, scope := range scopes {
		app.registerLocationForScope(methods, path, scope, middlewares)
	}
}

// registerLocationForScope registers a location with a specified scope.
func (app *App) registerLocationForScope(methods []string, path string, scope Scope, middlewares []middleware.Middleware) {
	host, err := app.apiHostForScope(scope)
	if err != nil {
		log.Errorf("Failed to register a location: %v", err)
		return
	}
	app.registerLocationForHost(methods, path, host, middlewares)
}

// registerLocationForHost registers a location for a specified hostname.
func (app *App) registerLocationForHost(methods []string, path, host string, middlewares []middleware.Middleware) {
	location := vulcan.NewLocation(host, methods, path, app.Config.Name, middlewares)

	if err := app.registry.RegisterLocation(location); err != nil {
		log.Errorf("Failed to register a location: %v %v", location, err)
		return
	}

	log.Infof("Registered: %v", location)
}

// apiHostForScope is a helper that returns an appropriate API hostname for a provided scope.
func (app *App) apiHostForScope(scope Scope) (string, error) {
	if scope == ScopePublic {
		return app.Config.PublicAPIHost, nil
	} else if scope == ScopeProtected {
		return app.Config.ProtectedAPIHost, nil
	} else {
		return "", fmt.Errorf("unknown scope value: %v", scope)
	}
}
<commit_msg>delete unneeded type declarations<commit_after>package scroll

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gorilla/mux"
	"github.com/mailgun/log"
	"github.com/mailgun/manners"
	"github.com/mailgun/metrics"

	"github.com/mailgun/scroll/vulcan"
	"github.com/mailgun/scroll/vulcan/middleware"
)

const (
	// Suggested result set limit for APIs that may return many entries (e.g. paging).
	DefaultLimit = 100

	// Suggested max allowed result set limit for APIs that may return many entries (e.g. paging).
	MaxLimit = 10000

	// Suggested max allowed amount of entries that batch APIs can accept (e.g. batch uploads).
	MaxBatchSize = 1000

	// Interval between Vulcand heartbeats (if the app if configured to register in it).
	defaultRegisterInterval = 2 * time.Second
)

// Represents an app.
type App struct {
	Config   AppConfig
	router   *mux.Router
	registry *vulcan.Registry
	stats    *appStats
}

// Represents a configuration object an app is created with.
type AppConfig struct {
	// name of the app being created
	Name string

	// IP/port the app will bind to
	ListenIP   string
	ListenPort int

	// optional router to use
	Router *mux.Router

	// hostnames of the public and protected API entrypoints used for vulcan registration
	PublicAPIHost    string
	ProtectedAPIHost string
	ProtectedAPIURL  string

	// whether to register the app's endpoint and handlers in vulcan
	Register bool

	// metrics service used for emitting the app's real-time metrics
	Client metrics.Client
}

// Create a new app.
func NewApp() *App {
	return NewAppWithConfig(AppConfig{})
}

// Create a new app with the provided configuration.
func NewAppWithConfig(config AppConfig) *App {
	var reg *vulcan.Registry
	if config.Register != false {
		reg = vulcan.NewRegistry(vulcan.Config{
			PublicAPIHost:    config.PublicAPIHost,
			ProtectedAPIHost: config.ProtectedAPIHost,
		})
	}

	router := config.Router
	if router == nil {
		router = mux.NewRouter()
	}

	return &App{
		Config:   config,
		router:   router,
		registry: reg,
		stats:    newAppStats(config.Client),
	}
}

// Register a handler function.
//
// If vulcan registration is enabled in the both app config and handler spec,
// the handler will be registered in the local etcd instance.
func (app *App) AddHandler(spec Spec) error {
	var handler http.HandlerFunc

	// make a handler depending on the function provided in the spec
	if spec.RawHandler != nil {
		handler = spec.RawHandler
	} else if spec.Handler != nil {
		handler = MakeHandler(app, spec.Handler, spec)
	} else if spec.HandlerWithBody != nil {
		handler = MakeHandlerWithBody(app, spec.HandlerWithBody, spec)
	} else {
		return fmt.Errorf("the spec does not provide a handler function: %v", spec)
	}

	// register the handler in the router
	route := app.router.HandleFunc(spec.Path, handler).Methods(spec.Methods...)
	if len(spec.Headers) != 0 {
		route.Headers(spec.Headers...)
	}

	// vulcan registration
	if app.registry != nil && spec.Register != false {
		app.registerLocation(spec.Methods, spec.Path, spec.Scopes, spec.Middlewares)
	}

	return nil
}

// GetHandler returns HTTP compatible Handler interface.
func (app *App) GetHandler() http.Handler {
	return app.router
}

// SetNotFoundHandler sets the handler for the case when URL can not be matched by the router.
func (app *App) SetNotFoundHandler(fn http.HandlerFunc) {
	app.router.NotFoundHandler = fn
}

// IsPublicRequest determines whether the provided request came through the public HTTP endpoint.
func (app *App) IsPublicRequest(request *http.Request) bool {
	return request.Host == app.Config.PublicAPIHost
}

// Start the app on the configured host/port.
//
// If vulcan registration is enabled in the app config, starts a goroutine that
// will be registering the app's endpoint once every minute in the local etcd
// instance.
//
// Supports graceful shutdown on 'kill' and 'int' signals.
func (app *App) Run() error {
	http.Handle("/", app.router)

	if app.registry != nil {
		go func() {
			// heartbeat can be stopped/resumed on USR1 signal
			heartbeatChan := make(chan os.Signal, 1)
			signal.Notify(heartbeatChan, syscall.SIGUSR1)

			for {
				select {
				// this will proceed to the "default" without blocking if there is no signal
				case s := <-heartbeatChan:
					log.Infof("Got signal: %v, pausing heartbeat", s)
					// now it blocks until another signal comes
					<-heartbeatChan
					log.Infof("Resuming heartbeat")
				default:
					app.registerEndpoint()
					time.Sleep(defaultRegisterInterval)
				}
			}
		}()
	}

	// listen for a shutdown signal
	go func() {
		exitChan := make(chan os.Signal, 1)
		signal.Notify(exitChan, os.Interrupt, os.Kill)
		s := <-exitChan
		log.Infof("Got shutdown signal: %v", s)
		manners.Close()
	}()

	return manners.ListenAndServe(
		fmt.Sprintf("%v:%v", app.Config.ListenIP, app.Config.ListenPort), nil)
}

// registerEndpoint is a helper for registering the app's endpoint in vulcan.
func (app *App) registerEndpoint() {
	endpoint, err := vulcan.NewEndpoint(app.Config.Name, app.Config.ListenIP, app.Config.ListenPort)
	if err != nil {
		log.Errorf("Failed to create an endpoint: %v", err)
		return
	}

	if err := app.registry.RegisterEndpoint(endpoint); err != nil {
		log.Errorf("Failed to register an endpoint: %v %v", endpoint, err)
		return
	}

	log.Infof("Registered: %v", endpoint)
}

// registerLocation is a helper for registering handlers in vulcan.
func (app *App) registerLocation(methods []string, path string, scopes []Scope, middlewares []middleware.Middleware) {
	for _, scope := range scopes {
		app.registerLocationForScope(methods, path, scope, middlewares)
	}
}

// registerLocationForScope registers a location with a specified scope.
func (app *App) registerLocationForScope(methods []string, path string, scope Scope, middlewares []middleware.Middleware) {
	host, err := app.apiHostForScope(scope)
	if err != nil {
		log.Errorf("Failed to register a location: %v", err)
		return
	}
	app.registerLocationForHost(methods, path, host, middlewares)
}

// registerLocationForHost registers a location for a specified hostname.
func (app *App) registerLocationForHost(methods []string, path, host string, middlewares []middleware.Middleware) {
	location := vulcan.NewLocation(host, methods, path, app.Config.Name, middlewares)

	if err := app.registry.RegisterLocation(location); err != nil {
		log.Errorf("Failed to register a location: %v %v", location, err)
		return
	}

	log.Infof("Registered: %v", location)
}

// apiHostForScope is a helper that returns an appropriate API hostname for a provided scope.
func (app *App) apiHostForScope(scope Scope) (string, error) {
	if scope == ScopePublic {
		return app.Config.PublicAPIHost, nil
	} else if scope == ScopeProtected {
		return app.Config.ProtectedAPIHost, nil
	} else {
		return "", fmt.Errorf("unknown scope value: %v", scope)
	}
}
<|endoftext|>


<commit_before>package gogist

import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
)

const t = `

    <meta name="go-import" content="%s git gist.github.com/%s/%s.git" />

`

// TODO: Move to a static file.
const explain = `

    <title>Go import redirect for GitHub Gists</title>

Welcome!

Ever see some tasty Go code in a GitHub Gist and want to try it out? What are you supposed to do, clone it into your own GitHub repo and go get it? Copy it locally? What are you a farmer?

Why can't you just import "gist.github.com/UserName/112358"? Because Gists don't support that, unfortunately. :(

Which is why I made this silly hack. Instead of import "gist.github.com/...", import "go-gist.appspot.com/...", and this site will tell the Go tool to go fetch the contents of the Gist instead.

It's all described in the docs. Those guys thought of everything.

By the way, this would be totally unnecessary if the Gist HTML page was served with the necessary <meta> tag. If you work at GitHub or know someone who does, bug them to add a tag to their Gist HTML so I can turn this site off.

`

func init() {
	r := mux.NewRouter()
	r.HandleFunc("/{username}/{gistID:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
		v := mux.Vars(r)
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(fmt.Sprintf(t, r.URL.Host+r.URL.Path, v["username"], v["gistID"])))
	}).Methods("GET")
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(explain))
	})
	http.Handle("/", r)
}
<commit_msg>Redirect to GitHub when non-go-get clients visit a redirecting URL<commit_after>package gogist

import (
	"fmt"
	"net/http"

	"github.com/gorilla/mux"
)

const t = `

    <meta name="go-import" content="%s git gist.github.com/%s/%s.git" />

`

func init() {
	r := mux.NewRouter()
	r.HandleFunc("/{username}/{gistID:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
		v := mux.Vars(r)
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(fmt.Sprintf(t, r.URL.Host+r.URL.Path, v["username"], v["gistID"])))
	}).Methods("GET")
	http.Handle("/", r)
}
<|endoftext|>