<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/exercism/cli/api"
	"github.com/exercism/cli/cmd"
)

const (
	// Version is the current release of the command-line app.
	// We try to follow Semantic Versioning (http://semver.org),
	// but with the http://exercism.io app being a prototype, a
	// lot of things get out of hand.
	Version = "2.2.1"

	descDebug     = "Outputs useful debug information."
	descConfigure = "Writes config values to a JSON file."
	descDemo      = "Fetches a demo problem for each language track on exercism.io."
	descFetch     = "Fetches your current problems on exercism.io, as well as the next unstarted problem in each language."
	descRestore   = "Restores completed and current problems on from exercism.io, along with your most recent iteration for each."
	descSubmit    = "Submits a new iteration to a problem on exercism.io."
	descSkip      = "Skips a problem given a language and slug."
	descUnsubmit  = "Deletes the most recently submitted solution."
	descUpgrade   = "Upgrades the CLI to the latest released version."
	descTracks    = "List the available language tracks"
	descOpen      = "Opens the current submission of the specified exercise"

	descLongRestore = "Restore will pull the latest revisions of exercises that have already been submitted. It will *not* overwrite existing files. If you have made changes to a file and have not submitted it, and you're trying to restore the last submitted version, first move that file out of the way, then call restore."
	descDownload    = "Downloads and saves a specified submission into the local system"
	descList        = "Lists all available assignments for a given language"
)

func main() {
	api.UserAgent = fmt.Sprintf("github.com/exercism/cli v%s (%s/%s)", Version, runtime.GOOS, runtime.GOARCH)

	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Version = Version
	app.HideVersion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "config, c",
			Usage:  "path to config file",
			EnvVar: "XDG_CONFIG_HOME,EXERCISM_CONFIG_FILE",
		},
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "turn on verbose logging",
		},
		cli.BoolFlag{
			Name:  "version",
			Usage: "print the version",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:   "debug",
			Usage:  descDebug,
			Action: cmd.Debug,
		},
		{
			Name:  "configure",
			Usage: descConfigure,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "dir, d",
					Usage: "path to exercises directory",
				},
				cli.StringFlag{
					Name:  "host, u",
					Usage: "exercism api host",
				},
				cli.StringFlag{
					Name:  "key, k",
					Usage: "exercism.io API key (see http://exercism.io/account)",
				},
				cli.StringFlag{
					Name:  "api, a",
					Usage: "exercism xapi host",
				},
			},
			Action: cmd.Configure,
		},
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     descDemo,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "dir, d",
					Usage: "path to use for the demo exercises",
				},
			},
			Action: cmd.Demo,
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     descFetch,
			Action:    cmd.Fetch,
		},
		{
			Name:        "restore",
			ShortName:   "r",
			Usage:       descRestore,
			Description: descLongRestore,
			Action:      cmd.Restore,
		},
		{
			Name:   "skip",
			Usage:  descSkip,
			Action: cmd.Skip,
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     descSubmit,
			Action:    cmd.Submit,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "test",
					Usage: "allow submission of test files",
				},
			},
		},
		{
			Name:      "unsubmit",
			ShortName: "u",
			Usage:     descUnsubmit,
			Action:    cmd.Unsubmit,
		},
		{
			Name:   "upgrade",
			Usage:  descUpgrade,
			Action: cmd.Upgrade,
		},
		{
			Name:      "tracks",
			ShortName: "t",
			Usage:     descTracks,
			Action:    cmd.Tracks,
		},
		{
			Name:      "open",
			ShortName: "op",
			Usage:     descOpen,
			Action:    cmd.Open,
		},
		{
			Name:      "download",
			ShortName: "dl",
			Usage:     descDownload,
			Action:    cmd.Download,
		},
		{
			Name:      "list",
			ShortName: "li",
			Usage:     descList,
			Action:    cmd.List,
		},
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Prefer EXERCISM_CONFIG_FILE to XDG_CONFIG_HOME<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/exercism/cli/api"
	"github.com/exercism/cli/cmd"
)

const (
	// Version is the current release of the command-line app.
	// We try to follow Semantic Versioning (http://semver.org),
	// but with the http://exercism.io app being a prototype, a
	// lot of things get out of hand.
	Version = "2.2.1"

	descDebug     = "Outputs useful debug information."
	descConfigure = "Writes config values to a JSON file."
	descDemo      = "Fetches a demo problem for each language track on exercism.io."
	descFetch     = "Fetches your current problems on exercism.io, as well as the next unstarted problem in each language."
	descRestore   = "Restores completed and current problems on from exercism.io, along with your most recent iteration for each."
	descSubmit    = "Submits a new iteration to a problem on exercism.io."
	descSkip      = "Skips a problem given a language and slug."
	descUnsubmit  = "Deletes the most recently submitted solution."
	descUpgrade   = "Upgrades the CLI to the latest released version."
	descTracks    = "List the available language tracks"
	descOpen      = "Opens the current submission of the specified exercise"

	descLongRestore = "Restore will pull the latest revisions of exercises that have already been submitted. It will *not* overwrite existing files. If you have made changes to a file and have not submitted it, and you're trying to restore the last submitted version, first move that file out of the way, then call restore."
	descDownload    = "Downloads and saves a specified submission into the local system"
	descList        = "Lists all available assignments for a given language"
)

func main() {
	api.UserAgent = fmt.Sprintf("github.com/exercism/cli v%s (%s/%s)", Version, runtime.GOOS, runtime.GOARCH)

	app := cli.NewApp()
	app.Name = "exercism"
	app.Usage = "A command line tool to interact with http://exercism.io"
	app.Version = Version
	app.HideVersion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "config, c",
			Usage:  "path to config file",
			EnvVar: "EXERCISM_CONFIG_FILE,XDG_CONFIG_HOME",
		},
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "turn on verbose logging",
		},
		cli.BoolFlag{
			Name:  "version",
			Usage: "print the version",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:   "debug",
			Usage:  descDebug,
			Action: cmd.Debug,
		},
		{
			Name:  "configure",
			Usage: descConfigure,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "dir, d",
					Usage: "path to exercises directory",
				},
				cli.StringFlag{
					Name:  "host, u",
					Usage: "exercism api host",
				},
				cli.StringFlag{
					Name:  "key, k",
					Usage: "exercism.io API key (see http://exercism.io/account)",
				},
				cli.StringFlag{
					Name:  "api, a",
					Usage: "exercism xapi host",
				},
			},
			Action: cmd.Configure,
		},
		{
			Name:      "demo",
			ShortName: "d",
			Usage:     descDemo,
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "dir, d",
					Usage: "path to use for the demo exercises",
				},
			},
			Action: cmd.Demo,
		},
		{
			Name:      "fetch",
			ShortName: "f",
			Usage:     descFetch,
			Action:    cmd.Fetch,
		},
		{
			Name:        "restore",
			ShortName:   "r",
			Usage:       descRestore,
			Description: descLongRestore,
			Action:      cmd.Restore,
		},
		{
			Name:   "skip",
			Usage:  descSkip,
			Action: cmd.Skip,
		},
		{
			Name:      "submit",
			ShortName: "s",
			Usage:     descSubmit,
			Action:    cmd.Submit,
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "test",
					Usage: "allow submission of test files",
				},
			},
		},
		{
			Name:      "unsubmit",
			ShortName: "u",
			Usage:     descUnsubmit,
			Action:    cmd.Unsubmit,
		},
		{
			Name:   "upgrade",
			Usage:  descUpgrade,
			Action: cmd.Upgrade,
		},
		{
			Name:      "tracks",
			ShortName: "t",
			Usage:     descTracks,
			Action:    cmd.Tracks,
		},
		{
			Name:      "open",
			ShortName: "op",
			Usage:     descOpen,
			Action:    cmd.Open,
		},
		{
			Name:      "download",
			ShortName: "dl",
			Usage:     descDownload,
			Action:    cmd.Download,
		},
		{
			Name:      "list",
			ShortName: "li",
			Usage:     descList,
			Action:    cmd.List,
		},
	}
	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package tugboat

import (
	"errors"
	"fmt"
	"io"

	"code.google.com/p/goauth2/oauth"
	"github.com/google/go-github/github"
	"github.com/joshk/pusher"
	"github.com/mattes/migrate/migrate"
	"golang.org/x/net/context"
)

// BaseURL is the baseURL where tugboat is running.
var BaseURL string

// Config is configuration for a new Tugboat instance.
type Config struct {
	Pusher struct {
		URL string
	}

	GitHub struct {
		Token string
	}

	// ProviderSecret is the secret used to sign JWT tokens for
	// authentication external providers.
	ProviderSecret []byte

	// DB connection string.
	DB string
}

// Tugboat provides methods for performing deployments.
type Tugboat struct {
	// Provider is a provider that will be used to fullfill deployments.
	Providers []Provider

	// MatchEnvironment controls what environments are allowed to be
	// deployed to. If a value is provided, Tugboat will only deploy if the
	// environment matches.
	MatchEnvironment string

	store *store

	deployments deploymentsService
	logs        logsService
	tokens      tokensService
}

// New returns a new Tugboat instance.
func New(config Config) (*Tugboat, error) {
	db, err := dialDB(config.DB)
	if err != nil {
		return nil, err
	}
	store := &store{db: db}

	pusher, err := newPusherClient(config.Pusher.URL)
	if err != nil {
		return nil, err
	}

	github := newGitHubClient(config.GitHub.Token)

	var updater multiUpdater

	if config.Pusher.URL != "" {
		updater = append(updater, &pusherUpdater{
			pusher: pusher,
		})
	}

	if config.GitHub.Token != "" {
		updater = append(updater, &githubUpdater{
			github: github.Repositories,
		})
	}

	deployments := newDeploymentsService(store, updater)
	logs := newLogsService(store, pusher)
	tokens := newTokensService(config.ProviderSecret)

	return &Tugboat{
		store:       store,
		deployments: deployments,
		logs:        logs,
		tokens:      tokens,
	}, nil
}

// TokensCreate creates a new authentication token for an external provider.
func (t *Tugboat) TokensCreate(token *Token) error {
	return t.tokens.TokensCreate(token)
}

// TokensFind finds a provider authentication token.
func (t *Tugboat) TokensFind(token string) (*Token, error) {
	return t.tokens.TokensFind(token)
}

// Deployments returns the most recent Deployments.
func (t *Tugboat) Deployments(q DeploymentsQuery) ([]*Deployment, error) {
	return t.store.Deployments(q)
}

// DeploymentsFind finds a Deployment by id.
func (t *Tugboat) DeploymentsFind(id string) (*Deployment, error) {
	return t.store.DeploymentsFind(id)
}

// DeploymentsCreate creates a new Deployment.
func (t *Tugboat) DeploymentsCreate(opts DeployOpts) (*Deployment, error) {
	d := newDeployment(opts)
	d.Started(opts.Provider)
	return d, t.deployments.DeploymentsCreate(d)
}

// DeploymentsUpdate updates a Deployment.
func (t *Tugboat) DeploymentsUpdate(d *Deployment) error {
	return t.deployments.DeploymentsUpdate(d)
}

// UpdateStatus updates the deployment using the given StatusUpdate
func (t *Tugboat) UpdateStatus(d *Deployment, update StatusUpdate) error {
	switch update.Status {
	case StatusFailed:
		d.Failed()
	case StatusErrored:
		var err error
		if update.Error != nil {
			err = *update.Error
		} else {
			err = errors.New("no error provided")
		}
		d.Errored(err)
	case StatusSucceeded:
		d.Succeeded()
	default:
		return errors.New("invalid status")
	}

	return t.DeploymentsUpdate(d)
}

// WriteLogs reads each line from r and creates a log line for the Deployment.
func (t *Tugboat) WriteLogs(d *Deployment, r io.Reader) error {
	w := &logWriter{
		createLogLine: t.logs.LogLinesCreate,
		deploymentID:  d.ID,
	}

	_, err := io.Copy(w, r)
	return err
}

// Logs returns a single string of text for all the entire log stream.
// TODO: Make this into something that writes to an io.Writer and change the
// frontend to stream the logs from a streaming endpoint.
func (t *Tugboat) Logs(d *Deployment) (string, error) {
	lines, err := t.store.LogLines(d)
	if err != nil {
		return "", err
	}

	out := ""
	for _, line := range lines {
		out += line.Text
	}

	return out, nil
}

