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

package gitlab

import (
	"fmt"
	"net/url"
	"time"
)

// MilestonesService handles communication with the milestone related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/milestones.html
type MilestonesService struct {
	client *Client
}

// Milestone represents a GitLab milestone.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/branches.html
type Milestone struct {
	ID          int        `json:"id"`
	Iid         int        `json:"iid"`
	ProjectID   int        `json:"project_id"`
	Title       string     `json:"title"`
	Description string     `json:"description"`
	DueDate     string     `json:"due_date"`
	State       string     `json:"state"`
	UpdatedAt   *time.Time `json:"updated_at"`
	CreatedAt   *time.Time `json:"created_at"`
}

func (m Milestone) String() string {
	return Stringify(m)
}

// ListMilestonesOptions represents the available ListMilestones() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
type ListMilestonesOptions struct {
	ListOptions
	IID *int `url:"iid,omitempty" json:"iid,omitempty"`
}

// ListMilestones returns a list of project milestones.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
func (s *MilestonesService) ListMilestones(
	pid interface{},
	opt *ListMilestonesOptions) ([]*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))

	req, err := s.client.NewRequest("GET", u, opt)
	if err != nil {
		return nil, nil, err
	}

	var m []*Milestone
	resp, err := s.client.Do(req, &m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// GetMilestone gets a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-single-milestone
func (s *MilestonesService) GetMilestone(
	pid interface{},
	milestone int) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// CreateMilestoneOptions represents the available CreateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
type CreateMilestoneOptions struct {
	Title       *string `url:"title,omitempty" json:"title,omitempty"`
	Description *string `url:"description,omitempty" json:"description,omitempty"`
	DueDate     *string `url:"due_date,omitempty" json:"due_date,omitempty"`
}

// CreateMilestone creates a new project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
func (s *MilestonesService) CreateMilestone(
	pid interface{},
	opt *CreateMilestoneOptions) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))

	req, err := s.client.NewRequest("POST", u, opt)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// UpdateMilestoneOptions represents the available UpdateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
type UpdateMilestoneOptions struct {
	Title       *string `url:"title,omitempty" json:"title,omitempty"`
	Description *string `url:"description,omitempty" json:"description,omitempty"`
	DueDate     *string `url:"due_date,omitempty" json:"due_date,omitempty"`
	StateEvent  *string `url:"state_event,omitempty" json:"state_event,omitempty"`
}

// UpdateMilestone updates an existing project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
func (s *MilestonesService) UpdateMilestone(
	pid interface{},
	milestone int,
	opt *UpdateMilestoneOptions) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
type GetMilestoneIssuesOptions struct {
	ListOptions
}

// GetMilestoneIssues gets all issues assigned to a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
func (s *MilestonesService) GetMilestoneIssues(
	pid interface{},
	milestone int,
	opt *GetMilestoneIssuesOptions) ([]*Issue, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d/issues", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("GET", u, opt)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue
	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<commit_msg>Add missing milestone parameter gitlab.Milestone.StartDate (#94)<commit_after>//
// Copyright 2015, Sander van Harmelen
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package gitlab

import (
	"fmt"
	"net/url"
	"time"
)

// MilestonesService handles communication with the milestone related methods
// of the GitLab API.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/milestones.html
type MilestonesService struct {
	client *Client
}

// Milestone represents a GitLab milestone.
//
// GitLab API docs: http://doc.gitlab.com/ce/api/milestones.html
type Milestone struct {
	ID          int        `json:"id"`
	Iid         int        `json:"iid"`
	ProjectID   int        `json:"project_id"`
	Title       string     `json:"title"`
	Description string     `json:"description"`
	StartDate   string     `json:"start_date"`
	DueDate     string     `json:"due_date"`
	State       string     `json:"state"`
	UpdatedAt   *time.Time `json:"updated_at"`
	CreatedAt   *time.Time `json:"created_at"`
}

func (m Milestone) String() string {
	return Stringify(m)
}

// ListMilestonesOptions represents the available ListMilestones() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
type ListMilestonesOptions struct {
	ListOptions
	IID *int `url:"iid,omitempty" json:"iid,omitempty"`
}

// ListMilestones returns a list of project milestones.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#list-project-milestones
func (s *MilestonesService) ListMilestones(
	pid interface{},
	opt *ListMilestonesOptions) ([]*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))

	req, err := s.client.NewRequest("GET", u, opt)
	if err != nil {
		return nil, nil, err
	}

	var m []*Milestone
	resp, err := s.client.Do(req, &m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// GetMilestone gets a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-single-milestone
func (s *MilestonesService) GetMilestone(
	pid interface{},
	milestone int) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// CreateMilestoneOptions represents the available CreateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
type CreateMilestoneOptions struct {
	Title       *string `url:"title,omitempty" json:"title,omitempty"`
	Description *string `url:"description,omitempty" json:"description,omitempty"`
	StartDate   *string `url:"start_date,omitempty" json:"start_date,omitempty"`
	DueDate     *string `url:"due_date,omitempty" json:"due_date,omitempty"`
}

// CreateMilestone creates a new project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#create-new-milestone
func (s *MilestonesService) CreateMilestone(
	pid interface{},
	opt *CreateMilestoneOptions) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones", url.QueryEscape(project))

	req, err := s.client.NewRequest("POST", u, opt)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// UpdateMilestoneOptions represents the available UpdateMilestone() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
type UpdateMilestoneOptions struct {
	Title       *string `url:"title,omitempty" json:"title,omitempty"`
	Description *string `url:"description,omitempty" json:"description,omitempty"`
	StartDate   *string `url:"start_date,omitempty" json:"start_date,omitempty"`
	DueDate     *string `url:"due_date,omitempty" json:"due_date,omitempty"`
	StateEvent  *string `url:"state_event,omitempty" json:"state_event,omitempty"`
}

// UpdateMilestone updates an existing project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#edit-milestone
func (s *MilestonesService) UpdateMilestone(
	pid interface{},
	milestone int,
	opt *UpdateMilestoneOptions) (*Milestone, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("PUT", u, opt)
	if err != nil {
		return nil, nil, err
	}

	m := new(Milestone)
	resp, err := s.client.Do(req, m)
	if err != nil {
		return nil, resp, err
	}

	return m, resp, err
}

// GetMilestoneIssuesOptions represents the available GetMilestoneIssues() options.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
type GetMilestoneIssuesOptions struct {
	ListOptions
}

// GetMilestoneIssues gets all issues assigned to a single project milestone.
//
// GitLab API docs:
// http://doc.gitlab.com/ce/api/milestones.html#get-all-issues-assigned-to-a-single-milestone
func (s *MilestonesService) GetMilestoneIssues(
	pid interface{},
	milestone int,
	opt *GetMilestoneIssuesOptions) ([]*Issue, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/milestones/%d/issues", url.QueryEscape(project), milestone)

	req, err := s.client.NewRequest("GET", u, opt)
	if err != nil {
		return nil, nil, err
	}

	var i []*Issue
	resp, err := s.client.Do(req, &i)
	if err != nil {
		return nil, resp, err
	}

	return i, resp, err
}
<|endoftext|>


<commit_before>package api

import (
	"context"
	"fmt"
	"net/http"
	"regexp"
	"strings"

	"github.com/go-chi/chi"
	"github.com/netlify/gotrue/api/provider"
	"github.com/netlify/gotrue/conf"
	"github.com/netlify/gotrue/mailer"
	"github.com/netlify/gotrue/storage"
	"github.com/netlify/gotrue/storage/dial"
	"github.com/netlify/netlify-commons/graceful"
	"github.com/rs/cors"
	"github.com/sebest/xff"
	"github.com/sirupsen/logrus"
)

const (
	audHeaderName  = "X-JWT-AUD"
	defaultVersion = "unknown version"
)

var bearerRegexp = regexp.MustCompile(`^(?:B|b)earer (\S+$)`)

// API is the main REST API
type API struct {
	handler http.Handler
	db      storage.Connection
	config  *conf.GlobalConfiguration
	version string
}

// ListenAndServe starts the REST API
func (a *API) ListenAndServe(hostAndPort string) {
	log := logrus.WithField("component", "api")
	server := graceful.NewGracefulServer(a.handler, log)
	if err := server.Bind(hostAndPort); err != nil {
		log.WithError(err).Fatal("http server bind failed")
	}

	if err := server.Listen(); err != nil {
		log.WithError(err).Fatal("http server listen failed")
	}
}

// NewAPI instantiates a new REST API
func NewAPI(globalConfig *conf.GlobalConfiguration, db storage.Connection) *API {
	return NewAPIWithVersion(context.Background(), globalConfig, db, defaultVersion)
}

// NewAPIWithVersion creates a new REST API using the specified version
func NewAPIWithVersion(ctx context.Context, globalConfig *conf.GlobalConfiguration, db storage.Connection, version string) *API {
	api := &API{config: globalConfig, db: db, version: version}

	xffmw, _ := xff.Default()

	r := newRouter()
	r.UseBypass(xffmw.Handler)
	r.Use(addRequestID)
	r.UseBypass(newStructuredLogger(logrus.StandardLogger()))
	r.Use(recoverer)

	r.Get("/health", api.HealthCheck)

	r.Route("/", func(r *router) {
		if globalConfig.MultiInstanceMode {
			r.Use(api.loadInstanceConfig)
		}

		r.Post("/signup", api.Signup)
		r.Post("/invite", api.Invite)
		r.Post("/recover", api.Recover)
		r.Post("/verify", api.Verify)
		r.Post("/token", api.Token)
		r.With(api.requireAuthentication).Post("/logout", api.Logout)

		r.Route("/user", func(r *router) {
			r.Use(api.requireAuthentication)
			r.Get("/", api.UserGet)
			r.Put("/", api.UserUpdate)
		})

		r.Route("/admin", func(r *router) {
			r.Use(addGetBody)
			r.Use(api.requireAuthentication)
			r.Use(api.requireAdmin)

			r.Get("/users", api.adminUsers)

			r.Post("/user", api.adminUserCreate)
			r.Get("/user", api.adminUserGet)
			r.Put("/user", api.adminUserUpdate)
			r.Delete("/user", api.adminUserDelete)
		})
	})

	if globalConfig.MultiInstanceMode {
		// Netlify microservice API
		r.With(api.verifyNetlifyRequest).Get("/", api.GetAppManifest)
		r.Route("/instances", func(r *router) {
			r.Use(api.verifyNetlifyRequest)

			r.Post("/", api.CreateInstance)
			r.Route("/{instance_id}", func(r *router) {
				r.With(api.loadInstance)

				r.Get("/", api.GetInstance)
				r.Put("/", api.UpdateInstance)
				r.Delete("/", api.DeleteInstance)
			})
		})
	}

	corsHandler := cors.New(cors.Options{
		AllowedMethods:   []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete},
		AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", audHeaderName},
		AllowCredentials: true,
	})

	api.handler = corsHandler.Handler(chi.ServerBaseContext(r, ctx))
	return api
}

// NewAPIFromConfigFile creates a new REST API using the provided configuration file.
func NewAPIFromConfigFile(filename string, version string) (*API, error) {
	globalConfig, err := conf.LoadGlobalFromFile(filename)
	if err != nil {
		return nil, err
	}
	config, err := conf.LoadConfigFromFile(filename)
	if err != nil {
		return nil, err
	}

	db, err := dial.Dial(globalConfig)
	if err != nil {
		return nil, err
	}

	if globalConfig.DB.Automigrate {
		if err := db.Automigrate(); err != nil {
			return nil, err
		}
	}

	ctx, err := WithInstanceConfig(context.Background(), config, "")
	if err != nil {
		logrus.Fatalf("Error loading instance config: %+v", err)
	}

	return NewAPIWithVersion(ctx, globalConfig, db, version), nil
}

func (a *API) HealthCheck(w http.ResponseWriter, r *http.Request) error {
	return sendJSON(w, http.StatusOK, map[string]string{
		"version":     a.version,
		"name":        "GoTrue",
		"description": "GoTrue is a user registration and authentication API",
	})
}

// Provider returns a Provider interface for the given name.
func (a *API) Provider(ctx context.Context, name string) (provider.Provider, error) {
	config := getConfig(ctx)
	name = strings.ToLower(name)

	switch name {
	case "github":
		return provider.NewGithubProvider(config.External.Github), nil
	case "bitbucket":
		return provider.NewBitbucketProvider(config.External.Bitbucket), nil
	case "gitlab":
		return provider.NewGitlabProvider(config.External.Gitlab), nil
	default:
		return nil, fmt.Errorf("Provider %s could not be found", name)
	}
}

func WithInstanceConfig(ctx context.Context, config *conf.Configuration, instanceID string) (context.Context, error) {
	ctx = withConfig(ctx, config)

	mailer := mailer.NewMailer(config)
	ctx = withMailer(ctx, mailer)
	ctx = withInstanceID(ctx, instanceID)

	return ctx, nil
}
<commit_msg>Attempt DB connection three times on startup<commit_after>package api

import (
	"context"
	"fmt"
	"net/http"
	"regexp"
	"strings"
	"time"

	"github.com/go-chi/chi"
	"github.com/netlify/gotrue/api/provider"
	"github.com/netlify/gotrue/conf"
	"github.com/netlify/gotrue/mailer"
	"github.com/netlify/gotrue/storage"
	"github.com/netlify/gotrue/storage/dial"
	"github.com/netlify/netlify-commons/graceful"
	"github.com/rs/cors"
	"github.com/sebest/xff"
	"github.com/sirupsen/logrus"
)

const (
	audHeaderName  = "X-JWT-AUD"
	defaultVersion = "unknown version"
)

var bearerRegexp = regexp.MustCompile(`^(?:B|b)earer (\S+$)`)

// API is the main REST API
type API struct {
	handler http.Handler
	db      storage.Connection
	config  *conf.GlobalConfiguration
	version string
}

// ListenAndServe starts the REST API
func (a *API) ListenAndServe(hostAndPort string) {
	log := logrus.WithField("component", "api")
	server := graceful.NewGracefulServer(a.handler, log)
	if err := server.Bind(hostAndPort); err != nil {
		log.WithError(err).Fatal("http server bind failed")
	}

	if err := server.Listen(); err != nil {
		log.WithError(err).Fatal("http server listen failed")
	}
}

// NewAPI instantiates a new REST API
func NewAPI(globalConfig *conf.GlobalConfiguration, db storage.Connection) *API {
	return NewAPIWithVersion(context.Background(), globalConfig, db, defaultVersion)
}

// NewAPIWithVersion creates a new REST API using the specified version
func NewAPIWithVersion(ctx context.Context, globalConfig *conf.GlobalConfiguration, db storage.Connection, version string) *API {
	api := &API{config: globalConfig, db: db, version: version}

	xffmw, _ := xff.Default()

	r := newRouter()
	r.UseBypass(xffmw.Handler)
	r.Use(addRequestID)
	r.UseBypass(newStructuredLogger(logrus.StandardLogger()))
	r.Use(recoverer)

	r.Get("/health", api.HealthCheck)

	r.Route("/", func(r *router) {
		if globalConfig.MultiInstanceMode {
			r.Use(api.loadInstanceConfig)
		}

		r.Post("/signup", api.Signup)
		r.Post("/invite", api.Invite)
		r.Post("/recover", api.Recover)
		r.Post("/verify", api.Verify)
		r.Post("/token", api.Token)
		r.With(api.requireAuthentication).Post("/logout", api.Logout)

		r.Route("/user", func(r *router) {
			r.Use(api.requireAuthentication)
			r.Get("/", api.UserGet)
			r.Put("/", api.UserUpdate)
		})

		r.Route("/admin", func(r *router) {
			r.Use(addGetBody)
			r.Use(api.requireAuthentication)
			r.Use(api.requireAdmin)

			r.Get("/users", api.adminUsers)

			r.Post("/user", api.adminUserCreate)
			r.Get("/user", api.adminUserGet)
			r.Put("/user", api.adminUserUpdate)
			r.Delete("/user", api.adminUserDelete)
		})
	})

	if globalConfig.MultiInstanceMode {
		// Netlify microservice API
		r.With(api.verifyNetlifyRequest).Get("/", api.GetAppManifest)
		r.Route("/instances", func(r *router) {
			r.Use(api.verifyNetlifyRequest)

			r.Post("/", api.CreateInstance)
			r.Route("/{instance_id}", func(r *router) {
				r.With(api.loadInstance)

				r.Get("/", api.GetInstance)
				r.Put("/", api.UpdateInstance)
				r.Delete("/", api.DeleteInstance)
			})
		})
	}

	corsHandler := cors.New(cors.Options{
		AllowedMethods:   []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete},
		AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", audHeaderName},
		AllowCredentials: true,
	})

	api.handler = corsHandler.Handler(chi.ServerBaseContext(r, ctx))
	return api
}

