<commit_before>package sql

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"
)

// Run executes a SQL query and returns a stream of row or message
func Run(slct string, db *DB) *PipeReader {
	slctUpper := strings.ToUpper(slct)
	if strings.Contains(slctUpper, "TRAIN") || strings.Contains(slctUpper, "PREDICT") {
		pr, e := newParser().Parse(slct)
		if e == nil && pr.extended {
			return runExtendedSQL(slct, db, pr)
		}
	}
	return runStandardSQL(slct, db)
}

// TODO(weiguo): isQuery is a hacky way to decide which API to call:
// https://golang.org/pkg/database/sql/#DB.Exec .
// We will need to extend our parser to be a full SQL parser in the future.
func isQuery(slct string) bool {
	s := strings.ToUpper(strings.TrimSpace(slct))
	has := strings.Contains
	if strings.HasPrefix(s, "SELECT") && !has(s, "INTO") {
		return true
	}
	if strings.HasPrefix(s, "SHOW") && (has(s, "CREATE") || has(s, "DATABASES") || has(s, "TABLES")) {
		return true
	}
	if strings.HasPrefix(s, "DESCRIBE") {
		return true
	}
	return false
}

func runStandardSQL(slct string, db *DB) *PipeReader {
	if isQuery(slct) {
		return runQuery(slct, db)
	}
	return runExec(slct, db)
}