// DEPRECATED: Deploy triggers a new deployment.
func (t *Tugboat) Deploy(ctx context.Context, opts DeployOpts) ([]*Deployment, error) {
	if t.MatchEnvironment != "" {
		if t.MatchEnvironment != opts.Environment {
			return nil, nil
		}
	}

	ps := t.Providers
	if len(ps) == 0 {
		ps = []Provider{&NullProvider{}}
	}

	var deployments []*Deployment

	for _, p := range ps {
		d, err := deploy(ctx, opts, p, t)
		if err != nil {
			return nil, err
		}

		deployments = append(deployments, d)
	}

	return deployments, nil
}

func (t *Tugboat) Reset() error {
	return t.store.Reset()
}

type client interface {
	DeploymentsCreate(DeployOpts) (*Deployment, error)
	WriteLogs(*Deployment, io.Reader) error
	UpdateStatus(*Deployment, StatusUpdate) error
}

// Deploy is the primary business logic for performing a deployment. It:
//
// 1. Creates the deployment within Tugboat.
// 2. Performs the deployment using the Provider.
// 3. Writes the log output to the deployment.
// 4. Updates the status depending on the eror returned from `fn`.
func deploy(ctx context.Context, opts DeployOpts, p Provider, t client) (deployment *Deployment, err error) {
	opts.Provider = p.Name()

	deployment, err = t.DeploymentsCreate(opts)
	if err != nil {
		return
	}

	r, w := io.Pipe()

	logsDone := make(chan struct{}, 1)
	go func() {
		// we're ignoring err here.
		_ = t.WriteLogs(deployment, r)
		close(logsDone)
	}()

	t.UpdateStatus(deployment, statusUpdate(func() error {
		err = p.Deploy(ctx, deployment, w)
		return err
	}))

	w.Close()

	// Wait for logs to finish streaming.
	<-logsDone

	return
}

// statusUpdate calls fn and, depending on the error or panic, returns an
// appropriate StatusUpdate.
func statusUpdate(fn func() error) (update StatusUpdate) {
	var err error

	defer func() {
		if v := recover(); v != nil {
			err = fmt.Errorf("%v", v)

			if v, ok := v.(error); ok {
				err = v
			}
		}

		// No error or panic. Success!
		if err == nil {
			update.Status = StatusSucceeded
			return
		}

		// ErrFailed is returned when the deployment failed and the user
		// should check the deployment logs.
		if err == ErrFailed {
			update.Status = StatusFailed
		} else {
			update.Status = StatusErrored
			update.Error = &err
		}
	}()

	err = fn()

	return
}

// Migrate runs the migrations.
func Migrate(db, path string) ([]error, bool) {
	return migrate.UpSync(db, path)
}

func newPusherClient(uri string) (Pusher, error) {
	if uri == "" {
		return &nullPusher{}, nil
	}

	c, err := ParsePusherCredentials(uri)
	if err != nil {
		return nil, err
	}

	return newAsyncPusher(
		pusher.NewClient(c.AppID, c.Key, c.Secret),
		1000,
	), nil
}

func newGitHubClient(token string) *github.Client {
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: token},
	}

	return github.NewClient(t.Client())
}
<commit_msg>Log errors.<commit_after>package tugboat

import (
	"errors"
	"fmt"
	"io"
	"log"

	"code.google.com/p/goauth2/oauth"
	"github.com/google/go-github/github"
	"github.com/joshk/pusher"
	"github.com/mattes/migrate/migrate"
	"golang.org/x/net/context"
)

// BaseURL is the baseURL where tugboat is running.
var BaseURL string

// Config is configuration for a new Tugboat instance.
type Config struct {
	Pusher struct {
		URL string
	}

	GitHub struct {
		Token string
	}

	// ProviderSecret is the secret used to sign JWT tokens for
	// authentication external providers.
	ProviderSecret []byte

	// DB connection string.
	DB string
}

// Tugboat provides methods for performing deployments.
type Tugboat struct {
	// Provider is a provider that will be used to fullfill deployments.
	Providers []Provider

	// MatchEnvironment controls what environments are allowed to be
	// deployed to. If a value is provided, Tugboat will only deploy if the
	// environment matches.
	MatchEnvironment string

	store *store

	deployments deploymentsService
	logs        logsService
	tokens      tokensService
}

// New returns a new Tugboat instance.
func New(config Config) (*Tugboat, error) {
	db, err := dialDB(config.DB)
	if err != nil {
		return nil, err
	}
	store := &store{db: db}

	pusher, err := newPusherClient(config.Pusher.URL)
	if err != nil {
		return nil, err
	}

	github := newGitHubClient(config.GitHub.Token)

	var updater multiUpdater

	if config.Pusher.URL != "" {
		updater = append(updater, &pusherUpdater{
			pusher: pusher,
		})
	}

	if config.GitHub.Token != "" {
		updater = append(updater, &githubUpdater{
			github: github.Repositories,
		})
	}

	deployments := newDeploymentsService(store, updater)
	logs := newLogsService(store, pusher)
	tokens := newTokensService(config.ProviderSecret)

	return &Tugboat{
		store:       store,
		deployments: deployments,
		logs:        logs,
		tokens:      tokens,
	}, nil
}

// TokensCreate creates a new authentication token for an external provider.
func (t *Tugboat) TokensCreate(token *Token) error {
	return t.tokens.TokensCreate(token)
}

// TokensFind finds a provider authentication token.
func (t *Tugboat) TokensFind(token string) (*Token, error) {
	return t.tokens.TokensFind(token)
}

// Deployments returns the most recent Deployments.
func (t *Tugboat) Deployments(q DeploymentsQuery) ([]*Deployment, error) {
	return t.store.Deployments(q)
}

// DeploymentsFind finds a Deployment by id.
func (t *Tugboat) DeploymentsFind(id string) (*Deployment, error) {
	return t.store.DeploymentsFind(id)
}

// DeploymentsCreate creates a new Deployment.
func (t *Tugboat) DeploymentsCreate(opts DeployOpts) (*Deployment, error) {
	d := newDeployment(opts)
	d.Started(opts.Provider)
	return d, t.deployments.DeploymentsCreate(d)
}

// DeploymentsUpdate updates a Deployment.
func (t *Tugboat) DeploymentsUpdate(d *Deployment) error {
	return t.deployments.DeploymentsUpdate(d)
}

// UpdateStatus updates the deployment using the given StatusUpdate
func (t *Tugboat) UpdateStatus(d *Deployment, update StatusUpdate) error {
	switch update.Status {
	case StatusFailed:
		d.Failed()
	case StatusErrored:
		var err error
		if update.Error != nil {
			err = *update.Error
		} else {
			err = errors.New("no error provided")
		}
		d.Errored(err)
	case StatusSucceeded:
		d.Succeeded()
	default:
		return errors.New("invalid status")
	}

	return t.DeploymentsUpdate(d)
}

// WriteLogs reads each line from r and creates a log line for the Deployment.
func (t *Tugboat) WriteLogs(d *Deployment, r io.Reader) error {
	w := &logWriter{
		createLogLine: t.logs.LogLinesCreate,
		deploymentID:  d.ID,
	}

	_, err := io.Copy(w, r)
	return err
}

// Logs returns a single string of text for all the entire log stream.
// TODO: Make this into something that writes to an io.Writer and change the
// frontend to stream the logs from a streaming endpoint.
func (t *Tugboat) Logs(d *Deployment) (string, error) {
	lines, err := t.store.LogLines(d)
	if err != nil {
		return "", err
	}

	out := ""
	for _, line := range lines {
		out += line.Text
	}

	return out, nil
}

// DEPRECATED: Deploy triggers a new deployment.
func (t *Tugboat) Deploy(ctx context.Context, opts DeployOpts) ([]*Deployment, error) {
	if t.MatchEnvironment != "" {
		if t.MatchEnvironment != opts.Environment {
			return nil, nil
		}
	}

	ps := t.Providers
	if len(ps) == 0 {
		ps = []Provider{&NullProvider{}}
	}

	var deployments []*Deployment

	for _, p := range ps {
		d, err := deploy(ctx, opts, p, t)
		if err != nil {
			return nil, err
		}

		deployments = append(deployments, d)
	}

	return deployments, nil
}

func (t *Tugboat) Reset() error {
	return t.store.Reset()
}

type client interface {
	DeploymentsCreate(DeployOpts) (*Deployment, error)
	WriteLogs(*Deployment, io.Reader) error
	UpdateStatus(*Deployment, StatusUpdate) error
}

// Deploy is the primary business logic for performing a deployment. It:
//
// 1. Creates the deployment within Tugboat.
// 2. Performs the deployment using the Provider.
// 3. Writes the log output to the deployment.
// 4. Updates the status depending on the eror returned from `fn`.
func deploy(ctx context.Context, opts DeployOpts, p Provider, t client) (deployment *Deployment, err error) {
	opts.Provider = p.Name()

	deployment, err = t.DeploymentsCreate(opts)
	if err != nil {
		return
	}

	r, w := io.Pipe()

	logsDone := make(chan struct{}, 1)
	go func() {
		// we're ignoring err here.
		werr := t.WriteLogs(deployment, r)
		log.Printf("write error: %v\n", werr)
		close(logsDone)
	}()

	t.UpdateStatus(deployment, statusUpdate(func() error {
		err = p.Deploy(ctx, deployment, w)
		return err
	}))

	w.Close()

	// Wait for logs to finish streaming.
	<-logsDone

	return
}

// statusUpdate calls fn and, depending on the error or panic, returns an
// appropriate StatusUpdate.
func statusUpdate(fn func() error) (update StatusUpdate) {
	var err error

	defer func() {
		if v := recover(); v != nil {
			err = fmt.Errorf("%v", v)

			if v, ok := v.(error); ok {
				err = v
			}
		}

		// No error or panic. Success!
		if err == nil {
			update.Status = StatusSucceeded
			return
		}

		// ErrFailed is returned when the deployment failed and the user
		// should check the deployment logs.
		if err == ErrFailed {
			update.Status = StatusFailed
		} else {
			update.Status = StatusErrored
			update.Error = &err
		}
	}()

	err = fn()

	return
}

// Migrate runs the migrations.
func Migrate(db, path string) ([]error, bool) {
	return migrate.UpSync(db, path)
}

func newPusherClient(uri string) (Pusher, error) {
	if uri == "" {
		return &nullPusher{}, nil
	}

	c, err := ParsePusherCredentials(uri)
	if err != nil {
		return nil, err
	}

	return newAsyncPusher(
		pusher.NewClient(c.AppID, c.Key, c.Secret),
		1000,
	), nil
}

func newGitHubClient(token string) *github.Client {
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: token},
	}

	return github.NewClient(t.Client())
}
<|endoftext|>


<commit_before>// Package structures aids in solving structural systems using direct stiffness method
package main

import "fmt"

func main() {
	fmt.Printf("Hello World.\n")
}
<commit_msg>snapshot of code<commit_after>// Package structures aids in solving structural systems using direct stiffness method
package main

import (
	"fmt"

	"github.com/gonum/matrix/mat64"
)

func main() {
	fmt.Printf("Hello World.\n")
	// initialize a 3 element float64 slice
	dx := make([]float64, 3)
	dx[0] = 2
	dx[1] = 2
	dx[2] = 3
	// pass the slice dx as data to the matrix x
	x := mat64.NewDense(3, 1, dx)

	// alternatively, create the matrix y by inserting the data directly as an argument
	y := mat64.NewDense(3, 1, []float64{1, 4, 5})

	// create an empty matrix for the addition
	z := mat64.NewDense(3, 1, []float64{0, 0, 0})

	// perform the addition
	z.Add(x, y)

	// print the output
	fmt.Printf("%f %f %f\n", z.At(0, 0), z.At(1, 0), z.At(2, 0))
}