// NewAPIFromConfigFile creates a new REST API using the provided configuration file.
func NewAPIFromConfigFile(filename string, version string) (*API, error) {
	globalConfig, err := conf.LoadGlobalFromFile(filename)
	if err != nil {
		return nil, err
	}
	config, err := conf.LoadConfigFromFile(filename)
	if err != nil {
		return nil, err
	}

	var db storage.Connection
	// try a couple times to connect to the database
	for i := 1; i <= 3; i++ {
		db, err = dial.Dial(globalConfig)
		if err == nil {
			break
		}
		logrus.WithError(err).WithField("attempt", i).Warn("Error connecting to database")
		time.Sleep(1 * time.Second)
	}
	if err != nil {
		return nil, err
	}

	if globalConfig.DB.Automigrate {
		if err := db.Automigrate(); err != nil {
			return nil, err
		}
	}

	ctx, err := WithInstanceConfig(context.Background(), config, "")
	if err != nil {
		logrus.Fatalf("Error loading instance config: %+v", err)
	}

	return NewAPIWithVersion(ctx, globalConfig, db, version), nil
}

func (a *API) HealthCheck(w http.ResponseWriter, r *http.Request) error {
	return sendJSON(w, http.StatusOK, map[string]string{
		"version":     a.version,
		"name":        "GoTrue",
		"description": "GoTrue is a user registration and authentication API",
	})
}

// Provider returns a Provider interface for the given name.
func (a *API) Provider(ctx context.Context, name string) (provider.Provider, error) {
	config := getConfig(ctx)
	name = strings.ToLower(name)

	switch name {
	case "github":
		return provider.NewGithubProvider(config.External.Github), nil
	case "bitbucket":
		return provider.NewBitbucketProvider(config.External.Bitbucket), nil
	case "gitlab":
		return provider.NewGitlabProvider(config.External.Gitlab), nil
	default:
		return nil, fmt.Errorf("Provider %s could not be found", name)
	}
}

func WithInstanceConfig(ctx context.Context, config *conf.Configuration, instanceID string) (context.Context, error) {
	ctx = withConfig(ctx, config)

	mailer := mailer.NewMailer(config)
	ctx = withMailer(ctx, mailer)
	ctx = withInstanceID(ctx, instanceID)

	return ctx, nil
}
<|endoftext|>


<commit_before>package v1

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/SpectoLabs/hoverfly/core/models"
	"github.com/SpectoLabs/hoverfly/core/views"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"net/http"
	"strconv"
	"github.com/SpectoLabs/hoverfly/core/handlers"
)

type AddHandler struct {
	Hoverfly HoverflyRecords
}

func (this *AddHandler) RegisterRoutes(mux *bone.Mux, am *handlers.AuthHandler) {
	mux.Post("/api/add", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Post),
	))
}