// FIXME(tony): how to deal with large tables?
// TODO(tony): test on null table elements
func runQuery(slct string, db *DB) *PipeReader {
	rd, wr := Pipe()
	go func() {
		defer wr.Close()

		err := func() error {
			defer func(startAt time.Time) {
				log.Debugf("runQuery %v finished, elapsed:%v", slct, time.Since(startAt))
			}(time.Now())

			rows, err := db.Query(slct)
			if err != nil {
				return fmt.Errorf("runQuery failed: %v", err)
			}
			defer rows.Close()

			cols, err := rows.Columns()
			if err != nil {
				return fmt.Errorf("failed to get columns: %v", err)
			}

			header := make(map[string]interface{})
			header["columnNames"] = cols
			if e := wr.Write(header); e != nil {
				return e
			}

			for rows.Next() {
				// Since we don't know the table schema in advance, need to
				// create an slice of empty interface and adds column type
				// at runtime. Some databases support dynamic types between
				// rows, such as sqlite's affinity. So we move columnTypes inside
				// the row.Next() loop.
				count := len(cols)
				values := make([]interface{}, count)
				columnTypes, err := rows.ColumnTypes()
				if err != nil {
					return fmt.Errorf("failed to get columnTypes: %v", err)
				}
				for i, ct := range columnTypes {
					v, e := createByType(ct.ScanType())
					if e != nil {
						return e
					}
					values[i] = v
				}

				if err := rows.Scan(values...); err != nil {
					return err
				}

				row := make([]interface{}, count)
				for i, val := range values {
					v, e := parseVal(val)
					if e != nil {
						return e
					}
					row[i] = v
				}
				if e := wr.Write(row); e != nil {
					return e
				}
			}
			return nil
		}()

		if err != nil {
			log.Errorf("runQuery error:%v", err)
			if err != ErrClosedPipe {
				if err := wr.Write(err); err != nil {
					log.Errorf("runQuery error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

func runExec(slct string, db *DB) *PipeReader {
	rd, wr := Pipe()
	go func() {
		defer wr.Close()

		err := func() error {
			defer func(startAt time.Time) {
				log.Debugf("runEexc %v finished, elapsed:%v", slct, time.Since(startAt))
			}(time.Now())

			res, e := db.Exec(slct)
			if e != nil {
				return fmt.Errorf("runExec failed: %v", e)
			}
			affected, e := res.RowsAffected()
			if e != nil {
				return fmt.Errorf("failed to get affected row number: %v", e)
			}
			if affected > 1 {
				return wr.Write(fmt.Sprintf("%d rows affected", affected))
			}
			return wr.Write(fmt.Sprintf("%d row affected", affected))
		}()
		if err != nil {
			log.Errorf("runExec error:%v", err)
			if err != ErrClosedPipe {
				if err := wr.Write(err); err != nil {
					log.Errorf("runExec error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

func runExtendedSQL(slct string, db *DB, pr *extendedSelect) *PipeReader {
	rd, wr := Pipe()
	go func() {
		defer wr.Close()

		err := func() error {
			defer func(startAt time.Time) {
				log.Debugf("runExtendedSQL %v finished, elapsed:%v", slct, time.Since(startAt))
			}(time.Now())

			// NOTE: the temporary directory must be in a host directory
			// which can be mounted to Docker containers.  If I don't
			// specify the "/tmp" prefix, ioutil.TempDir would by default
			// generate a directory in /private/tmp for macOS, which
			// cannot be mounted by Docker into the container.  For more
			// detailed, please refer to
			// https://docs.docker.com/docker-for-mac/osxfs/#namespaces.
			cwd, e := ioutil.TempDir("/tmp", "sqlflow")
			if e != nil {
				return e
			}
			defer os.RemoveAll(cwd)

			// FIXME(tony): temporary branch to alps
			if os.Getenv("SQLFLOW_submitter") == "alps" {
				return submitALPS(wr, pr, db, cwd)
			}

			if pr.train {
				return train(pr, slct, db, cwd, wr)
			}
			return pred(pr, db, cwd, wr)
		}()

		if err != nil {
			log.Errorf("runExtendedSQL error:%v", err)
			if err != ErrClosedPipe {
				if err := wr.Write(err); err != nil {
					log.Errorf("runExtendedSQL error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

type logChanWriter struct {
	wr *PipeWriter

	m    sync.Mutex
	buf  bytes.Buffer
	prev string
}

func (cw *logChanWriter) Write(p []byte) (n int, err error) {
	// Both cmd.Stdout and cmd.Stderr are writing to cw
	cw.m.Lock()
	defer cw.m.Unlock()

	n, err = cw.buf.Write(p)
	if err != nil {
		return n, err
	}

	for {
		line, err := cw.buf.ReadString('\n')
		cw.prev = cw.prev + line
		// ReadString returns err != nil if and only if the returned Data
		// does not end in delim.
		if err != nil {
			break
		}

		if err := cw.wr.Write(cw.prev); err != nil {
			return len(cw.prev), err
		}
		cw.prev = ""
	}
	return n, nil
}

func train(tr *extendedSelect, slct string, db *DB, cwd string, wr *PipeWriter) error {
	fts, e := verify(tr, db)
	if e != nil {
		return e
	}

	var program bytes.Buffer
	if e := genTF(&program, tr, fts, db); e != nil {
		return e
	}

	cw := &logChanWriter{wr: wr}
	cmd := tensorflowCmd(cwd, db.driverName)
	cmd.Stdin = &program
	cmd.Stdout = cw
	cmd.Stderr = cw
	if e := cmd.Run(); e != nil {
		return fmt.Errorf("training failed %v", e)
	}

	m := model{workDir: cwd, TrainSelect: slct}
	return m.save(db, tr.save)
}

func pred(pr *extendedSelect, db *DB, cwd string, wr *PipeWriter) error {
	m, e := load(db, pr.model, cwd)
	if e != nil {
		return e
	}

	// Parse the training SELECT statement used to train
	// the model for the prediction.
	tr, e := newParser().Parse(m.TrainSelect)
	if e != nil {
		return e
	}

	if e := verifyColumnNameAndType(tr, pr, db); e != nil {
		return e
	}

	if e := createPredictionTable(tr, pr, db); e != nil {
		return e
	}

	pr.trainClause = tr.trainClause
	fts, e := verify(pr, db)

	var buf bytes.Buffer
	if e := genTF(&buf, pr, fts, db); e != nil {
		return e
	}

	cw := &logChanWriter{wr: wr}
	cmd := tensorflowCmd(cwd, db.driverName)
	cmd.Stdin = &buf
	cmd.Stdout = cw
	cmd.Stderr = cw
	return cmd.Run()
}

// Create prediction table with appropriate column type.
// If prediction table already exists, it will be overwritten.
func createPredictionTable(trainParsed, predParsed *extendedSelect, db *DB) error {
	if len(strings.Split(predParsed.into, ".")) != 3 {
		return fmt.Errorf("invalid predParsed.into %s. should be DBName.TableName.ColumnName", predParsed.into)
	}
	tableName := strings.Join(strings.Split(predParsed.into, ".")[:2], ".")
	columnName := strings.Split(predParsed.into, ".")[2]

	dropStmt := fmt.Sprintf("drop table if exists %s;", tableName)
	if _, e := db.Query(dropStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", dropStmt, e)
	}

	fts, e := verify(trainParsed, db)
	if e != nil {
		return e
	}

	var b bytes.Buffer
	fmt.Fprintf(&b, "create table %s (", tableName)
	for _, c := range trainParsed.columns {
		typ, ok := fts.get(c.val)
		if !ok {
			return fmt.Errorf("createPredictionTable: Cannot find type of field %s", c.val)
		}
		stype, e := universalizeColumnType(db.driverName, typ)
		if e != nil {
			return e
		}
		fmt.Fprintf(&b, "%s %s, ", c.val, stype)
	}
	typ, _ := fts.get(trainParsed.label)
	stype, e := universalizeColumnType(db.driverName, typ)
	if e != nil {
		return e
	}
	fmt.Fprintf(&b, "%s %s);", columnName, stype)

	createStmt := b.String()
	if _, e := db.Query(createStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", createStmt, e)
	}
	return nil
}
<commit_msg>Shorten function runQuery (#420)<commit_after>package sql

import (
	"bytes"
	"database/sql"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"time"
)

// Run executes a SQL query and returns a stream of row or message
func Run(slct string, db *DB) *PipeReader {
	slctUpper := strings.ToUpper(slct)
	if strings.Contains(slctUpper, "TRAIN") || strings.Contains(slctUpper, "PREDICT") {
		pr, e := newParser().Parse(slct)
		if e == nil && pr.extended {
			return runExtendedSQL(slct, db, pr)
		}
	}
	return runStandardSQL(slct, db)
}

// TODO(weiguo): isQuery is a hacky way to decide which API to call:
// https://golang.org/pkg/database/sql/#DB.Exec .
// We will need to extend our parser to be a full SQL parser in the future.
func isQuery(slct string) bool {
	s := strings.ToUpper(strings.TrimSpace(slct))
	has := strings.Contains
	if strings.HasPrefix(s, "SELECT") && !has(s, "INTO") {
		return true
	}
	if strings.HasPrefix(s, "SHOW") && (has(s, "CREATE") || has(s, "DATABASES") || has(s, "TABLES")) {
		return true
	}
	if strings.HasPrefix(s, "DESCRIBE") {
		return true
	}
	return false
}

func runStandardSQL(slct string, db *DB) *PipeReader {
	if isQuery(slct) {
		return runQuery(slct, db)
	}
	return runExec(slct, db)
}

// query runs slct and writes the retrieved rows into pipe wr.
func query(slct string, db *DB, wr *PipeWriter) error {
	defer func(startAt time.Time) {
		log.Debugf("runQuery %v finished, elapsed:%v", slct, time.Since(startAt))
	}(time.Now())

	rows, err := db.Query(slct)
	if err != nil {
		return fmt.Errorf("runQuery failed: %v", err)
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return fmt.Errorf("failed to get columns: %v", err)
	}

	columnTypes, err := rows.ColumnTypes()
	if err != nil {
		return fmt.Errorf("failed to get columnTypes: %v", err)
	}

	header := make(map[string]interface{})
	header["columnNames"] = columns
	if e := wr.Write(header); e != nil {
		return e
	}

	for rows.Next() {
		if e := parseRow(columns, columnTypes, rows, wr); e != nil {
			return e
		}
	}
	return nil
}

// parseRow calls rows.Scan to retrieve the current row, and convert
// each cell value from {}interface to an accurary value.  It then
// writes the converted row into wr.
func parseRow(columns []string, columnTypes []*sql.ColumnType, rows *sql.Rows, wr *PipeWriter) error {
	// Since we don't know the table schema in advance, we create
	// a slice of empty interface and add column types at
	// runtime. Some databases support dynamic types between rows,
	// such as sqlite's affinity. So we move columnTypes inside
	// the row.Next() loop.
	count := len(columns)
	values := make([]interface{}, count)
	for i, ct := range columnTypes {
		v, e := createByType(ct.ScanType())
		if e != nil {
			return e
		}
		values[i] = v
	}

	if err := rows.Scan(values...); err != nil {
		return err
	}

	row := make([]interface{}, count)
	for i, val := range values {
		v, e := parseVal(val)
		if e != nil {
			return e
		}
		row[i] = v
	}
	if e := wr.Write(row); e != nil {
		return e
	}
	return nil
}

// runQeury creates a pipe before starting a goroutine that execute
// query, which runs slct and writes retrieved rows to a pipe.
// runQuery returns the read end of the pipe.  The caller doesn't have
// to close the pipe because the query goroutine will close it after
// data retrieval.
func runQuery(slct string, db *DB) *PipeReader {
	// FIXME(tony): how to deal with large tables?
	// TODO(tony): test on null table elements
	rd, wr := Pipe()
	go func() {
		defer wr.Close()
		if e := query(slct, db, wr); e != nil {
			log.Errorf("runQuery error:%v", e)
			if e != ErrClosedPipe {
				if err := wr.Write(e); err != nil {
					log.Errorf("runQuery error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

func runExec(slct string, db *DB) *PipeReader {
	rd, wr := Pipe()
	go func() {
		defer wr.Close()

		err := func() error {
			defer func(startAt time.Time) {
				log.Debugf("runEexc %v finished, elapsed:%v", slct, time.Since(startAt))
			}(time.Now())

			res, e := db.Exec(slct)
			if e != nil {
				return fmt.Errorf("runExec failed: %v", e)
			}
			affected, e := res.RowsAffected()
			if e != nil {
				return fmt.Errorf("failed to get affected row number: %v", e)
			}
			if affected > 1 {
				return wr.Write(fmt.Sprintf("%d rows affected", affected))
			}
			return wr.Write(fmt.Sprintf("%d row affected", affected))
		}()
		if err != nil {
			log.Errorf("runExec error:%v", err)
			if err != ErrClosedPipe {
				if err := wr.Write(err); err != nil {
					log.Errorf("runExec error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

func runExtendedSQL(slct string, db *DB, pr *extendedSelect) *PipeReader {
	rd, wr := Pipe()
	go func() {
		defer wr.Close()

		err := func() error {
			defer func(startAt time.Time) {
				log.Debugf("runExtendedSQL %v finished, elapsed:%v", slct, time.Since(startAt))
			}(time.Now())

			// NOTE: the temporary directory must be in a host directory
			// which can be mounted to Docker containers.  If I don't
			// specify the "/tmp" prefix, ioutil.TempDir would by default
			// generate a directory in /private/tmp for macOS, which
			// cannot be mounted by Docker into the container.  For more
			// detailed, please refer to
			// https://docs.docker.com/docker-for-mac/osxfs/#namespaces.
			cwd, e := ioutil.TempDir("/tmp", "sqlflow")
			if e != nil {
				return e
			}
			defer os.RemoveAll(cwd)

			// FIXME(tony): temporary branch to alps
			if os.Getenv("SQLFLOW_submitter") == "alps" {
				return submitALPS(wr, pr, db, cwd)
			}

			if pr.train {
				return train(pr, slct, db, cwd, wr)
			}
			return pred(pr, db, cwd, wr)
		}()

		if err != nil {
			log.Errorf("runExtendedSQL error:%v", err)
			if err != ErrClosedPipe {
				if err := wr.Write(err); err != nil {
					log.Errorf("runExtendedSQL error(piping):%v", err)
				}
			}
		}
	}()
	return rd
}

type logChanWriter struct {
	wr *PipeWriter

	m    sync.Mutex
	buf  bytes.Buffer
	prev string
}

func (cw *logChanWriter) Write(p []byte) (n int, err error) {
	// Both cmd.Stdout and cmd.Stderr are writing to cw
	cw.m.Lock()
	defer cw.m.Unlock()

	n, err = cw.buf.Write(p)
	if err != nil {
		return n, err
	}

	for {
		line, err := cw.buf.ReadString('\n')
		cw.prev = cw.prev + line
		// ReadString returns err != nil if and only if the returned Data
		// does not end in delim.
		if err != nil {
			break
		}

		if err := cw.wr.Write(cw.prev); err != nil {
			return len(cw.prev), err
		}
		cw.prev = ""
	}
	return n, nil
}

func train(tr *extendedSelect, slct string, db *DB, cwd string, wr *PipeWriter) error {
	fts, e := verify(tr, db)
	if e != nil {
		return e
	}

	var program bytes.Buffer
	if e := genTF(&program, tr, fts, db); e != nil {
		return e
	}

	cw := &logChanWriter{wr: wr}
	cmd := tensorflowCmd(cwd, db.driverName)
	cmd.Stdin = &program
	cmd.Stdout = cw
	cmd.Stderr = cw
	if e := cmd.Run(); e != nil {
		return fmt.Errorf("training failed %v", e)
	}

	m := model{workDir: cwd, TrainSelect: slct}
	return m.save(db, tr.save)
}

func pred(pr *extendedSelect, db *DB, cwd string, wr *PipeWriter) error {
	m, e := load(db, pr.model, cwd)
	if e != nil {
		return e
	}

	// Parse the training SELECT statement used to train
	// the model for the prediction.
	tr, e := newParser().Parse(m.TrainSelect)
	if e != nil {
		return e
	}

	if e := verifyColumnNameAndType(tr, pr, db); e != nil {
		return e
	}

	if e := createPredictionTable(tr, pr, db); e != nil {
		return e
	}

	pr.trainClause = tr.trainClause
	fts, e := verify(pr, db)

	var buf bytes.Buffer
	if e := genTF(&buf, pr, fts, db); e != nil {
		return e
	}

	cw := &logChanWriter{wr: wr}
	cmd := tensorflowCmd(cwd, db.driverName)
	cmd.Stdin = &buf
	cmd.Stdout = cw
	cmd.Stderr = cw
	return cmd.Run()
}

// Create prediction table with appropriate column type.
// If prediction table already exists, it will be overwritten.
func createPredictionTable(trainParsed, predParsed *extendedSelect, db *DB) error {
	if len(strings.Split(predParsed.into, ".")) != 3 {
		return fmt.Errorf("invalid predParsed.into %s. should be DBName.TableName.ColumnName", predParsed.into)
	}
	tableName := strings.Join(strings.Split(predParsed.into, ".")[:2], ".")
	columnName := strings.Split(predParsed.into, ".")[2]

	dropStmt := fmt.Sprintf("drop table if exists %s;", tableName)
	if _, e := db.Query(dropStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", dropStmt, e)
	}

	fts, e := verify(trainParsed, db)
	if e != nil {
		return e
	}

	var b bytes.Buffer
	fmt.Fprintf(&b, "create table %s (", tableName)
	for _, c := range trainParsed.columns {
		typ, ok := fts.get(c.val)
		if !ok {
			return fmt.Errorf("createPredictionTable: Cannot find type of field %s", c.val)
		}
		stype, e := universalizeColumnType(db.driverName, typ)
		if e != nil {
			return e
		}
		fmt.Fprintf(&b, "%s %s, ", c.val, stype)
	}
	typ, _ := fts.get(trainParsed.label)
	stype, e := universalizeColumnType(db.driverName, typ)
	if e != nil {
		return e
	}
	fmt.Fprintf(&b, "%s %s);", columnName, stype)

	createStmt := b.String()
	if _, e := db.Query(createStmt); e != nil {
		return fmt.Errorf("failed executing %s: %q", createStmt, e)
	}
	return nil
}
<|endoftext|>


<commit_before>// Package version implements the version command for any microservice.
package version

import (
	"fmt"
	"runtime"

	"github.com/spf13/cobra"

	"github.com/giantswarm/microerror"
)

// Config represents the configuration used to create a new version command.
type Config struct {
	// Settings.
	Description string
	GitCommit   string
	Name        string
	Source      string
}

// DefaultConfig provides a default configuration to create a new version
// command by best effort.
func DefaultConfig() Config {
	return Config{
		// Settings.
		Description: "",
		GitCommit:   "",
		Name:        "",
		Source:      "",
	}
}

// New creates a new configured version command.
func New(config Config) (Command, error) {
	// Settings.
	if config.Description == "" {
		return nil, microerror.Maskf(invalidConfigError, "description commit must not be empty")
	}
	if config.GitCommit == "" {
		return nil, microerror.Maskf(invalidConfigError, "git commit must not be empty")
	}
	if config.Name == "" {
		return nil, microerror.Maskf(invalidConfigError, "name must not be empty")
	}
	if config.Source == "" {
		return nil, microerror.Maskf(invalidConfigError, "name must not be empty")
	}

	newCommand := &command{
		// Internals.
		cobraCommand: nil,

		// Settings.
		description: config.Description,
		gitCommit:   config.GitCommit,
		name:        config.Name,
		source:      config.Source,
	}

	newCommand.cobraCommand = &cobra.Command{
		Use:   "version",
		Short: "Show version information of the microservice.",
		Long:  "Show version information of the microservice.",
		Run:   newCommand.Execute,
	}

	return newCommand, nil
}

type command struct {
	// Internals.
	cobraCommand *cobra.Command

	// Settings.
	description string
	gitCommit   string
	name        string
	source      string
}

func (c *command) CobraCommand() *cobra.Command {
	return c.cobraCommand
}

func (c *command) Execute(cmd *cobra.Command, args []string) {
	fmt.Printf("Description:    %s\n", c.description)
	fmt.Printf("Git Commit:     %s\n", c.gitCommit)
	fmt.Printf("Go Version:     %s\n", runtime.Version())
	fmt.Printf("Name:           %s\n", c.name)
	fmt.Printf("OS / Arch:      %s / %s\n", runtime.GOOS, runtime.GOARCH)
	fmt.Printf("Source:         %s\n", c.source)
}
<commit_msg>Fixing error annotation (name -> source) (#97)<commit_after>// Package version implements the version command for any microservice.
package version

import (
	"fmt"
	"runtime"

	"github.com/spf13/cobra"

	"github.com/giantswarm/microerror"
)

// Config represents the configuration used to create a new version command.
type Config struct {
	// Settings.
	Description string
	GitCommit   string
	Name        string
	Source      string
}

// DefaultConfig provides a default configuration to create a new version
// command by best effort.
func DefaultConfig() Config {
	return Config{
		// Settings.
		Description: "",
		GitCommit:   "",
		Name:        "",
		Source:      "",
	}
}

// New creates a new configured version command.
func New(config Config) (Command, error) {
	// Settings.
	if config.Description == "" {
		return nil, microerror.Maskf(invalidConfigError, "description commit must not be empty")
	}
	if config.GitCommit == "" {
		return nil, microerror.Maskf(invalidConfigError, "git commit must not be empty")
	}
	if config.Name == "" {
		return nil, microerror.Maskf(invalidConfigError, "name must not be empty")
	}
	if config.Source == "" {
		return nil, microerror.Maskf(invalidConfigError, "source must not be empty")
	}

	newCommand := &command{
		// Internals.
		cobraCommand: nil,

		// Settings.
		description: config.Description,
		gitCommit:   config.GitCommit,
		name:        config.Name,
		source:      config.Source,
	}

	newCommand.cobraCommand = &cobra.Command{
		Use:   "version",
		Short: "Show version information of the microservice.",
		Long:  "Show version information of the microservice.",
		Run:   newCommand.Execute,
	}

	return newCommand, nil
}

type command struct {
	// Internals.
	cobraCommand *cobra.Command

	// Settings.
	description string
	gitCommit   string
	name        string
	source      string
}

func (c *command) CobraCommand() *cobra.Command {
	return c.cobraCommand
}

func (c *command) Execute(cmd *cobra.Command, args []string) {
	fmt.Printf("Description:    %s\n", c.description)
	fmt.Printf("Git Commit:     %s\n", c.gitCommit)
	fmt.Printf("Go Version:     %s\n", runtime.Version())
	fmt.Printf("Name:           %s\n", c.name)
	fmt.Printf("OS / Arch:      %s / %s\n", runtime.GOOS, runtime.GOARCH)
	fmt.Printf("Source:         %s\n", c.source)
}
<|endoftext|>


<commit_before>package wallet

import (
	"testing"

	"github.com/NebulousLabs/Sia/consensus"
)

// testFundTransaction funds and completes a transaction using the
// build-your-own transaction functions, checking that a no-refund transaction
// is created that is valid.
func (wt *walletTester) testFundTransaction() {
	// Build a transaction that intentionally needs a refund.
	id, err := wt.wallet.RegisterTransaction(consensus.Transaction{})
	fund := wt.wallet.Balance(false).Sub(consensus.NewCurrency64(1))
	if err != nil {
		wt.t.Fatal(err)
	}
	_, err = wt.wallet.FundTransaction(id, fund)
	if err != nil {
		wt.t.Fatal(err)
	}
	wt.updateWait()
	_, _, err = wt.wallet.AddMinerFee(id, fund)
	if err != nil {
		wt.t.Fatal(err)
	}
	t, err := wt.wallet.SignTransaction(id, true)
	if err != nil {
		wt.t.Fatal(err)
	}
	err = wt.tpool.AcceptTransaction(t)
	if err != nil {
		wt.t.Fatal(err)
	}
	wt.updateWait()

	// Check that the length of the created transaction is 1 siacoin, and that
	// the unconfirmed balance of the wallet is 1.
	if len(t.SiacoinOutputs) != 0 {
		wt.t.Error("more than zero siacoin outputs created in custom transaction")
	}
	if wt.wallet.Balance(true).Cmp(consensus.NewCurrency64(1)) != 0 {
		wt.t.Error(wt.wallet.Balance(true).MarshalJSON())
		wt.t.Error("wallet balance not reporting at one?")
	}

	// Dump the transaction pool into a block and see that the balance still
	// registers correctly.
	_, _, err = wt.miner.FindBlock()
	if err != nil {
		wt.t.Fatal(err)
	}

	// Check that the length of the created transaction is 1 siacoin, and that
	// the unconfirmed balance of the wallet is 1.
	if len(t.SiacoinOutputs) != 0 {
		wt.t.Error("more than zero siacoin outputs created in custom transaction")
	}
	if wt.wallet.Balance(true).Cmp(consensus.NewCurrency64(1)) != 0 {
		wt.t.Error(wt.wallet.Balance(true).MarshalJSON())
		wt.t.Error("wallet balance not reporting at one?")
	}
}

// TestFundTransaction creates a wallet tester and uses it to call
// testFundTransaction.
func TestFundTransaction(t *testing.T) {
	wt := NewWalletTester("Wallet - TestFundTransaction", t)
	wt.testFundTransaction()
}
<commit_msg>stop using MarshalJSON to display currency type<commit_after>package wallet

import (
	"testing"

	"github.com/NebulousLabs/Sia/consensus"
)

// testFundTransaction funds and completes a transaction using the
// build-your-own transaction functions, checking that a no-refund transaction
// is created that is valid.
func (wt *walletTester) testFundTransaction() {
	// Build a transaction that intentionally needs a refund.
	id, err := wt.wallet.RegisterTransaction(consensus.Transaction{})
	fund := wt.wallet.Balance(false).Sub(consensus.NewCurrency64(1))
	if err != nil {
		wt.t.Fatal(err)
	}
	_, err = wt.wallet.FundTransaction(id, fund)
	if err != nil {
		wt.t.Fatal(err)
	}
	wt.updateWait()
	_, _, err = wt.wallet.AddMinerFee(id, fund)
	if err != nil {
		wt.t.Fatal(err)
	}
	t, err := wt.wallet.SignTransaction(id, true)
	if err != nil {
		wt.t.Fatal(err)
	}
	err = wt.tpool.AcceptTransaction(t)
	if err != nil {
		wt.t.Fatal(err)
	}
	wt.updateWait()

	// Check that the length of the created transaction is 1 siacoin, and that
	// the unconfirmed balance of the wallet is 1.
	if len(t.SiacoinOutputs) != 0 {
		wt.t.Error("more than zero siacoin outputs created in custom transaction")
	}
	if wt.wallet.Balance(true).Cmp(consensus.NewCurrency64(1)) != 0 {
		wt.t.Error(wt.wallet.Balance(true))
		wt.t.Error("wallet balance not reporting at one?")
	}

	// Dump the transaction pool into a block and see that the balance still
	// registers correctly.
	_, _, err = wt.miner.FindBlock()
	if err != nil {
		wt.t.Fatal(err)
	}

	// Check that the length of the created transaction is 1 siacoin, and that
	// the unconfirmed balance of the wallet is 1.
	if len(t.SiacoinOutputs) != 0 {
		wt.t.Error("more than zero siacoin outputs created in custom transaction")
	}
	if wt.wallet.Balance(true).Cmp(consensus.NewCurrency64(1)) != 0 {
		wt.t.Error(wt.wallet.Balance(true))
		wt.t.Error("wallet balance not reporting at one?")
	}
}

// TestFundTransaction creates a wallet tester and uses it to call
// testFundTransaction.
func TestFundTransaction(t *testing.T) {
	wt := NewWalletTester("Wallet - TestFundTransaction", t)
	wt.testFundTransaction()
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"github.com/github/git-media/gitmedia"
	"github.com/github/git-media/pointer"
	"github.com/spf13/cobra"
	"io"
	"os"
	"path/filepath"
)

var (
	smudgeInfo = false
	smudgeCmd  = &cobra.Command{
		Use:   "smudge",
		Short: "Implements the Git smudge filter",
		Run:   smudgeCommand,
	}
)

func smudgeCommand(cmd *cobra.Command, args []string) {
	gitmedia.InstallHooks()

	b := &bytes.Buffer{}
	r := io.TeeReader(os.Stdin, b)

	ptr, err := pointer.Decode(r)
	if err != nil {
		mr := io.MultiReader(b, os.Stdin)
		_, err := io.Copy(os.Stdout, mr)
		if err != nil {
			Panic(err, "Error writing data to stdout:")
		}
		return
	}

	if smudgeInfo {
		localPath, err := gitmedia.LocalMediaPath(ptr.Oid)
		if err != nil {
			Exit(err.Error())
		}

		stat, err := os.Stat(localPath)
		if err != nil {
			Print("%d --", ptr.Size)
		} else {
			Print("%d %s", stat.Size(), localPath)
		}
		return
	}

	filename := smudgeFilename(args, err)
	cb, file, err := gitmedia.CopyCallbackFile("smudge", filename, 1, 1)
	if err != nil {
		Error(err.Error())
	}

	err = ptr.Smudge(os.Stdout, cb)
	if file != nil {
		file.Close()
	}

	if err != nil {
		ptr.Encode(os.Stdout)
		LoggedError(err, "Error accessing media: %s (%s)", filename, ptr.Oid)
	}
}

func smudgeFilename(args []string, err error) string {
	if len(args) > 0 {
		return args[0]
	}

	if smudgeErr, ok := err.(*pointer.SmudgeError); ok {
		return filepath.Base(smudgeErr.Filename)
	}

	return "<unknown file>"
}

func init() {
	smudgeCmd.Flags().BoolVarP(&smudgeInfo, "info", "i", false, "whatever")
	RootCmd.AddCommand(smudgeCmd)
}
<commit_msg>ララララー ラララー ララ<commit_after>package commands

import (
	"bytes"
	"github.com/github/git-media/gitmedia"
	"github.com/github/git-media/pointer"
	"github.com/spf13/cobra"
	"io"
	"os"
	"path/filepath"
)

var (
	smudgeInfo = false
	smudgeCmd  = &cobra.Command{
		Use:   "smudge",
		Short: "Implements the Git smudge filter",
		Run:   smudgeCommand,
	}
)

func smudgeCommand(cmd *cobra.Command, args []string) {
	gitmedia.InstallHooks()

	b := &bytes.Buffer{}
	r := io.TeeReader(os.Stdin, b)

	ptr, err := pointer.Decode(r)
	if err != nil {
		mr := io.MultiReader(b, os.Stdin)
		_, err := io.Copy(os.Stdout, mr)
		if err != nil {
			Panic(err, "Error writing data to stdout:")
		}
		return
	}

	if smudgeInfo {
		localPath, err := gitmedia.LocalMediaPath(ptr.Oid)
		if err != nil {
			Exit(err.Error())
		}

		stat, err := os.Stat(localPath)
		if err != nil {
			Print("%d --", ptr.Size)
		} else {
			Print("%d %s", stat.Size(), localPath)
		}
		return
	}

	filename := smudgeFilename(args, err)
	cb, file, err := gitmedia.CopyCallbackFile("smudge", filename, 1, 1)
	if err != nil {
		Error(err.Error())
	}

	err = ptr.Smudge(os.Stdout, cb)
	if file != nil {
		file.Close()
	}

	err = ptr.CreateLink(filename)
	if err != nil {
		Panic(err, "Unable to write link file %s", err)
	}

	if err != nil {
		ptr.Encode(os.Stdout)
		LoggedError(err, "Error accessing media: %s (%s)", filename, ptr.Oid)
	}
}

func smudgeFilename(args []string, err error) string {
	if len(args) > 0 {
		return args[0]
	}

	if smudgeErr, ok := err.(*pointer.SmudgeError); ok {
		return filepath.Base(smudgeErr.Filename)
	}

	return "<unknown file>"
}

func init() {
	smudgeCmd.Flags().BoolVarP(&smudgeInfo, "info", "i", false, "whatever")
	RootCmd.AddCommand(smudgeCmd)
}
<|endoftext|>


<commit_before>package main

func main() {
}
<commit_msg>fsnofity example<commit_after>package main

import (
	"github.com/howeyc/fsnotify"
	"log"
)

func main() {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	done := make(chan bool)

	// Process events
	go func() {
		for {
			select {
			case ev := <-watcher.Event:
				log.Println("event:", ev)
			case err := <-watcher.Error:
				log.Println("error:", err)
			}
		}
	}()

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

	<-done

	/* ... do stuff ... */
	watcher.Close()
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"io"
	"os"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/filepathfilter"
	"github.com/git-lfs/git-lfs/lfs"
	"github.com/git-lfs/git-lfs/localstorage"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/git-lfs/git-lfs/tools/humanize"
	"github.com/spf13/cobra"
)

var (
	// smudgeSkip is a command-line flag belonging to the "git-lfs smudge"
	// command specifying whether to skip the smudge process.
	smudgeSkip = false
)

// smudge smudges the given `*lfs.Pointer`, "ptr", and writes its objects
// contents to the `io.Writer`, "to".
//
// If the encoded LFS pointer is not parse-able as a pointer, the contents of
// that file will instead be spooled to a temporary location on disk and then
// copied out back to Git. If the pointer file is empty, an empty file will be
// written with no error.
//
// If the smudged object did not "pass" the include and exclude filterset, it
// will not be downloaded, and the object will remain a pointer on disk, as if
// the smudge filter had not been applied at all.
//
// Any errors encountered along the way will be returned immediately if they
// were non-fatal, otherwise execution will halt and the process will be
// terminated by using the `commands.Panic()` func.
func smudge(to io.Writer, from io.Reader, filename string, skip bool, filter *filepathfilter.Filter) (int64, error) {
	ptr, pbuf, perr := lfs.DecodeFrom(from)
	if perr != nil {
		n, err := tools.Spool(to, pbuf, localstorage.Objects().TempDir)
		if err != nil {
			return 0, errors.Wrap(err, perr.Error())
		}

		if n != 0 {
			return 0, errors.NewNotAPointerError(errors.Errorf(
				"Unable to parse pointer at: %q", filename,
			))
		}
		return 0, nil
	}

	lfs.LinkOrCopyFromReference(ptr.Oid, ptr.Size)
	cb, file, err := lfs.CopyCallbackFile("download", filename, 1, 1)
	if err != nil {
		return 0, err
	}

	download := !skip
	if download {
		download = filter.Allows(filename)
	}

	n, err := ptr.Smudge(to, filename, download, getTransferManifest(), cb)
	if file != nil {
		file.Close()
	}

	if err != nil {
		ptr.Encode(to)
		// Download declined error is ok to skip if we weren't requesting download
		if !(errors.IsDownloadDeclinedError(err) && !download) {
			var oid string = ptr.Oid
			if len(oid) >= 7 {
				oid = oid[:7]
			}

			LoggedError(err, "Error downloading object: %s (%s): %s", filename, oid, err)
			if !cfg.SkipDownloadErrors() {
				os.Exit(2)
			}
		}
	}

	return n, nil
}

func smudgeCommand(cmd *cobra.Command, args []string) {
	requireStdin("This command should be run by the Git 'smudge' filter")
	lfs.InstallHooks(false)

	if !smudgeSkip && cfg.Os.Bool("GIT_LFS_SKIP_SMUDGE", false) {
		smudgeSkip = true
	}
	filter := filepathfilter.New(cfg.FetchIncludePaths(), cfg.FetchExcludePaths())

	if n, err := smudge(os.Stdout, os.Stdin, smudgeFilename(args), smudgeSkip, filter); err != nil {
		if errors.IsNotAPointerError(err) {
			fmt.Fprintln(os.Stderr, err.Error())
		} else {
			Error(err.Error())
		}
	} else if possiblyMalformedSmudge(n) {
		fmt.Fprintln(os.Stderr, "Possibly malformed smudge on Windows: see `git lfs help smudge` for more info.")
	}
}

func smudgeFilename(args []string) string {
	if len(args) > 0 {
		return args[0]
	}
	return "<unknown file>"
}

func possiblyMalformedSmudge(n int64) bool {
	return n > 4*humanize.Gigabyte
}

func init() {
	RegisterCommand("smudge", smudgeCommand, func(cmd *cobra.Command) {
		cmd.Flags().BoolVarP(&smudgeSkip, "skip", "s", false, "")
	})
}
<commit_msg>commands/smudge: teach 'delayedSmudge' func<commit_after>package commands

import (
	"fmt"
	"io"
	"os"

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/filepathfilter"
	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/lfs"
	"github.com/git-lfs/git-lfs/localstorage"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/git-lfs/git-lfs/tools/humanize"
	"github.com/git-lfs/git-lfs/tq"
	"github.com/spf13/cobra"
)

var (
	// smudgeSkip is a command-line flag belonging to the "git-lfs smudge"
	// command specifying whether to skip the smudge process.
	smudgeSkip = false
)

// delayedSmudge performs a 'delayed' smudge, adding the LFS pointer to the
// `*tq.TransferQueue` "tq" if the file is not present locally, passes the given
// filepathfilter, and is not skipped. If the pointer is malformed, or already
// exists, it streams the contents to be written into the working copy to "to".
//
// delayedSmudge returns the number of bytes written, whether the checkout was
// delayed, the *lfs.Pointer that was smudged, and an error, if one occurred.
func delayedSmudge(s *git.FilterProcessScanner, to io.Writer, from io.Reader, tq *tq.TransferQueue, filename string, skip bool, filter *filepathfilter.Filter) (int64, bool, *lfs.Pointer, error) {
	ptr, pbuf, perr := lfs.DecodeFrom(from)
	if perr != nil {
		// Write 'statusFromErr(nil)', even though 'perr != nil', since
		// we are about to write non-delayed smudged contents to "to".
		if err := s.WriteStatus(statusFromErr(nil)); err != nil {
			return 0, false, nil, err
		}

		n, err := tools.Spool(to, pbuf, localstorage.Objects().TempDir)
		if err != nil {
			return n, false, nil, errors.Wrap(err, perr.Error())
		}

		if n != 0 {
			return 0, false, nil, errors.NewNotAPointerError(errors.Errorf(
				"Unable to parse pointer at: %q", filename,
			))
		}
		return 0, false, nil, nil
	}

	lfs.LinkOrCopyFromReference(ptr.Oid, ptr.Size)

	path, err := lfs.LocalMediaPath(ptr.Oid)
	if err != nil {
		return 0, false, nil, err
	}

	if !skip && filter.Allows(filename) {
		if _, statErr := os.Stat(path); err == nil || !os.IsNotExist(statErr) {
			tq.Add(filename, path, ptr.Oid, ptr.Size)
			return 0, true, ptr, nil
		}
	}

	if err := s.WriteStatus(statusFromErr(nil)); err != nil {
		return 0, false, nil, err
	}

	n, err := ptr.Encode(to)
	return int64(n), false, ptr, err
}

// smudge smudges the given `*lfs.Pointer`, "ptr", and writes its objects
// contents to the `io.Writer`, "to".
//
// If the encoded LFS pointer is not parse-able as a pointer, the contents of
// that file will instead be spooled to a temporary location on disk and then
// copied out back to Git. If the pointer file is empty, an empty file will be
// written with no error.
//
// If the smudged object did not "pass" the include and exclude filterset, it
// will not be downloaded, and the object will remain a pointer on disk, as if
// the smudge filter had not been applied at all.
//
// Any errors encountered along the way will be returned immediately if they
// were non-fatal, otherwise execution will halt and the process will be
// terminated by using the `commands.Panic()` func.
func smudge(to io.Writer, from io.Reader, filename string, skip bool, filter *filepathfilter.Filter) (int64, error) {
	ptr, pbuf, perr := lfs.DecodeFrom(from)
	if perr != nil {
		n, err := tools.Spool(to, pbuf, localstorage.Objects().TempDir)
		if err != nil {
			return 0, errors.Wrap(err, perr.Error())
		}

		if n != 0 {
			return 0, errors.NewNotAPointerError(errors.Errorf(
				"Unable to parse pointer at: %q", filename,
			))
		}
		return 0, nil
	}

	lfs.LinkOrCopyFromReference(ptr.Oid, ptr.Size)
	cb, file, err := lfs.CopyCallbackFile("download", filename, 1, 1)
	if err != nil {
		return 0, err
	}

	download := !skip
	if download {
		download = filter.Allows(filename)
	}

	n, err := ptr.Smudge(to, filename, download, getTransferManifest(), cb)
	if file != nil {
		file.Close()
	}

	if err != nil {
		ptr.Encode(to)
		// Download declined error is ok to skip if we weren't requesting download
		if !(errors.IsDownloadDeclinedError(err) && !download) {
			var oid string = ptr.Oid
			if len(oid) >= 7 {
				oid = oid[:7]
			}

			LoggedError(err, "Error downloading object: %s (%s): %s", filename, oid, err)
			if !cfg.SkipDownloadErrors() {
				os.Exit(2)
			}
		}
	}

	return n, nil
}

func smudgeCommand(cmd *cobra.Command, args []string) {
	requireStdin("This command should be run by the Git 'smudge' filter")
	lfs.InstallHooks(false)

	if !smudgeSkip && cfg.Os.Bool("GIT_LFS_SKIP_SMUDGE", false) {
		smudgeSkip = true
	}
	filter := filepathfilter.New(cfg.FetchIncludePaths(), cfg.FetchExcludePaths())

	if n, err := smudge(os.Stdout, os.Stdin, smudgeFilename(args), smudgeSkip, filter); err != nil {
		if errors.IsNotAPointerError(err) {
			fmt.Fprintln(os.Stderr, err.Error())
		} else {
			Error(err.Error())
		}
	} else if possiblyMalformedSmudge(n) {
		fmt.Fprintln(os.Stderr, "Possibly malformed smudge on Windows: see `git lfs help smudge` for more info.")
	}
}

func smudgeFilename(args []string) string {
	if len(args) > 0 {
		return args[0]
	}
	return "<unknown file>"
}

func possiblyMalformedSmudge(n int64) bool {
	return n > 4*humanize.Gigabyte
}

func init() {
	RegisterCommand("smudge", smudgeCommand, func(cmd *cobra.Command) {
		cmd.Flags().BoolVarP(&smudgeSkip, "skip", "s", false, "")
	})
}
<|endoftext|>


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

package main

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"strings"
	"time"
)

const (
	M_PATH        = "migrations"
	M_DATE_FORMAT = "20060102_150405"
)

// generateMigration generates migration file template for database schema update.
// The generated file template consists of an up() method for updating schema and
// a down() method for reverting the update.
func generateMigration(mname string, curpath string) {
	migrationFilePath := path.Join(curpath, "database", M_PATH)
	if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
		// create migrations directory
		if err := os.MkdirAll(migrationFilePath, 0777); err != nil {
			ColorLog("[ERRO] Could not create migration directory: %s\n", err)
			os.Exit(2)
		}
	}
	// create file
	today := time.Now().Format(M_DATE_FORMAT)
	fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname))
	if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
		defer f.Close()
		content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
		content = strings.Replace(content, "{{CurrTime}}", today, -1)
		f.WriteString(content)
		// gofmt generated source code
		formatSourceCode(fpath)
		ColorLog("[INFO] Migration file generated: %s\n", fpath)
	} else {
		// error creating file
		ColorLog("[ERRO] Could not create migration file: %s\n", err)
		os.Exit(2)
	}
}

// formatSourceCode formats the source code using gofmt
func formatSourceCode(fpath string) {
	cmd := exec.Command("gofmt", "-w", fpath)
	cmd.Run()
}

const MIGRATION_TPL = `package main

import (
	"time"

	"github.com/astaxie/beego/migration"
)

// DO NOT MODIFY
type {{StructName}} struct {
	migration.Migration
}

// DO NOT MODIFY
func init() {
	m := &{{StructName}}{}
	m.Created = "{{CurrTime}}"
	migration.Register("{{StructName}}", m)
}

// Run the migrations
func (m *{{StructName}}) Up() {
	// use m.Sql("CREATE TABLE ...") to make schema update
}

// Reverse the migrations
func (m *{{StructName}}) Down() {
	// use m.Sql("DROP TABLE ...") to reverse schema update
}
`
<commit_msg>update migration template<commit_after>// Copyright 2013 bee authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package main

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"strings"
	"time"
)

const (
	M_PATH        = "migrations"
	M_DATE_FORMAT = "20060102_150405"
)

// generateMigration generates migration file template for database schema update.
// The generated file template consists of an up() method for updating schema and
// a down() method for reverting the update.
func generateMigration(mname string, curpath string) {
	migrationFilePath := path.Join(curpath, "database", M_PATH)
	if _, err := os.Stat(migrationFilePath); os.IsNotExist(err) {
		// create migrations directory
		if err := os.MkdirAll(migrationFilePath, 0777); err != nil {
			ColorLog("[ERRO] Could not create migration directory: %s\n", err)
			os.Exit(2)
		}
	}
	// create file
	today := time.Now().Format(M_DATE_FORMAT)
	fpath := path.Join(migrationFilePath, fmt.Sprintf("%s_%s.go", today, mname))
	if f, err := os.OpenFile(fpath, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err == nil {
		defer f.Close()
		content := strings.Replace(MIGRATION_TPL, "{{StructName}}", camelCase(mname)+"_"+today, -1)
		content = strings.Replace(content, "{{CurrTime}}", today, -1)
		f.WriteString(content)
		// gofmt generated source code
		formatSourceCode(fpath)
		ColorLog("[INFO] Migration file generated: %s\n", fpath)
	} else {
		// error creating file
		ColorLog("[ERRO] Could not create migration file: %s\n", err)
		os.Exit(2)
	}
}

// formatSourceCode formats the source code using gofmt
func formatSourceCode(fpath string) {
	cmd := exec.Command("gofmt", "-w", fpath)
	cmd.Run()
}

const MIGRATION_TPL = `package main

import (
	"github.com/astaxie/beego/migration"
)

// DO NOT MODIFY
type {{StructName}} struct {
	migration.Migration
}

// DO NOT MODIFY
func init() {
	m := &{{StructName}}{}
	m.Created = "{{CurrTime}}"
	migration.Register("{{StructName}}", m)
}

// Run the migrations
func (m *{{StructName}}) Up() {
	// use m.Sql("CREATE TABLE ...") to make schema update
}

// Reverse the migrations
func (m *{{StructName}}) Down() {
	// use m.Sql("DROP TABLE ...") to reverse schema update
}
`
<|endoftext|>


<commit_before>package versions

import "fmt"

type setSubtract struct {
	from setI
	sub  setI
}

func (s setSubtract) Has(v Version) bool {
	return s.from.Has(v) && !s.sub.Has(v)
}

func (s setSubtract) AllRequested() Set {
	// Our set requests anything that is requested by "from", unless it'd
	// be excluded by "sub". Notice that the whole of "sub" is used, rather
	// than just the requested parts, because requesting is a positive
	// action only.
	return Set{setI: s.from}.AllRequested().Subtract(Set{setI: s.sub})
}

func (s setSubtract) GoString() string {
	return fmt.Sprintf("(%#v).Subtract(%#v)", s.from, s.sub)
}

// Subtract returns a new set that has all of the versions from the receiver
// except for any versions in the other given set.
//
// If the receiver is finite then the returned set is also finite.
func (s Set) Subtract(other Set) Set {
	if other.setI == None || s.setI == None {
		return s
	}
	if other.setI == All {
		return None
	}
	return Set{
		setI: setSubtract{
			from: s,
			sub:  other,
		},
	}
}

var _ setFinite = setSubtract{}

func (s setSubtract) isFinite() bool {
	// subtract is finite if its "from" is finite
	return isFinite(s.from)
}

func (s setSubtract) listVersions() List {
	ret := s.from.(setFinite).listVersions()
	ret = ret.Filter(Set{setI: s.sub})
	return ret
}
<commit_msg>Construct properly setSubtract objects<commit_after>package versions

import "fmt"

type setSubtract struct {
	from setI
	sub  setI
}

func (s setSubtract) Has(v Version) bool {
	return s.from.Has(v) && !s.sub.Has(v)
}

func (s setSubtract) AllRequested() Set {
	// Our set requests anything that is requested by "from", unless it'd
	// be excluded by "sub". Notice that the whole of "sub" is used, rather
	// than just the requested parts, because requesting is a positive
	// action only.
	return Set{setI: s.from}.AllRequested().Subtract(Set{setI: s.sub})
}

func (s setSubtract) GoString() string {
	return fmt.Sprintf("(%#v).Subtract(%#v)", s.from, s.sub)
}

// Subtract returns a new set that has all of the versions from the receiver
// except for any versions in the other given set.
//
// If the receiver is finite then the returned set is also finite.
func (s Set) Subtract(other Set) Set {
	if other == None || s == None {
		return s
	}
	if other == All {
		return None
	}
	return Set{
		setI: setSubtract{
			from: s.setI,
			sub:  other.setI,
		},
	}
}

var _ setFinite = setSubtract{}

func (s setSubtract) isFinite() bool {
	// subtract is finite if its "from" is finite
	return isFinite(s.from)
}

func (s setSubtract) listVersions() List {
	ret := s.from.(setFinite).listVersions()
	ret = ret.Filter(Set{setI: s.sub})
	return ret
}
<|endoftext|>


<commit_before>package vfscommon

import (
	"os"
	"runtime"
	"time"

	"github.com/rclone/rclone/fs"
)

// Options is options for creating the vfs
type Options struct {
	NoSeek            bool          // don't allow seeking if set
	NoChecksum        bool          // don't check checksums if set
	ReadOnly          bool          // if set VFS is read only
	NoModTime         bool          // don't read mod times for files
	DirCacheTime      time.Duration // how long to consider directory listing cache valid
	PollInterval      time.Duration
	Umask             int
	UID               uint32
	GID               uint32
	DirPerms          os.FileMode
	FilePerms         os.FileMode
	ChunkSize         fs.SizeSuffix // if > 0 read files in chunks
	ChunkSizeLimit    fs.SizeSuffix // if > ChunkSize double the chunk size after each chunk until reached
	CacheMode         CacheMode
	CacheMaxAge       time.Duration
	CacheMaxSize      fs.SizeSuffix
	CachePollInterval time.Duration
	CaseInsensitive   bool
	WriteWait         time.Duration // time to wait for in-sequence write
	ReadWait          time.Duration // time to wait for in-sequence read
}

// DefaultOpt is the default values uses for Opt
var DefaultOpt = Options{
	NoModTime:         false,
	NoChecksum:        false,
	NoSeek:            false,
	DirCacheTime:      5 * 60 * time.Second,
	PollInterval:      time.Minute,
	ReadOnly:          false,
	Umask:             0,
	UID:               ^uint32(0), // these values instruct WinFSP-FUSE to use the current user
	GID:               ^uint32(0), // overriden for non windows in mount_unix.go
	DirPerms:          os.FileMode(0777),
	FilePerms:         os.FileMode(0666),
	CacheMode:         CacheModeOff,
	CacheMaxAge:       3600 * time.Second,
	CachePollInterval: 60 * time.Second,
	ChunkSize:         128 * fs.MebiByte,
	ChunkSizeLimit:    -1,
	CacheMaxSize:      -1,
	CaseInsensitive:   runtime.GOOS == "windows" || runtime.GOOS == "darwin", // default to true on Windows and Mac, false otherwise
	WriteWait:         1000 * time.Millisecond,
	ReadWait:          5 * time.Millisecond,
}
<commit_msg>vfs: change default --vfs-read-wait to 20ms<commit_after>package vfscommon

import (
	"os"
	"runtime"
	"time"

	"github.com/rclone/rclone/fs"
)

// Options is options for creating the vfs
type Options struct {
	NoSeek            bool          // don't allow seeking if set
	NoChecksum        bool          // don't check checksums if set
	ReadOnly          bool          // if set VFS is read only
	NoModTime         bool          // don't read mod times for files
	DirCacheTime      time.Duration // how long to consider directory listing cache valid
	PollInterval      time.Duration
	Umask             int
	UID               uint32
	GID               uint32
	DirPerms          os.FileMode
	FilePerms         os.FileMode
	ChunkSize         fs.SizeSuffix // if > 0 read files in chunks
	ChunkSizeLimit    fs.SizeSuffix // if > ChunkSize double the chunk size after each chunk until reached
	CacheMode         CacheMode
	CacheMaxAge       time.Duration
	CacheMaxSize      fs.SizeSuffix
	CachePollInterval time.Duration
	CaseInsensitive   bool
	WriteWait         time.Duration // time to wait for in-sequence write
	ReadWait          time.Duration // time to wait for in-sequence read
}

// DefaultOpt is the default values uses for Opt
var DefaultOpt = Options{
	NoModTime:         false,
	NoChecksum:        false,
	NoSeek:            false,
	DirCacheTime:      5 * 60 * time.Second,
	PollInterval:      time.Minute,
	ReadOnly:          false,
	Umask:             0,
	UID:               ^uint32(0), // these values instruct WinFSP-FUSE to use the current user
	GID:               ^uint32(0), // overriden for non windows in mount_unix.go
	DirPerms:          os.FileMode(0777),
	FilePerms:         os.FileMode(0666),
	CacheMode:         CacheModeOff,
	CacheMaxAge:       3600 * time.Second,
	CachePollInterval: 60 * time.Second,
	ChunkSize:         128 * fs.MebiByte,
	ChunkSizeLimit:    -1,
	CacheMaxSize:      -1,
	CaseInsensitive:   runtime.GOOS == "windows" || runtime.GOOS == "darwin", // default to true on Windows and Mac, false otherwise
	WriteWait:         1000 * time.Millisecond,
	ReadWait:          20 * time.Millisecond,
}
<|endoftext|>


<commit_before>// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package repository

import (
	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	repo_module "code.gitea.io/gitea/modules/repository"
)

// GenerateRepository generates a repository from a template
func GenerateRepository(doer, owner *models.User, templateRepo *models.Repository, opts models.GenerateRepoOptions) (_ *models.Repository, err error) {
	var generateRepo *models.Repository
	if err = models.WithTx(func(ctx models.DBContext) error {
		generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts)
		if err != nil {
			return err
		}

		// Git Content
		if opts.GitContent && !templateRepo.IsEmpty {
			if err = repo_module.GenerateGitContent(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Topics
		if opts.Topics {
			if err = models.GenerateTopics(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Git Hooks
		if opts.GitHooks {
			if err = models.GenerateGitHooks(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Webhooks
		if opts.Webhooks {
			if err = models.GenerateWebhooks(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Avatar
		if opts.Avatar && len(templateRepo.Avatar) > 0 {
			if err = models.GenerateAvatar(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Issue Labels
		if opts.IssueLabels {
			if err = models.GenerateIssueLabels(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		return nil
	}); err != nil {
		if generateRepo != nil && generateRepo.ID > 0 {
			if errDelete := models.DeleteRepository(doer, owner.ID, generateRepo.ID); errDelete != nil {
				log.Error("Rollback deleteRepository: %v", errDelete)
			}
		}
		return nil, err
	}

	notification.NotifyCreateRepository(doer, owner, generateRepo)

	return generateRepo, nil
}
<commit_msg>add permission check for ``GenerateRepository`` (#15946)<commit_after>// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package repository

import (
	"code.gitea.io/gitea/models"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/notification"
	repo_module "code.gitea.io/gitea/modules/repository"
)

// GenerateRepository generates a repository from a template
func GenerateRepository(doer, owner *models.User, templateRepo *models.Repository, opts models.GenerateRepoOptions) (_ *models.Repository, err error) {
	if !doer.IsAdmin && !owner.CanCreateRepo() {
		return nil, models.ErrReachLimitOfRepo{
			Limit: owner.MaxRepoCreation,
		}
	}

	var generateRepo *models.Repository
	if err = models.WithTx(func(ctx models.DBContext) error {
		generateRepo, err = repo_module.GenerateRepository(ctx, doer, owner, templateRepo, opts)
		if err != nil {
			return err
		}

		// Git Content
		if opts.GitContent && !templateRepo.IsEmpty {
			if err = repo_module.GenerateGitContent(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Topics
		if opts.Topics {
			if err = models.GenerateTopics(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Git Hooks
		if opts.GitHooks {
			if err = models.GenerateGitHooks(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Webhooks
		if opts.Webhooks {
			if err = models.GenerateWebhooks(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Avatar
		if opts.Avatar && len(templateRepo.Avatar) > 0 {
			if err = models.GenerateAvatar(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		// Issue Labels
		if opts.IssueLabels {
			if err = models.GenerateIssueLabels(ctx, templateRepo, generateRepo); err != nil {
				return err
			}
		}

		return nil
	}); err != nil {
		if generateRepo != nil && generateRepo.ID > 0 {
			if errDelete := models.DeleteRepository(doer, owner.ID, generateRepo.ID); errDelete != nil {
				log.Error("Rollback deleteRepository: %v", errDelete)
			}
		}
		return nil, err
	}

	notification.NotifyCreateRepository(doer, owner, generateRepo)

	return generateRepo, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/maputnik/desktop/filewatch"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "maputnik"
	app.Usage = "Server for integrating Maputnik locally"
	app.Version = "Editor: 1.7.0; Desktop: 1.0.6"

	app.Flags = []cli.Flag{
		&cli.StringFlag{
			Name:  "file, f",
			Usage: "Allow access to JSON style from web client",
		},
		&cli.BoolFlag{
			Name:  "watch",
			Usage: "Notify web client about JSON style file changes",
		},
		&cli.IntFlag{
			Name: "port",
			Value: 8000,
			Usage: "TCP port to listen on",
		},
		cli.StringFlag{
			Name:  "static",
			Usage: "Serve directory under /static/",
		}
	}

	app.Action = func(c *cli.Context) error {
		gui := http.FileServer(assetFS())

		router := mux.NewRouter().StrictSlash(true)

		filename := c.String("file")
		if filename != "" {
			fmt.Printf("%s is accessible via Maputnik\n", filename)
			// Allow access to reading and writing file on the local system
			path, _ := filepath.Abs(filename)
			accessor := StyleFileAccessor(path)
			router.Path("/styles").Methods("GET").HandlerFunc(accessor.ListFiles)
			router.Path("/styles/{styleId}").Methods("GET").HandlerFunc(accessor.ReadFile)
			router.Path("/styles/{styleId}").Methods("PUT").HandlerFunc(accessor.SaveFile)

			// Register websocket to notify we clients about file changes
			if c.Bool("watch") {
				router.Path("/ws").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					filewatch.ServeWebsocketFileWatcher(filename, w, r)
				})
			}
		}

		staticDir := c.String("static")
    if staticDir != "" {
	    h := http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))
	    router.PathPrefix("/static/").Handler(h)
    }

		router.PathPrefix("/").Handler(http.StripPrefix("/", gui))
		loggedRouter := handlers.LoggingHandler(os.Stdout, router)
		corsRouter := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}), handlers.AllowedMethods([]string{"GET", "PUT"}), handlers.AllowedOrigins([]string{"*"}), handlers.AllowCredentials())(loggedRouter)

		fmt.Printf("Exposing Maputnik on http://localhost:%d\n", c.Int("port"))
		return http.ListenAndServe(fmt.Sprintf(":%d", c.Int("port")), corsRouter)
	}

	app.Run(os.Args)
}
<commit_msg>Fix syntax error<commit_after>package main

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
	"github.com/maputnik/desktop/filewatch"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "maputnik"
	app.Usage = "Server for integrating Maputnik locally"
	app.Version = "Editor: 1.7.0; Desktop: 1.0.6"

	app.Flags = []cli.Flag{
		&cli.StringFlag{
			Name:  "file, f",
			Usage: "Allow access to JSON style from web client",
		},
		&cli.BoolFlag{
			Name:  "watch",
			Usage: "Notify web client about JSON style file changes",
		},
		&cli.IntFlag{
			Name: "port",
			Value: 8000,
			Usage: "TCP port to listen on",
		},
		cli.StringFlag{
			Name:  "static",
			Usage: "Serve directory under /static/",
		},
	}

	app.Action = func(c *cli.Context) error {
		gui := http.FileServer(assetFS())

		router := mux.NewRouter().StrictSlash(true)

		filename := c.String("file")
		if filename != "" {
			fmt.Printf("%s is accessible via Maputnik\n", filename)
			// Allow access to reading and writing file on the local system
			path, _ := filepath.Abs(filename)
			accessor := StyleFileAccessor(path)
			router.Path("/styles").Methods("GET").HandlerFunc(accessor.ListFiles)
			router.Path("/styles/{styleId}").Methods("GET").HandlerFunc(accessor.ReadFile)
			router.Path("/styles/{styleId}").Methods("PUT").HandlerFunc(accessor.SaveFile)

			// Register websocket to notify we clients about file changes
			if c.Bool("watch") {
				router.Path("/ws").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
					filewatch.ServeWebsocketFileWatcher(filename, w, r)
				})
			}
		}

		staticDir := c.String("static")
    if staticDir != "" {
	    h := http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))
	    router.PathPrefix("/static/").Handler(h)
    }

		router.PathPrefix("/").Handler(http.StripPrefix("/", gui))
		loggedRouter := handlers.LoggingHandler(os.Stdout, router)
		corsRouter := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}), handlers.AllowedMethods([]string{"GET", "PUT"}), handlers.AllowedOrigins([]string{"*"}), handlers.AllowCredentials())(loggedRouter)

		fmt.Printf("Exposing Maputnik on http://localhost:%d\n", c.Int("port"))
		return http.ListenAndServe(fmt.Sprintf(":%d", c.Int("port")), corsRouter)
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"

	"github.com/levenlabs/go-srvclient"
	"github.com/levenlabs/golib/rpcutil"
	"net/url"
)

func main() {
	bin := os.Args[0]
	argv := os.Args[1:]
	if len(argv) != 3 {
		fmt.Printf("Usage: %s <url> <service.method> <parameters>\n\n", bin)
		fmt.Printf(`Example: %s 'http://localhost:5555/api' 'Foo.DoAThing' '{"foo":"bar"}'`, bin)
		fmt.Print("\n\n")
		return
	}

	u, method, body := argv[0], argv[1], argv[2]
	if uo, err := url.Parse(u); err == nil {
		uo.Host = srvclient.MaybeSRV(uo.Host)
		u = uo.String()
	}
	var ret interface{}
	err := rpcutil.JSONRPC2RawCall(u, &ret, method, body)
	if err != nil {
		fmt.Println(err)
		return
	}

	out, err := json.MarshalIndent(ret, "", "    ")
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(string(out))
}
<commit_msg>make rpc-cli use lever and llog, make it possible to output result as an INFO message<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/url"
	"os"
	"time"

	"github.com/levenlabs/go-llog"
	"github.com/levenlabs/go-srvclient"
	"github.com/levenlabs/golib/rpcutil"
	"github.com/mediocregopher/lever"
)

func main() {
	l := lever.New("rpc-cli", &lever.Opts{
		HelpHeader:         "Usage: rpc-cli [options] <url> <service.method> <parameters>\n",
		DisallowConfigFile: true,
	})
	l.Add(lever.Param{
		Name:        "--llog",
		Description: "Instead of outputting the return as json, output a llog-style message with the returned json object as the key/value params",
		Flag:        true,
	})
	l.Parse()

	argv := l.ParamRest()
	if len(argv) != 3 {
		fmt.Print(l.Help())
		exit(0)
	}

	u, method, body := argv[0], argv[1], argv[2]
	if uo, err := url.Parse(u); err == nil {
		uo.Host = srvclient.MaybeSRV(uo.Host)
		u = uo.String()
	}
	var ret interface{}
	err := rpcutil.JSONRPC2RawCall(u, &ret, method, body)
	if err != nil {
		llog.Error("error calling rpc method", llog.KV{"err": err})
		exit(1)
	}

	if l.ParamFlag("--llog") {
		retm, ok := ret.(map[string]interface{})
		if !ok {
			llog.Error("return value not a json object, can't llog")
			exit(1)
		}
		llog.Info("output from "+method, llog.KV(retm))
		exit(0)
	}

	out, err := json.MarshalIndent(ret, "", "    ")
	if err != nil {
		llog.Error("error marshalling json", llog.KV{"err": err})
		exit(1)
	}

	fmt.Println(string(out))
}

func exit(i int) {
	time.Sleep(100 * time.Millisecond)
	os.Exit(i)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"github.com/robfig/goconfig"
	"log"
	"net/http"
)

var configFile string

type fonduConfig struct {
	DataDir    string
	Port       string
	PypiMirror string
}

var Config = fonduConfig{
	"data",
	"3638",
	"http://pypi.python.org",
}

// Parse flags and set up configuration
func init() {
	flag.StringVar(&configFile, "f", "", "path to a configuration file")
	flag.Parse()

	if configFile != "" {
		c, err := config.ReadDefault(configFile)
		if err != nil {
			log.Println("Unable to load config from: " + configFile)
			return
		}
		d, _ := c.String("fondu", "data_dir")
		if d != "" {
			Config.DataDir = d
		}
		p, _ := c.String("fondu", "port")
		if p != "" {
			Config.Port = p
		}
		m, _ := c.String("fondu", "pypi_mirror")
		if m != "" {
			Config.PypiMirror = m
		}
	}
}

func main() {
	http.HandleFunc("/simple", simpleIndexHandler)
	http.HandleFunc("/simple/", simpleHandler)
	http.Handle("/file/", http.StripPrefix("/file", http.FileServer(http.Dir(Config.DataDir))))
	http.HandleFunc("/fondu/cached-file/", cachedFileHandler)
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("*", http.NotFound)
	log.Println("Starting fondu on port " + Config.Port)
	http.ListenAndServe(":"+Config.Port, nil)
}
<commit_msg>Let's hope this is the last time<commit_after>package main

import (
	"flag"
	"github.com/robfig/config"
	"log"
	"net/http"
)

var configFile string

type fonduConfig struct {
	DataDir    string
	Port       string
	PypiMirror string
}

var Config = fonduConfig{
	"data",
	"3638",
	"http://pypi.python.org",
}

// Parse flags and set up configuration
func init() {
	flag.StringVar(&configFile, "f", "", "path to a configuration file")
	flag.Parse()

	if configFile != "" {
		c, err := config.ReadDefault(configFile)
		if err != nil {
			log.Println("Unable to load config from: " + configFile)
			return
		}
		d, _ := c.String("fondu", "data_dir")
		if d != "" {
			Config.DataDir = d
		}
		p, _ := c.String("fondu", "port")
		if p != "" {
			Config.Port = p
		}
		m, _ := c.String("fondu", "pypi_mirror")
		if m != "" {
			Config.PypiMirror = m
		}
	}
}

func main() {
	http.HandleFunc("/simple", simpleIndexHandler)
	http.HandleFunc("/simple/", simpleHandler)
	http.Handle("/file/", http.StripPrefix("/file", http.FileServer(http.Dir(Config.DataDir))))
	http.HandleFunc("/fondu/cached-file/", cachedFileHandler)
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("*", http.NotFound)
	log.Println("Starting fondu on port " + Config.Port)
	http.ListenAndServe(":"+Config.Port, nil)
}
<|endoftext|>


<commit_before>package login

// What I cloned from ...
// https://github.com/douglasmakey/oauth2-example/blob/master/handlers/oauth_google.go

import(
	"context"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

var(
	// GoogleClientID and GoogleClientSecret are credentials you'll get
	// when you setup OAuth2 logins on the google side. You *must*
	// specify these two values.
	GoogleClientID string
	GoogleClientSecret string
)

const(
	GoogleOAuthEmailScope = "https://www.googleapis.com/auth/userinfo.email" // WTF to get this
	oauthGoogleUrlAPI = "https://www.googleapis.com/oauth2/v2/userinfo?access_token="
)

type GoogleOauth2 struct {
	oauth2.Config
}
func (g GoogleOauth2)Name() string { return "google" }

// {{{ NewGoogleOauth2

func NewGoogleOauth2() GoogleOauth2 {
	g := GoogleOauth2{
		Config: oauth2.Config{
			ClientID:     GoogleClientID,     // config.Get("google.oauth2.appid"),
			ClientSecret: GoogleClientSecret, // config.Get("google.oauth2.secret"),
			Endpoint:     google.Endpoint,
			Scopes:       []string{GoogleOAuthEmailScope},
		},
	}

	// Build this from some package variables
	g.Config.RedirectURL = Host + getCallbackRelativeUrl(g)

	return g
}

// }}}

// {{{ goauth2.GetLoginUrl

func (goauth2 GoogleOauth2)GetLoginUrl(w http.ResponseWriter, r *http.Request) string {
	// AuthCodeURL is a token to protect the user from CSRF attacks. It
	// is also attached to the response as a cookie.
	oauthState := generateStateOauthCookie(w)
	return goauth2.Config.AuthCodeURL(oauthState)
}

// }}}
// {{{ goauth2.GetLogoutUrl

func (goauth2 GoogleOauth2)GetLogoutUrl(w http.ResponseWriter, r *http.Request) string {
	loginUrl := makeUrlAbsolute(r, "/")

	args1 := url.Values{}
	args1.Add("continue", loginUrl)

	args2 := url.Values{}
	args2.Add("continue", "https://appengine.google.com/_ah/logout?" + args1.Encode())

	// This weird thing bounces you through a "are you sure you want to redirect" notice,
	// which is fine. You can't just redirect anywhere, it has to go to a google url.
	return "https://www.google.com/accounts/Logout?" + args2.Encode()
}

// }}}
// {{{ goauth2.CallbackToEmail

func (goauth2 GoogleOauth2)CallbackToEmail(r *http.Request) (string, error) {
	// Read oauthState from Cookie
	if oauthState,err := r.Cookie("oauthstate"); err != nil {
		return "", fmt.Errorf("no oauth google cookie: %v", err)
	} else if r.FormValue("state") != oauthState.Value {
		return "", fmt.Errorf("invalid oauth google state")
	}

	email,err := goauth2.getEmailFromGoogle(r.FormValue("code"))
	return email,err
}

// }}}

// {{{ goauth2.getEmailFromGoogle

func (goauth2 GoogleOauth2)getEmailFromGoogle(code string) (string, error) {
	if data,err := goauth2.getUserDataFromGoogle(code); err != nil {
		return "", err
	} else {
		var jsonMap map[string]interface{}
		if err := json.Unmarshal([]byte(data), &jsonMap); err != nil {
			return "", fmt.Errorf("google oauth unmarshal:"+err.Error())
		}

		emailVar := jsonMap["email"];
		if emailVar == nil {
			return "", fmt.Errorf("google oauth callback: jsonmap had no 'email'\n%#v", jsonMap)
		}

		if email,ok := emailVar.(string); !ok {
			return "", fmt.Errorf("google oauth callback: 'email' not a string\n%#v", jsonMap)
		} else {
			return email, nil
		}
	}
}

// }}}
// {{{ goauth2.getUserDataFromGoogle

func (goauth2 GoogleOauth2)getUserDataFromGoogle(code string) ([]byte, error) {
	token, err := goauth2.Config.Exchange(context.Background(), code)
	if err != nil {
		return nil, fmt.Errorf("code exchange wrong: %s", err.Error())
	}

	response, err := http.Get(oauthGoogleUrlAPI + token.AccessToken)
	if err != nil {
		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
	}

	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("failed read response: %s", err.Error())
	}

	return contents, nil
}

// }}}

// {{{ generateStateOauthCookie

func generateStateOauthCookie(w http.ResponseWriter) string {
	var expiration = time.Now().Add(20 * time.Minute)

	b := make([]byte, 16)
	rand.Read(b)
	state := base64.URLEncoding.EncodeToString(b)
	cookie := http.Cookie{Name: "oauthstate", Value: state, Expires: expiration}
	http.SetCookie(w, &cookie)

	return state
}

// }}}

// {{{ -------------------------={ E N D }=----------------------------------

// Local variables:
// folded-file: t
// end:

// }}}
<commit_msg>Start flagging these problems<commit_after>package login

// What I cloned from ...
// https://github.com/douglasmakey/oauth2-example/blob/master/handlers/oauth_google.go

import(
	"context"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"time"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

var(
	// GoogleClientID and GoogleClientSecret are credentials you'll get
	// when you setup OAuth2 logins on the google side. You *must*
	// specify these two values.
	GoogleClientID string
	GoogleClientSecret string
)

const(
	GoogleOAuthEmailScope = "https://www.googleapis.com/auth/userinfo.email" // WTF to get this
	oauthGoogleUrlAPI = "https://www.googleapis.com/oauth2/v2/userinfo?access_token="
)

type GoogleOauth2 struct {
	oauth2.Config
}
func (g GoogleOauth2)Name() string { return "google" }

// {{{ NewGoogleOauth2

func NewGoogleOauth2() GoogleOauth2 {
	g := GoogleOauth2{
		Config: oauth2.Config{
			ClientID:     GoogleClientID,     // config.Get("google.oauth2.appid"),
			ClientSecret: GoogleClientSecret, // config.Get("google.oauth2.secret"),
			Endpoint:     google.Endpoint,
			Scopes:       []string{GoogleOAuthEmailScope},
		},
	}

	// Build this from some package variables
	g.Config.RedirectURL = Host + getCallbackRelativeUrl(g)

	return g
}

// }}}

// {{{ goauth2.GetLoginUrl

func (goauth2 GoogleOauth2)GetLoginUrl(w http.ResponseWriter, r *http.Request) string {
	// AuthCodeURL is a token to protect the user from CSRF attacks. It
	// is also attached to the response as a cookie.
	oauthState := generateStateOauthCookie(w)
	return goauth2.Config.AuthCodeURL(oauthState)
}

// }}}
// {{{ goauth2.GetLogoutUrl

func (goauth2 GoogleOauth2)GetLogoutUrl(w http.ResponseWriter, r *http.Request) string {
	loginUrl := makeUrlAbsolute(r, "/")

	args1 := url.Values{}
	args1.Add("continue", loginUrl)

	args2 := url.Values{}
	args2.Add("continue", "https://appengine.google.com/_ah/logout?" + args1.Encode())

	// This weird thing bounces you through a "are you sure you want to redirect" notice,
	// which is fine. You can't just redirect anywhere, it has to go to a google url.
	return "https://www.google.com/accounts/Logout?" + args2.Encode()
}

// }}}
// {{{ goauth2.CallbackToEmail

func (goauth2 GoogleOauth2)CallbackToEmail(r *http.Request) (string, error) {
	// Read oauthState from Cookie
	if oauthState,err := r.Cookie("oauthstate"); err != nil {
		log.Printf("no oauth google cookie: %v", err)
		return "", fmt.Errorf("no oauth google cookie: %v", err)
	} else if r.FormValue("state") != oauthState.Value {
		return "", fmt.Errorf("invalid oauth google state")
	}

	email,err := goauth2.getEmailFromGoogle(r.FormValue("code"))
	return email,err
}

// }}}

// {{{ goauth2.getEmailFromGoogle

func (goauth2 GoogleOauth2)getEmailFromGoogle(code string) (string, error) {
	if data,err := goauth2.getUserDataFromGoogle(code); err != nil {
		return "", err
	} else {
		var jsonMap map[string]interface{}
		if err := json.Unmarshal([]byte(data), &jsonMap); err != nil {
			return "", fmt.Errorf("google oauth unmarshal:"+err.Error())
		}

		emailVar := jsonMap["email"];
		if emailVar == nil {
			return "", fmt.Errorf("google oauth callback: jsonmap had no 'email'\n%#v", jsonMap)
		}

		if email,ok := emailVar.(string); !ok {
			return "", fmt.Errorf("google oauth callback: 'email' not a string\n%#v", jsonMap)
		} else {
			return email, nil
		}
	}
}

// }}}
// {{{ goauth2.getUserDataFromGoogle

func (goauth2 GoogleOauth2)getUserDataFromGoogle(code string) ([]byte, error) {
	token, err := goauth2.Config.Exchange(context.Background(), code)
	if err != nil {
		return nil, fmt.Errorf("code exchange wrong: %s", err.Error())
	}

	response, err := http.Get(oauthGoogleUrlAPI + token.AccessToken)
	if err != nil {
		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
	}

	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("failed read response: %s", err.Error())
	}

	return contents, nil
}

// }}}

// {{{ generateStateOauthCookie

func generateStateOauthCookie(w http.ResponseWriter) string {
	var expiration = time.Now().Add(20 * time.Minute)

	b := make([]byte, 16)
	rand.Read(b)
	state := base64.URLEncoding.EncodeToString(b)
	cookie := http.Cookie{Name: "oauthstate", Value: state, Expires: expiration}
	http.SetCookie(w, &cookie)

	return state
}

// }}}

// {{{ -------------------------={ E N D }=----------------------------------

// Local variables:
// folded-file: t
// end:

// }}}
<|endoftext|>


<commit_before>package sqlx

import (
	"database/sql"
	"errors"
	"fmt"
	"reflect"
)

type ChunkFunk interface{}

type Chunker struct {
	rows *sql.Rows
}

func NewChunker(r *sql.Rows) *Chunker {
	return &Chunker{r}
}

func (self *Chunker) Chunk(n int, f ChunkFunk) error {
	defer self.rows.Close()

	funcValue := reflect.ValueOf(f)
	funcType := funcValue.Type()

	if funcType.Kind() != reflect.Func {
		return errors.New("sqlx: two parameter not a func")
	}

	if funcType.NumIn() != 1 {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	sliceType := funcType.In(0)

	if sliceType.Kind() != reflect.Slice {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	numOut := funcType.NumOut()

	if numOut > 1 {
		return errors.New("sqlx: return must be bool")
	}

	if numOut == 1 {
		outType := funcType.Out(0)
		if outType.Kind() != reflect.Bool {
			return errors.New("sqlx: return must be bool")
		}
	}

	columns, err := self.rows.Columns()

	if err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	sliceValuePrt := reflect.New(sliceType)
	sliceValue := reflect.Indirect(sliceValuePrt)

	sliceElem := sliceType.Elem()
	structValuePrt := reflect.New(sliceElem)
	structValue := reflect.Indirect(structValuePrt)

	if structValue.Kind() != reflect.Struct {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	structType := structValue.Type()

	count := structType.NumField()
	fieldsMap := make(map[int]string)

	for i := 0; i < count; i++ {
		f := structType.Field(i)
		if f.Anonymous || f.PkgPath != "" {
			continue
		}
		fieldsMap[i] = toSnake(f.Name)
	}

	var found bool = false
	var interrupt bool = false
	var i int = 1
	for self.rows.Next() {
		structValuePrt := reflect.New(sliceElem)
		structValue := reflect.Indirect(structValuePrt)

		fields := make(map[string]reflect.Value)

		for k, v := range fieldsMap {
			fields[v] = structValue.Field(k)
		}

		values := make([]interface{}, len(columns))

		for i, column := range columns {
			if field, ok := fields[column]; ok {
				values[i] = field.Addr().Interface()
			} else {
				values[i] = &sql.NullString{}
			}
		}

		if err := self.rows.Scan(values...); err != nil {
			return fmt.Errorf("sqlx: %s", err)
		}

		sliceValue.Set(reflect.Append(sliceValue, structValue))

		if i == n {
			out := funcValue.Call([]reflect.Value{sliceValue})
			sliceValue = reflect.Indirect(reflect.New(sliceType))
			found = true
			i = 1
			if len(out) > 0 && !out[0].Bool() {
				interrupt = true
				break
			}
			continue
		}

		i++
		found = true
	}

	if !interrupt && sliceValue.Len() > 0 {
		funcValue.Call([]reflect.Value{sliceValue})
	}

	if err := self.rows.Err(); err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	if !found {
		return sql.ErrNoRows
	}

	if err := self.rows.Close(); err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	return nil
}
<commit_msg>Fix ErrNoRows for Chancker<commit_after>package sqlx

import (
	"database/sql"
	"errors"
	"fmt"
	"reflect"
)

type ChunkFunk interface{}

type Chunker struct {
	rows *sql.Rows
}

func NewChunker(r *sql.Rows) *Chunker {
	return &Chunker{r}
}

func (self *Chunker) Chunk(n int, f ChunkFunk) error {
	defer self.rows.Close()

	funcValue := reflect.ValueOf(f)
	funcType := funcValue.Type()

	if funcType.Kind() != reflect.Func {
		return errors.New("sqlx: two parameter not a func")
	}

	if funcType.NumIn() != 1 {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	sliceType := funcType.In(0)

	if sliceType.Kind() != reflect.Slice {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	numOut := funcType.NumOut()

	if numOut > 1 {
		return errors.New("sqlx: return must be bool")
	}

	if numOut == 1 {
		outType := funcType.Out(0)
		if outType.Kind() != reflect.Bool {
			return errors.New("sqlx: return must be bool")
		}
	}

	columns, err := self.rows.Columns()

	if err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	sliceValuePrt := reflect.New(sliceType)
	sliceValue := reflect.Indirect(sliceValuePrt)

	sliceElem := sliceType.Elem()
	structValuePrt := reflect.New(sliceElem)
	structValue := reflect.Indirect(structValuePrt)

	if structValue.Kind() != reflect.Struct {
		return errors.New("sqlx: two parameter must be func([]Struct)")
	}

	structType := structValue.Type()

	count := structType.NumField()
	fieldsMap := make(map[int]string)

	for i := 0; i < count; i++ {
		f := structType.Field(i)
		if f.Anonymous || f.PkgPath != "" {
			continue
		}
		fieldsMap[i] = toSnake(f.Name)
	}

	var found bool = false
	var interrupt bool = false
	var i int = 1
	for self.rows.Next() {
		structValuePrt := reflect.New(sliceElem)
		structValue := reflect.Indirect(structValuePrt)

		fields := make(map[string]reflect.Value)

		for k, v := range fieldsMap {
			fields[v] = structValue.Field(k)
		}

		values := make([]interface{}, len(columns))

		for i, column := range columns {
			if field, ok := fields[column]; ok {
				values[i] = field.Addr().Interface()
			} else {
				values[i] = &sql.NullString{}
			}
		}

		if err := self.rows.Scan(values...); err != nil {
			return fmt.Errorf("sqlx: %s", err)
		}

		sliceValue.Set(reflect.Append(sliceValue, structValue))

		if i == n {
			out := funcValue.Call([]reflect.Value{sliceValue})
			sliceValue = reflect.Indirect(reflect.New(sliceType))
			found = true
			i = 1
			if len(out) > 0 && !out[0].Bool() {
				interrupt = true
				break
			}
			continue
		}

		i++
		found = true
	}

	if !interrupt && sliceValue.Len() > 0 {
		funcValue.Call([]reflect.Value{sliceValue})
	}

	if err := self.rows.Err(); err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	if !found {
		return ErrNoRows
	}

	if err := self.rows.Close(); err != nil {
		return fmt.Errorf("sqlx: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package listsellers_test

import (
	"github.com/luistm/banksaurus/next/listsellers"
	"github.com/luistm/testkit"
	"testing"
)

func TestUnitNewInteractor(t *testing.T) {

	t.Run("Returns error if sellers repository undefined", func(t *testing.T) {
		_, err := listsellers.NewInteractor(nil)
		testkit.AssertEqual(t, listsellers.ErrSellersRepositoryUndefined, err)
	})
}
<commit_msg>Adds test to check if it does not return error<commit_after>package listsellers_test

import (
	"github.com/luistm/banksaurus/next/listsellers"
	"github.com/luistm/testkit"
	"testing"
	"github.com/luistm/banksaurus/next/entity/seller"
)

type sellerRepository struct{}

func (*sellerRepository) GetAll() []*seller.Entity {
	panic("implement me")
}

func TestUnitNewInteractor(t *testing.T) {

	t.Run("Returns error if sellers repository undefined", func(t *testing.T) {
		_, err := listsellers.NewInteractor(nil)
		testkit.AssertEqual(t, listsellers.ErrSellersRepositoryUndefined, err)
	})

	t.Run("Does not return error if sellers repository is defined", func(t *testing.T){
		_, err := listsellers.NewInteractor(&sellerRepository{})
		testkit.AssertIsNil(t, err)
	})
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/jessevdk/go-flags"
)

const version = "v0.0.1"

type opts struct {
	Help    bool   `short:"h" long:"help" description:"Print this message and quit"`
	Version bool   `short:"v" long:"version" description:"Print version information and quit"`
	OutDir  string `short:"o" long:"output" description:"Specify an output directory for Ghost posts"`
}

func init() {
}

func main() {
	opts := &opts{}
	p := flags.NewParser(opts, flags.PrintErrors)
	args, err := p.Parse()
	if err != nil {
		return
	}

	if opts.Help || (len(args) == 0 && len(os.Args) < 2) {
		fmt.Fprintf(os.Stderr, helpText)
		return
	}

	if opts.Version {
		fmt.Fprintf(os.Stderr, "md2ghost: %s\n", version)
		return
	}

	if len(args) > 0 {
		targetDir := "."
		if len(os.Args) == 2 {
			targetDir = os.Args[1]
		}
		pattern := targetDir + "/*.md"
		files, err := filepath.Glob(pattern)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		defer fp.Close()

		scanner := bufio.NewScanner(fp)
		for scanner.Scan() {
			fmt.Println(scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
	}
}

const helpText = `md2ghost - Convert a markdown files into Ghost posts.

Usage: md2ghost [option] <file|directory>

Options:

  -o, --output  Specify an output directory for Ghost posts
  -h, --help    Print this message and quit
  -v, --version Print version information and quit

Example:

  $ md2ghost .
  $ md2ghost -o path/to/output_directory path/to/your_directory
`
<commit_msg>:lipstick: Delete unnecessary conditional expressions<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"

	"github.com/jessevdk/go-flags"
)

const version = "v0.0.1"

type opts struct {
	Help    bool   `short:"h" long:"help" description:"Print this message and quit"`
	Version bool   `short:"v" long:"version" description:"Print version information and quit"`
	OutDir  string `short:"o" long:"output" description:"Specify an output directory for Ghost posts"`
}

func init() {
}

func main() {
	opts := &opts{}
	p := flags.NewParser(opts, flags.PrintErrors)
	args, err := p.Parse()
	if err != nil {
		return
	}

	if opts.Help || (len(args) == 0 && len(os.Args) < 2) {
		fmt.Fprintf(os.Stderr, helpText)
		return
	}

	if opts.Version {
		fmt.Fprintf(os.Stderr, "md2ghost: %s\n", version)
		return
	}

	var fp *os.File
	var pattern string

	// MEMO: args[0] != "" だと panic: runtime error: index out of range
	if len(args) != 0 {
		pattern = args[0] + "/*.md"
	} else {
		pattern = "." + "/*.md"
	}

	files, err := filepath.Glob(pattern)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return
	}
	for _, file := range files {
		fp, err = os.Open(file)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
		defer fp.Close()

		scanner := bufio.NewScanner(fp)
		for scanner.Scan() {
			fmt.Println(scanner.Text())
		}
		if err := scanner.Err(); err != nil {
			fmt.Fprintln(os.Stderr, err)
			return
		}
	}
}

const helpText = `md2ghost - Convert a markdown files into Ghost posts.

Usage: md2ghost [option] <file|directory>

Options:

  -o, --output  Specify an output directory for Ghost posts
  -h, --help    Print this message and quit
  -v, --version Print version information and quit

Example:

  $ md2ghost .
  $ md2ghost -o path/to/output_directory path/to/your_directory
`
<|endoftext|>


<commit_before>package reviewboard

import (
	// Stdlib
	"bytes"
	"errors"
	"fmt"
	"regexp"
	"strconv"

	// Internal
	"github.com/salsita/salsaflow/config"
	"github.com/salsita/salsaflow/errs"
	"github.com/salsita/salsaflow/git"
	"github.com/salsita/salsaflow/log"
	"github.com/salsita/salsaflow/modules/common"
	"github.com/salsita/salsaflow/repo"
	"github.com/salsita/salsaflow/shell"
)

const Id = "review_board"

type codeReviewTool struct{}

func Factory() (common.CodeReviewTool, error) {
	repo.AddInitHook(ensureRbtVersion)
	return &codeReviewTool{}, nil
}

func (tool *codeReviewTool) PostReviewRequest(commit *git.Commit) error {
	msg := "Post review request for commit " + commit.SHA
	stdout, stderr, err := shell.Run(
		"rbt", "post", "--guess-fields", "yes", "--branch", commit.StoryId, commit.SHA)
	if err != nil {
		return errs.NewError(msg, stderr, err)
	}
	logger := log.V(log.Info)
	logger.Lock()
	logger.UnsafeOk(msg)
	fmt.Print(stdout)
	logger.Unlock()
	return nil
}

func (tool *codeReviewTool) PrintPostReviewRequestFollowup() {
	log.Println(`
Now, please, take some time to go through all the review requests,
check and annotate them for the reviewers to make them more happy (less sad).

If you find any issues you want to fix right before publishing, fix them now,
amend the relevant commits and use:

  $ rbt post -r <RB request id> <commit SHA>

to update the relevant review request.

When you think the review requests are ready to be published,
publish them in Review Board. Then merge your branch into ` + config.TrunkBranch + ` and push.
`)
}

func ensureRbtVersion() error {
	msg := "Check the RBTools version being used"
	log.Run(msg)

	// rbt prints the version string to stderr. WHY? Know knows...
	_, stderr, err := shell.Run("rbt", "--version")
	if err != nil {
		return errs.NewError(msg, stderr, err)
	}

	pattern := regexp.MustCompile("^RBTools (([0-9]+)[.]([0-9]+).*)")
	parts := pattern.FindStringSubmatch(stderr.String())
	if len(parts) != 4 {
		err := errors.New("failed to parse 'rbt --version' output: " + stderr.String())
		return errs.NewError(msg, nil, err)
	}
	rbtVersion := parts[1]
	// No need to check errors, we know the format is correct.
	major, _ := strconv.Atoi(parts[2])
	minor, _ := strconv.Atoi(parts[3])

	if !(major == 0 && minor == 6) {
		hint := `
You need RBTools version 0.6. Please run

  $ pip install rbtool~=0.6 --allow-external rbtool --allow-unverified rbtool

to install the correct version.

`
		return errs.NewError(
			msg,
			bytes.NewBufferString(hint),
			errors.New("unsupported rbt version detected: "+rbtVersion))
	}

	return nil
}
<commit_msg>modules/reviewboard: Rewrite the followup message<commit_after>package reviewboard

import (
	// Stdlib
	"bytes"
	"errors"
	"fmt"
	"regexp"
	"strconv"

	// Internal
	"github.com/salsita/salsaflow/errs"
	"github.com/salsita/salsaflow/git"
	"github.com/salsita/salsaflow/log"
	"github.com/salsita/salsaflow/modules/common"
	"github.com/salsita/salsaflow/repo"
	"github.com/salsita/salsaflow/shell"
)

const Id = "review_board"

type codeReviewTool struct{}

func Factory() (common.CodeReviewTool, error) {
	repo.AddInitHook(ensureRbtVersion)
	return &codeReviewTool{}, nil
}

func (tool *codeReviewTool) PostReviewRequest(commit *git.Commit) error {
	msg := "Post review request for commit " + commit.SHA
	stdout, stderr, err := shell.Run(
		"rbt", "post", "--guess-fields", "yes", "--branch", commit.StoryId, commit.SHA)
	if err != nil {
		return errs.NewError(msg, stderr, err)
	}
	logger := log.V(log.Info)
	logger.Lock()
	logger.UnsafeNewLine("")
	logger.UnsafeOk(msg)
	fmt.Print(stdout)
	logger.Unlock()
	return nil
}

func (tool *codeReviewTool) PrintPostReviewRequestFollowup() {
	log.Println(`
Now, please, take some time to go through all the review requests,
check and annotate them for the reviewers to make them more happy (less sad).

If you find any issues you want to fix right before publishing, fix them now,
and if you still can, amend the relevant commits and use:

  $ rbt post -r <RB request id> <commit SHA>

to update (replace) the relevant review request.

In case you cannot amend the relevant commits any more, use the usual
review update command to update the review requests.

When you think that you are ready, publish the review requests in Review Board.
`)
}

func ensureRbtVersion() error {
	msg := "Check the RBTools version being used"
	log.Run(msg)

	// rbt prints the version string to stderr. WHY? Know knows...
	_, stderr, err := shell.Run("rbt", "--version")
	if err != nil {
		return errs.NewError(msg, stderr, err)
	}

	pattern := regexp.MustCompile("^RBTools (([0-9]+)[.]([0-9]+).*)")
	parts := pattern.FindStringSubmatch(stderr.String())
	if len(parts) != 4 {
		err := errors.New("failed to parse 'rbt --version' output: " + stderr.String())
		return errs.NewError(msg, nil, err)
	}
	rbtVersion := parts[1]
	// No need to check errors, we know the format is correct.
	major, _ := strconv.Atoi(parts[2])
	minor, _ := strconv.Atoi(parts[3])

	if !(major == 0 && minor == 6) {
		hint := `
You need RBTools version 0.6. Please run

  $ pip install rbtool~=0.6 --allow-external rbtool --allow-unverified rbtool

to install the correct version.

`
		return errs.NewError(
			msg,
			bytes.NewBufferString(hint),
			errors.New("unsupported rbt version detected: "+rbtVersion))
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
)

const version = "v0.0.1"

var (
	flHelp    = flag.Bool("help", false, "Print this message and quit")
	flVersion = flag.Bool("version", false, "Print version information and quit")
)

func init() {
	flag.BoolVar(flHelp, "h", false, "Print this message and quit")
	flag.BoolVar(flVersion, "v", false, "Print version information and quit")
}

func main() {
	flag.Parse()

	if *flHelp {
		fmt.Fprintf(os.Stderr, helpText)
		os.Exit(0)
	}

	if *flVersion {
		fmt.Fprintf(os.Stderr, "md2ghost: %s\n", version)
		os.Exit(0)
	}
}

const helpText = `md2ghost - Convert a markdown files into Ghost posts.

Usage: md2ghost [option] <file|directory>

Options:

  -o, --output  Specify an output directory for Ghost posts
  -h, --help    Print this message and quit
  -v, --version Print version information and quit

Example:

  $ md2ghost .
  $ md2ghost -o path/to/output_directory path/to/your_directory
`
<commit_msg>If no command line arguments to show help<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
)

const version = "v0.0.1"

var (
	flHelp    = flag.Bool("help", false, "Print this message and quit")
	flVersion = flag.Bool("version", false, "Print version information and quit")
)

func init() {
	flag.BoolVar(flHelp, "h", false, "Print this message and quit")
	flag.BoolVar(flVersion, "v", false, "Print version information and quit")
}

func main() {
	flag.Parse()

	if *flHelp || flag.NArg() == 0 {
		fmt.Fprintf(os.Stderr, helpText)
		os.Exit(0)
	}

	if *flVersion {
		fmt.Fprintf(os.Stderr, "md2ghost: %s\n", version)
		os.Exit(0)
	}
}

const helpText = `md2ghost - Convert a markdown files into Ghost posts.

Usage: md2ghost [option] <file|directory>

Options:

  -o, --output  Specify an output directory for Ghost posts
  -h, --help    Print this message and quit
  -v, --version Print version information and quit

Example:

  $ md2ghost .
  $ md2ghost -o path/to/output_directory path/to/your_directory
`
<|endoftext|>