func solve(m int, n int, coord mat64.Matrix, con mat64.Matrix, re mat64.Matrix, load mat64.Matrix, w mat64.Matrix, E []float64, G []float64, A []float64, Iz []float64, Iy []float64, J []float64, St mat64.Matrix, be []float64) (Q mat64.Matrix, V mat64.Matrix, R mat64.Matrix) {
	/*--Initialization------------------------------------------------------------------*/

	//initialize a 12x12 matrix for each member
	var Ni []mat64.Matrix
	for index := 0; index < m; index++ {
		Ni[index] = mat64.NewDense(12, 12, nil)
	}
	//initialize a 6n x 6n global stiffness matrix
	S := mat64.NewDense(6*n, 6*n, nil)
	//initialize a 6n x 1 matrix of fixed end forces in global coordinates
	Pf := mat64.NewDense(6*n, 1, nil)
	//initialize a 12m x 1 matrix of internal forces in local coordinates
	Q = mat64.NewDense(12*m, 1, nil)
	//initialize a 12m x 1 matrix of fixed end forces in local coordinates
	Qfi := mat64.NewDense(12*m, 1, nil)
	//initialize a 12 x m matrix of element code numbers (locations) in the global stiffness matrix
	Ei := mat64.NewDense(12, m, nil)
	//initialize the deflections in global coordinates
	V = mat64.NewDense(12*m, 1, nil)
	//initialize the support reactions in global coordinates
	R = mat64.NewDense(12*m, 1, nil)

	/*--Coordinate Transformation------------------------------------------------------------------*/
	var Hv mat64.Vector
	for i := 0; i < m; i++ {
		H := mat64.Col(nil, i, con)
		Hv = mat64.NewVector()
	}

	/*--Return Results------------------------------------------------------------------*/
	return Q, V, R
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"sort"

	"github.com/garyburd/redigo/redis"
	"github.com/twinj/uuid"
)

const (
	// GetPermission = permission to get (and transform) images
	GetPermission = "get"
	// UploadPermission = permission to upload images
	UploadPermission = "upload"
)

var (
	permissionsByKey map[string]map[string]bool
)

func init() {
	// Change the UUID format to remove surrounding braces and dashes
	uuid.SwitchFormat(uuid.Clean, true)
}

func authInit() error {
	keys, err := listKeys()
	if err != nil {
		return err
	}

	permissionsByKey = make(map[string]map[string]bool)

	// Set up permissions for when there's no API key
	permissionsByKey[""] = make(map[string]bool)
	permissionsByKey[""][GetPermission] = !Config.authorisedGet
	permissionsByKey[""][UploadPermission] = !Config.authorisedUpload

	// Set up permissions for API keys
	for _, key := range keys {
		permissions, err := infoAboutKey(key)
		if err != nil {
			return err
		}
		permissionsByKey[key] = make(map[string]bool)
		for _, permission := range permissions {
			permissionsByKey[key][permission] = true
		}
	}

	return nil
}

func hasPermission(key, permission string) bool {
	val, ok := permissionsByKey[key][permission]
	if ok {
		return val
	}
	return false
}

func generateKey() (string, string, error) {
	key := uuid.NewV4().String()
	secretKey := uuid.NewV4().String()
	_, err := Conn.Do("SADD", "api-keys", key)
	if err != nil {
		return "", "", err
	}
	_, err = Conn.Do("HSET", "key:"+key, "secret", secretKey)
	if err != nil {
		return "", "", err
	}
	_, err = Conn.Do("SADD", "key:"+key+":permissions", GetPermission, UploadPermission)
	return key, secretKey, err
}

func generateSecret(key string) (string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return "", err
	}

	secretKey := uuid.NewV4().String()
	_, err = Conn.Do("HSET", "key:"+key, "secret", secretKey)
	if err != nil {
		return "", err
	}

	return secretKey, nil
}

func infoAboutKey(key string) ([]string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return nil, err
	}
	permissions, err := redis.Strings(Conn.Do("SMEMBERS", "key:"+key+":permissions"))
	if err != nil {
		return nil, err
	}
	sort.Strings(permissions)
	return permissions, nil
}

func listKeys() ([]string, error) {
	return redis.Strings(Conn.Do("SMEMBERS", "api-keys"))
}

func modifyKey(key, op, permission string) error {
	err := checkKeyExists(key)
	if err != nil {
		return err
	}
	if op != "add" && op != "remove" {
		return errors.New("modifier needs to be 'add' or 'remove'")
	}
	if permission != GetPermission && permission != UploadPermission {
		return fmt.Errorf("modifier needs to end with a valid permission: %s or %s", GetPermission, UploadPermission)
	}
	if op == "add" {
		_, err = Conn.Do("SADD", "key:"+key+":permissions", permission)
	} else {
		_, err = Conn.Do("SREM", "key:"+key+":permissions", permission)
	}
	return err
}

func removeKey(key string) error {
	err := checkKeyExists(key)
	if err != nil {
		return err
	}
	_, err = Conn.Do("SREM", "api-keys", key)
	if err != nil {
		return err
	}
	_, err = Conn.Do("DEL", "key:"+key+":permissions")
	return err
}

func getSecretForKey(key string) (string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return "", err
	}

	secret, err := redis.String(Conn.Do("HGET", "key:"+key, "secret"))
	if err != nil {
		return "", err
	}

	return secret, nil
}

func authPermissionsOptions() string {
	return fmt.Sprintf("%s/%s", GetPermission, UploadPermission)
}

func checkKeyExists(key string) error {
	exists, err := redis.Bool(Conn.Do("SISMEMBER", "api-keys", key))
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("key does not exist")
	}
	return nil
}

func isValidSignature(signature, secret string, queryParams map[string]string) bool {
	var keys []string
	for key := range queryParams {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	queryString := ""
	for _, key := range keys {
		if queryString != "" {
			queryString += "&"
		}
		queryString += key + "=" + queryParams[key]
	}

	expected := signQueryString(queryString, secret)
	decodedSignature, err := hex.DecodeString(signature)
	if err != nil {
		return false
	}
	return hmac.Equal(decodedSignature, expected)
}

func signQueryString(queryString, secret string) []byte {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(queryString))
	return mac.Sum(nil)
}
<commit_msg>method signature has changed<commit_after>package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"sort"

	"github.com/garyburd/redigo/redis"
	"github.com/twinj/uuid"
)

const (
	// GetPermission = permission to get (and transform) images
	GetPermission = "get"
	// UploadPermission = permission to upload images
	UploadPermission = "upload"
)

var (
	permissionsByKey map[string]map[string]bool
)

func init() {
	// Change the UUID format to remove surrounding braces and dashes
	uuid.SwitchFormat(uuid.Clean)
}

func authInit() error {
	keys, err := listKeys()
	if err != nil {
		return err
	}

	permissionsByKey = make(map[string]map[string]bool)

	// Set up permissions for when there's no API key
	permissionsByKey[""] = make(map[string]bool)
	permissionsByKey[""][GetPermission] = !Config.authorisedGet
	permissionsByKey[""][UploadPermission] = !Config.authorisedUpload

	// Set up permissions for API keys
	for _, key := range keys {
		permissions, err := infoAboutKey(key)
		if err != nil {
			return err
		}
		permissionsByKey[key] = make(map[string]bool)
		for _, permission := range permissions {
			permissionsByKey[key][permission] = true
		}
	}

	return nil
}

func hasPermission(key, permission string) bool {
	val, ok := permissionsByKey[key][permission]
	if ok {
		return val
	}
	return false
}

func generateKey() (string, string, error) {
	key := uuid.NewV4().String()
	secretKey := uuid.NewV4().String()
	_, err := Conn.Do("SADD", "api-keys", key)
	if err != nil {
		return "", "", err
	}
	_, err = Conn.Do("HSET", "key:"+key, "secret", secretKey)
	if err != nil {
		return "", "", err
	}
	_, err = Conn.Do("SADD", "key:"+key+":permissions", GetPermission, UploadPermission)
	return key, secretKey, err
}

func generateSecret(key string) (string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return "", err
	}

	secretKey := uuid.NewV4().String()
	_, err = Conn.Do("HSET", "key:"+key, "secret", secretKey)
	if err != nil {
		return "", err
	}

	return secretKey, nil
}

func infoAboutKey(key string) ([]string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return nil, err
	}
	permissions, err := redis.Strings(Conn.Do("SMEMBERS", "key:"+key+":permissions"))
	if err != nil {
		return nil, err
	}
	sort.Strings(permissions)
	return permissions, nil
}

func listKeys() ([]string, error) {
	return redis.Strings(Conn.Do("SMEMBERS", "api-keys"))
}

func modifyKey(key, op, permission string) error {
	err := checkKeyExists(key)
	if err != nil {
		return err
	}
	if op != "add" && op != "remove" {
		return errors.New("modifier needs to be 'add' or 'remove'")
	}
	if permission != GetPermission && permission != UploadPermission {
		return fmt.Errorf("modifier needs to end with a valid permission: %s or %s", GetPermission, UploadPermission)
	}
	if op == "add" {
		_, err = Conn.Do("SADD", "key:"+key+":permissions", permission)
	} else {
		_, err = Conn.Do("SREM", "key:"+key+":permissions", permission)
	}
	return err
}

func removeKey(key string) error {
	err := checkKeyExists(key)
	if err != nil {
		return err
	}
	_, err = Conn.Do("SREM", "api-keys", key)
	if err != nil {
		return err
	}
	_, err = Conn.Do("DEL", "key:"+key+":permissions")
	return err
}

func getSecretForKey(key string) (string, error) {
	err := checkKeyExists(key)
	if err != nil {
		return "", err
	}

	secret, err := redis.String(Conn.Do("HGET", "key:"+key, "secret"))
	if err != nil {
		return "", err
	}

	return secret, nil
}

func authPermissionsOptions() string {
	return fmt.Sprintf("%s/%s", GetPermission, UploadPermission)
}

func checkKeyExists(key string) error {
	exists, err := redis.Bool(Conn.Do("SISMEMBER", "api-keys", key))
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("key does not exist")
	}
	return nil
}

func isValidSignature(signature, secret string, queryParams map[string]string) bool {
	var keys []string
	for key := range queryParams {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	queryString := ""
	for _, key := range keys {
		if queryString != "" {
			queryString += "&"
		}
		queryString += key + "=" + queryParams[key]
	}

	expected := signQueryString(queryString, secret)
	decodedSignature, err := hex.DecodeString(signature)
	if err != nil {
		return false
	}
	return hmac.Equal(decodedSignature, expected)
}

func signQueryString(queryString, secret string) []byte {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(queryString))
	return mac.Sum(nil)
}
<|endoftext|>


<commit_before>// Use of this source code is governed by the CC0 1.0
// license that can be found in the LICENSE file or here:
// http://creativecommons.org/publicdomain/zero/1.0/

// Package base implements encoding and decoding of data in to specified base encoded data.
//
// Package base handles any base between base2 and base62 eg. base6, base32, base36, base60 etc.
//
// The base ASCII representation is probably not compatible with any other implementation of the corresponding base.
// For a standard implementations of base32 please see encoding/base32 in the standard lib.
package base

import (
	"log"
	"math/big"
)

const digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// Precalculated buffer size multipliers for all valid bases
var bufferSizeMultiplier = []float64{0, 0, 8, 5.052, 4, 3.452, 3.097, 2.852, 2.671, 2.53, 2.413, 2.317, 2.233, 2.168, 2.104, 2.052, 2, 1.962, 1.923, 1.884, 1.852, 1.826, 1.8, 1.775, 1.749, 1.73, 1.704, 1.684, 1.665, 1.652, 1.633, 1.62, 1.6, 1.588, 1.575, 1.562, 1.549, 1.542, 1.53, 1.517, 1.504, 1.497, 1.483, 1.478, 1.471, 1.459, 1.452, 1.446, 1.439, 1.426, 1.42, 1.413, 1.407, 1.4, 1.394, 1.388, 1.381, 1.375, 1.368, 1.362, 1.355, 1.355, 1.349}

// Encode takes an []byte b containing byte data and returns []byte r containing base b encoded data.
//
// b can not be grater than 62 or less than 2. If b is over 36 then r is case sensitive.
//
// Take note that Encode will remove any null bytes in the start of u, if this is important for your application save original size of the raw string.
func Encode(u []byte, b int) (r []byte) {

	if b < 2 || b > len(digits) {
		log.Fatalln("Illegal Encode base")
	}

	a := big.NewInt(0).SetBytes(u)
	if a.Uint64() == uint64(0) {
		return []byte{}
	}

	base := big.NewInt(int64(b))
	rem := big.NewInt(0)

	// Calculate the necessary buffer size for the defined base
	i := int((float64(len(a.Bytes())))*bufferSizeMultiplier[b]) + 1
	d := make([]byte, i)

	for a.Cmp(base) >= 0 {
		i--
		a.QuoRem(a, base, rem)
		d[i] = digits[int(rem.Int64())]
	}

	// last character when a < base
	i--
	d[i] = digits[int(a.Int64())]

	return d[i:]
}