// ManualAddHandler - manually add new request/responses, using a form
func (this *AddHandler) Post(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	err := req.ParseForm()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Got error while parsing form")
	}

	// request details
	destination := req.PostFormValue("inputDestination")
	method := req.PostFormValue("inputMethod")
	path := req.PostFormValue("inputPath")
	query := req.PostFormValue("inputQuery")
	reqBody := req.PostFormValue("inputRequestBody")

	preq := models.RequestDetails{
		Destination: destination,
		Method:      method,
		Path:        path,
		Query:       query,
		Body:        reqBody}

	// response
	respStatusCode := req.PostFormValue("inputResponseStatusCode")
	respBody := req.PostFormValue("inputResponseBody")
	contentType := req.PostFormValue("inputContentType")

	headers := make(map[string][]string)

	// getting content type
	if contentType == "xml" {
		headers["Content-Type"] = []string{"application/xml"}
	} else if contentType == "json" {
		headers["Content-Type"] = []string{"application/json"}
	} else {
		headers["Content-Type"] = []string{"text/html"}
	}

	sc, _ := strconv.Atoi(respStatusCode)

	presp := models.ResponseDetails{
		Status:  sc,
		Headers: headers,
		Body:    respBody,
	}

	log.WithFields(log.Fields{
		"respBody":    respBody,
		"contentType": contentType,
	}).Info("manually adding request/response")

	p := models.RequestResponsePair{Request: preq, Response: presp}

	var pairViews []views.RequestResponsePairView

	pairViews = append(pairViews, *p.ConvertToRequestResponsePairView())

	err = this.Hoverfly.ImportRequestResponsePairViews(pairViews)

	w.Header().Set("Content-Type", "application/json")
	var response MessageResponse

	if err != nil {
		response.Message = fmt.Sprintf("Got error: %s", err.Error())
		w.WriteHeader(400)

	} else {
		// redirecting to home
		response.Message = "Record added successfuly"
		w.WriteHeader(201)
	}
	b, err := response.Encode()
	if err != nil {
		// failed to read response body
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Could not encode response body!")
		http.Error(w, "Failed to encode response", 500)
		return
	}
	w.Write(b)

}
<commit_msg>Removed models dependency from add_handler<commit_after>package v1

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/SpectoLabs/hoverfly/core/handlers"
	"github.com/SpectoLabs/hoverfly/core/util"
	"github.com/SpectoLabs/hoverfly/core/views"
	"github.com/codegangsta/negroni"
	"github.com/go-zoo/bone"
	"net/http"
	"strconv"
)

type AddHandler struct {
	Hoverfly HoverflyRecords
}

func (this *AddHandler) RegisterRoutes(mux *bone.Mux, am *handlers.AuthHandler) {
	mux.Post("/api/add", negroni.New(
		negroni.HandlerFunc(am.RequireTokenAuthentication),
		negroni.HandlerFunc(this.Post),
	))
}

// ManualAddHandler - manually add new request/responses, using a form
func (this *AddHandler) Post(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
	err := req.ParseForm()

	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Got error while parsing form")
	}

	// request details
	destination := req.PostFormValue("inputDestination")
	method := req.PostFormValue("inputMethod")
	path := req.PostFormValue("inputPath")
	query := req.PostFormValue("inputQuery")
	reqBody := req.PostFormValue("inputRequestBody")

	preq := views.RequestDetailsView{
		Destination: util.StringToPointer(destination),
		Method:      util.StringToPointer(method),
		Path:        util.StringToPointer(path),
		Query:       util.StringToPointer(query),
		Body:        util.StringToPointer(reqBody),
	}

	// response
	respStatusCode := req.PostFormValue("inputResponseStatusCode")
	respBody := req.PostFormValue("inputResponseBody")
	contentType := req.PostFormValue("inputContentType")

	headers := make(map[string][]string)

	// getting content type
	if contentType == "xml" {
		headers["Content-Type"] = []string{"application/xml"}
	} else if contentType == "json" {
		headers["Content-Type"] = []string{"application/json"}
	} else {
		headers["Content-Type"] = []string{"text/html"}
	}

	sc, _ := strconv.Atoi(respStatusCode)

	presp := views.ResponseDetailsView{
		Status:  sc,
		Headers: headers,
		Body:    respBody,
	}

	log.WithFields(log.Fields{
		"respBody":    respBody,
		"contentType": contentType,
	}).Info("manually adding request/response")

	p := views.RequestResponsePairView{Request: preq, Response: presp}

	var pairViews []views.RequestResponsePairView

	pairViews = append(pairViews, p)

	err = this.Hoverfly.ImportRequestResponsePairViews(pairViews)

	w.Header().Set("Content-Type", "application/json")
	var response MessageResponse

	if err != nil {
		response.Message = fmt.Sprintf("Got error: %s", err.Error())
		w.WriteHeader(400)

	} else {
		// redirecting to home
		response.Message = "Record added successfuly"
		w.WriteHeader(201)
	}
	b, err := response.Encode()
	if err != nil {
		// failed to read response body
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Error("Could not encode response body!")
		http.Error(w, "Failed to encode response", 500)
		return
	}
	w.Write(b)

}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	lxdshared "github.com/lxc/lxd/shared"

	"github.com/juju/errors"
	"github.com/juju/utils"

	"github.com/juju/juju/container/lxc"
)

const (
	// remoteLocalName is a specific remote name in the default LXD config.
	// See https://github.com/lxc/lxd/blob/master/config.go:defaultRemote.
	remoteLocalName  = "local"
	remoteIDForLocal = remoteLocalName
)

// Local is LXD's default "remote". Essentially it is an unencrypted,
// unauthenticated connection to localhost over a unix socket.
var Local = Remote{
	Name: remoteLocalName,
	Host: "", // The LXD API turns this into the local unix socket.
	Cert: nil,
}

// Remote describes a LXD "remote" server for a client. In
// particular it holds the information needed for the client
// to connect to the remote.
type Remote struct {
	// Name is a label for this remote.
	Name string

	// Host identifies the host to which the client should connect.
	// An empty string is interpreted as:
	//   "localhost over a unix socket (unencrypted)".
	Host string

	// Cert holds the TLS certificate data for the client to use.
	Cert *Cert
}

// isLocal determines if the remote is the implicit "local" remote,
// an unencrypted, unauthenticated unix socket to a locally running LXD.
func (r Remote) isLocal() bool {
	return r.Host == Local.Host
}

// ID identifies the remote to the raw LXD client code. For the
// non-local case this is Remote.Name. For the local case it is the
// remote name that LXD special-cases for the local unix socket.
func (r Remote) ID() string {
	if r.isLocal() {
		return remoteIDForLocal
	}
	return r.Name
}

// WithDefaults updates a copy of the remote with default values
// where needed.
func (r Remote) WithDefaults() (Remote, error) {
	// Note that r is a value receiver, so it is an implicit copy.

	if r.isLocal() {
		return r.withLocalDefaults(), nil
	}

	if r.Cert == nil {
		certPEM, keyPEM, err := lxdshared.GenerateMemCert()
		if err != nil {
			return r, errors.Trace(err)
		}
		cert := NewCert(certPEM, keyPEM)
		r.Cert = &cert
	}

	cert, err := r.Cert.WithDefaults()
	if err != nil {
		return r, errors.Trace(err)
	}
	r.Cert = &cert

	return r, nil
}

func (r Remote) withLocalDefaults() Remote {
	if r.Name == "" {
		r.Name = remoteLocalName
	}

	// TODO(ericsnow) Set r.Cert to nil?

	return r
}

// Validate checks the Remote fields for invalid values.
func (r Remote) Validate() error {
	if r.Name == "" {
		return errors.NotValidf("remote missing name,")
	}

	if r.isLocal() {
		if err := r.validateLocal(); err != nil {
			return errors.Trace(err)
		}
		return nil
	}

	// TODO(ericsnow) Ensure the host is a valid hostname or address?

	if r.Cert == nil {
		return errors.NotValidf("remote without cert")
	} else if err := r.Cert.Validate(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

func (r Remote) validateLocal() error {
	if r.Cert != nil {
		return errors.NotValidf("hostless remote with cert")
	}

	return nil
}

// UsingTCP converts the remote into a non-local version. For
// non-local remotes this is a no-op.
//
// For a "local" remote (see Local), the remote is changed to a one
// with the host set to the IP address of the local lxcbr0 bridge
// interface. The remote is also set up for remote access, setting
// the cert if not already set.
func (r Remote) UsingTCP() (Remote, error) {
	// Note that r is a value receiver, so it is an implicit copy.

	if !r.isLocal() {
		return r, nil
	}

	netIF := lxc.DefaultLxcBridge
	addr, err := utils.GetAddressForInterface(netIF)
	if err != nil {
		return r, errors.Trace(err)
	}
	r.Host = addr

	r, err = r.WithDefaults()
	if err != nil {
		return r, errors.Trace(err)
	}

	// TODO(ericsnow) Change r.Name if "local"? Prepend "juju-"?

	return r, nil
}

// TODO(ericsnow) Add a "Connect(Config)" method that connects
// to the remote and returns the corresponding Client.

// TODO(ericsnow) Add a "Register" method to Client that adds the remote
// to the client's remote?
<commit_msg>lxd: include default port in hostname<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// +build go1.3

package lxdclient

import (
	lxdshared "github.com/lxc/lxd/shared"

	"github.com/juju/errors"
	"github.com/juju/utils"

	"github.com/juju/juju/container/lxc"
)

const (
	// remoteLocalName is a specific remote name in the default LXD config.
	// See https://github.com/lxc/lxd/blob/master/config.go:defaultRemote.
	remoteLocalName  = "local"
	remoteIDForLocal = remoteLocalName
)

// Local is LXD's default "remote". Essentially it is an unencrypted,
// unauthenticated connection to localhost over a unix socket.
var Local = Remote{
	Name: remoteLocalName,
	Host: "", // The LXD API turns this into the local unix socket.
	Cert: nil,
}

// Remote describes a LXD "remote" server for a client. In
// particular it holds the information needed for the client
// to connect to the remote.
type Remote struct {
	// Name is a label for this remote.
	Name string

	// Host identifies the host to which the client should connect.
	// An empty string is interpreted as:
	//   "localhost over a unix socket (unencrypted)".
	Host string

	// Cert holds the TLS certificate data for the client to use.
	Cert *Cert
}

// isLocal determines if the remote is the implicit "local" remote,
// an unencrypted, unauthenticated unix socket to a locally running LXD.
func (r Remote) isLocal() bool {
	return r.Host == Local.Host
}

// ID identifies the remote to the raw LXD client code. For the
// non-local case this is Remote.Name. For the local case it is the
// remote name that LXD special-cases for the local unix socket.
func (r Remote) ID() string {
	if r.isLocal() {
		return remoteIDForLocal
	}
	return r.Name
}

// WithDefaults updates a copy of the remote with default values
// where needed.
func (r Remote) WithDefaults() (Remote, error) {
	// Note that r is a value receiver, so it is an implicit copy.

	if r.isLocal() {
		return r.withLocalDefaults(), nil
	}

	if r.Cert == nil {
		certPEM, keyPEM, err := lxdshared.GenerateMemCert()
		if err != nil {
			return r, errors.Trace(err)
		}
		cert := NewCert(certPEM, keyPEM)
		r.Cert = &cert
	}

	cert, err := r.Cert.WithDefaults()
	if err != nil {
		return r, errors.Trace(err)
	}
	r.Cert = &cert

	return r, nil
}

func (r Remote) withLocalDefaults() Remote {
	if r.Name == "" {
		r.Name = remoteLocalName
	}

	// TODO(ericsnow) Set r.Cert to nil?

	return r
}

// Validate checks the Remote fields for invalid values.
func (r Remote) Validate() error {
	if r.Name == "" {
		return errors.NotValidf("remote missing name,")
	}

	if r.isLocal() {
		if err := r.validateLocal(); err != nil {
			return errors.Trace(err)
		}
		return nil
	}

	// TODO(ericsnow) Ensure the host is a valid hostname or address?

	if r.Cert == nil {
		return errors.NotValidf("remote without cert")
	} else if err := r.Cert.Validate(); err != nil {
		return errors.Trace(err)
	}

	return nil
}

func (r Remote) validateLocal() error {
	if r.Cert != nil {
		return errors.NotValidf("hostless remote with cert")
	}

	return nil
}

// UsingTCP converts the remote into a non-local version. For
// non-local remotes this is a no-op.
//
// For a "local" remote (see Local), the remote is changed to a one
// with the host set to the IP address of the local lxcbr0 bridge
// interface. The remote is also set up for remote access, setting
// the cert if not already set.
func (r Remote) UsingTCP() (Remote, error) {
	// Note that r is a value receiver, so it is an implicit copy.

	if !r.isLocal() {
		return r, nil
	}

	netIF := lxc.DefaultLxcBridge
	addr, err := utils.GetAddressForInterface(netIF)
	if err != nil {
		return r, errors.Trace(err)
	}
	r.Host = addr + ":8443"

	r, err = r.WithDefaults()
	if err != nil {
		return r, errors.Trace(err)
	}

	// TODO(ericsnow) Change r.Name if "local"? Prepend "juju-"?

	return r, nil
}

// TODO(ericsnow) Add a "Connect(Config)" method that connects
// to the remote and returns the corresponding Client.

// TODO(ericsnow) Add a "Register" method to Client that adds the remote
// to the client's remote?
<|endoftext|>


<commit_before>// Package api implements the HTTP API for Cassabon
package api

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/zenazn/goji/graceful"
	"github.com/zenazn/goji/web"

	"github.com/jeffpierce/cassabon/config"
)

type CassabonAPI struct {
	server *web.Mux
}

func (api *CassabonAPI) Start() {
	// Add to waitgroup and run go routine.
	config.G.OnReload1WG.Add(1)
	go api.run()
}

func (api *CassabonAPI) Stop() {
	config.G.Log.System.LogInfo("API received Stop command, gracefully shutting down.")
	graceful.Shutdown()
	config.G.OnReload1WG.Done()
}

func (api *CassabonAPI) run() {
	// Initialize API server
	api.server = web.New()

	// Define routes
	api.server.Get("/paths", api.pathsHandler)
	api.server.Get("/metrics", api.metricsHandler)
	api.server.Get("/healthcheck", api.healthHandler)
	api.server.Delete("/remove/path/:path", api.deletePathHandler)
	api.server.Delete("/remove/metric/:metric", api.deleteMetricHandler)
	api.server.Get("/", api.notFound)

	api.server.Use(requestLogger)

	config.G.Log.System.LogInfo("API initialized, serving!")
	graceful.ListenAndServe(config.G.API.Listen, api.server)
}

func (api *CassabonAPI) pathsHandler(w http.ResponseWriter, r *http.Request) {
	// Create channel for use in communicating with the statGopher
	ch := make(chan []byte)
	_ = r.ParseForm()
	pathQuery := config.IndexQuery{r.Form.Get("query"), ch}
	config.G.Log.API.LogDebug("Received query: %s", pathQuery.Query)
	config.G.Channels.Gopher <- pathQuery
	resp := <-pathQuery.Channel
	close(pathQuery.Channel)
	fmt.Fprintf(w, string(resp))
}

func (api *CassabonAPI) metricsHandler(w http.ResponseWriter, r *http.Request) {
	// Have to wait for the Cassandra worker to get implemented.
	fmt.Fprintf(w, "Not yet implemented.")
}

func (api *CassabonAPI) healthHandler(w http.ResponseWriter, r *http.Request) {
	health, err := ioutil.ReadFile(config.G.API.HealthCheckFile)
	if err != nil {
		config.G.Log.API.LogError("Cannot read healthcheck file, error %v", err)
		fmt.Fprint(w, "DEAD")
	}
	fmt.Fprintf(w, string(health))
}

func (api *CassabonAPI) deletePathHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	// TODO:  Implement this in datastore.
	fmt.Fprintf(w, "Not yet implemented, would have deleted %s", c.URLParams["path"])
}

func (api *CassabonAPI) deleteMetricHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	// TODO:  Implement this in datastore.
	fmt.Fprintf(w, "Not yet implemented, would have deleted %s", c.URLParams["metric"])
}

func (api *CassabonAPI) notFound(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Cassabon.  You know, for stats!")
}
<commit_msg>Avoid race by moving read of global config out of goroutine<commit_after>// Package api implements the HTTP API for Cassabon
package api

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/zenazn/goji/graceful"
	"github.com/zenazn/goji/web"

	"github.com/jeffpierce/cassabon/config"
)

type CassabonAPI struct {
	server   *web.Mux
	hostPort string
}

func (api *CassabonAPI) Start() {
	// Add to waitgroup and run go routine.
	api.hostPort = config.G.API.Listen
	config.G.OnReload1WG.Add(1)
	go api.run()
}

func (api *CassabonAPI) Stop() {
	config.G.Log.System.LogInfo("API received Stop command, gracefully shutting down.")
	graceful.Shutdown()
	config.G.OnReload1WG.Done()
}

func (api *CassabonAPI) run() {
	// Initialize API server
	api.server = web.New()

	// Define routes
	api.server.Get("/paths", api.pathsHandler)
	api.server.Get("/metrics", api.metricsHandler)
	api.server.Get("/healthcheck", api.healthHandler)
	api.server.Delete("/remove/path/:path", api.deletePathHandler)
	api.server.Delete("/remove/metric/:metric", api.deleteMetricHandler)
	api.server.Get("/", api.notFound)

	api.server.Use(requestLogger)

	config.G.Log.System.LogInfo("API initialized, serving!")
	graceful.ListenAndServe(api.hostPort, api.server)
}

func (api *CassabonAPI) pathsHandler(w http.ResponseWriter, r *http.Request) {
	// Create channel for use in communicating with the statGopher
	ch := make(chan []byte)
	_ = r.ParseForm()
	pathQuery := config.IndexQuery{r.Form.Get("query"), ch}
	config.G.Log.API.LogDebug("Received query: %s", pathQuery.Query)
	config.G.Channels.Gopher <- pathQuery
	resp := <-pathQuery.Channel
	close(pathQuery.Channel)
	fmt.Fprintf(w, string(resp))
}

func (api *CassabonAPI) metricsHandler(w http.ResponseWriter, r *http.Request) {
	// Have to wait for the Cassandra worker to get implemented.
	fmt.Fprintf(w, "Not yet implemented.")
}

func (api *CassabonAPI) healthHandler(w http.ResponseWriter, r *http.Request) {
	health, err := ioutil.ReadFile(config.G.API.HealthCheckFile)
	if err != nil {
		config.G.Log.API.LogError("Cannot read healthcheck file, error %v", err)
		fmt.Fprint(w, "DEAD")
	}
	fmt.Fprintf(w, string(health))
}

func (api *CassabonAPI) deletePathHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	// TODO:  Implement this in datastore.
	fmt.Fprintf(w, "Not yet implemented, would have deleted %s", c.URLParams["path"])
}

func (api *CassabonAPI) deleteMetricHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	// TODO:  Implement this in datastore.
	fmt.Fprintf(w, "Not yet implemented, would have deleted %s", c.URLParams["metric"])
}

func (api *CassabonAPI) notFound(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Cassabon.  You know, for stats!")
}
<|endoftext|>


<commit_before>// api provides common functionality for all the iron.io APIs
package api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/iron-io/iron_go/config"
)

type URL struct {
	URL      url.URL
	Settings config.Settings
}

var (
	debug bool
	HttpClient = &http.Client{}
)

func dbg(v ...interface{}) {
	if debug {
		fmt.Fprintln(os.Stderr, v...)
	}
}

func init() {
	if os.Getenv("IRON_API_DEBUG") != "" {
		debug = true
		dbg("debugging of api enabled")
	}
}

func Action(cs config.Settings, prefix string, suffix ...string) *URL {
	parts := append([]string{prefix}, suffix...)
	return ActionEndpoint(cs, strings.Join(parts, "/"))
}

func ActionEndpoint(cs config.Settings, endpoint string) *URL {
	u := &URL{Settings: cs, URL: url.URL{}}
	u.URL.Scheme = cs.Scheme
	u.URL.Host = fmt.Sprintf("%s:%d", cs.Host, cs.Port)
	u.URL.Path = fmt.Sprintf("/%s/projects/%s/%s", cs.ApiVersion, cs.ProjectId, endpoint)
	return u
}