// Decode takes an []byte u containing base b encoded data and returns []byte r containing byte data.
//
// b can not be grater than 62 or less than 2. If b is over 36 then u is case sensitive.
//
// u may not contain characters outside of the base character representation, e.g. base 2 can only contain "0" and "1" while base62 can only contain 0-9a-zA-Z.
//
// Take note that Decode will remove any null bytes in the start of r, if this is important for your application save original size of the raw string.
func Decode(u []byte, b int) (r []byte) {

	if b < 2 || b > len(digits) {
		log.Fatalln("Illegal Decode base")
	}

	base := big.NewInt(int64(b))
	v := big.NewInt(0)
	n := big.NewInt(0)

	for i := 0; i < len(u); i++ {
		u := u[i]
		switch {
		case '0' <= u && u <= '9':
			v.SetInt64(int64(u - '0'))
		case 'a' <= u && u <= 'z':
			v.SetInt64(int64(u - 'a' + 10))
		case 'A' <= u && u <= 'Z':
			if b <= 36 {
				v.SetInt64(int64(u - 'A' + 10))
			} else {
				v.SetInt64(int64(u - 'A' + 36))
			}
		}
		if v.Int64() >= base.Int64() {
			// If a parser uses base.Decode it can use recover() to handle this otherwise fatal error.
			// See http://blog.golang.org/defer-panic-and-recover for more information.
			panic("Illegal characters in u []byte")
		}
		n.Mul(n, base)
		n.Add(n, v)
	}
	return n.Bytes()
}
<commit_msg>added a better panic message.<commit_after>// Use of this source code is governed by the CC0 1.0
// license that can be found in the LICENSE file or here:
// http://creativecommons.org/publicdomain/zero/1.0/

// Package base implements encoding and decoding of data in to specified base encoded data.
//
// Package base handles any base between base2 and base62 eg. base6, base32, base36, base60 etc.
//
// The base ASCII representation is probably not compatible with any other implementation of the corresponding base.
// For a standard implementations of base32 please see encoding/base32 in the standard lib.
package base

import (
	"log"
	"math/big"
)

const digits = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// Precalculated buffer size multipliers for all valid bases
var bufferSizeMultiplier = []float64{0, 0, 8, 5.052, 4, 3.452, 3.097, 2.852, 2.671, 2.53, 2.413, 2.317, 2.233, 2.168, 2.104, 2.052, 2, 1.962, 1.923, 1.884, 1.852, 1.826, 1.8, 1.775, 1.749, 1.73, 1.704, 1.684, 1.665, 1.652, 1.633, 1.62, 1.6, 1.588, 1.575, 1.562, 1.549, 1.542, 1.53, 1.517, 1.504, 1.497, 1.483, 1.478, 1.471, 1.459, 1.452, 1.446, 1.439, 1.426, 1.42, 1.413, 1.407, 1.4, 1.394, 1.388, 1.381, 1.375, 1.368, 1.362, 1.355, 1.355, 1.349}

// Encode takes an []byte b containing byte data and returns []byte r containing base b encoded data.
//
// b can not be grater than 62 or less than 2. If b is over 36 then r is case sensitive.
//
// Take note that Encode will remove any null bytes in the start of u, if this is important for your application save original size of the raw string.
func Encode(u []byte, b int) (r []byte) {

	if b < 2 || b > len(digits) {
		log.Fatalln("Illegal Encode base")
	}

	a := big.NewInt(0).SetBytes(u)
	if a.Uint64() == uint64(0) {
		return []byte{}
	}

	base := big.NewInt(int64(b))
	rem := big.NewInt(0)

	// Calculate the necessary buffer size for the defined base
	i := int((float64(len(a.Bytes())))*bufferSizeMultiplier[b]) + 1
	d := make([]byte, i)

	for a.Cmp(base) >= 0 {
		i--
		a.QuoRem(a, base, rem)
		d[i] = digits[int(rem.Int64())]
	}

	// last character when a < base
	i--
	d[i] = digits[int(a.Int64())]

	return d[i:]
}

// Decode takes an []byte u containing base b encoded data and returns []byte r containing byte data.
//
// b can not be grater than 62 or less than 2. If b is over 36 then u is case sensitive.
//
// u may not contain characters outside of the base character representation, e.g. base 2 can only contain "0" and "1" while base62 can only contain 0-9a-zA-Z.
//
// Take note that Decode will remove any null bytes in the start of r, if this is important for your application save original size of the raw string.
func Decode(u []byte, b int) (r []byte) {

	if b < 2 || b > len(digits) {
		log.Fatalln("Illegal Decode base")
	}

	base := big.NewInt(int64(b))
	v := big.NewInt(0)
	n := big.NewInt(0)

	for i := 0; i < len(u); i++ {
		u := u[i]
		switch {
		case '0' <= u && u <= '9':
			v.SetInt64(int64(u - '0'))
		case 'a' <= u && u <= 'z':
			v.SetInt64(int64(u - 'a' + 10))
		case 'A' <= u && u <= 'Z':
			if b <= 36 {
				v.SetInt64(int64(u - 'A' + 10))
			} else {
				v.SetInt64(int64(u - 'A' + 36))
			}
		}
		if v.Int64() >= base.Int64() {
			// If a parser uses base.Decode it can use recover() to handle this otherwise fatal error.
			// See http://blog.golang.org/defer-panic-and-recover for more information.
			panic("Illegal characters in u []byte.\nUse recover() to handle this otherwise fatal error.")
		}
		n.Mul(n, base)
		n.Add(n, v)
	}
	return n.Bytes()
}
<|endoftext|>


<commit_before>// Go wrapper for the BitX API.
// The API is documented here: https://bitx.co/api
package bitx

import (
	"bytes"
	_ "crypto/sha512"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"time"
)

const userAgent = "bitx-go/0.0.3"

var base = url.URL{Scheme: "https", Host: "api.mybitx.com"}

type Client struct {
	api_key_id, api_key_secret string
}

// Pass an empty string for the api_key_id if you will only access the public
// API.
func NewClient(api_key_id, api_key_secret string) *Client {
	return &Client{api_key_id, api_key_secret}
}

func (c *Client) call(method, path string, params url.Values,
	result interface{}) error {
	u := base
	u.Path = path

	var body *bytes.Reader
	if method == "GET" {
		u.RawQuery = params.Encode()
		body = bytes.NewReader(nil)
	} else if method == "POST" {
		body = bytes.NewReader([]byte(params.Encode()))
	} else {
		return errors.New("Unsupported method")
	}

	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return err
	}
	if c.api_key_id != "" {
		req.SetBasicAuth(c.api_key_id, c.api_key_secret)
	}
	req.Header.Add("User-Agent", userAgent)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	r, err := (&http.Client{}).Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	if r.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(r.Body)
		return errors.New(fmt.Sprintf(
			"BitX error %d: %s: %s",
			r.StatusCode, r.Status, string(body)))
	}

	if err := json.NewDecoder(r.Body).Decode(result); err != nil {
		return err
	}

	return nil
}

type ticker struct {
	Error     string `json:"error"`
	Timestamp int64  `json:"timestamp"`
	Bid       string `json:"bid"`
	Ask       string `json:"ask"`
	Last      string `json:"last_trade"`
	Volume24H string `json:"rolling_24_hour_volume"`
}

type Ticker struct {
	Timestamp                 time.Time
	Bid, Ask, Last, Volume24H float64
}

// Returns the latest ticker indicators for the given currency pair..
func (c *Client) Ticker(pair string) (Ticker, error) {
	var r ticker
	err := c.call("GET", "/api/1/ticker", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return Ticker{}, err
	}
	if r.Error != "" {
		return Ticker{}, errors.New("BitX error: " + r.Error)
	}

	t := time.Unix(r.Timestamp/1000, 0)

	bid, err := strconv.ParseFloat(r.Bid, 64)
	if err != nil {
		return Ticker{}, err
	}

	ask, err := strconv.ParseFloat(r.Ask, 64)
	if err != nil {
		return Ticker{}, err
	}

	last, err := strconv.ParseFloat(r.Last, 64)
	if err != nil {
		return Ticker{}, err
	}

	volume24h, err := strconv.ParseFloat(r.Volume24H, 64)
	if err != nil {
		return Ticker{}, err
	}

	return Ticker{t, bid, ask, last, volume24h}, nil
}

type orderbookEntry struct {
	Price  string `json:"price"`
	Volume string `json:"volume"`
}

type orderbook struct {
	Error string           `json:"error"`
	Asks  []orderbookEntry `json:"asks"`
	Bids  []orderbookEntry `json:"bids"`
}

type OrderBookEntry struct {
	Price, Volume float64
}

func convert(entries []orderbookEntry) (r []OrderBookEntry) {
	r = make([]OrderBookEntry, len(entries))
	for i, e := range entries {
		price, _ := strconv.ParseFloat(e.Price, 64)
		volume, _ := strconv.ParseFloat(e.Volume, 64)
		r[i].Price = price
		r[i].Volume = volume
	}
	return r
}

// Returns a list of bids and asks in the order book for the given currency
// pair.
func (c *Client) OrderBook(pair string) (
	bids, asks []OrderBookEntry, err error) {

	var r orderbook
	err = c.call("GET", "/api/1/orderbook", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, nil, err
	}
	if r.Error != "" {
		return nil, nil, errors.New("BitX error: " + r.Error)
	}

	return convert(r.Bids), convert(r.Asks), nil
}

type trade struct {
	Timestamp int64  `json:"timestamp"`
	Price     string `json:"price"`
	Volume    string `json:"volume"`
}

type trades struct {
	Error  string  `json:"error"`
	Trades []trade `json:"trades"`
}

type Trade struct {
	Timestamp     time.Time
	Price, Volume float64
}

// Returns a list of the most recent trades for the given currency pair.
func (c *Client) Trades(pair string) ([]Trade, error) {
	var r trades
	err := c.call("GET", "/api/1/trades", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, err
	}
	if r.Error != "" {
		return nil, errors.New("BitX error: " + r.Error)
	}

	tr := make([]Trade, len(r.Trades))
	for i, t := range r.Trades {
		tr[i].Timestamp = time.Unix(t.Timestamp/1000, 0)
		price, _ := strconv.ParseFloat(t.Price, 64)
		volume, _ := strconv.ParseFloat(t.Volume, 64)
		tr[i].Price = price
		tr[i].Volume = volume
	}
	return tr, nil
}

type postorder struct {
	OrderId string `json:"order_id"`
	Error   string `json:"error"`
}

type OrderType string

const BID = OrderType("BID")
const ASK = OrderType("ASK")

// Create a new trade order.
func (c *Client) PostOrder(pair string, order_type OrderType,
	volume, price float64) (string, error) {
	form := make(url.Values)
	form.Add("volume", fmt.Sprintf("%f", volume))
	form.Add("price", fmt.Sprintf("%f", price))
	form.Add("pair", pair)
	form.Add("type", string(order_type))

	var r postorder
	err := c.call("POST", "/api/1/postorder", form, &r)
	if err != nil {
		return "", err
	}
	if r.Error != "" {
		return "", errors.New("BitX error: " + r.Error)
	}

	return r.OrderId, nil
}

type order struct {
	Error             string `json:"error"`
	OrderId           string `json:"order_id"`
	CreationTimestamp int64  `json:"creation_timestamp"`
	Type              string `json:"type"`
	State             string `json:"state"`
	LimitPrice        string `json:"limit_price"`
	LimitVolume       string `json:"limit_volume"`
	Base              string `json:"base"`
	Counter           string `json:"counter"`
	FeeBase           string `json:"fee_base"`
	FeeCounter        string `json:"fee_counter"`
}

type orders struct {
	Error  string  `json:"error"`
	Orders []order `json:"orders"`
}

type OrderState string

const Pending = OrderState("PENDING")
const Complete = OrderState("COMPLETE")

type Order struct {
	Id                  string
	CreatedAt           time.Time
	Type                OrderType
	State               OrderState
	LimitPrice          float64
	LimitVolume         float64
	Base, Counter       float64
	FeeBase, FeeCounter float64
}

func atofloat64(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}

func parseOrder(bo order) Order {
	var o Order
	o.Id = bo.OrderId
	o.Type = OrderType(bo.Type)
	o.State = OrderState(bo.State)
	o.CreatedAt = time.Unix(bo.CreationTimestamp/1000, 0)
	o.LimitPrice = atofloat64(bo.LimitPrice)
	o.LimitVolume = atofloat64(bo.LimitVolume)
	o.Base = atofloat64(bo.Base)
	o.Counter = atofloat64(bo.Counter)
	o.FeeBase = atofloat64(bo.FeeBase)
	o.FeeCounter = atofloat64(bo.FeeCounter)
	return o
}

// Returns a list of the most recently placed orders.
// The list is truncated after 100 items.
func (c *Client) ListOrders(pair string) ([]Order, error) {
	var r orders
	err := c.call("GET", "/api/1/listorders", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, err
	}
	if r.Error != "" {
		return nil, errors.New("BitX error: " + r.Error)
	}

	orders := make([]Order, len(r.Orders))
	for i, bo := range r.Orders {
		orders[i] = parseOrder(bo)
	}
	return orders, nil
}

var pathIDRegex = regexp.MustCompile("^[[:alnum:]]+$")

func isValidPathID(id string) bool {
	if len(id) == 0 || len(id) > 255 {
		return false
	}
	return pathIDRegex.MatchString(id)
}

// Get an order by its id.
func (c *Client) GetOrder(id string) (*Order, error) {
	if !isValidPathID(id) {
		return nil, errors.New("invalid order id")
	}
	var bo order
	err := c.call("GET", "/api/1/orders/"+id, nil, &bo)
	if err != nil {
		return nil, err
	}
	if bo.Error != "" {
		return nil, errors.New("BitX error: " + bo.Error)
	}
	o := parseOrder(bo)
	return &o, nil
}

type stoporder struct {
	Success bool   `json:"success"`
	Error   string `json:"error"`
}

// Request to stop an order.
func (c *Client) StopOrder(id string) error {
	form := make(url.Values)
	form.Add("order_id", id)
	var r stoporder
	err := c.call("POST", "/api/1/stoporder", form, &r)
	if err != nil {
		return err
	}
	if r.Error != "" {
		return errors.New("BitX error: " + r.Error)
	}
	return nil
}

type balance struct {
	Asset    string `json:"asset"`
	Balance  string `json:"balance"`
	Reserved string `json:"reserved"`
}

type balances struct {
	Error   string    `json:"error"`
	Balance []balance `json:"balance"`
}

// Returns the trading account balance and reserved funds.
func (c *Client) Balance(asset string) (
	balance float64, reserved float64, err error) {
	var r balances
	err = c.call("GET", "/api/1/balance", url.Values{"asset": {asset}}, &r)
	if err != nil {
		return 0, 0, err
	}
	if r.Error != "" {
		return 0, 0, errors.New("BitX error: " + r.Error)
	}
	if len(r.Balance) == 0 {
		return 0, 0, errors.New("Balance not returned")
	}

	balance = atofloat64(r.Balance[0].Balance)
	reserved = atofloat64(r.Balance[0].Reserved)
	return balance, reserved, nil
}

func (c *Client) Send(amount, currency, address, desc, message string) error {
	form := make(url.Values)
	form.Add("amount", amount)
	form.Add("currency", currency)
	form.Add("address", address)
	form.Add("description", desc)
	form.Add("message", message)

	var r stoporder
	err := c.call("POST", "/api/1/send", form, &r)
	if err != nil {
		return err
	}
	if r.Error != "" {
		return errors.New("BitX error: " + r.Error)
	}

	return nil
}
<commit_msg>Add Balances function to get all account balances.<commit_after>// Go wrapper for the BitX API.
// The API is documented here: https://bitx.co/api
package bitx

import (
	"bytes"
	_ "crypto/sha512"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"time"
)

const userAgent = "bitx-go/0.0.3"

var base = url.URL{Scheme: "https", Host: "api.mybitx.com"}

type Client struct {
	api_key_id, api_key_secret string
}

// Pass an empty string for the api_key_id if you will only access the public
// API.
func NewClient(api_key_id, api_key_secret string) *Client {
	return &Client{api_key_id, api_key_secret}
}

func (c *Client) call(method, path string, params url.Values,
	result interface{}) error {
	u := base
	u.Path = path

	var body *bytes.Reader
	if method == "GET" {
		u.RawQuery = params.Encode()
		body = bytes.NewReader(nil)
	} else if method == "POST" {
		body = bytes.NewReader([]byte(params.Encode()))
	} else {
		return errors.New("Unsupported method")
	}

	req, err := http.NewRequest(method, u.String(), body)
	if err != nil {
		return err
	}
	if c.api_key_id != "" {
		req.SetBasicAuth(c.api_key_id, c.api_key_secret)
	}
	req.Header.Add("User-Agent", userAgent)
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	r, err := (&http.Client{}).Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()

	if r.StatusCode != http.StatusOK {
		body, _ := ioutil.ReadAll(r.Body)
		return errors.New(fmt.Sprintf(
			"BitX error %d: %s: %s",
			r.StatusCode, r.Status, string(body)))
	}

	if err := json.NewDecoder(r.Body).Decode(result); err != nil {
		return err
	}

	return nil
}

type ticker struct {
	Error     string `json:"error"`
	Timestamp int64  `json:"timestamp"`
	Bid       string `json:"bid"`
	Ask       string `json:"ask"`
	Last      string `json:"last_trade"`
	Volume24H string `json:"rolling_24_hour_volume"`
}

type Ticker struct {
	Timestamp                 time.Time
	Bid, Ask, Last, Volume24H float64
}

// Returns the latest ticker indicators for the given currency pair..
func (c *Client) Ticker(pair string) (Ticker, error) {
	var r ticker
	err := c.call("GET", "/api/1/ticker", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return Ticker{}, err
	}
	if r.Error != "" {
		return Ticker{}, errors.New("BitX error: " + r.Error)
	}

	t := time.Unix(r.Timestamp/1000, 0)

	bid, err := strconv.ParseFloat(r.Bid, 64)
	if err != nil {
		return Ticker{}, err
	}

	ask, err := strconv.ParseFloat(r.Ask, 64)
	if err != nil {
		return Ticker{}, err
	}

	last, err := strconv.ParseFloat(r.Last, 64)
	if err != nil {
		return Ticker{}, err
	}

	volume24h, err := strconv.ParseFloat(r.Volume24H, 64)
	if err != nil {
		return Ticker{}, err
	}

	return Ticker{t, bid, ask, last, volume24h}, nil
}

type orderbookEntry struct {
	Price  string `json:"price"`
	Volume string `json:"volume"`
}

type orderbook struct {
	Error string           `json:"error"`
	Asks  []orderbookEntry `json:"asks"`
	Bids  []orderbookEntry `json:"bids"`
}

type OrderBookEntry struct {
	Price, Volume float64
}

func convert(entries []orderbookEntry) (r []OrderBookEntry) {
	r = make([]OrderBookEntry, len(entries))
	for i, e := range entries {
		price, _ := strconv.ParseFloat(e.Price, 64)
		volume, _ := strconv.ParseFloat(e.Volume, 64)
		r[i].Price = price
		r[i].Volume = volume
	}
	return r
}

// Returns a list of bids and asks in the order book for the given currency
// pair.
func (c *Client) OrderBook(pair string) (
	bids, asks []OrderBookEntry, err error) {

	var r orderbook
	err = c.call("GET", "/api/1/orderbook", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, nil, err
	}
	if r.Error != "" {
		return nil, nil, errors.New("BitX error: " + r.Error)
	}

	return convert(r.Bids), convert(r.Asks), nil
}

type trade struct {
	Timestamp int64  `json:"timestamp"`
	Price     string `json:"price"`
	Volume    string `json:"volume"`
}

type trades struct {
	Error  string  `json:"error"`
	Trades []trade `json:"trades"`
}

type Trade struct {
	Timestamp     time.Time
	Price, Volume float64
}

// Returns a list of the most recent trades for the given currency pair.
func (c *Client) Trades(pair string) ([]Trade, error) {
	var r trades
	err := c.call("GET", "/api/1/trades", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, err
	}
	if r.Error != "" {
		return nil, errors.New("BitX error: " + r.Error)
	}

	tr := make([]Trade, len(r.Trades))
	for i, t := range r.Trades {
		tr[i].Timestamp = time.Unix(t.Timestamp/1000, 0)
		price, _ := strconv.ParseFloat(t.Price, 64)
		volume, _ := strconv.ParseFloat(t.Volume, 64)
		tr[i].Price = price
		tr[i].Volume = volume
	}
	return tr, nil
}

type postorder struct {
	OrderId string `json:"order_id"`
	Error   string `json:"error"`
}

type OrderType string

const BID = OrderType("BID")
const ASK = OrderType("ASK")

// Create a new trade order.
func (c *Client) PostOrder(pair string, order_type OrderType,
	volume, price float64) (string, error) {
	form := make(url.Values)
	form.Add("volume", fmt.Sprintf("%f", volume))
	form.Add("price", fmt.Sprintf("%f", price))
	form.Add("pair", pair)
	form.Add("type", string(order_type))

	var r postorder
	err := c.call("POST", "/api/1/postorder", form, &r)
	if err != nil {
		return "", err
	}
	if r.Error != "" {
		return "", errors.New("BitX error: " + r.Error)
	}

	return r.OrderId, nil
}

type order struct {
	Error             string `json:"error"`
	OrderId           string `json:"order_id"`
	CreationTimestamp int64  `json:"creation_timestamp"`
	Type              string `json:"type"`
	State             string `json:"state"`
	LimitPrice        string `json:"limit_price"`
	LimitVolume       string `json:"limit_volume"`
	Base              string `json:"base"`
	Counter           string `json:"counter"`
	FeeBase           string `json:"fee_base"`
	FeeCounter        string `json:"fee_counter"`
}

type orders struct {
	Error  string  `json:"error"`
	Orders []order `json:"orders"`
}

type OrderState string

const Pending = OrderState("PENDING")
const Complete = OrderState("COMPLETE")

type Order struct {
	Id                  string
	CreatedAt           time.Time
	Type                OrderType
	State               OrderState
	LimitPrice          float64
	LimitVolume         float64
	Base, Counter       float64
	FeeBase, FeeCounter float64
}

func atofloat64(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}

func parseOrder(bo order) Order {
	var o Order
	o.Id = bo.OrderId
	o.Type = OrderType(bo.Type)
	o.State = OrderState(bo.State)
	o.CreatedAt = time.Unix(bo.CreationTimestamp/1000, 0)
	o.LimitPrice = atofloat64(bo.LimitPrice)
	o.LimitVolume = atofloat64(bo.LimitVolume)
	o.Base = atofloat64(bo.Base)
	o.Counter = atofloat64(bo.Counter)
	o.FeeBase = atofloat64(bo.FeeBase)
	o.FeeCounter = atofloat64(bo.FeeCounter)
	return o
}

// Returns a list of the most recently placed orders.
// The list is truncated after 100 items.
func (c *Client) ListOrders(pair string) ([]Order, error) {
	var r orders
	err := c.call("GET", "/api/1/listorders", url.Values{"pair": {pair}}, &r)
	if err != nil {
		return nil, err
	}
	if r.Error != "" {
		return nil, errors.New("BitX error: " + r.Error)
	}

	orders := make([]Order, len(r.Orders))
	for i, bo := range r.Orders {
		orders[i] = parseOrder(bo)
	}
	return orders, nil
}

var pathIDRegex = regexp.MustCompile("^[[:alnum:]]+$")

func isValidPathID(id string) bool {
	if len(id) == 0 || len(id) > 255 {
		return false
	}
	return pathIDRegex.MatchString(id)
}

// Get an order by its id.
func (c *Client) GetOrder(id string) (*Order, error) {
	if !isValidPathID(id) {
		return nil, errors.New("invalid order id")
	}
	var bo order
	err := c.call("GET", "/api/1/orders/"+id, nil, &bo)
	if err != nil {
		return nil, err
	}
	if bo.Error != "" {
		return nil, errors.New("BitX error: " + bo.Error)
	}
	o := parseOrder(bo)
	return &o, nil
}