func VersionAction(cs config.Settings) *URL {
	u := &URL{Settings: cs, URL: url.URL{Scheme: cs.Scheme}}
	u.URL.Host = fmt.Sprintf("%s:%d", cs.Host, cs.Port)
	u.URL.Path = "/version"
	return u
}

func (u *URL) QueryAdd(key string, format string, value interface{}) *URL {
	query := u.URL.Query()
	query.Add(key, fmt.Sprintf(format, value))
	u.URL.RawQuery = query.Encode()
	return u
}

func (u *URL) Req(method string, in, out interface{}) (err error) {
	var reqBody io.Reader
	if in != nil {
		data, err := json.Marshal(in)
		if err != nil {
			return err
		}
		reqBody = bytes.NewBuffer(data)
	}
	response, err := u.Request(method, reqBody)
	if response != nil {
		defer response.Body.Close()
	}
	if err == nil && out != nil {
		err = json.NewDecoder(response.Body).Decode(out)
		dbg("u:", u, "out:", fmt.Sprintf("%#v\n", out))
	}

	return
}

var MaxRequestRetries = 5

func (u *URL) Request(method string, body io.Reader) (response *http.Response, err error) {
	var bodyBytes []byte
	if body == nil {
		bodyBytes = []byte{}
	} else {
		bodyBytes, err = ioutil.ReadAll(body)
		if err != nil {
			return nil, err
		}
	}

	request, err := http.NewRequest(method, u.URL.String(), nil)
	if err != nil {
		return nil, err
	}

	request.Header.Set("Authorization", "OAuth "+u.Settings.Token)
	request.Header.Set("Accept", "application/json")
	request.Header.Set("Accept-Encoding", "gzip/deflate")
	request.Header.Set("User-Agent", u.Settings.UserAgent)

	if body != nil {
		request.Header.Set("Content-Type", "application/json")
	}

	dbg("request:", fmt.Sprintf("%#v\n", request))

	for tries := 0; tries <= MaxRequestRetries; tries++ {
		request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
		response, err = HttpClient.Do(request)
		if err != nil {
			if err == io.EOF {
				continue
			}
			return
		}

		if response.StatusCode == http.StatusServiceUnavailable {
			delay := (tries + 1) * 10 // smooth out delays from 0-2
			time.Sleep(time.Duration(delay*delay) * time.Millisecond)
			continue
		}

		break
	}

	// DumpResponse(response)
	if err = ResponseAsError(response); err != nil {
		return
	}

	return
}

func DumpRequest(req *http.Request) {
	out, err := httputil.DumpRequestOut(req, true)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", out)
}

func DumpResponse(response *http.Response) {
	out, err := httputil.DumpResponse(response, true)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", out)
}

var HTTPErrorDescriptions = map[int]string{
	http.StatusUnauthorized:     "The OAuth token is either not provided or invalid",
	http.StatusNotFound:         "The resource, project, or endpoint being requested doesn't exist.",
	http.StatusMethodNotAllowed: "This endpoint doesn't support that particular verb",
	http.StatusNotAcceptable:    "Required fields are missing",
}

func ResponseAsError(response *http.Response) HTTPResponseError {
	if response.StatusCode == http.StatusOK {
		return nil
	}

	defer response.Body.Close()
	desc, found := HTTPErrorDescriptions[response.StatusCode]
	if found {
		return resErr{response: response, error: response.Status + ": " + desc}
	}

	out := map[string]interface{}{}
	err := json.NewDecoder(response.Body).Decode(&out)
	if err != nil {
		return resErr{response: response, error: fmt.Sprint(response.Status, ": ", err.Error())}
	}
	if msg, ok := out["msg"]; ok {
		return resErr{response: response, error: fmt.Sprint(response.Status, ": ", msg)}
	}

	return resErr{response: response, error: response.Status + ": Unknown API Response"}
}

type HTTPResponseError interface {
	Error() string
	Response() *http.Response
}

type resErr struct {
	error    string
	response *http.Response
}

func (h resErr) Error() string            { return h.error }
func (h resErr) Response() *http.Response { return h.response }
<commit_msg>add comment for HttpClient package variable<commit_after>// api provides common functionality for all the iron.io APIs
package api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/iron-io/iron_go/config"
)

type URL struct {
	URL      url.URL
	Settings config.Settings
}

var (
	debug bool

	// HttpClient is the client used by iron_go to make each http request. It is exported in case
	// the client would like to modify it from the default behavior from http.DefaultClient.
	HttpClient = &http.Client{}
)

func dbg(v ...interface{}) {
	if debug {
		fmt.Fprintln(os.Stderr, v...)
	}
}

func init() {
	if os.Getenv("IRON_API_DEBUG") != "" {
		debug = true
		dbg("debugging of api enabled")
	}
}

func Action(cs config.Settings, prefix string, suffix ...string) *URL {
	parts := append([]string{prefix}, suffix...)
	return ActionEndpoint(cs, strings.Join(parts, "/"))
}

func ActionEndpoint(cs config.Settings, endpoint string) *URL {
	u := &URL{Settings: cs, URL: url.URL{}}
	u.URL.Scheme = cs.Scheme
	u.URL.Host = fmt.Sprintf("%s:%d", cs.Host, cs.Port)
	u.URL.Path = fmt.Sprintf("/%s/projects/%s/%s", cs.ApiVersion, cs.ProjectId, endpoint)
	return u
}

func VersionAction(cs config.Settings) *URL {
	u := &URL{Settings: cs, URL: url.URL{Scheme: cs.Scheme}}
	u.URL.Host = fmt.Sprintf("%s:%d", cs.Host, cs.Port)
	u.URL.Path = "/version"
	return u
}

func (u *URL) QueryAdd(key string, format string, value interface{}) *URL {
	query := u.URL.Query()
	query.Add(key, fmt.Sprintf(format, value))
	u.URL.RawQuery = query.Encode()
	return u
}

func (u *URL) Req(method string, in, out interface{}) (err error) {
	var reqBody io.Reader
	if in != nil {
		data, err := json.Marshal(in)
		if err != nil {
			return err
		}
		reqBody = bytes.NewBuffer(data)
	}
	response, err := u.Request(method, reqBody)
	if response != nil {
		defer response.Body.Close()
	}
	if err == nil && out != nil {
		err = json.NewDecoder(response.Body).Decode(out)
		dbg("u:", u, "out:", fmt.Sprintf("%#v\n", out))
	}

	return
}

var MaxRequestRetries = 5

func (u *URL) Request(method string, body io.Reader) (response *http.Response, err error) {
	var bodyBytes []byte
	if body == nil {
		bodyBytes = []byte{}
	} else {
		bodyBytes, err = ioutil.ReadAll(body)
		if err != nil {
			return nil, err
		}
	}

	request, err := http.NewRequest(method, u.URL.String(), nil)
	if err != nil {
		return nil, err
	}

	request.Header.Set("Authorization", "OAuth "+u.Settings.Token)
	request.Header.Set("Accept", "application/json")
	request.Header.Set("Accept-Encoding", "gzip/deflate")
	request.Header.Set("User-Agent", u.Settings.UserAgent)

	if body != nil {
		request.Header.Set("Content-Type", "application/json")
	}

	dbg("request:", fmt.Sprintf("%#v\n", request))

	for tries := 0; tries <= MaxRequestRetries; tries++ {
		request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
		response, err = HttpClient.Do(request)
		if err != nil {
			if err == io.EOF {
				continue
			}
			return
		}

		if response.StatusCode == http.StatusServiceUnavailable {
			delay := (tries + 1) * 10 // smooth out delays from 0-2
			time.Sleep(time.Duration(delay*delay) * time.Millisecond)
			continue
		}

		break
	}

	// DumpResponse(response)
	if err = ResponseAsError(response); err != nil {
		return
	}

	return
}

func DumpRequest(req *http.Request) {
	out, err := httputil.DumpRequestOut(req, true)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", out)
}

func DumpResponse(response *http.Response) {
	out, err := httputil.DumpResponse(response, true)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%q\n", out)
}

var HTTPErrorDescriptions = map[int]string{
	http.StatusUnauthorized:     "The OAuth token is either not provided or invalid",
	http.StatusNotFound:         "The resource, project, or endpoint being requested doesn't exist.",
	http.StatusMethodNotAllowed: "This endpoint doesn't support that particular verb",
	http.StatusNotAcceptable:    "Required fields are missing",
}

func ResponseAsError(response *http.Response) HTTPResponseError {
	if response.StatusCode == http.StatusOK {
		return nil
	}

	defer response.Body.Close()
	desc, found := HTTPErrorDescriptions[response.StatusCode]
	if found {
		return resErr{response: response, error: response.Status + ": " + desc}
	}

	out := map[string]interface{}{}
	err := json.NewDecoder(response.Body).Decode(&out)
	if err != nil {
		return resErr{response: response, error: fmt.Sprint(response.Status, ": ", err.Error())}
	}
	if msg, ok := out["msg"]; ok {
		return resErr{response: response, error: fmt.Sprint(response.Status, ": ", msg)}
	}

	return resErr{response: response, error: response.Status + ": Unknown API Response"}
}

type HTTPResponseError interface {
	Error() string
	Response() *http.Response
}

type resErr struct {
	error    string
	response *http.Response
}

func (h resErr) Error() string            { return h.error }
func (h resErr) Response() *http.Response { return h.response }
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"net/url"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/paked/gerrycode/communicator"
	"gopkg.in/mgo.v2/bson"
)

type Image struct {
	ID  bson.ObjectId `bson:"_id" json:"id"`
	URL string        `bson:"url" json:"url"`
}

func (i Image) BID() bson.ObjectId {
	return i.ID
}

func (i Image) C() string {
	return "images"
}

type Number struct {
	ID     bson.ObjectId `bson:"_id" json:"id"`
	For    bson.ObjectId `bson:"for" json:"for"`
	Number float64       `bson:"number" json:"number"`
}