type stoporder struct {
	Success bool   `json:"success"`
	Error   string `json:"error"`
}

// Request to stop an order.
func (c *Client) StopOrder(id string) error {
	form := make(url.Values)
	form.Add("order_id", id)
	var r stoporder
	err := c.call("POST", "/api/1/stoporder", form, &r)
	if err != nil {
		return err
	}
	if r.Error != "" {
		return errors.New("BitX error: " + r.Error)
	}
	return nil
}

type balance struct {
	Asset       string `json:"asset"`
	Balance     string `json:"balance"`
	Reserved    string `json:"reserved"`
	Unconfirmed string `json:"unconfirmed"`
}

type balances struct {
	Error   string    `json:"error"`
	Balance []balance `json:"balance"`
}

type Balance struct {
	Asset       string
	Balance     float64
	Reserved    float64
	Unconfirmed float64
}

func parseBalances(bal []balance) []Balance {
	var bl []Balance
	for _, b := range bal {
		var r Balance
		r.Asset = b.Asset
		r.Balance = atofloat64(b.Balance)
		r.Reserved = atofloat64(b.Reserved)
		r.Unconfirmed = atofloat64(b.Unconfirmed)
		bl = append(bl, r)
	}
	return bl
}

// Returns the trading account balance and reserved funds.
func (c *Client) Balance(asset string) (
	balance float64, reserved float64, err error) {
	var r balances
	err = c.call("GET", "/api/1/balance", url.Values{"asset": {asset}}, &r)
	if err != nil {
		return 0, 0, err
	}
	if r.Error != "" {
		return 0, 0, errors.New("BitX error: " + r.Error)
	}
	if len(r.Balance) == 0 {
		return 0, 0, errors.New("Balance not returned")
	}
	bl := parseBalances(r.Balance)
	return bl[0].Balance, bl[0].Reserved, nil
}

// Balances return the balances of all accounts.
func (c *Client) Balances() ([]Balance, error) {
	var r balances
	err := c.call("GET", "/api/1/balance", nil, &r)
	if err != nil {
		return nil, err
	}
	if r.Error != "" {
		return nil, errors.New("BitX error: " + r.Error)
	}
	return parseBalances(r.Balance), nil
}

func (c *Client) Send(amount, currency, address, desc, message string) error {
	form := make(url.Values)
	form.Add("amount", amount)
	form.Add("currency", currency)
	form.Add("address", address)
	form.Add("description", desc)
	form.Add("message", message)

	var r stoporder
	err := c.call("POST", "/api/1/send", form, &r)
	if err != nil {
		return err
	}
	if r.Error != "" {
		return errors.New("BitX error: " + r.Error)
	}

	return nil
}
<|endoftext|>


<commit_before>package pretty

import (
	"fmt"
	"os"
	"text/tabwriter"
)

// A TabPrinter is an object that allows printing tab-aligned words on multiple lines,
// up to a maximum number per line
type TabPrinter struct {
	w            *tabwriter.Writer
	current, max int
}

// create a TabPrinter
//
// max specifies the maximum number of 'words' per line
func NewTabPrinter(max int) *TabPrinter {
	tp := &TabPrinter{new(tabwriter.Writer), 0, max}
	tp.w.Init(os.Stdout, 0, 8, 0, '\t', 0)

	return tp
}

// print a 'word'
//
// when the maximum number of words per lines is reached, this will print the formatted line
func (tp *TabPrinter) Print(arg interface{}) {
	if tp.current > 0 {
		if (tp.current % tp.max) == 0 {
			fmt.Fprintln(tp.w, "")
			tp.w.Flush()
		} else {
			fmt.Fprint(tp.w, "\t")
		}
	}

	tp.current++
	fmt.Fprint(tp.w, arg)
}

// print current line
//
// terminate current line and print - call this after all words have been printed
func (tp *TabPrinter) Println() {
	if tp.current > 0 && (tp.current%tp.max) != 0 {
		fmt.Fprintln(tp.w, "")
		tp.w.Flush()
	}

	tp.current = 0
}
<commit_msg>make sure there is at least one space between words<commit_after>package pretty

import (
	"fmt"
	"os"
	"text/tabwriter"
)

// A TabPrinter is an object that allows printing tab-aligned words on multiple lines,
// up to a maximum number per line
type TabPrinter struct {
	w            *tabwriter.Writer
	current, max int
}

// create a TabPrinter
//
// max specifies the maximum number of 'words' per line
func NewTabPrinter(max int) *TabPrinter {
	tp := &TabPrinter{new(tabwriter.Writer), 0, max}
	tp.w.Init(os.Stdout, 0, 8, 1, '\t', 0)

	return tp
}

// print a 'word'
//
// when the maximum number of words per lines is reached, this will print the formatted line
func (tp *TabPrinter) Print(arg interface{}) {
	if tp.current > 0 {
		if (tp.current % tp.max) == 0 {
			fmt.Fprintln(tp.w, "")
			tp.w.Flush()
		} else {
			fmt.Fprint(tp.w, "\t")
		}
	}

	tp.current++
	fmt.Fprint(tp.w, arg)
}

// print current line
//
// terminate current line and print - call this after all words have been printed
func (tp *TabPrinter) Println() {
	if tp.current > 0 && (tp.current%tp.max) != 0 {
		fmt.Fprintln(tp.w, "")
		tp.w.Flush()
	}

	tp.current = 0
}
<|endoftext|>


<commit_before>package celeriac

import (
	"time"
)

/*
Event defines a base event emitted by Celery workers.
*/
type Event struct {
	// Type is the Celery event type. See supported events listed in "constants.go"
	Type string `json:"type"`

	// Hostname is the name of the host on which the Celery worker is operating
	Hostname string `json:"hostname"`

	// Timestamp is the current time of the event
	Timestamp float32 `json:"timestamp"`

	// PID is the process ID
	PID int `json:"pid"`

	// Clock is the current clock time
	Clock int `json:"clock"`

	// UTCOffset is the offset from UTC for the time when this event is valid
	UTCOffset int `json:"utcoffset"`
}

/*
NewEvent is a factory function to create a new Event object
*/
func NewEvent() *Event {
	return &Event{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,
	}
}

/*
TimestampFormatted returns a formatted string representation of the task event timestamp
*/
func (event *Event) TimestampFormatted() string {
	// First convert float64 to a time.Time
	dt := time.Unix(int64(event.Timestamp), 0)

	// Convert the timestamp to our own string representation
	return dt.UTC().Format(ConstTimeFormat)
}

/*
WorkerEvent defines an event emitted by workers, specific to its operation. Event "types" emitted are:
	- "worker-online"
	- "worker-offline"
	- "worker-heartbeat"

Example worker event json:
{
	"sw_sys": "Darwin",
	"clock": 74,
	"timestamp": 1843965659.580637,
	"hostname": "celery@Stefans-Mac.local",
	"pid": 10837,
	"sw_ver": "3.1.18",
	"utcoffset": -11,
	"loadavg": [2.0, 2.41, 2.54],
	"processed": 6,
	"active": 0,
	"freq": 2.0,
	"type": "worker-offline",
	"sw_ident": "py-celery"
}
*/
type WorkerEvent struct {
	Type      string  `json:"type"`
	Hostname  string  `json:"hostname"`
	Timestamp float32 `json:"timestamp"`
	PID       int     `json:"pid"`
	Clock     int     `json:"clock"`
	UTCOffset int     `json:"utcoffset"`

	// SWSystem is the software system being used
	SWSystem string `json:"sw_sys"`

	// SWVersion is the software version being used
	SWVersion string `json:"sw_ver"`

	// LoadAverage is an array of average CPU loadings for the worker
	LoadAverage []float32 `json:"loadavg"`

	// Freq is the worker frequency use
	Freq float32 `json:"freq"`

	// SWIdentity is the software identity
	SWIdentity string `json:"sw_ident"`

	// Processed is the number of items processed
	Processed int `json:"processed, omitempt"`

	// Active is the active number of workers
	Active int `json:"active, omitempty"`
}

/*
NewWorkerEvent is a factory function to create a new WorkerEvent object
*/
func NewWorkerEvent() *WorkerEvent {
	return &WorkerEvent{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,

		SWSystem:    "",
		SWVersion:   "",
		LoadAverage: []float32{},
		Processed:   0,
		Active:      0,
		Freq:        0,
		SWIdentity:  "",
	}
}

/*
TaskEvent defines an event emitted by workers reponding to tasks. Event "types" emitted are:
	- "task-received"
	- "task-started"
	- "task-succeeded"
	- "task-failed"
	- "task-revoked"
	- "task-retried"

Example event json (Task received):
{
	"retries": 0,
	"args": "[]",
	"name": "workers.ingester.ingest",
	"clock": 59,
	"timestamp": 1463965647.276326,
	"expires": null,
	"pid": 10837,
	"utcoffset": -11,
	"eta": null,
	"kwargs": "{u'sourceUrl': u'https://www.google.com.au/search?q=nature&espv=2&biw=1216&bih=639&source=lnms&tbm=isch&sa=X&ved=0CAYQ_AUoAWoVChMIn-2Zma23yAIVyLqUCh3CdwBl'}",
	"type": "task-received",
	"hostname": "celery@My-Mac.local",
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba"
}

Example event json (Task started):
{
	"utcoffset": -11,
	"type": "task-started",
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba",
	"clock": 60,
	"timestamp": 1463965647.278163,
	"hostname": "celery@My-Mac.local",
	"pid": 10837
}

Example event json (Task succeeded):
{
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba",
	"clock": 61,
	"timestamp": 1463965647.282055,
	"hostname": "celery@My-Mac.local",
	"pid": 10837,
	"utcoffset": -11,
	"result": "\\"{'sourceUrl': u'https://www.google.com.au/search?q=nature&espv=2&biw=1216&bih=639&source=lnms&tbm=isch&sa=X&ved=0CAYQ_AUoAWoVChMIn-2Zma23yAIVyLqUCh3CdwBl', 'ingestCount': 23}\\"",
	"runtime": 0.004214855001919204,
	"type": "task-succeeded"
}
*/

/*
TaskEvent is the JSON schema for Celery task events
*/
type TaskEvent struct {
	Type      string  `json:"type"`
	Hostname  string  `json:"hostname"`
	Timestamp float32 `json:"timestamp"`
	PID       int     `json:"pid"`
	Clock     int     `json:"clock"`
	UTCOffset int     `json:"utcoffset"`

	// UUID is the id of the task
	UUID string `json:"uuid"`

	// Name is the textual name of the task executed
	Name string `json:"name, omitempty"`

	// Args is a string of the arguments passed to the task
	Args string `json:"args, omitempty"`

	// Kwargs is a string of the key-word arguments passed to the task
	Kwargs string `json:"kwargs, omitempty"`

	// Result is a string containing the result of a completed task
	Result string `json:"result, omitempty"`

	// Runtime is a ...
	Runtime float32 `json:"runtime, omitempty"`

	// Retries is the number of re-tries this task has performed
	Retries int `json:"retries, omitempty"`

	// ETA is the estimated time of completion
	ETA int `json:"eta, omitempty"`

	// Exception is a string containing error/exception information
	Exception string `json:"exception, omitempty"`

	// Traceback is a string containing extended error information
	Traceback string `json:"traceback, omitempty"`

	// Terminated is a flag indicating whether the task has been terminated
	Terminated bool `json:"terminated, omitempty"`

	// Signum is the sigal number
	Signum int `json:"signum, omitempty"`

	// Expired is a flag indicating whether the task has expired due to factors
	Expired bool `json:"expired, omitempty"`
}

/*
NewTaskEvent is a factory function to create a new TaskEvent object
*/
func NewTaskEvent() *TaskEvent {
	return &TaskEvent{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,

		UUID:       "",
		Name:       "",
		Args:       "",
		Result:     "",
		Runtime:    0,
		Retries:    0,
		ETA:        0,
		Exception:  "",
		Traceback:  "",
		Terminated: false,
		Signum:     0,
		Expired:    false,
	}
}
<commit_msg>Fixed error whereby Signum is returned from Celery as string or sometimes an int value. Added more example json from Celery events for when task revoked.<commit_after>package celeriac

import (
	"time"
)

/*
Event defines a base event emitted by Celery workers.
*/
type Event struct {
	// Type is the Celery event type. See supported events listed in "constants.go"
	Type string `json:"type"`

	// Hostname is the name of the host on which the Celery worker is operating
	Hostname string `json:"hostname"`

	// Timestamp is the current time of the event
	Timestamp float32 `json:"timestamp"`

	// PID is the process ID
	PID int `json:"pid"`

	// Clock is the current clock time
	Clock int `json:"clock"`

	// UTCOffset is the offset from UTC for the time when this event is valid
	UTCOffset int `json:"utcoffset"`
}

/*
NewEvent is a factory function to create a new Event object
*/
func NewEvent() *Event {
	return &Event{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,
	}
}

/*
TimestampFormatted returns a formatted string representation of the task event timestamp
*/
func (event *Event) TimestampFormatted() string {
	// First convert float64 to a time.Time
	dt := time.Unix(int64(event.Timestamp), 0)

	// Convert the timestamp to our own string representation
	return dt.UTC().Format(ConstTimeFormat)
}

/*
WorkerEvent defines an event emitted by workers, specific to its operation. Event "types" emitted are:
	- "worker-online"
	- "worker-offline"
	- "worker-heartbeat"

Example worker event json:
{
	"sw_sys": "Darwin",
	"clock": 74,
	"timestamp": 1843965659.580637,
	"hostname": "celery@Stefans-Mac.local",
	"pid": 10837,
	"sw_ver": "3.1.18",
	"utcoffset": -11,
	"loadavg": [2.0, 2.41, 2.54],
	"processed": 6,
	"active": 0,
	"freq": 2.0,
	"type": "worker-offline",
	"sw_ident": "py-celery"
}
*/
type WorkerEvent struct {
	Type      string  `json:"type"`
	Hostname  string  `json:"hostname"`
	Timestamp float32 `json:"timestamp"`
	PID       int     `json:"pid"`
	Clock     int     `json:"clock"`
	UTCOffset int     `json:"utcoffset"`

	// SWSystem is the software system being used
	SWSystem string `json:"sw_sys"`

	// SWVersion is the software version being used
	SWVersion string `json:"sw_ver"`

	// LoadAverage is an array of average CPU loadings for the worker
	LoadAverage []float32 `json:"loadavg"`

	// Freq is the worker frequency use
	Freq float32 `json:"freq"`

	// SWIdentity is the software identity
	SWIdentity string `json:"sw_ident"`

	// Processed is the number of items processed
	Processed int `json:"processed, omitempt"`

	// Active is the active number of workers
	Active int `json:"active, omitempty"`
}

/*
NewWorkerEvent is a factory function to create a new WorkerEvent object
*/
func NewWorkerEvent() *WorkerEvent {
	return &WorkerEvent{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,

		SWSystem:    "",
		SWVersion:   "",
		LoadAverage: []float32{},
		Processed:   0,
		Active:      0,
		Freq:        0,
		SWIdentity:  "",
	}
}

/*
TaskEvent defines an event emitted by workers reponding to tasks. Event "types" emitted are:
	- "task-received"
	- "task-started"
	- "task-succeeded"
	- "task-failed"
	- "task-revoked"
	- "task-retried"

Example event json (Task received):
{
	"retries": 0,
	"args": "[]",
	"name": "workers.ingester.ingest",
	"clock": 59,
	"timestamp": 1463965647.276326,
	"expires": null,
	"pid": 10837,
	"utcoffset": -11,
	"eta": null,
	"kwargs": "{u'sourceUrl': u'https://www.google.com.au/search?q=nature&espv=2&biw=1216&bih=639&source=lnms&tbm=isch&sa=X&ved=0CAYQ_AUoAWoVChMIn-2Zma23yAIVyLqUCh3CdwBl'}",
	"type": "task-received",
	"hostname": "celery@worker1.My-Mac.local",
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba"
}

Example event json (Task started):
{
	"utcoffset": -11,
	"type": "task-started",
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba",
	"clock": 60,
	"timestamp": 1463965647.278163,
	"hostname": "celery@worker1.My-Mac.local",
	"pid": 10837
}

Example event json (Task succeeded):
{
	"uuid": "8e42b71d-175b-47c1-52e8-0f2e82ddd9ba",
	"clock": 61,
	"timestamp": 1463965647.282055,
	"hostname": "celery@worker1.My-Mac.local",
	"pid": 10837,
	"utcoffset": -11,
	"result": "\\"{'sourceUrl': u'https://www.google.com.au/search?q=nature&espv=2&biw=1216&bih=639&source=lnms&tbm=isch&sa=X&ved=0CAYQ_AUoAWoVChMIn-2Zma23yAIVyLqUCh3CdwBl', 'ingestCount': 23}\\"",
	"runtime": 0.004214855001919204,
	"type": "task-succeeded"
}

Example event json (Task revoked):
NOTE: It appears that "signum" is sometimes returned as a string and sometimes as an integer!!
{
	"type": "task-revoked",
	"uuid": "9e4c1cf3-6b66-482e-5145-0eb4d12f91ab",
	"clock": 1549,
	"timestamp": 1444938011.962136,
	"hostname": "celery@worker1.My-Mac.local",
	"pid": 46221,
	"utcoffset": -11,

	"terminated": true,
	"signum": "15",
	"expired": false
}

{
	"terminated": true,
	"type": "task-revoked",
	"uuid": "9e4c1cf3-6b66-482e-5145-0eb4d12f91ab",
	"clock": 1550,
	"timestamp": 1444938011.978788,
	"hostname": "celery@worker1.My-Mac.local",
	"pid": 46221,
	"utcoffset": -11,
	"signum": 15,
	"expired": false
}

*/

/*
TaskEvent is the JSON schema for Celery task events
*/
type TaskEvent struct {
	Type      string  `json:"type"`
	Hostname  string  `json:"hostname"`
	Timestamp float32 `json:"timestamp"`
	PID       int     `json:"pid"`
	Clock     int     `json:"clock"`
	UTCOffset int     `json:"utcoffset"`

	// UUID is the id of the task
	UUID string `json:"uuid"`

	// Name is the textual name of the task executed
	Name string `json:"name, omitempty"`

	// Args is a string of the arguments passed to the task
	Args string `json:"args, omitempty"`

	// Kwargs is a string of the key-word arguments passed to the task
	Kwargs string `json:"kwargs, omitempty"`

	// Result is a string containing the result of a completed task
	Result string `json:"result, omitempty"`

	// Runtime is a ...
	Runtime float32 `json:"runtime, omitempty"`

	// Retries is the number of re-tries this task has performed
	Retries int `json:"retries, omitempty"`

	// ETA is the estimated time of completion
	ETA int `json:"eta, omitempty"`

	// Exception is a string containing error/exception information
	Exception string `json:"exception, omitempty"`

	// Traceback is a string containing extended error information
	Traceback string `json:"traceback, omitempty"`

	// Terminated is a flag indicating whether the task has been terminated
	Terminated bool `json:"terminated, omitempty"`

	// Signum is the signal number
	Signum interface{} `json:"signum, omitempty"`

	// Expired is a flag indicating whether the task has expired due to factors
	Expired bool `json:"expired, omitempty"`
}

/*
NewTaskEvent is a factory function to create a new TaskEvent object
*/
func NewTaskEvent() *TaskEvent {
	return &TaskEvent{
		Type:      "",
		Hostname:  "",
		Timestamp: 0,
		PID:       0,
		Clock:     0,
		UTCOffset: 0,

		UUID:       "",
		Name:       "",
		Args:       "",
		Result:     "",
		Runtime:    0,
		Retries:    0,
		ETA:        0,
		Exception:  "",
		Traceback:  "",
		Terminated: false,
		Signum:     "",
		Expired:    false,
	}
}
<|endoftext|>


<commit_before>package main

import "net"
import "fmt"
import "bufio"
import "strings" // only needed below for sample processing

func main() {

	fmt.Println("Launching server...")

	// listen on all interfaces
	ln, _ := net.Listen("tcp", ":8081")

	// accept connection on port
	conn, _ := ln.Accept()

	// run loop forever (or until ctrl-c)
	for {
		// will listen for message to process ending in newline (\n)
		message, err := bufio.NewReader(conn).ReadString('\n')

		// exit if any exception occurs
		if err != nil {
			break
		}
		// output message received
		fmt.Print("Message Received:", string(message))

		// sample process for string received
		newmessage := strings.ToUpper(message)

		// send new string back to client
		conn.Write([]byte(newmessage + "\n"))
	}
}
<commit_msg>handling exception reading and supporting multiple connections<commit_after>package main

import "net"
import "fmt"
import "bufio"
import "strings" // only needed below for sample processing
import "log"

func handleConnection(conn net.Conn){
   for {
      // will listen for message to process ending in newline (\n)
      message, err := bufio.NewReader(conn).ReadString('\n')
      if err != nil{ break }
      // output message received
      fmt.Print("Message Received:", string(message))

      // sample process for string received
      newmessage := strings.ToUpper(message)

      // send new string back to client
      conn.Write([]byte(newmessage + "\n"))
   }
}

func main() {

   fmt.Println("Launching server...")

   // listen on all interfaces
   ln, _ := net.Listen("tcp", ":8081")

   // run loop forever (or until ctrl-c)
   for {
      // accept connection on port
      conn, err := ln.Accept()
      if err != nil{ log.Fatal(err); break }
      go handleConnection(conn)
   }
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
)

// DELETEs the blob
func blobDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}

	err := os.Remove(blobPath)
	if err != nil && os.IsNotExist(err) {
		http.Error(w, "File Not Found", 404)
		return
	} else if err != nil {
		panic(err)
	}

	http.Error(w, "Accepted", 202)
}

// GETs the blob
func blobGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}

	blobData, err := ioutil.ReadFile(blobPath)
	if err != nil && os.IsNotExist(err) {
		http.Error(w, "File Not Found", 404)
		return
	} else if err != nil {
		panic(err)
	}
	defer r.Body.Close()

	if r.Form.Get("rscd") != "" {
		w.Header().Set("Content-Disposition", r.Form.Get("rscd"))
	}

	w.Write(blobData)
}

// Handles a PUT on a blob (creates the blob, block, or commits the block list)
func blobPut(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	blobUncommittedPath := filepath.Join(blobBase, container, "uncommitted", blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}
	if filepath.Clean(blobUncommittedPath) != blobUncommittedPath {
		log.Printf("Bad path %s", blobUncommittedPath)
		http.Error(w, "Bad Request", 400)
	}

	blobData, err := ioutil.ReadAll(r.Body)
	check(err)
	defer r.Body.Close()

	comp := r.FormValue("comp")
	if comp == "block" {
		blockid := r.FormValue("blockid")
		blockPath := blobUncommittedPath + "_" + blockid

		if filepath.Clean(blockPath) != blockPath {
			log.Printf("Bad path %s", blockPath)
			http.Error(w, "Bad Request", 400)
			return
		}

		err = ioutil.WriteFile(blockPath, blobData, 0777)
		check(err)

		http.Error(w, "Created", 201)
	} else if comp == "blocklist" {
		list := BlobBlockListResponse{}
		err := xml.Unmarshal(blobData, &list)
		if err != nil {
			log.Println("Bad block list")
			http.Error(w, "Bad Request", 400)
			return
		}

		file, err := os.Create(blobPath)
		check(err)
		defer file.Close()
		for _, blockId := range list.Blocks {
			blockPath := blobUncommittedPath + "_" + blockId
			blockData, err := ioutil.ReadFile(blockPath)
			check(err)
			os.Remove(blockPath)
			_, err = file.Write(blockData)
			check(err)
		}

		http.Error(w, "Created", 201)
	} else {
		log.Println("PUT-ing a blob directly is not supported")
		http.Error(w, "Internal Server Error", 500)
	}
}