func (n Number) BID() bson.ObjectId {
	return n.ID
}

func (n Number) C() string {
	return "numbers"
}

func main() {
	r := mux.NewRouter()
	api := r.PathPrefix("/api").Subrouter()

	r.HandleFunc("/", homeHandler).Methods("GET")
	api.HandleFunc("/image/new", createImageHandler).Methods("POST")
	api.HandleFunc("/image/{image_id}/number/new", addNumberHandler).Methods("POST")

	http.Handle("/", r)

	fmt.Println("Listening on port 8080")
	fmt.Println(http.ListenAndServe("localhost:8080", nil))
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

func createImageHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	location := r.FormValue("url")

	u, err := url.Parse(location)
	if err != nil {
		c.Error("Not a good URL!")
		return
	}

	location = u.String()

	i := Image{
		ID:  bson.NewObjectId(),
		URL: location,
	}

	c.OKWithData("Here is your image", i)
}

func addNumberHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	imageId := mux.Vars(r)["image_id"]
	numberString := r.FormValue("number")

	number, err := strconv.ParseFloat(numberString, 64)
	if err != nil {
		c.Error("That is not a valid float!")
		return
	}

	if !bson.IsObjectIdHex(imageId) {
		c.Error("Not valid image id!")
		return
	}

	n := Number{
		ID:     bson.NewObjectId(),
		For:    bson.ObjectIdHex(imageId),
		Number: number,
	}

	c.OKWithData("Here is your number", n)
}
<commit_msg>main: images are now inserted into the DB<commit_after>package main

import (
	"fmt"
	"net/http"
	"net/url"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/paked/gerrycode/communicator"
	"github.com/paked/models"
	"gopkg.in/mgo.v2/bson"
)

type Image struct {
	ID  bson.ObjectId `bson:"_id" json:"id"`
	URL string        `bson:"url" json:"url"`
}

func (i Image) BID() bson.ObjectId {
	return i.ID
}

func (i Image) C() string {
	return "images"
}

type Number struct {
	ID     bson.ObjectId `bson:"_id" json:"id"`
	For    bson.ObjectId `bson:"for" json:"for"`
	Number float64       `bson:"number" json:"number"`
}

func (n Number) BID() bson.ObjectId {
	return n.ID
}

func (n Number) C() string {
	return "numbers"
}

func main() {
	models.Init("localhost", "imagenumberdescriptions")
	r := mux.NewRouter()
	api := r.PathPrefix("/api").Subrouter()

	r.HandleFunc("/", homeHandler).Methods("GET")
	api.HandleFunc("/image/new", createImageHandler).Methods("POST")
	api.HandleFunc("/image/{image_id}/number/new", addNumberHandler).Methods("POST")

	http.Handle("/", r)

	fmt.Println("Listening on port 8080")
	fmt.Println(http.ListenAndServe("localhost:8080", nil))
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

func createImageHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	location := r.FormValue("url")

	u, err := url.Parse(location)
	if err != nil {
		c.Error("Not a good URL!")
		return
	}

	location = u.String()

	var i Image
	if err := models.Restore(&i, bson.M{"url": location}); err == nil {
		c.Fail("An image with that URL already exists")
		return
	}

	i = Image{
		ID:  bson.NewObjectId(),
		URL: location,
	}

	if err := models.Persist(i); err != nil {
		c.Fail("An error with the database has occured")
		return
	}

	c.OKWithData("Here is your image", i)
}

func addNumberHandler(w http.ResponseWriter, r *http.Request) {
	c := communicator.New(w)
	imageId := mux.Vars(r)["image_id"]
	numberString := r.FormValue("number")

	number, err := strconv.ParseFloat(numberString, 64)
	if err != nil {
		c.Error("That is not a valid float!")
		return
	}

	if !bson.IsObjectIdHex(imageId) {
		c.Error("Not valid image id!")
		return
	}

	n := Number{
		ID:     bson.NewObjectId(),
		For:    bson.ObjectIdHex(imageId),
		Number: number,
	}

	c.OKWithData("Here is your number", n)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/fogleman/primitive/primitive"
	"github.com/nfnt/resize"
)

var (
	Input      string
	Outputs    flagArray
	Background string
	Number     int
	Alpha      int
	InputSize  int
	OutputSize int
	Mode       int
	Workers    int
	V, VV      bool
)

type flagArray []string

func (i *flagArray) String() string {
	return strings.Join(*i, ", ")
}

func (i *flagArray) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func init() {
	flag.StringVar(&Input, "i", "", "input image path")
	flag.Var(&Outputs, "o", "output image path")
	flag.StringVar(&Background, "bg", "", "background color (hex)")
	flag.IntVar(&Number, "n", 0, "number of primitives")
	flag.IntVar(&Alpha, "a", 128, "alpha value")
	flag.IntVar(&InputSize, "r", 256, "resize large input images to this size")
	flag.IntVar(&OutputSize, "s", 1024, "output image size")
	flag.IntVar(&Mode, "m", 1, "0=combo 1=triangle 2=rect 3=ellipse 4=circle 5=rotatedrect")
	flag.IntVar(&Workers, "j", 0, "number of parallel workers (default uses all cores)")
	flag.BoolVar(&V, "v", false, "verbose")
	flag.BoolVar(&VV, "vv", false, "very verbose")
}

func errorMessage(message string) bool {
	fmt.Fprintln(os.Stderr, message)
	return false
}

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

func main() {
	// parse and validate arguments
	flag.Parse()
	ok := true
	if Input == "" {
		ok = errorMessage("ERROR: input argument required")
	}
	if len(Outputs) == 0 {
		ok = errorMessage("ERROR: output argument required")
	}
	if Number == 0 {
		ok = errorMessage("ERROR: number argument required")
	}
	if !ok {
		fmt.Println("Usage: primitive [OPTIONS] -i input -o output -n shape_count")
		flag.PrintDefaults()
		os.Exit(1)
	}

	// set log level
	if V {
		primitive.LogLevel = 1
	}
	if VV {
		primitive.LogLevel = 2
	}

	// seed random number generator
	rand.Seed(time.Now().UTC().UnixNano())

	// determine worker count
	if Workers < 1 {
		Workers = runtime.NumCPU()
	}

	// read input image
	primitive.Log(1, "reading %s\n", Input)
	input, err := primitive.LoadImage(Input)
	check(err)

	// scale down input image if needed
	size := uint(InputSize)
	input = resize.Thumbnail(size, size, input, resize.Bilinear)

	// determine background color
	var bg primitive.Color
	if Background == "" {
		bg = primitive.MakeColor(primitive.AverageImageColor(input))
	} else {
		bg = primitive.MakeHexColor(Background)
	}

	// run algorithm
	model := primitive.NewModel(input, bg, OutputSize, Workers)
	primitive.Log(1, "%d: t=%.3f, score=%.6f\n", 0, 0.0, model.Score)
	start := time.Now()
	for i := 1; i <= Number; i++ {
		// find optimal shape and add it to the model
		t := time.Now()
		n := model.Step(primitive.ShapeType(Mode), Alpha)
		nps := primitive.NumberString(float64(n) / time.Since(t).Seconds())
		elapsed := time.Since(start).Seconds()
		primitive.Log(1, "%d: t=%.3f, score=%.6f, n=%d, n/s=%s\n", i, elapsed, model.Score, n, nps)

		// write output image(s)
		for _, output := range Outputs {
			ext := strings.ToLower(filepath.Ext(output))
			saveFrames := strings.Contains(output, "%") && ext != ".gif"
			// saveFrames = saveFrames && i%10 == 0
			if saveFrames || i == Number {
				path := output
				if saveFrames {
					path = fmt.Sprintf(output, i)
				}
				primitive.Log(1, "writing %s\n", path)
				switch ext {
				default:
					check(fmt.Errorf("unrecognized file extension: %s", ext))
				case ".png":
					check(primitive.SavePNG(path, model.Context.Image()))
				case ".jpg", ".jpeg":
					check(primitive.SaveJPG(path, model.Context.Image(), 95))
				case ".svg":
					check(primitive.SaveFile(path, model.SVG()))
				case ".gif":
					frames := model.Frames(0.001)
					check(primitive.SaveGIFImageMagick(path, frames, 50, 250))
				}
			}
		}
	}
}
<commit_msg>-r 0 indicates no resize<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/fogleman/primitive/primitive"
	"github.com/nfnt/resize"
)

var (
	Input      string
	Outputs    flagArray
	Background string
	Number     int
	Alpha      int
	InputSize  int
	OutputSize int
	Mode       int
	Workers    int
	V, VV      bool
)

type flagArray []string

func (i *flagArray) String() string {
	return strings.Join(*i, ", ")
}

func (i *flagArray) Set(value string) error {
	*i = append(*i, value)
	return nil
}

func init() {
	flag.StringVar(&Input, "i", "", "input image path")
	flag.Var(&Outputs, "o", "output image path")
	flag.StringVar(&Background, "bg", "", "background color (hex)")
	flag.IntVar(&Number, "n", 0, "number of primitives")
	flag.IntVar(&Alpha, "a", 128, "alpha value")
	flag.IntVar(&InputSize, "r", 256, "resize large input images to this size")
	flag.IntVar(&OutputSize, "s", 1024, "output image size")
	flag.IntVar(&Mode, "m", 1, "0=combo 1=triangle 2=rect 3=ellipse 4=circle 5=rotatedrect")
	flag.IntVar(&Workers, "j", 0, "number of parallel workers (default uses all cores)")
	flag.BoolVar(&V, "v", false, "verbose")
	flag.BoolVar(&VV, "vv", false, "very verbose")
}

func errorMessage(message string) bool {
	fmt.Fprintln(os.Stderr, message)
	return false
}

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