// Handles a GET on a container (lists blobs)
func blobContainerGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	prefix := r.FormValue("prefix")

	containerPath := filepath.Join(blobBase, container)
	if filepath.Clean(containerPath) != containerPath {
		log.Printf("Bad path %s", containerPath)
		http.Error(w, "Bad Request", 400)
		return
	}

	blobs := []BlobResult{}
	containerInfo, err := ioutil.ReadDir(containerPath)
	check(err)

	for _, file := range containerInfo {
		if !file.IsDir() {
			if prefix != "" && !strings.HasPrefix(file.Name(), prefix) {
				continue
			}
			blobs = append(blobs, BlobResult{
				Name:     file.Name(),
				Snapshot: time.Now(),
				Properties: BlobPropertiesResult{
					LastModified:          TimeRFC1123(file.ModTime()),
					Etag:                  "",
					ContentMD5:            "",
					ContentLength:         file.Size(),
					ContentType:           "",
					ContentEncoding:       "",
					CacheControl:          "",
					ContentLanguage:       "",
					ContentDisposition:    "",
					BlobType:              BlobTypeBlock,
					SequenceNumber:        0,
					CopyID:                "",
					CopyStatus:            "",
					CopySource:            "",
					CopyProgress:          "",
					CopyCompletionTime:    TimeRFC1123(time.Now()),
					CopyStatusDescription: "",
					LeaseStatus:           "",
					LeaseState:            "",
					LeaseDuration:         "",
					ServerEncrypted:       false,
					IncrementalCopy:       false,
				},
				Metadata: "",
			})
		}
	}

	err = writeXML(w, BlobEnumerationResults{
		xml.Name{},
		"",
		"",
		0,
		"",
		blobs,
		"",
	})
	check(err)
}

// Handles a PUT on a container (creates the container)
func blobContainerPut(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	restype := r.FormValue("restype")
	container := ps.ByName("container")

	if restype == "container" {
		containerPath := filepath.Join(blobBase, container)
		if filepath.Clean(containerPath) != containerPath {
			log.Printf("Bad path %s", containerPath)
			http.Error(w, "Bad Request", 400)
			return
		}
		containerUncommittedPath := filepath.Join(containerPath, "uncommitted")
		_, err := os.Stat(containerPath)
		if err != nil {
			err = os.Mkdir(containerPath, 0777)
			check(err)
			err = os.Mkdir(containerUncommittedPath, 0777)
			check(err)
			http.Error(w, "Created", 201)
		} else {
			http.Error(w, "The specified container already exists.", 409)
			writeXML(w, BlobErrorResponse{
				Code:    "ContainerAlreadyExists",
				Message: "The specified container already exists.",
			})
		}
	} else {
		http.Error(w, "Bad Request", 400)
	}
}
<commit_msg>support PUT-ing a blob directly<commit_after>package main

import (
	"encoding/xml"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/julienschmidt/httprouter"
)

// DELETEs the blob
func blobDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}

	err := os.Remove(blobPath)
	if err != nil && os.IsNotExist(err) {
		http.Error(w, "File Not Found", 404)
		return
	} else if err != nil {
		panic(err)
	}

	http.Error(w, "Accepted", 202)
}

// GETs the blob
func blobGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}

	blobData, err := ioutil.ReadFile(blobPath)
	if err != nil && os.IsNotExist(err) {
		http.Error(w, "File Not Found", 404)
		return
	} else if err != nil {
		panic(err)
	}
	defer r.Body.Close()

	if r.Form.Get("rscd") != "" {
		w.Header().Set("Content-Disposition", r.Form.Get("rscd"))
	}

	w.Write(blobData)
}

// Handles a PUT on a blob (creates the blob, block, or commits the block list)
func blobPut(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	blob := ps.ByName("blob")
	blobPath := filepath.Join(blobBase, container, blob)
	blobUncommittedPath := filepath.Join(blobBase, container, "uncommitted", blob)
	if filepath.Clean(blobPath) != blobPath {
		log.Printf("Bad path %s", blobPath)
		http.Error(w, "Bad Request", 400)
	}
	if filepath.Clean(blobUncommittedPath) != blobUncommittedPath {
		log.Printf("Bad path %s", blobUncommittedPath)
		http.Error(w, "Bad Request", 400)
	}

	blobData, err := ioutil.ReadAll(r.Body)
	check(err)
	defer r.Body.Close()

	comp := r.FormValue("comp")
	if comp == "block" {
		blockid := r.FormValue("blockid")
		blockPath := blobUncommittedPath + "_" + blockid

		if filepath.Clean(blockPath) != blockPath {
			log.Printf("Bad path %s", blockPath)
			http.Error(w, "Bad Request", 400)
			return
		}

		err = ioutil.WriteFile(blockPath, blobData, 0777)
		check(err)

		http.Error(w, "Created", 201)
	} else if comp == "blocklist" {
		list := BlobBlockListResponse{}
		err := xml.Unmarshal(blobData, &list)
		if err != nil {
			log.Println("Bad block list")
			http.Error(w, "Bad Request", 400)
			return
		}

		file, err := os.Create(blobPath)
		check(err)
		defer file.Close()
		for _, blockId := range list.Blocks {
			blockPath := blobUncommittedPath + "_" + blockId
			blockData, err := ioutil.ReadFile(blockPath)
			check(err)
			os.Remove(blockPath)
			_, err = file.Write(blockData)
			check(err)
		}

		http.Error(w, "Created", 201)
	} else {
		err = ioutil.WriteFile(blobPath, blobData, 0777)
		check(err)

		http.Error(w, "Created", 201)
	}
}

// Handles a GET on a container (lists blobs)
func blobContainerGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	container := ps.ByName("container")
	prefix := r.FormValue("prefix")

	containerPath := filepath.Join(blobBase, container)
	if filepath.Clean(containerPath) != containerPath {
		log.Printf("Bad path %s", containerPath)
		http.Error(w, "Bad Request", 400)
		return
	}

	blobs := []BlobResult{}
	containerInfo, err := ioutil.ReadDir(containerPath)
	check(err)

	for _, file := range containerInfo {
		if !file.IsDir() {
			if prefix != "" && !strings.HasPrefix(file.Name(), prefix) {
				continue
			}
			blobs = append(blobs, BlobResult{
				Name:     file.Name(),
				Snapshot: time.Now(),
				Properties: BlobPropertiesResult{
					LastModified:          TimeRFC1123(file.ModTime()),
					Etag:                  "",
					ContentMD5:            "",
					ContentLength:         file.Size(),
					ContentType:           "",
					ContentEncoding:       "",
					CacheControl:          "",
					ContentLanguage:       "",
					ContentDisposition:    "",
					BlobType:              BlobTypeBlock,
					SequenceNumber:        0,
					CopyID:                "",
					CopyStatus:            "",
					CopySource:            "",
					CopyProgress:          "",
					CopyCompletionTime:    TimeRFC1123(time.Now()),
					CopyStatusDescription: "",
					LeaseStatus:           "",
					LeaseState:            "",
					LeaseDuration:         "",
					ServerEncrypted:       false,
					IncrementalCopy:       false,
				},
				Metadata: "",
			})
		}
	}

	err = writeXML(w, BlobEnumerationResults{
		xml.Name{},
		"",
		"",
		0,
		"",
		blobs,
		"",
	})
	check(err)
}

// Handles a PUT on a container (creates the container)
func blobContainerPut(w http.ResponseWriter, r *http.Request, ps httprouter.Params, c BlobRequestContext) {
	restype := r.FormValue("restype")
	container := ps.ByName("container")

	if restype == "container" {
		containerPath := filepath.Join(blobBase, container)
		if filepath.Clean(containerPath) != containerPath {
			log.Printf("Bad path %s", containerPath)
			http.Error(w, "Bad Request", 400)
			return
		}
		containerUncommittedPath := filepath.Join(containerPath, "uncommitted")
		_, err := os.Stat(containerPath)
		if err != nil {
			err = os.Mkdir(containerPath, 0777)
			check(err)
			err = os.Mkdir(containerUncommittedPath, 0777)
			check(err)
			http.Error(w, "Created", 201)
		} else {
			http.Error(w, "The specified container already exists.", 409)
			writeXML(w, BlobErrorResponse{
				Code:    "ContainerAlreadyExists",
				Message: "The specified container already exists.",
			})
		}
	} else {
		http.Error(w, "Bad Request", 400)
	}
}
<|endoftext|>


<commit_before>// Copyright 2012 tsuru 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 fs provides types and methods for interacting with the filesystem,
// as an abstraction layer.
//
// It provides an implementation that uses the operating system filesystem, and
// an interface that should be implemented if you want to provide your own
// filesystem.
package fs

import (
	"io"
	"os"
)

// File represents a file in the filesystem.
type File interface {
	io.Closer
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Writer
	Stat() (os.FileInfo, error)
	WriteString(s string) (ret int, err error)
	Truncate(size int64) error
}

// Fs is the filesystem interface.
//
// Any simulated or real filesystem should implement this interface.
type Fs interface {
	// Create creates a file in the filesystem, returning the file and an
	// error, if any happens.
	Create(name string) (File, error)

	// Mkdir creates a directory in the filesystem, return an error if any
	// happens.
	Mkdir(name string, perm os.FileMode) error

	// MkdirAll creates a directory path and all parents that does not exist
	// yet.
	MkdirAll(path string, perm os.FileMode) error

	// Open opens a file, returning it or an error, if any happens.
	Open(name string) (File, error)

	// OpenFile opens a file using the given flags and the given mode.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)

	// Remove removes a file identified by name, returning an error, if any
	// happens.
	Remove(name string) error

	// RemoveAll removes a directory path and all any children it contains. It
	// does not fail if the path does not exist (return nil).
	RemoveAll(path string) error

	// Stat returns a FileInfo describing the named file, or an error, if any
	// happens.
	Stat(name string) (os.FileInfo, error)
}

// OsFs is a Fs implementation that uses functions provided by the os package.
//
// For details in any method, check the documentation of the os package
// (http://golang.org/pkg/os/).
type OsFs struct{}

func (fs OsFs) Create(name string) (File, error) {
	return os.Create(name)
}

func (fs OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

func (fs OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

func (fs OsFs) Open(name string) (File, error) {
	return os.Open(name)
}

func (fs OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
	return os.OpenFile(name, flag, perm)
}

func (fs OsFs) Remove(name string) error {
	return os.Remove(name)
}

func (fs OsFs) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

func (fs OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}
<commit_msg>fs: added Fd method to the File interface<commit_after>// Copyright 2012 tsuru 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 fs provides types and methods for interacting with the filesystem,
// as an abstraction layer.
//
// It provides an implementation that uses the operating system filesystem, and
// an interface that should be implemented if you want to provide your own
// filesystem.
package fs

import (
	"io"
	"os"
)

// File represents a file in the filesystem.
type File interface {
	io.Closer
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Writer
	Fd() uintptr
	Stat() (os.FileInfo, error)
	WriteString(s string) (ret int, err error)
	Truncate(size int64) error
}

// Fs is the filesystem interface.
//
// Any simulated or real filesystem should implement this interface.
type Fs interface {
	// Create creates a file in the filesystem, returning the file and an
	// error, if any happens.
	Create(name string) (File, error)

	// Mkdir creates a directory in the filesystem, return an error if any
	// happens.
	Mkdir(name string, perm os.FileMode) error

	// MkdirAll creates a directory path and all parents that does not exist
	// yet.
	MkdirAll(path string, perm os.FileMode) error

	// Open opens a file, returning it or an error, if any happens.
	Open(name string) (File, error)

	// OpenFile opens a file using the given flags and the given mode.
	OpenFile(name string, flag int, perm os.FileMode) (File, error)

	// Remove removes a file identified by name, returning an error, if any
	// happens.
	Remove(name string) error

	// RemoveAll removes a directory path and all any children it contains. It
	// does not fail if the path does not exist (return nil).
	RemoveAll(path string) error

	// Stat returns a FileInfo describing the named file, or an error, if any
	// happens.
	Stat(name string) (os.FileInfo, error)
}

// OsFs is a Fs implementation that uses functions provided by the os package.
//
// For details in any method, check the documentation of the os package
// (http://golang.org/pkg/os/).
type OsFs struct{}

func (fs OsFs) Create(name string) (File, error) {
	return os.Create(name)
}

func (fs OsFs) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

func (fs OsFs) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

func (fs OsFs) Open(name string) (File, error) {
	return os.Open(name)
}

func (fs OsFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
	return os.OpenFile(name, flag, perm)
}

func (fs OsFs) Remove(name string) error {
	return os.Remove(name)
}

func (fs OsFs) RemoveAll(path string) error {
	return os.RemoveAll(path)
}

func (fs OsFs) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}
<|endoftext|>