func main() {
	// parse and validate arguments
	flag.Parse()
	ok := true
	if Input == "" {
		ok = errorMessage("ERROR: input argument required")
	}
	if len(Outputs) == 0 {
		ok = errorMessage("ERROR: output argument required")
	}
	if Number == 0 {
		ok = errorMessage("ERROR: number argument required")
	}
	if !ok {
		fmt.Println("Usage: primitive [OPTIONS] -i input -o output -n shape_count")
		flag.PrintDefaults()
		os.Exit(1)
	}

	// set log level
	if V {
		primitive.LogLevel = 1
	}
	if VV {
		primitive.LogLevel = 2
	}

	// seed random number generator
	rand.Seed(time.Now().UTC().UnixNano())

	// determine worker count
	if Workers < 1 {
		Workers = runtime.NumCPU()
	}

	// read input image
	primitive.Log(1, "reading %s\n", Input)
	input, err := primitive.LoadImage(Input)
	check(err)

	// scale down input image if needed
	size := uint(InputSize)
	if size > 0 {
		input = resize.Thumbnail(size, size, input, resize.Bilinear)
	}

	// determine background color
	var bg primitive.Color
	if Background == "" {
		bg = primitive.MakeColor(primitive.AverageImageColor(input))
	} else {
		bg = primitive.MakeHexColor(Background)
	}

	// run algorithm
	model := primitive.NewModel(input, bg, OutputSize, Workers)
	primitive.Log(1, "%d: t=%.3f, score=%.6f\n", 0, 0.0, model.Score)
	start := time.Now()
	for i := 1; i <= Number; i++ {
		// find optimal shape and add it to the model
		t := time.Now()
		n := model.Step(primitive.ShapeType(Mode), Alpha)
		nps := primitive.NumberString(float64(n) / time.Since(t).Seconds())
		elapsed := time.Since(start).Seconds()
		primitive.Log(1, "%d: t=%.3f, score=%.6f, n=%d, n/s=%s\n", i, elapsed, model.Score, n, nps)

		// write output image(s)
		for _, output := range Outputs {
			ext := strings.ToLower(filepath.Ext(output))
			saveFrames := strings.Contains(output, "%") && ext != ".gif"
			// saveFrames = saveFrames && i%10 == 0
			if saveFrames || i == Number {
				path := output
				if saveFrames {
					path = fmt.Sprintf(output, i)
				}
				primitive.Log(1, "writing %s\n", path)
				switch ext {
				default:
					check(fmt.Errorf("unrecognized file extension: %s", ext))
				case ".png":
					check(primitive.SavePNG(path, model.Context.Image()))
				case ".jpg", ".jpeg":
					check(primitive.SaveJPG(path, model.Context.Image(), 95))
				case ".svg":
					check(primitive.SaveFile(path, model.SVG()))
				case ".gif":
					frames := model.Frames(0.001)
					check(primitive.SaveGIFImageMagick(path, frames, 50, 250))
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

// This software is an expense tracker i made to read the transactions exported from
// my bank account.

import (
	"fmt"
	"go-cli-bank/categories"
	"go-cli-bank/infrastructure"
	"go-cli-bank/reports"
	"os"

	docopt "github.com/docopt/docopt-go"
	// flag "github.com/ogier/pflag"
)

// CommandCreateCategory handles category creation command
func CommandCreateCategory(name string) error {

	dbHandler := infrastructure.DatabaseHandler{}
	cr := categories.CategoryRepository{DBHandler: &dbHandler}
	i := categories.Interactor{Repository: &cr}
	_, err := i.NewCategory(name)
	if err != nil {
		return err
	}

	return nil
}

// CommandShowReport handles report commands
func CommandShowReport(inputFilePath string) error {
	file, err := infrastructure.OpenFile(inputFilePath)
	if err != nil {
		return err
	}
	defer file.Close()

	err = reports.MonthlyReport(file)
	if err != nil {
		return err
	}

	return nil
}

func errorf(format string, args ...interface{}) {
	fmt.Fprintln(os.Stderr, format, args)
	os.Exit(2)
}

var usage = `Your command line money manager.

Usage:
	go-cli-bank -h | --help
	go-cli-bank report --input <file>

Options:
	-f --input    The path to the transactions list.
	-h --help     Show this screen.
`

func main() {

	arguments, _ := docopt.Parse(usage, nil, true, "Go CLI Bank 0.0.1", false)

	// createCategory := arguments[]
	// inputFilePath := ""

	// inputFilePath := flag.String("load", "", "Specify the path to the input file")
	// showReport := flag.Bool("report", false, "Show report")
	// createCategory := flag.String("category", "", "Create category")
	// flag.Parse()

	// if createCategory {
	// 	if err := CommandCreateCategory(createCategory); err != nil {
	// 		errorf("Failed to create category: %v\n", err)
	// 	}
	// }

	if arguments["report"].(bool) {
		if err := CommandShowReport(arguments["<file>"].(string)); err != nil {
			errorf("Failed to show report: %v\n", err)
		}
	}

}

// var DATABASE_NAME string = "./go-cli-bank.db"
// var DATABASE_ENGINE = "sqlite3"

// func toExcel(value decimal.Decimal, description string) {
// 	var file *xlsx.File
// 	var sheet *xlsx.Sheet
// 	var row *xlsx.Row
// 	var cell *xlsx.Cell
// 	var err error

// 	file = xlsx.NewFile()
// 	sheet, err = file.AddSheet("Sheet1")
// 	if err != nil {
// 		fmt.Printf(err.Error())
// 	}
// 	row = sheet.AddRow()
// 	cell = row.AddCell()
// 	cell.Value = description
// 	cell = row.AddCell()
// 	// cell.Value = strconv.FormatFloat(value, 'f', 2, 64)
// 	cell.Value = value.String()

// 	err = file.Save("MyXLSXFile.xlsx")
// 	if err != nil {
// 		fmt.Printf(err.Error())
// 	}
// }
<commit_msg>Uses docopt to create category<commit_after>package main

// This software is an expense tracker i made to read the transactions exported from
// my bank account.

import (
	"fmt"
	"go-cli-bank/categories"
	"go-cli-bank/infrastructure"
	"go-cli-bank/reports"
	"os"

	docopt "github.com/docopt/docopt-go"
	// flag "github.com/ogier/pflag"
)

// CommandCreateCategory handles category creation command
func CommandCreateCategory(name string) error {

	dbHandler := infrastructure.DatabaseHandler{}
	cr := categories.CategoryRepository{DBHandler: &dbHandler}
	i := categories.Interactor{Repository: &cr}
	_, err := i.NewCategory(name)
	if err != nil {
		return err
	}

	return nil
}

// CommandShowReport handles report commands
func CommandShowReport(inputFilePath string) error {
	file, err := infrastructure.OpenFile(inputFilePath)
	if err != nil {
		return err
	}
	defer file.Close()

	err = reports.MonthlyReport(file)
	if err != nil {
		return err
	}

	return nil
}

func errorf(format string, args ...interface{}) {
	fmt.Fprintln(os.Stderr, format, args)
	os.Exit(2)
}

var usage = `Your command line money manager.

Usage:
	go-cli-bank -h | --help
	go-cli-bank report --input <file>
	go-cli-bank category new <name>

Options:
	--input    The path to the transactions list.
	-h --help     Show this screen.
`

func main() {

	arguments, _ := docopt.Parse(usage, nil, true, "Go CLI Bank 0.0.1", false)

	if arguments["category"].(bool) && arguments["new"].(bool) {
		if err := CommandCreateCategory(arguments["<name>"].(string)); err != nil {
			errorf("Failed to create category: %v\n", err)
		}
	}

	if arguments["report"].(bool) {
		if err := CommandShowReport(arguments["<file>"].(string)); err != nil {
			errorf("Failed to show report: %v\n", err)
		}
	}

}

// var DATABASE_NAME string = "./go-cli-bank.db"
// var DATABASE_ENGINE = "sqlite3"

// func toExcel(value decimal.Decimal, description string) {
// 	var file *xlsx.File
// 	var sheet *xlsx.Sheet
// 	var row *xlsx.Row
// 	var cell *xlsx.Cell
// 	var err error

// 	file = xlsx.NewFile()
// 	sheet, err = file.AddSheet("Sheet1")
// 	if err != nil {
// 		fmt.Printf(err.Error())
// 	}
// 	row = sheet.AddRow()
// 	cell = row.AddCell()
// 	cell.Value = description
// 	cell = row.AddCell()
// 	// cell.Value = strconv.FormatFloat(value, 'f', 2, 64)
// 	cell.Value = value.String()

// 	err = file.Save("MyXLSXFile.xlsx")
// 	if err != nil {
// 		fmt.Printf(err.Error())
// 	}
// }
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/go.tools/go/types"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
)

var (
	universe string
	own      string
)

func init() {
	flag.StringVar(&universe, "universe", "std", "Comma-separated list of Which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&own, "own", "", "Comma-separated list of packages whose types to check for implemented interfaces.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Context
}

func NewContext() *Context {
	ctx := &Context{
		allImports: make(map[string]*types.Package),
	}

	ctx.context = types.Context{
		Import: ctx.importer,
	}

	return ctx
}

func (ctx *Context) importer(imports map[string]*types.Package, path string) (pkg *types.Package, err error) {
	// types.Importer does not seem to be designed for recursive
	// parsing like we're doing here. Specifically, each nested import
	// will maintain its own imports map. This will lead to duplicate
	// imports and in turn packages, which will lead to funny errors
	// such as "cannot pass argument ip (variable of type net.IP) to
	// variable of type net.IP"
	//
	// To work around this, we keep a global imports map, allImports,
	// to which we add all nested imports, and which we use as the
	// cache, instead of imports.
	//
	// Since all nested imports will also use this importer, there
	// should be no way to end up with duplicate imports.

	// We first try to use GcImport directly. This has the downside of
	// using possibly out-of-date packages, but it has the upside of
	// not having to parse most of the Go standard library.

	buildPkg, buildErr := build.Import(path, ".", 0)
	// If we found no build dir, assume we're dealing with installed
	// but no source. If we found a build dir, only use GcImport if
	// it's in GOROOT. This way we always use up-to-date code for
	// normal packages but avoid parsing the standard library.
	if (buildErr == nil && buildPkg.Goroot) || buildErr != nil {
		pkg, err = types.GcImport(ctx.allImports, path)
		if err == nil {
			// We don't use imports, but per API we have to add the package.
			imports[pkg.Path()] = pkg
			ctx.allImports[pkg.Path()] = pkg
			return pkg, nil
		}
	}

	// See if we already imported this package
	if pkg = ctx.allImports[path]; pkg != nil && pkg.Complete() {
		return pkg, nil
	}

	// allImports failed, try to use go/build
	if buildErr != nil {
		return nil, buildErr
	}

	// TODO check if the .a file is up to date and use it instead
	fmt.Println("we have to build", path, "ourselves")
	fileSet := token.NewFileSet()

	isGoFile := func(d os.FileInfo) bool {
		allFiles := make([]string, 0, len(buildPkg.GoFiles)+len(buildPkg.CgoFiles))
		allFiles = append(allFiles, buildPkg.GoFiles...)
		allFiles = append(allFiles, buildPkg.CgoFiles...)

		for _, file := range allFiles {
			if file == d.Name() {
				return true
			}
		}
		return false
	}
	pkgs, err := parser.ParseDir(fileSet, buildPkg.Dir, isGoFile, 0)
	if err != nil {
		return nil, err
	}

	delete(pkgs, "documentation")
	var astPkg *ast.Package
	var name string
	for name, astPkg = range pkgs {
		// Use the first non-main package, or the only package we
		// found.
		//
		// NOTE(dh) I can't think of a reason why there should be
		// multiple packages in a single directory, but ParseDir
		// accommodates for that possibility.
		if len(pkgs) == 1 || name != "main" {
			break
		}
	}

	if astPkg == nil {
		return nil, fmt.Errorf("can't find import: %s", name)
	}

	var ff []*ast.File
	for _, f := range astPkg.Files {
		ff = append(ff, f)
	}

	context := types.Context{
		Import: ctx.importer,
	}

	pkg, err = context.Check(name, fileSet, ff...)
	if err != nil {
		return pkg, err
	}
	if !pkg.Complete() {
		pkg = types.NewPackage(pkg.Pos(), pkg.Path(), pkg.Name(), pkg.Scope(), pkg.Imports(), true)
	}

	imports[path] = pkg
	ctx.allImports[path] = pkg
	return pkg, nil
}

func (ctx *Context) getTypes(paths ...string) []Type {
	var typs []Type

	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			// FIXME better error handling
			fmt.Printf("Couldn't import %s: %s\n", path, err)
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			fmt.Println("GcImport", path)
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				// TODO better error handling
				fmt.Printf("Couldn't import %s: %s\n", path, err)
				continue
			}
		} else {
			fmt.Println("Manual parsing", path)
			if len(buildPkg.GoFiles) == 0 {
				// TODO proper error handling
				fmt.Printf("Couldn't parse %s: No go files\n", path)
				continue
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					// TODO proper error handling
					fmt.Printf("Couldn't parse %s: %s", err)
					continue
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				// FIXME better error handling
				fmt.Printf("Couldn't parse %s: %s\n", path, err)
				continue
			}
			fmt.Println(pkg.Name(), pkg.Complete())
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles...)
}

func main() {
	if own == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	stdlib := ctx.getTypes(matchPackages(universe)...)
	toCheck := ctx.getTypes(matchPackages(own)...)

	interfaces := getInterfaces(stdlib)

	for _, typ := range toCheck {
		var implements []string
		var implementsPointer []string
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if fnc, _ := types.MissingMethod(typ.Object.Type(), iface.Underlying); fnc == nil {
				s := fmt.Sprintf("%s.%s",
					iface.Obj.Pkg().Name(), iface.Name)
				implements = append(implements, s)
			}

			// TODO DRY
			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if fnc, _ := types.MissingMethod(typ.Pointer.Underlying(), iface.Underlying); fnc == nil {
					s := fmt.Sprintf("%s.%s",
						iface.Obj.Pkg().Name(), iface.Name)
					implementsPointer = append(implementsPointer, s)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Name(), typ.Object.Name())
			for _, impl := range implements {
				fmt.Printf("\t%s\n", impl)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Name(), typ.Object.Name())
			for _, impl := range implementsPointer {
				fmt.Printf("\t%s\n", impl)
			}
		}
	}
}
<commit_msg>remove debug output for gc imported packages<commit_after>package main

import (
	"code.google.com/p/go.tools/go/types"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
)

var (
	universe string
	own      string
)

func init() {
	flag.StringVar(&universe, "universe", "std", "Comma-separated list of Which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&own, "own", "", "Comma-separated list of packages whose types to check for implemented interfaces.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Context
}

func NewContext() *Context {
	ctx := &Context{
		allImports: make(map[string]*types.Package),
	}

	ctx.context = types.Context{
		Import: ctx.importer,
	}

	return ctx
}

func (ctx *Context) importer(imports map[string]*types.Package, path string) (pkg *types.Package, err error) {
	// types.Importer does not seem to be designed for recursive
	// parsing like we're doing here. Specifically, each nested import
	// will maintain its own imports map. This will lead to duplicate
	// imports and in turn packages, which will lead to funny errors
	// such as "cannot pass argument ip (variable of type net.IP) to
	// variable of type net.IP"
	//
	// To work around this, we keep a global imports map, allImports,
	// to which we add all nested imports, and which we use as the
	// cache, instead of imports.
	//
	// Since all nested imports will also use this importer, there
	// should be no way to end up with duplicate imports.

	// We first try to use GcImport directly. This has the downside of
	// using possibly out-of-date packages, but it has the upside of
	// not having to parse most of the Go standard library.

	buildPkg, buildErr := build.Import(path, ".", 0)
	// If we found no build dir, assume we're dealing with installed
	// but no source. If we found a build dir, only use GcImport if
	// it's in GOROOT. This way we always use up-to-date code for
	// normal packages but avoid parsing the standard library.
	if (buildErr == nil && buildPkg.Goroot) || buildErr != nil {
		pkg, err = types.GcImport(ctx.allImports, path)
		if err == nil {
			// We don't use imports, but per API we have to add the package.
			imports[pkg.Path()] = pkg
			ctx.allImports[pkg.Path()] = pkg
			return pkg, nil
		}
	}

	// See if we already imported this package
	if pkg = ctx.allImports[path]; pkg != nil && pkg.Complete() {
		return pkg, nil
	}

	// allImports failed, try to use go/build
	if buildErr != nil {
		return nil, buildErr
	}

	// TODO check if the .a file is up to date and use it instead
	fmt.Println("we have to build", path, "ourselves")
	fileSet := token.NewFileSet()

	isGoFile := func(d os.FileInfo) bool {
		allFiles := make([]string, 0, len(buildPkg.GoFiles)+len(buildPkg.CgoFiles))
		allFiles = append(allFiles, buildPkg.GoFiles...)
		allFiles = append(allFiles, buildPkg.CgoFiles...)

		for _, file := range allFiles {
			if file == d.Name() {
				return true
			}
		}
		return false
	}
	pkgs, err := parser.ParseDir(fileSet, buildPkg.Dir, isGoFile, 0)
	if err != nil {
		return nil, err
	}

	delete(pkgs, "documentation")
	var astPkg *ast.Package
	var name string
	for name, astPkg = range pkgs {
		// Use the first non-main package, or the only package we
		// found.
		//
		// NOTE(dh) I can't think of a reason why there should be
		// multiple packages in a single directory, but ParseDir
		// accommodates for that possibility.
		if len(pkgs) == 1 || name != "main" {
			break
		}
	}

	if astPkg == nil {
		return nil, fmt.Errorf("can't find import: %s", name)
	}

	var ff []*ast.File
	for _, f := range astPkg.Files {
		ff = append(ff, f)
	}

	context := types.Context{
		Import: ctx.importer,
	}

	pkg, err = context.Check(name, fileSet, ff...)
	if err != nil {
		return pkg, err
	}
	if !pkg.Complete() {
		pkg = types.NewPackage(pkg.Pos(), pkg.Path(), pkg.Name(), pkg.Scope(), pkg.Imports(), true)
	}

	imports[path] = pkg
	ctx.allImports[path] = pkg
	return pkg, nil
}

func (ctx *Context) getTypes(paths ...string) []Type {
	var typs []Type

	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			// FIXME better error handling
			fmt.Printf("Couldn't import %s: %s\n", path, err)
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				// TODO better error handling
				fmt.Printf("Couldn't import %s: %s\n", path, err)
				continue
			}
		} else {
			fmt.Println("Manual parsing", path)
			if len(buildPkg.GoFiles) == 0 {
				// TODO proper error handling
				fmt.Printf("Couldn't parse %s: No go files\n", path)
				continue
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					// TODO proper error handling
					fmt.Printf("Couldn't parse %s: %s", err)
					continue
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				// FIXME better error handling
				fmt.Printf("Couldn't parse %s: %s\n", path, err)
				continue
			}
			fmt.Println(pkg.Name(), pkg.Complete())
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles...)
}

func main() {
	if own == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	stdlib := ctx.getTypes(matchPackages(universe)...)
	toCheck := ctx.getTypes(matchPackages(own)...)

	interfaces := getInterfaces(stdlib)

	for _, typ := range toCheck {
		var implements []string
		var implementsPointer []string
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if fnc, _ := types.MissingMethod(typ.Object.Type(), iface.Underlying); fnc == nil {
				s := fmt.Sprintf("%s.%s",
					iface.Obj.Pkg().Name(), iface.Name)
				implements = append(implements, s)
			}

			// TODO DRY
			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if fnc, _ := types.MissingMethod(typ.Pointer.Underlying(), iface.Underlying); fnc == nil {
					s := fmt.Sprintf("%s.%s",
						iface.Obj.Pkg().Name(), iface.Name)
					implementsPointer = append(implementsPointer, s)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Name(), typ.Object.Name())
			for _, impl := range implements {
				fmt.Printf("\t%s\n", impl)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Name(), typ.Object.Name())
			for _, impl := range implementsPointer {
				fmt.Printf("\t%s\n", impl)
			}
		}
	}
}
<|endoftext|>