<commit_before>package qbit

import (
	"errors"
	"fmt"
	"strings"
)

func NewBuilder() *Builder {
	return &Builder{
		prettyMode: true,
		query:      NewQuery(),
		errors:     []error{},
	}
}

const BUILDER_DELIMITER  = "\n"

// builder is a subset of dialect could be used for common sql queries
// it has all the common functions except multiple statements & table crudders
type Builder struct {
	prettyMode bool
	query      *Query
	errors     []error
}

// function resets query and its errors
func (b *Builder) Reset() {
	b.query = NewQuery()
	b.errors = []error{}
}

// function builds the query clauses and returns the sql and bindings
func (b *Builder) Build() (string, []interface{}, error) {

	if b.HasError() {
		errs := []string{}
		for _, err := range b.errors {
			errs = append(errs, err.Error())
		}
		err := errors.New(strings.Join(errs, "\n"))
		b.errors = []error{}
		return "", nil, err
	}

//	var delimiter string
//
//	if b.prettyMode {
//		delimiter = "\n"
//	} else {
//		delimiter = " "
//	}

	bindings := b.query.Bindings()
	sql := fmt.Sprintf("%s;", strings.Join(b.query.Clauses(), BUILDER_DELIMITER))

	b.query = NewQuery()

	return sql, bindings, nil
}

func (b *Builder) AddError(err error) {
	b.errors = append(b.errors, err)
}

func (b *Builder) HasError() bool {
	return len(b.errors) > 0
}

func (b *Builder) Errors() []error {
	return b.errors
}

func (b *Builder) questionMarks(values ...interface{}) []string {
	questionMarks := make([]string, len(values))
	for k, _ := range values {
		questionMarks[k] = "?"
	}
	return questionMarks
}

// function generates an "insert into %s(%s)" statement
func (b *Builder) Insert(table string, columns ...string) *Builder {
	clause := fmt.Sprintf("INSERT INTO %s(%s)", table, strings.Join(columns, ", "))
	b.query.AddClause(clause)
	return b
}

// function generates "values(%s)" statement and add bindings for each value
func (b *Builder) Values(values ...interface{}) *Builder {
	b.query.AddBinding(values...)
	clause := fmt.Sprintf("VALUES (%s)", strings.Join(b.questionMarks(values...), ", "))
	b.query.AddClause(clause)
	return b
}

// function generates "update %s" statement
func (b *Builder) Update(table string) *Builder {
	clause := fmt.Sprintf("UPDATE %s", table)
	b.query.AddClause(clause)
	return b
}

// function generates "set a = ?" statement for each key a and add bindings for map value
func (b *Builder) Set(m map[string]interface{}) *Builder {
	updates := []string{}
	for k, v := range m {
		updates = append(updates, fmt.Sprintf("%s = ?", k))
		b.query.AddBinding(v)
	}
	clause := fmt.Sprintf("SET %s", strings.Join(updates, ", "))
	b.query.AddClause(clause)
	return b
}

// function generates "delete" statement
func (b *Builder) Delete(table string) *Builder {
	b.query.AddClause(fmt.Sprintf("DELETE FROM %s", table))
	return b
}

// function generates "select %s" statement
func (b *Builder) Select(columns ...string) *Builder {
	clause := fmt.Sprintf("SELECT %s", strings.Join(columns, ", "))
	b.query.AddClause(clause)
	return b
}

// function generates "from %s" statement for each table name
func (b *Builder) From(tables ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("FROM %s", strings.Join(tables, ", ")))
	return b
}

// function generates "inner join %s on %s" statement for each expression
func (b *Builder) InnerJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("INNER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// function generates "cross join %s" statement for table
func (b *Builder) CrossJoin(table string) *Builder {
	b.query.AddClause(fmt.Sprintf("CROSS JOIN %s", table))
	return b
}

// function generates "left outer join %s on %s" statement for each expression
func (b *Builder) LeftOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("LEFT OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// function generates "right outer join %s on %s" statement for each expression
func (b *Builder) RightOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("RIGHT OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// function generates "full outer join %s on %s" for each expression
func (b *Builder) FullOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("FULL OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// function generates "where %s" for the expression and adds bindings for each value
func (b *Builder) Where(expression string, bindings ...interface{}) *Builder {
	b.query.AddClause(fmt.Sprintf("WHERE %s", expression))
	b.query.AddBinding(bindings...)
	return b
}

// function generates "order by %s" for each expression
func (b *Builder) OrderBy(expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("ORDER BY %s", strings.Join(expressions, ", ")))
	return b
}

// function generates "group by %s" for each column
func (b *Builder) GroupBy(columns ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("GROUP BY %s", strings.Join(columns, ", ")))
	return b
}

// function generates "having %s" for each expression
func (b *Builder) Having(expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("HAVING %s", strings.Join(expressions, ", ")))
	return b
}

// function generates limit %d offset %d for offset and count
func (b *Builder) Limit(offset int, count int) *Builder {
	b.query.AddClause(fmt.Sprintf("LIMIT %d OFFSET %d", count, offset))
	return b
}

// aggregates

// function generates "avg(%s)" statement for column
func (b *Builder) Avg(column string) string {
	return fmt.Sprintf("AVG(%s)", column)
}

// function generates "count(%s)" statement for column
func (b *Builder) Count(column string) string {
	return fmt.Sprintf("COUNT(%s)", column)
}

// function generates "sum(%s)" statement for column
func (b *Builder) Sum(column string) string {
	return fmt.Sprintf("SUM(%s)", column)
}

// function generates "min(%s)" statement for column
func (b *Builder) Min(column string) string {
	return fmt.Sprintf("MIN(%s)", column)
}

// function generates "max(%s)" statement for column
func (b *Builder) Max(column string) string {
	return fmt.Sprintf("MAX(%s)", column)
}

// expressions

// function generates "%s not in (%s)" for key and adds bindings for each value
func (b *Builder) NotIn(key string, values ...interface{}) string {
	b.query.AddBinding(values...)
	return fmt.Sprintf("%s NOT IN (%s)", key, strings.Join(b.questionMarks(values...), ","))
}

// function generates "%s in (%s)" for key and adds bindings for each value
func (b *Builder) In(key string, values ...interface{}) string {
	b.query.AddBinding(values...)
	return fmt.Sprintf("%s IN (%s)", key, strings.Join(b.questionMarks(values...), ","))
}

// function generates "%s != ?" for key and adds binding for value
func (b *Builder) NotEq(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s != ?", key)
}

// function generates "%s = ?" for key and adds binding for value
func (b *Builder) Eq(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s = ?", key)
}

// function generates "%s > ?" for key and adds binding for value
func (b *Builder) Gt(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s > ?", key)
}

// function generates "%s >= ?" for key and adds binding for value
func (b *Builder) Gte(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s >= ?", key)
}

// function generates "%s < ?" for key and adds binding for value
func (b *Builder) St(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s < ?", key)
}

// function generates "%s <= ?" for key and adds binding for value
func (b *Builder) Ste(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s <= ?", key)
}

// function generates " AND " between any number of expressions
func (b *Builder) And(expressions ...string) string {
	return fmt.Sprintf("(%s)", strings.Join(expressions, " AND "))
}

// function generates " OR " between any number of expressions
func (b *Builder) Or(expressions ...string) string {
	return strings.Join(expressions, " OR ")
}

// function generates generic CREATE TABLE statement
func (b *Builder) CreateTable(table string, fields []string, constraints []string) *Builder {

	b.query.AddClause(fmt.Sprintf("CREATE TABLE %s(", table))

	for k, f := range fields {
		clause := fmt.Sprintf("\t%s", f)
		if len(fields)-1 > k || len(constraints) > 0 {
			clause += ","
		}
		b.query.AddClause(clause)
	}

	for k, c := range constraints {
		constraint := fmt.Sprintf("\t%s", c)
		if len(constraints)-1 > k {
			constraint += ","
		}
		b.query.AddClause(fmt.Sprintf("%s", constraint))
	}

	b.query.AddClause(")")
	return b
}

// function generates generic ALTER TABLE statement
func (b *Builder) AlterTable(table string) *Builder {

	b.query.AddClause(fmt.Sprintf("ALTER TABLE %s", table))
	return b
}

// function generates generic DROP TABLE statement
func (b *Builder) DropTable(table string) *Builder {

	b.query.AddClause(fmt.Sprintf("DROP TABLE %s", table))
	return b
}

// function generates generic ADD COLUMN statement
func (b *Builder) Add(colName string, colType string) *Builder {

	b.query.AddClause(fmt.Sprintf("ADD %s %s", colName, colType))
	return b
}

// function generates generic DROP COLUMN statement
func (b *Builder) Drop(colName string) *Builder {

	b.query.AddClause(fmt.Sprintf("DROP %s", colName))
	return b
}
<commit_msg>fix lint errors of builder<commit_after>package qbit

import (
	"errors"
	"fmt"
	"strings"
)

// NewBuilder generates a new builder object
func NewBuilder() *Builder {
	return &Builder{
		prettyMode: true,
		query:      NewQuery(),
		errors:     []error{},
	}
}

const builderDelimiter = "\n"

// Builder is a subset of dialect could be used for common sql queries
// it has all the common functions except multiple statements & table crudders
type Builder struct {
	prettyMode bool
	query      *Query
	errors     []error
}

// Reset clears query bindings and its errors
func (b *Builder) Reset() {
	b.query = NewQuery()
	b.errors = []error{}
}

// Build generates sql query and bindings from clauses and bindings.
// The query clauses and returns the sql and bindings
func (b *Builder) Build() (string, []interface{}, error) {

	if b.HasError() {
		errs := []string{}
		for _, err := range b.errors {
			errs = append(errs, err.Error())
		}
		err := errors.New(strings.Join(errs, "\n"))
		b.errors = []error{}
		return "", nil, err
	}

	//	var delimiter string
	//
	//	if b.prettyMode {
	//		delimiter = "\n"
	//	} else {
	//		delimiter = " "
	//	}

	bindings := b.query.Bindings()
	sql := fmt.Sprintf("%s;", strings.Join(b.query.Clauses(), builderDelimiter))

	b.query = NewQuery()

	return sql, bindings, nil
}

// AddError appends a new error to builder
func (b *Builder) AddError(err error) {
	b.errors = append(b.errors, err)
}

// HasError returns if the builder has any syntax or build errors
func (b *Builder) HasError() bool {
	return len(b.errors) > 0
}

// Errors returns builder errors as an error slice
func (b *Builder) Errors() []error {
	return b.errors
}

func (b *Builder) questionMarks(values ...interface{}) []string {
	questionMarks := make([]string, len(values))
	for k := range values {
		questionMarks[k] = "?"
	}
	return questionMarks
}

// Insert generates an "insert into %s(%s)" statement
func (b *Builder) Insert(table string, columns ...string) *Builder {
	clause := fmt.Sprintf("INSERT INTO %s(%s)", table, strings.Join(columns, ", "))
	b.query.AddClause(clause)
	return b
}

// Values generates "values(%s)" statement and add bindings for each value
func (b *Builder) Values(values ...interface{}) *Builder {
	b.query.AddBinding(values...)
	clause := fmt.Sprintf("VALUES (%s)", strings.Join(b.questionMarks(values...), ", "))
	b.query.AddClause(clause)
	return b
}

// Update generates "update %s" statement
func (b *Builder) Update(table string) *Builder {
	clause := fmt.Sprintf("UPDATE %s", table)
	b.query.AddClause(clause)
	return b
}

// Set generates "set a = ?" statement for each key a and add bindings for map value
func (b *Builder) Set(m map[string]interface{}) *Builder {
	updates := []string{}
	for k, v := range m {
		updates = append(updates, fmt.Sprintf("%s = ?", k))
		b.query.AddBinding(v)
	}
	clause := fmt.Sprintf("SET %s", strings.Join(updates, ", "))
	b.query.AddClause(clause)
	return b
}

// Delete generates "delete" statement
func (b *Builder) Delete(table string) *Builder {
	b.query.AddClause(fmt.Sprintf("DELETE FROM %s", table))
	return b
}

// Select generates "select %s" statement
func (b *Builder) Select(columns ...string) *Builder {
	clause := fmt.Sprintf("SELECT %s", strings.Join(columns, ", "))
	b.query.AddClause(clause)
	return b
}

// From generates "from %s" statement for each table name
func (b *Builder) From(tables ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("FROM %s", strings.Join(tables, ", ")))
	return b
}

// InnerJoin generates "inner join %s on %s" statement for each expression
func (b *Builder) InnerJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("INNER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// CrossJoin generates "cross join %s" statement for table
func (b *Builder) CrossJoin(table string) *Builder {
	b.query.AddClause(fmt.Sprintf("CROSS JOIN %s", table))
	return b
}

// LeftOuterJoin generates "left outer join %s on %s" statement for each expression
func (b *Builder) LeftOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("LEFT OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// RightOuterJoin generates "right outer join %s on %s" statement for each expression
func (b *Builder) RightOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("RIGHT OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// FullOuterJoin generates "full outer join %s on %s" for each expression
func (b *Builder) FullOuterJoin(table string, expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("FULL OUTER JOIN %s ON %s", table, strings.Join(expressions, " ")))
	return b
}

// Where generates "where %s" for the expression and adds bindings for each value
func (b *Builder) Where(expression string, bindings ...interface{}) *Builder {
	b.query.AddClause(fmt.Sprintf("WHERE %s", expression))
	b.query.AddBinding(bindings...)
	return b
}

// OrderBy generates "order by %s" for each expression
func (b *Builder) OrderBy(expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("ORDER BY %s", strings.Join(expressions, ", ")))
	return b
}

// GroupBy generates "group by %s" for each column
func (b *Builder) GroupBy(columns ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("GROUP BY %s", strings.Join(columns, ", ")))
	return b
}

// Having generates "having %s" for each expression
func (b *Builder) Having(expressions ...string) *Builder {
	b.query.AddClause(fmt.Sprintf("HAVING %s", strings.Join(expressions, ", ")))
	return b
}

// Limit generates limit %d offset %d for offset and count
func (b *Builder) Limit(offset int, count int) *Builder {
	b.query.AddClause(fmt.Sprintf("LIMIT %d OFFSET %d", count, offset))
	return b
}

// aggregates

// Avg function generates "avg(%s)" statement for column
func (b *Builder) Avg(column string) string {
	return fmt.Sprintf("AVG(%s)", column)
}

// Count function generates "count(%s)" statement for column
func (b *Builder) Count(column string) string {
	return fmt.Sprintf("COUNT(%s)", column)
}

// Sum function generates "sum(%s)" statement for column
func (b *Builder) Sum(column string) string {
	return fmt.Sprintf("SUM(%s)", column)
}

// Min function generates "min(%s)" statement for column
func (b *Builder) Min(column string) string {
	return fmt.Sprintf("MIN(%s)", column)
}

// Max function generates "max(%s)" statement for column
func (b *Builder) Max(column string) string {
	return fmt.Sprintf("MAX(%s)", column)
}

// expressions

// NotIn function generates "%s not in (%s)" for key and adds bindings for each value
func (b *Builder) NotIn(key string, values ...interface{}) string {
	b.query.AddBinding(values...)
	return fmt.Sprintf("%s NOT IN (%s)", key, strings.Join(b.questionMarks(values...), ","))
}

// In function generates "%s in (%s)" for key and adds bindings for each value
func (b *Builder) In(key string, values ...interface{}) string {
	b.query.AddBinding(values...)
	return fmt.Sprintf("%s IN (%s)", key, strings.Join(b.questionMarks(values...), ","))
}

// NotEq function generates "%s != ?" for key and adds binding for value
func (b *Builder) NotEq(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s != ?", key)
}

// Eq function generates "%s = ?" for key and adds binding for value
func (b *Builder) Eq(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s = ?", key)
}

// Gt function generates "%s > ?" for key and adds binding for value
func (b *Builder) Gt(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s > ?", key)
}

// Gte function generates "%s >= ?" for key and adds binding for value
func (b *Builder) Gte(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s >= ?", key)
}

// St function generates "%s < ?" for key and adds binding for value
func (b *Builder) St(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s < ?", key)
}

// Ste function generates "%s <= ?" for key and adds binding for value
func (b *Builder) Ste(key string, value interface{}) string {
	b.query.AddBinding(value)
	return fmt.Sprintf("%s <= ?", key)
}

// And function generates " AND " between any number of expressions
func (b *Builder) And(expressions ...string) string {
	return fmt.Sprintf("(%s)", strings.Join(expressions, " AND "))
}

// Or function generates " OR " between any number of expressions
func (b *Builder) Or(expressions ...string) string {
	return strings.Join(expressions, " OR ")
}

// CreateTable generates generic CREATE TABLE statement
func (b *Builder) CreateTable(table string, fields []string, constraints []string) *Builder {

	b.query.AddClause(fmt.Sprintf("CREATE TABLE %s(", table))

	for k, f := range fields {
		clause := fmt.Sprintf("\t%s", f)
		if len(fields)-1 > k || len(constraints) > 0 {
			clause += ","
		}
		b.query.AddClause(clause)
	}

	for k, c := range constraints {
		constraint := fmt.Sprintf("\t%s", c)
		if len(constraints)-1 > k {
			constraint += ","
		}
		b.query.AddClause(fmt.Sprintf("%s", constraint))
	}

	b.query.AddClause(")")
	return b
}

// AlterTable generates generic ALTER TABLE statement
func (b *Builder) AlterTable(table string) *Builder {

	b.query.AddClause(fmt.Sprintf("ALTER TABLE %s", table))
	return b
}

// DropTable generates generic DROP TABLE statement
func (b *Builder) DropTable(table string) *Builder {

	b.query.AddClause(fmt.Sprintf("DROP TABLE %s", table))
	return b
}

// Add generates generic ADD COLUMN statement
func (b *Builder) Add(colName string, colType string) *Builder {

	b.query.AddClause(fmt.Sprintf("ADD %s %s", colName, colType))
	return b
}

// Drop generates generic DROP COLUMN statement
func (b *Builder) Drop(colName string) *Builder {

	b.query.AddClause(fmt.Sprintf("DROP %s", colName))
	return b
}
<|endoftext|>


<commit_before>package docker

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

type Builder struct {
	runtime *Runtime
}

func NewBuilder(runtime *Runtime) *Builder {
	return &Builder{
		runtime: runtime,
	}
}

func (builder *Builder) Run(image *Image, cmd ...string) (*Container, error) {
	// FIXME: pass a NopWriter instead of nil
	config, err := ParseRun(append([]string{"-d", image.Id}, cmd...), nil, builder.runtime.capabilities)
	if config.Image == "" {
		return nil, fmt.Errorf("Image not specified")
	}
	if len(config.Cmd) == 0 {
		return nil, fmt.Errorf("Command not specified")
	}
	if config.Tty {
		return nil, fmt.Errorf("The tty mode is not supported within the builder")
	}

	// Create new container
	container, err := builder.runtime.Create(config)
	if err != nil {
		return nil, err
	}
	if err := container.Start(); err != nil {
		return nil, err
	}
	return container, nil
}

func (builder *Builder) Commit(container *Container, repository, tag, comment, author string) (*Image, error) {
	return builder.runtime.Commit(container.Id, repository, tag, comment, author)
}

func (builder *Builder) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := builder.runtime.Get(c)
		builder.runtime.Destroy(tmp)
		Debugf("Removing container %s", c)
	}
	for i := range images {
		builder.runtime.graph.Delete(i)
		Debugf("Removing image %s", i)
	}
}

func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) error {
	var (
		image, base   *Image
		tmpContainers map[string]struct{} = make(map[string]struct{})
		tmpImages     map[string]struct{} = make(map[string]struct{})
	)
	defer builder.clearTmp(tmpContainers, tmpImages)

	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		line = strings.TrimSpace(line)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, "	", 2)
		if len(tmp) != 2 {
			return fmt.Errorf("Invalid Dockerfile format")
		}
		switch tmp[0] {
		case "from":
			fmt.Fprintf(stdout, "FROM %s\n", tmp[1])
			image, err = builder.runtime.repositories.LookupImage(tmp[1])
			if err != nil {
				return err
			}
			break
		case "run":
			fmt.Fprintf(stdout, "RUN %s\n", tmp[1])
			if image == nil {
				return fmt.Errorf("Please provide a source image with `from` prior to run")
			}

			// Create the container and start it
			c, err := builder.Run(image, "/bin/sh", "-c", tmp[1])
			if err != nil {
				return err
			}
			tmpContainers[c.Id] = struct{}{}

			// Wait for it to finish
			if result := c.Wait(); result != 0 {
				return fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", tmp[1], result)
			}

			// Commit the container
			base, err = builder.Commit(c, "", "", "", "")
			if err != nil {
				return err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.Id)
			break
		case "copy":
			return fmt.Errorf("The copy operator has not yet been implemented")
		default:
			fmt.Fprintf(stdout, "Skipping unknown op %s\n", tmp[0])
		}
	}
	if base != nil {
		// The build is successful, keep the temporary containers and images
		for i := range tmpImages {
			delete(tmpImages, i)
		}
		for i := range tmpContainers {
			delete(tmpContainers, i)
		}
		fmt.Fprintf(stdout, "Build finished. image id: %s\n", base.Id)
	} else {
		fmt.Fprintf(stdout, "An error occured during the build\n")
	}
	return nil
}
<commit_msg>Implement the COPY operator within the builder<commit_after>package docker

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

type Builder struct {
	runtime *Runtime
}

func NewBuilder(runtime *Runtime) *Builder {
	return &Builder{
		runtime: runtime,
	}
}

func (builder *Builder) Run(image *Image, cmd ...string) (*Container, error) {
	// FIXME: pass a NopWriter instead of nil
	config, err := ParseRun(append([]string{"-d", image.Id}, cmd...), nil, builder.runtime.capabilities)
	if config.Image == "" {
		return nil, fmt.Errorf("Image not specified")
	}
	if len(config.Cmd) == 0 {
		return nil, fmt.Errorf("Command not specified")
	}
	if config.Tty {
		return nil, fmt.Errorf("The tty mode is not supported within the builder")
	}

	// Create new container
	container, err := builder.runtime.Create(config)
	if err != nil {
		return nil, err
	}
	if err := container.Start(); err != nil {
		return nil, err
	}
	return container, nil
}

func (builder *Builder) Commit(container *Container, repository, tag, comment, author string) (*Image, error) {
	return builder.runtime.Commit(container.Id, repository, tag, comment, author)
}

func (builder *Builder) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := builder.runtime.Get(c)
		builder.runtime.Destroy(tmp)
		Debugf("Removing container %s", c)
	}
	for i := range images {
		builder.runtime.graph.Delete(i)
		Debugf("Removing image %s", i)
	}
}

func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) error {
	var (
		image, base   *Image
		tmpContainers map[string]struct{} = make(map[string]struct{})
		tmpImages     map[string]struct{} = make(map[string]struct{})
	)
	defer builder.clearTmp(tmpContainers, tmpImages)

	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}
		line = strings.TrimSpace(line)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, "	", 2)
		if len(tmp) != 2 {
			return fmt.Errorf("Invalid Dockerfile format")
		}
		switch tmp[0] {
		case "from":
			fmt.Fprintf(stdout, "FROM %s\n", tmp[1])
			image, err = builder.runtime.repositories.LookupImage(tmp[1])
			if err != nil {
				return err
			}
			break
		case "run":
			fmt.Fprintf(stdout, "RUN %s\n", tmp[1])
			if image == nil {
				return fmt.Errorf("Please provide a source image with `from` prior to run")
			}

			// Create the container and start it
			c, err := builder.Run(image, "/bin/sh", "-c", tmp[1])
			if err != nil {
				return err
			}
			tmpContainers[c.Id] = struct{}{}

			// Wait for it to finish
			if result := c.Wait(); result != 0 {
				return fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", tmp[1], result)
			}

			// Commit the container
			base, err = builder.Commit(c, "", "", "", "")
			if err != nil {
				return err
			}
			tmpImages[base.Id] = struct{}{}

			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			break
		case "copy":
			if image == nil {
				return fmt.Errorf("Please provide a source image with `from` prior to copy")
			}
			tmp2 := strings.SplitN(tmp[1], " ", 2)
			if len(tmp) != 2 {
				return fmt.Errorf("Invalid COPY format")
			}
			fmt.Fprintf(stdout, "COPY %s to %s in %s\n", tmp2[0], tmp2[1], base.ShortId())

			file, err := Download(tmp2[0], stdout)
			if err != nil {
				return err
			}
			defer file.Body.Close()

			c, err := builder.Run(base, "echo", "insert", tmp2[0], tmp2[1])
			if err != nil {
				return err
			}

			if err := c.Inject(file.Body, tmp2[1]); err != nil {
				return err
			}

			base, err = builder.Commit(c, "", "", "", "")
			if err != nil {
				return err
			}
			fmt.Fprintf(stdout, "===> %s\n", base.ShortId())
			break
		default:
			fmt.Fprintf(stdout, "Skipping unknown op %s\n", tmp[0])
		}
	}
	if base != nil {
		// The build is successful, keep the temporary containers and images
		for i := range tmpImages {
			delete(tmpImages, i)
		}
		for i := range tmpContainers {
			delete(tmpContainers, i)
		}
		fmt.Fprintf(stdout, "Build finished. image id: %s\n", base.ShortId())
	} else {
		fmt.Fprintf(stdout, "An error occured during the build\n")
	}
	return nil
}
<|endoftext|>


<commit_before>// This is Free Software covered by the terms of the MIT license.
// See LICENSE file for details.
// Copyright 2017 by Intevation GmbH
package main

import (
	"strings"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/s-l-teichmann/creoleto/parser"
)

type builder struct {
	*parser.BaseCreole10Listener
	current *node

	stack []interface{}
}

type headingBuilder struct {
	depth      int
	hasContent bool
}

func newBuilder() *builder {
	return &builder{
		current: &node{},
	}
}

func (b *builder) push(x interface{}) {
	b.stack = append(b.stack, x)
}

func (b *builder) pop() interface{} {
	l := len(b.stack)
	x := b.stack[l-1]
	b.stack[l-1] = nil
	b.stack = b.stack[:l-1]
	return x
}

func (b *builder) top() interface{} {
	return b.stack[len(b.stack)-1]
}

func (b *builder) up() {
	if b.current != nil {
		b.current = b.current.parent
	}
}

func (b *builder) down(n *node) {
	b.current = link(n, b.current)
}

func (b *builder) find(typ nodeType) *node {
	for n := b.current; n != nil && n.nodeType != typ; n = n.parent {
	}
	return nil
}

func (b *builder) resolveLineBreaks(txt string) {
	for i, t := range strings.Split(txt, `\\`) {
		if i > 0 {
			link(&node{nodeType: lineBreakNode}, b.current)
		}
		link(text(strings.Replace(t, "~", "", -1)), b.current)
	}
}

func (b *builder) EnterHeading(c *parser.HeadingContext) {
	b.push(&headingBuilder{})
}

func (b *builder) EnterHeading_markup(c *parser.Heading_markupContext) {
	if hb := b.top().(*headingBuilder); !hb.hasContent {
		hb.depth++
	}
}

func (b *builder) ExitHeading_content(c *parser.Heading_contentContext) {
	b.top().(*headingBuilder).hasContent = true
}

func (b *builder) ExitHeading(c *parser.HeadingContext) {

	hb := b.pop().(*headingBuilder)

	trim := strings.Repeat("=", hb.depth)
	content := strings.TrimSpace(c.GetText())
	content = strings.TrimSuffix(strings.TrimPrefix(content, trim), trim)
	content = strings.TrimSpace(content)

	var typ nodeType
	switch hb.depth {
	case 1:
		typ = heading1Node
	case 2:
		typ = heading2Node
	case 3:
		typ = heading3Node
	case 4:
		typ = heading4Node
	case 5:
		typ = heading5Node
	default:
		typ = heading6Node
	}

	link(&node{nodeType: typ, value: content}, b.current)
}

func (b *builder) EnterParagraph(c *parser.ParagraphContext) {
	b.down(&node{nodeType: paragraphNode})
}

func (b *builder) ExitParagraph(c *parser.ParagraphContext) {
	b.up()
}

// text_first_element

/*
func (b *builder) EnterText_firstelement(c *parser.Text_firstelementContext) {
	fmt.Fprintln(os.Stderr, "1. EnterText_firstelement")
}

func (b *builder) ExitText_firstelement(c *parser.Text_firstelementContext) {
	fmt.Fprintln(os.Stderr, "1. ExitText_firstelement")
}
*/

// text_first_unformattedelement

/*
func (b *builder) EnterText_first_unformattedelement(c *parser.Text_first_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "1. ExitText_first_unformattedelement")
}
*/

func (b *builder) ExitText_first_unformattedelement(c *parser.Text_first_unformattedelementContext) {
	// fmt.Fprintf(os.Stderr, "1. ExitText_firstunformattedelement: '%s'\n", c.GetText())
	b.resolveLineBreaks(c.GetText())
}

func (b *builder) ExitText_lineseparator(c *parser.Text_lineseparatorContext) {
	link(text("\n"), b.current)
}

// text_unformattedelement

/*
func (b *builder) EnterText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "EnterText_unformattedelement")
}
*/

func (b *builder) ExitText_unformatted(c *parser.Text_unformattedContext) {
	//fmt.Fprintf(os.Stderr, "ExitText_unformatted '%s'\n", c.GetText())
	b.resolveLineBreaks(c.GetText())
}

/*
func (b *builder) EnterText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "EnterText_line")
}
*/

/*
func (b *builder) ExitText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "ExitText_line:", c.GetText())
}
*/

func (b *builder) EnterText_formattedelement(c *parser.Text_formattedelementContext) {
	//fmt.Fprintln(os.Stderr, "***EnterText_formattedelement")
	// type to be overwritten in ital_markup or bold_markup
	b.push(b.current)
}

func (b *builder) ExitText_formattedelement(c *parser.Text_formattedelementContext) {
	//fmt.Fprintln(os.Stderr, "***ExitText_formattedelement")
	b.current = b.pop().(*node)
}

func (b *builder) ExitNowiki_inline_content(c *parser.Nowiki_inline_contentContext) {
	nw := &node{nodeType: noWikiInlineNode}
	txt := strings.Replace(c.GetText(), "~", "", -1)
	link(text(txt), nw)
	link(nw, b.current)
}

func (b *builder) ExitNowiki_block_content(c *parser.Nowiki_block_contentContext) {
	nw := &node{nodeType: noWikiNode}
	link(text(c.GetText()), nw)
	link(nw, b.current)
}

func (b *builder) createFormatNode(typ nodeType) {
	// Do we have already one of these?
	if b.find(typ) == nil {
		// create one and descent.
		b.down(&node{nodeType: typ})
	}
}

func (b *builder) ExitHorizontalrule(c *parser.HorizontalruleContext) {
	link(&node{nodeType: horizontalLineNode}, b.current)
}

func (b *builder) EnterItal_markup(c *parser.Ital_markupContext) {
	//fmt.Fprintln(os.Stderr, "//EnterItal_markup")
	b.createFormatNode(italicsNode)
}

func (b *builder) EnterBold_markup(c *parser.Bold_markupContext) {
	//fmt.Fprintln(os.Stderr, "**EnterBold_markup")
	b.createFormatNode(boldNode)
}

// list_ord

func (b *builder) EnterList_ord(c *parser.List_ordContext) {
	b.down(&node{nodeType: orderedListNode})
}

func (b *builder) ExitList_ord(c *parser.List_ordContext) {
	b.up()
}

// list_unord

func (b *builder) EnterList_unord(c *parser.List_unordContext) {
	b.down(&node{nodeType: unorderedListNode})
}

func (b *builder) ExitList_unord(c *parser.List_unordContext) {
	b.up()
}

// list_elem

func (b *builder) EnterList_elem(c *parser.List_elemContext) {
	b.down(&node{nodeType: listItemNode})
}

func (b *builder) ExitList_elem(c *parser.List_elemContext) {
	b.up()
}

// table

func (b *builder) EnterTable(c *parser.TableContext) {
	b.down(&node{nodeType: tableNode})
}

func (b *builder) ExitTable(c *parser.TableContext) {
	b.up()
}

// table_row

func (b *builder) EnterTable_row(c *parser.Table_rowContext) {
	// Type may be corrected later.
	b.down(&node{nodeType: tableRowNode})
}

func (b *builder) ExitTable_row(c *parser.Table_rowContext) {
	b.up()
}

// table_normalcell

func (b *builder) EnterTable_normalcell(c *parser.Table_normalcellContext) {
	b.down(&node{nodeType: tableCellNode})
}

func (b *builder) ExitTable_normalcell(c *parser.Table_normalcellContext) {
	b.up()
}

// table_headercell

func (b *builder) EnterTable_headercell(c *parser.Table_headercellContext) {
	// fix row type
	if f := b.find(tableRowNode); f != nil {
		f.nodeType = tableHeaderRowNode
	}
	b.down(&node{nodeType: tableHeaderCellNode})
}

func (b *builder) ExitTable_headercell(c *parser.Table_headercellContext) {
	b.up()
}

func (b *builder) ExitTable_unformatted(c *parser.Table_unformattedContext) {
	b.resolveLineBreaks(c.GetText())
}

func (b *builder) EnterTable_formattedelement(c *parser.Table_formattedelementContext) {
	b.push(b.current)
}

func (b *builder) ExitTable_formattedelement(c *parser.Table_formattedelementContext) {
	b.current = b.pop().(*node)
}

// image

func (b *builder) EnterImage(c *parser.ImageContext) {
	b.push(&image{})
}

func (b *builder) ExitImage(c *parser.ImageContext) {
	img := b.pop().(*image)
	link(&node{nodeType: imageNode, value: img}, b.current)
}

func (b *builder) ExitImage_uri(c *parser.Image_uriContext) {
	b.top().(*image).src = c.GetText()
}

func (b *builder) ExitImage_alternativetext(c *parser.Image_alternativetextContext) {
	b.top().(*image).alt = c.GetText()
}

// link

func (b *builder) EnterLink(c *parser.LinkContext) {
	b.down(&node{nodeType: linkNode})
}

func (b *builder) ExitLink(c *parser.LinkContext) {
	b.up()
}

func (b *builder) ExitLink_uri(c *parser.Link_uriContext) {
	if f := b.find(linkNode); f != nil {
		f.value = c.GetText()
	}
}

func (b *builder) ExitLink_descriptiontext(c *parser.Link_descriptiontextContext) {
	link(text(c.GetText()), b.current)
}

func (b *builder) parse(data string) (*document, error) {

	input := antlr.NewInputStream(data)
	lexer := parser.NewCreole10Lexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	pa := parser.NewCreole10Parser(stream)
	pa.AddParseListener(b)
	pa.GetInterpreter().SetPredictionMode(antlr.PredictionModeSLL)
	//pa.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
	//pa.BuildParseTrees = true
	pa.Start()
	//antlr.ParseTreeWalkerDefault.Walk(p, tree)

	// TODO: Write own ErrorListener.

	doc := &document{root: b.current}

	return doc, nil
}
<commit_msg>Fixed another unformatted element case.<commit_after>// This is Free Software covered by the terms of the MIT license.
// See LICENSE file for details.
// Copyright 2017 by Intevation GmbH
package main

import (
	"strings"

	"github.com/antlr/antlr4/runtime/Go/antlr"
	"github.com/s-l-teichmann/creoleto/parser"
)

type builder struct {
	*parser.BaseCreole10Listener
	current *node

	stack []interface{}
}

type headingBuilder struct {
	depth      int
	hasContent bool
}

func newBuilder() *builder {
	return &builder{
		current: &node{},
	}
}

func (b *builder) push(x interface{}) {
	b.stack = append(b.stack, x)
}

func (b *builder) pop() interface{} {
	l := len(b.stack)
	x := b.stack[l-1]
	b.stack[l-1] = nil
	b.stack = b.stack[:l-1]
	return x
}

func (b *builder) top() interface{} {
	return b.stack[len(b.stack)-1]
}

func (b *builder) up() {
	if b.current != nil {
		b.current = b.current.parent
	}
}

func (b *builder) down(n *node) {
	b.current = link(n, b.current)
}

func (b *builder) find(typ nodeType) *node {
	for n := b.current; n != nil && n.nodeType != typ; n = n.parent {
	}
	return nil
}

func (b *builder) resolveLineBreaks(txt string) {
	for i, t := range strings.Split(txt, `\\`) {
		if i > 0 {
			link(&node{nodeType: lineBreakNode}, b.current)
		}
		link(text(strings.Replace(t, "~", "", -1)), b.current)
	}
}

func (b *builder) EnterHeading(c *parser.HeadingContext) {
	b.push(&headingBuilder{})
}

func (b *builder) EnterHeading_markup(c *parser.Heading_markupContext) {
	if hb := b.top().(*headingBuilder); !hb.hasContent {
		hb.depth++
	}
}

func (b *builder) ExitHeading_content(c *parser.Heading_contentContext) {
	b.top().(*headingBuilder).hasContent = true
}

func (b *builder) ExitHeading(c *parser.HeadingContext) {

	hb := b.pop().(*headingBuilder)

	trim := strings.Repeat("=", hb.depth)
	content := strings.TrimSpace(c.GetText())
	content = strings.TrimSuffix(strings.TrimPrefix(content, trim), trim)
	content = strings.TrimSpace(content)

	var typ nodeType
	switch hb.depth {
	case 1:
		typ = heading1Node
	case 2:
		typ = heading2Node
	case 3:
		typ = heading3Node
	case 4:
		typ = heading4Node
	case 5:
		typ = heading5Node
	default:
		typ = heading6Node
	}

	link(&node{nodeType: typ, value: content}, b.current)
}

func (b *builder) EnterParagraph(c *parser.ParagraphContext) {
	b.down(&node{nodeType: paragraphNode})
}

func (b *builder) ExitParagraph(c *parser.ParagraphContext) {
	b.up()
}

// text_first_element

/*
func (b *builder) EnterText_firstelement(c *parser.Text_firstelementContext) {
	fmt.Fprintln(os.Stderr, "1. EnterText_firstelement")
}

func (b *builder) ExitText_firstelement(c *parser.Text_firstelementContext) {
	fmt.Fprintln(os.Stderr, "1. ExitText_firstelement")
}
*/

// text_first_unformattedelement

/*
func (b *builder) EnterText_first_unformattedelement(c *parser.Text_first_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "1. ExitText_first_unformattedelement")
}
*/

func (b *builder) ExitText_first_unformatted(c *parser.Text_first_unformattedContext) {
	b.resolveLineBreaks(c.GetText())
}

func (b *builder) ExitText_lineseparator(c *parser.Text_lineseparatorContext) {
	link(text("\n"), b.current)
}

// text_unformattedelement

/*
func (b *builder) EnterText_unformattedelement(c *parser.Text_unformattedelementContext) {
	fmt.Fprintln(os.Stderr, "EnterText_unformattedelement")
}
*/

func (b *builder) ExitText_unformatted(c *parser.Text_unformattedContext) {
	//fmt.Fprintf(os.Stderr, "ExitText_unformatted '%s'\n", c.GetText())
	b.resolveLineBreaks(c.GetText())
}

/*
func (b *builder) EnterText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "EnterText_line")
}
*/

/*
func (b *builder) ExitText_line(c *parser.Text_lineContext) {
	fmt.Fprintln(os.Stderr, "ExitText_line:", c.GetText())
}
*/

func (b *builder) EnterText_formattedelement(c *parser.Text_formattedelementContext) {
	//fmt.Fprintln(os.Stderr, "***EnterText_formattedelement")
	// type to be overwritten in ital_markup or bold_markup
	b.push(b.current)
}

func (b *builder) ExitText_formattedelement(c *parser.Text_formattedelementContext) {
	//fmt.Fprintln(os.Stderr, "***ExitText_formattedelement")
	b.current = b.pop().(*node)
}

func (b *builder) ExitNowiki_inline_content(c *parser.Nowiki_inline_contentContext) {
	nw := &node{nodeType: noWikiInlineNode}
	txt := strings.Replace(c.GetText(), "~", "", -1)
	link(text(txt), nw)
	link(nw, b.current)
}

func (b *builder) ExitNowiki_block_content(c *parser.Nowiki_block_contentContext) {
	nw := &node{nodeType: noWikiNode}
	link(text(c.GetText()), nw)
	link(nw, b.current)
}

func (b *builder) createFormatNode(typ nodeType) {
	// Do we have already one of these?
	if b.find(typ) == nil {
		// create one and descent.
		b.down(&node{nodeType: typ})
	}
}

func (b *builder) ExitHorizontalrule(c *parser.HorizontalruleContext) {
	link(&node{nodeType: horizontalLineNode}, b.current)
}

func (b *builder) EnterItal_markup(c *parser.Ital_markupContext) {
	//fmt.Fprintln(os.Stderr, "//EnterItal_markup")
	b.createFormatNode(italicsNode)
}

func (b *builder) EnterBold_markup(c *parser.Bold_markupContext) {
	//fmt.Fprintln(os.Stderr, "**EnterBold_markup")
	b.createFormatNode(boldNode)
}

// list_ord

func (b *builder) EnterList_ord(c *parser.List_ordContext) {
	b.down(&node{nodeType: orderedListNode})
}

func (b *builder) ExitList_ord(c *parser.List_ordContext) {
	b.up()
}

// list_unord

func (b *builder) EnterList_unord(c *parser.List_unordContext) {
	b.down(&node{nodeType: unorderedListNode})
}

func (b *builder) ExitList_unord(c *parser.List_unordContext) {
	b.up()
}

// list_elem

func (b *builder) EnterList_elem(c *parser.List_elemContext) {
	b.down(&node{nodeType: listItemNode})
}

func (b *builder) ExitList_elem(c *parser.List_elemContext) {
	b.up()
}

// table

func (b *builder) EnterTable(c *parser.TableContext) {
	b.down(&node{nodeType: tableNode})
}

func (b *builder) ExitTable(c *parser.TableContext) {
	b.up()
}

// table_row

func (b *builder) EnterTable_row(c *parser.Table_rowContext) {
	// Type may be corrected later.
	b.down(&node{nodeType: tableRowNode})
}

func (b *builder) ExitTable_row(c *parser.Table_rowContext) {
	b.up()
}

// table_normalcell

func (b *builder) EnterTable_normalcell(c *parser.Table_normalcellContext) {
	b.down(&node{nodeType: tableCellNode})
}

func (b *builder) ExitTable_normalcell(c *parser.Table_normalcellContext) {
	b.up()
}

// table_headercell

func (b *builder) EnterTable_headercell(c *parser.Table_headercellContext) {
	// fix row type
	if f := b.find(tableRowNode); f != nil {
		f.nodeType = tableHeaderRowNode
	}
	b.down(&node{nodeType: tableHeaderCellNode})
}

func (b *builder) ExitTable_headercell(c *parser.Table_headercellContext) {
	b.up()
}

func (b *builder) ExitTable_unformatted(c *parser.Table_unformattedContext) {
	b.resolveLineBreaks(c.GetText())
}

func (b *builder) EnterTable_formattedelement(c *parser.Table_formattedelementContext) {
	b.push(b.current)
}

func (b *builder) ExitTable_formattedelement(c *parser.Table_formattedelementContext) {
	b.current = b.pop().(*node)
}

// image

func (b *builder) EnterImage(c *parser.ImageContext) {
	b.push(&image{})
}

func (b *builder) ExitImage(c *parser.ImageContext) {
	img := b.pop().(*image)
	link(&node{nodeType: imageNode, value: img}, b.current)
}

func (b *builder) ExitImage_uri(c *parser.Image_uriContext) {
	b.top().(*image).src = c.GetText()
}

func (b *builder) ExitImage_alternativetext(c *parser.Image_alternativetextContext) {
	b.top().(*image).alt = c.GetText()
}

// link

func (b *builder) EnterLink(c *parser.LinkContext) {
	b.down(&node{nodeType: linkNode})
}

func (b *builder) ExitLink(c *parser.LinkContext) {
	b.up()
}

func (b *builder) ExitLink_uri(c *parser.Link_uriContext) {
	if f := b.find(linkNode); f != nil {
		f.value = c.GetText()
	}
}

func (b *builder) ExitLink_descriptiontext(c *parser.Link_descriptiontextContext) {
	link(text(c.GetText()), b.current)
}

func (b *builder) parse(data string) (*document, error) {

	input := antlr.NewInputStream(data)
	lexer := parser.NewCreole10Lexer(input)
	stream := antlr.NewCommonTokenStream(lexer, 0)
	pa := parser.NewCreole10Parser(stream)
	pa.AddParseListener(b)
	pa.GetInterpreter().SetPredictionMode(antlr.PredictionModeSLL)
	//pa.AddErrorListener(antlr.NewDiagnosticErrorListener(true))
	//pa.BuildParseTrees = true
	pa.Start()
	//antlr.ParseTreeWalkerDefault.Walk(p, tree)

	// TODO: Write own ErrorListener.

	doc := &document{root: b.current}

	return doc, nil
}
<|endoftext|>


<commit_before>package main

import (
	//"fmt"
	"log"
)

type BuildQueue struct {
	queue chan string
}

func MakeBuildQueue() *BuildQueue {
	bq := BuildQueue{}
	bq.queue = make(chan string, 100)
	go builder(bq.queue)
	return &bq
}

func (bq *BuildQueue) EnQueue(pkg string) {
	bq.queue <- pkg
}

func builder(queue <-chan string) {
	for {
		pkg := <-queue

		log.Println("Processing Package: ", pkg)

		var err error
		err = goget(pkg, "build.log")
		if err == nil {
			log.Println(" Running Tests on: ", pkg)
			err = gotest(pkg, "test.log")
		}
		if err == nil {
			log.Println(" Processing Coverage on: ", pkg)
			err = gotest(pkg, "cover.log")
		}

		if err == nil {
			log.Println(" Done")
		} else {
			log.Println(" Error: ", err)
		}
	}
}
<commit_msg>fix typo<commit_after>package main

import (
	//"fmt"
	"log"
)

type BuildQueue struct {
	queue chan string
}

func MakeBuildQueue() *BuildQueue {
	bq := BuildQueue{}
	bq.queue = make(chan string, 100)
	go builder(bq.queue)
	return &bq
}

func (bq *BuildQueue) EnQueue(pkg string) {
	bq.queue <- pkg
}

func builder(queue <-chan string) {
	for {
		pkg := <-queue

		log.Println("Processing Package: ", pkg)

		var err error
		err = goget(pkg, "build.log")
		if err == nil {
			log.Println(" Running Tests on: ", pkg)
			err = gotest(pkg, "test.log")
		}
		if err == nil {
			log.Println(" Processing Coverage on: ", pkg)
			err = gocover(pkg, "cover.log")
		}

		if err == nil {
			log.Println(" Done")
		} else {
			log.Println(" Error: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

// Associate ClowdWatchEvent Rule and descripbed Rule(name based)
func AssociateRules(cweRules []*cloudwatchevents.Rule, describedRules []Rule) []Rule {
	if l := len(cweRules) - len(describedRules); l > 0 {
		r := make([]Rule, l)
		describedRules = append(describedRules, r...)
	}
	dupCWERules := make([]*cloudwatchevents.Rule, len(cweRules))
	copy(dupCWERules, cweRules)

	for i, rule := range describedRules {
		for j, cweRule := range dupCWERules {
			if *cweRule.Name == rule.Name {
				describedRules[i].ActualRule = *cweRule
				dupCWERules = DeleteRuleFromSlice(dupCWERules, j)
				break
			}
		}
	}
	if len(dupCWERules) > 0 {
		for _, dupRule := range dupCWERules {
			for j, rule := range describedRules {
				if rule.ActualRule.Arn == nil {
					describedRules[j].ActualRule = *dupRule
				}
			}
		}
	}
	return describedRules
}

func AssociateTargets(cweTargets []*cloudwatchevents.Target, describedTargets []Target) []Target {
	// if ClowdWatchEvents Targets is more than declareted targets, append number of lack target{}
	if l := len(cweTargets) - len(describedTargets); l > 0 {
		t := make([]Target, l)
		describedTargets = append(describedTargets, t...)
	}
	dupCWETargets := make([]*cloudwatchevents.Target, len(cweTargets))
	copy(dupCWETargets, cweTargets)

	for i, target := range describedTargets {
		for j, cweTarget := range cweTargets {
			if CompareString(&target.Arn, cweTarget.Arn) && CompareString(&target.Id, cweTarget.Id) {
				describedTargets[i].ActualTarget = *cweTarget
				dupCWETargets = DeleteTargetFromSlice(dupCWETargets, j)
				break
			}
		}
	}
	if len(dupCWETargets) > 0 {
		for _, dupTarget := range dupCWETargets {
			for j, target := range describedTargets {
				if target.ActualTarget.Arn == nil {
					describedTargets[j].ActualTarget = *dupTarget
				}
			}
		}
	}

	return describedTargets
}

// judge is rule need update
// compare rule and ActualRule
func JudgeRuleNeedUpdate(r *Rule) {
	if !CompareString(&r.Name, r.ActualRule.Name) ||
		!CompareString(&r.Description, r.ActualRule.Description) ||
		!CompareString(&r.EventPattern, r.ActualRule.EventPattern) ||
		!CompareString(&r.ScheduleExpression, r.ActualRule.ScheduleExpression) ||
		!CompareString(&r.State, r.ActualRule.State) {
		r.NeedUpdate = true
	}
}

func JudgeRuleNeedDelete(r *Rule) {
	if r.Name == "" &&
		r.Description == "" &&
		r.EventPattern == "" &&
		r.ScheduleExpression == "" &&
		r.RoleArn == "" &&
		r.State == "" &&
		r.ActualRule.Name != nil {
		r.NeedDelete = true
	}
}

// judge is target need update
// compare target and ActualTarget
func JudgeTargetNeedUpdate(t *Target) {
	if !CompareString(&t.Arn, t.ActualTarget.Arn) ||
		!CompareString(&t.Id, t.ActualTarget.Id) ||
		!CompareString(&t.Input, t.ActualTarget.Input) ||
		!CompareString(&t.InputPath, t.ActualTarget.InputPath) {
		t.NeedUpdate = true
	}
}

func JudgeTargetNeedDelete(t *Target) {
	if t.Arn == "" &&
		t.Id == "" &&
		t.ActualTarget.Arn != nil {
		t.NeedDelete = true
	}
}

// check all rules and targets, update "NeedUpdate" and "NeedDelete" field
func CheckIsNeedUpdateOrDelete(rules []Rule) {
	for i, _ := range rules {
		JudgeRuleNeedUpdate(&rules[i])
		JudgeRuleNeedDelete(&rules[i])
		for j, _ := range rules[i].Targets {
			JudgeTargetNeedUpdate(&rules[i].Targets[j])
			JudgeTargetNeedDelete(&rules[i].Targets[j])
		}
	}
}
<commit_msg>Fix wrong target of for loop<commit_after>package main

import (
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

// Associate ClowdWatchEvent Rule and descripbed Rule(name based)
func AssociateRules(cweRules []*cloudwatchevents.Rule, describedRules []Rule) []Rule {
	if l := len(cweRules) - len(describedRules); l > 0 {
		r := make([]Rule, l)
		describedRules = append(describedRules, r...)
	}
	dupCWERules := make([]*cloudwatchevents.Rule, len(cweRules))
	copy(dupCWERules, cweRules)

	for i, rule := range describedRules {
		for j, cweRule := range dupCWERules {
			if *cweRule.Name == rule.Name {
				describedRules[i].ActualRule = *cweRule
				dupCWERules = DeleteRuleFromSlice(dupCWERules, j)
				break
			}
		}
	}
	if len(dupCWERules) > 0 {
		for _, dupRule := range dupCWERules {
			for j, rule := range describedRules {
				if rule.ActualRule.Arn == nil {
					describedRules[j].ActualRule = *dupRule
				}
			}
		}
	}
	return describedRules
}

func AssociateTargets(cweTargets []*cloudwatchevents.Target, describedTargets []Target) []Target {
	// if ClowdWatchEvents Targets is more than declareted targets, append number of lack target{}
	if l := len(cweTargets) - len(describedTargets); l > 0 {
		t := make([]Target, l)
		describedTargets = append(describedTargets, t...)
	}
	dupCWETargets := make([]*cloudwatchevents.Target, len(cweTargets))
	copy(dupCWETargets, cweTargets)

	for i, target := range describedTargets {
		for j, cweTarget := range dupCWETargets {
			if CompareString(&target.Arn, cweTarget.Arn) && CompareString(&target.Id, cweTarget.Id) {
				describedTargets[i].ActualTarget = *cweTarget
				dupCWETargets = DeleteTargetFromSlice(dupCWETargets, j)
				break
			}
		}
	}
	if len(dupCWETargets) > 0 {
		for _, dupTarget := range dupCWETargets {
			for j, target := range describedTargets {
				if target.ActualTarget.Arn == nil {
					describedTargets[j].ActualTarget = *dupTarget
				}
			}
		}
	}

	return describedTargets
}

// judge is rule need update
// compare rule and ActualRule
func JudgeRuleNeedUpdate(r *Rule) {
	if !CompareString(&r.Name, r.ActualRule.Name) ||
		!CompareString(&r.Description, r.ActualRule.Description) ||
		!CompareString(&r.EventPattern, r.ActualRule.EventPattern) ||
		!CompareString(&r.ScheduleExpression, r.ActualRule.ScheduleExpression) ||
		!CompareString(&r.State, r.ActualRule.State) {
		r.NeedUpdate = true
	}
}

func JudgeRuleNeedDelete(r *Rule) {
	if r.Name == "" &&
		r.Description == "" &&
		r.EventPattern == "" &&
		r.ScheduleExpression == "" &&
		r.RoleArn == "" &&
		r.State == "" &&
		r.ActualRule.Name != nil {
		r.NeedDelete = true
	}
}

// judge is target need update
// compare target and ActualTarget
func JudgeTargetNeedUpdate(t *Target) {
	if !CompareString(&t.Arn, t.ActualTarget.Arn) ||
		!CompareString(&t.Id, t.ActualTarget.Id) ||
		!CompareString(&t.Input, t.ActualTarget.Input) ||
		!CompareString(&t.InputPath, t.ActualTarget.InputPath) {
		t.NeedUpdate = true
	}
}

func JudgeTargetNeedDelete(t *Target) {
	if t.Arn == "" &&
		t.Id == "" &&
		t.ActualTarget.Arn != nil {
		t.NeedDelete = true
	}
}

// check all rules and targets, update "NeedUpdate" and "NeedDelete" field
func CheckIsNeedUpdateOrDelete(rules []Rule) {
	for i, _ := range rules {
		JudgeRuleNeedUpdate(&rules[i])
		JudgeRuleNeedDelete(&rules[i])
		for j, _ := range rules[i].Targets {
			JudgeTargetNeedUpdate(&rules[i].Targets[j])
			JudgeTargetNeedDelete(&rules[i].Targets[j])
		}
	}
}
<|endoftext|>


<commit_before>package shared

import (
	"fmt"
	log "gopkg.in/inconshreveable/log15.v2"
	"runtime"
)

type Logger interface {
	Debug(msg string, ctx ...interface{})
	Info(msg string, ctx ...interface{})
	Warn(msg string, ctx ...interface{})
	Error(msg string, ctx ...interface{})
	Crit(msg string, ctx ...interface{})
}

var Log Logger

type nullLogger struct{}

func (nl nullLogger) Debug(msg string, ctx ...interface{}) {}
func (nl nullLogger) Info(msg string, ctx ...interface{})  {}
func (nl nullLogger) Warn(msg string, ctx ...interface{})  {}
func (nl nullLogger) Error(msg string, ctx ...interface{}) {}
func (nl nullLogger) Crit(msg string, ctx ...interface{})  {}

func init() {
	Log = nullLogger{}
}

// General wrappers around Logger interface functions.
func LogDebug(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Warn(msg, log.Ctx(ctx))
	}
}

func LogInfo(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Info(msg, log.Ctx(ctx))
	}
}

func LogWarn(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Warn(msg, log.Ctx(ctx))
	}
}

func LogError(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Error(msg, log.Ctx(ctx))
	}
}

func LogCrit(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Crit(msg, log.Ctx(ctx))
	}
}

// Wrappers around Logger interface functions that send a string to the Logger
// by running it through fmt.Sprintf().
func LogInfof(format string, args ...interface{}) {
	if Log != nil {
		Log.Info(fmt.Sprintf(format, args...))
	}
}

func LogDebugf(format string, args ...interface{}) {
	if Log != nil {
		Log.Debug(fmt.Sprintf(format, args...))
	}
}

func LogWarnf(format string, args ...interface{}) {
	if Log != nil {
		Log.Warn(fmt.Sprintf(format, args...))
	}
}

func LogErrorf(format string, args ...interface{}) {
	if Log != nil {
		Log.Error(fmt.Sprintf(format, args...))
	}
}

func LogCritf(format string, args ...interface{}) {
	if Log != nil {
		Log.Crit(fmt.Sprintf(format, args...))
	}
}

func PrintStack() {
	buf := make([]byte, 1<<16)
	runtime.Stack(buf, true)
	LogDebugf("%s", buf)
}
<commit_msg>shared/log: fix LogDebug()<commit_after>package shared

import (
	"fmt"
	log "gopkg.in/inconshreveable/log15.v2"
	"runtime"
)

type Logger interface {
	Debug(msg string, ctx ...interface{})
	Info(msg string, ctx ...interface{})
	Warn(msg string, ctx ...interface{})
	Error(msg string, ctx ...interface{})
	Crit(msg string, ctx ...interface{})
}

var Log Logger

type nullLogger struct{}

func (nl nullLogger) Debug(msg string, ctx ...interface{}) {}
func (nl nullLogger) Info(msg string, ctx ...interface{})  {}
func (nl nullLogger) Warn(msg string, ctx ...interface{})  {}
func (nl nullLogger) Error(msg string, ctx ...interface{}) {}
func (nl nullLogger) Crit(msg string, ctx ...interface{})  {}

func init() {
	Log = nullLogger{}
}

// General wrappers around Logger interface functions.
func LogDebug(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Debug(msg, log.Ctx(ctx))
	}
}

func LogInfo(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Info(msg, log.Ctx(ctx))
	}
}

func LogWarn(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Warn(msg, log.Ctx(ctx))
	}
}

func LogError(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Error(msg, log.Ctx(ctx))
	}
}

func LogCrit(msg string, ctx map[string]interface{}) {
	if Log != nil {
		Log.Crit(msg, log.Ctx(ctx))
	}
}

// Wrappers around Logger interface functions that send a string to the Logger
// by running it through fmt.Sprintf().
func LogInfof(format string, args ...interface{}) {
	if Log != nil {
		Log.Info(fmt.Sprintf(format, args...))
	}
}

func LogDebugf(format string, args ...interface{}) {
	if Log != nil {
		Log.Debug(fmt.Sprintf(format, args...))
	}
}

func LogWarnf(format string, args ...interface{}) {
	if Log != nil {
		Log.Warn(fmt.Sprintf(format, args...))
	}
}

func LogErrorf(format string, args ...interface{}) {
	if Log != nil {
		Log.Error(fmt.Sprintf(format, args...))
	}
}

func LogCritf(format string, args ...interface{}) {
	if Log != nil {
		Log.Crit(fmt.Sprintf(format, args...))
	}
}

func PrintStack() {
	buf := make([]byte, 1<<16)
	runtime.Stack(buf, true)
	LogDebugf("%s", buf)
}
<|endoftext|>


<commit_before>package thirdpartysw

import (
	"encoding/json"
	"fmt"
	"github.com/golang/glog"
	"github.com/jmuldoon/flac2mp3util/util"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

const (
	thirdpartyswdir  string = "./thirdpartysw"
	sourceconfigname string = "sources.json"
	dependencyswpath string = "./deps"
	clienttimeout    int    = 300
)

type ThirdPartyer interface {
	ReadURLs() (err error)
	Download() (err error)
}

type ThirdPartyType struct {
	Client       *http.Client
	Dependencies []*Url
}

type Url struct {
	URL string `json:"url"`
}

var thirdParty *ThirdPartyType

func init() {
	thirdParty = &ThirdPartyType{
		Client: &http.Client{
			Timeout: time.Second * 300,
		},
	}
}

// InitDepsFolder creates the deps (dependencies) folder if it doesn't already
// exist
func initDepsFolder() (err error) {
	abs, err := filepath.Abs(dependencyswpath)
	if err != nil {
		return err
	}
	// if it exists we ignore the error, by not creating the dir
	if _, err := os.Stat(abs); os.IsNotExist(err) {
		os.Mkdir(abs, 0777)
	}
	return nil
}

// Download retrieves the tarballs from the url list given as a parameter.
func (tp *ThirdPartyType) Download() (err error) {
	if err := initDepsFolder(); err != nil {
		return err
	}
	for _, el := range tp.Dependencies {
		resp, err := tp.Client.Get(el.URL)
		if err != nil {
			return err
		}
		defer resp.Body.Close()
		fmt.Printf("%+v\n", resp.Body)
	}
	return nil
}

// decode takes the ThirdPartyType as a receiver to decode the io.Reader json
// structure and store it in the ThirdPartyType's Dependencies field.
func (tp *ThirdPartyType) decode(file io.Reader) (err error) {
	if err = json.NewDecoder(file).Decode(&tp.Dependencies); err != nil {
		return err
	}
	return nil
}

// read takes the ThirdPartyType as a receiver to readin the json information
// from the file specified by the path
func (tp *ThirdPartyType) read(path string) (err error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return err
	}
	if err := tp.decode(file); err != nil {
		return err
	}

	return nil
}

// ReadURLs reads in the URLs from the sources.json file and stores them in the
// receiver ThirdPartyType's field Dependencies.
func (tp *ThirdPartyType) ReadURLs() (err error) {
	absPath, err := util.AbsolutePathHelper(thirdpartyswdir, sourceconfigname)
	glog.V(2).Infoln(absPath)
	if err != nil {
		return err
	}
	if err := tp.read(absPath); err != nil {
		return err
	}
	for i, el := range tp.Dependencies {
		glog.V(2).Infof("%d: %s\n", i, el.URL)
	}
	return nil
}
<commit_msg>modded the client request for the download to contain the necessary headers<commit_after>package thirdpartysw

import (
	"compress/gzip"
	"encoding/json"
	"fmt"
	"github.com/golang/glog"
	"github.com/jmuldoon/flac2mp3util/util"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

const (
	thirdpartyswdir  string        = "./thirdpartysw"
	sourceconfigname string        = "sources.json"
	dependencyswpath string        = "./deps"
	clienttimeout    time.Duration = 300
)

type ThirdPartyer interface {
	ReadURLs() (err error)
	Download() (err error)
}

type ThirdPartyType struct {
	Client       *http.Client
	Dependencies []*Url
}

type Url struct {
	URL string `json:"url"`
}

var thirdParty *ThirdPartyType

// init sets up the client to be used for the http requests since the default
// one is garbage due to not having a timeout.
func init() {
	thirdParty = &ThirdPartyType{
		Client: &http.Client{
			Timeout: time.Second * clienttimeout,
		},
	}
}

// InitDepsFolder creates the deps (dependencies) folder if it doesn't already
// exist
func initDepsFolder() (err error) {
	abs, err := filepath.Abs(dependencyswpath)
	if err != nil {
		return err
	}
	// if it exists we ignore the error, by not creating the dir
	if _, err := os.Stat(abs); os.IsNotExist(err) {
		os.Mkdir(abs, 0777)
	}
	return nil
}

// Download retrieves the tarballs from the url list given as a parameter.
func (tp *ThirdPartyType) Download() (err error) {
	if err := initDepsFolder(); err != nil {
		return err
	}
	for _, el := range tp.Dependencies {
		req, err := http.NewRequest("GET", el.URL, nil)
		if err != nil {
			return err
		}
		req.Header.Add("Accept-Encoding", "gzip")

		resp, err := tp.Client.Do(req)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		var reader io.ReadCloser
		switch resp.Header.Get("Content-Encoding") {
		case "gzip":
			reader, err = gzip.NewReader(resp.Body)
			if err != nil {
				return err
			}
			defer reader.Close()
		default:
			return fmt.Errorf("Download: failed due to incorrect header response")
		}
	}
	return nil
}

// decode takes the ThirdPartyType as a receiver to decode the io.Reader json
// structure and store it in the ThirdPartyType's Dependencies field.
func (tp *ThirdPartyType) decode(file io.Reader) (err error) {
	if err = json.NewDecoder(file).Decode(&tp.Dependencies); err != nil {
		return err
	}
	return nil
}

// read takes the ThirdPartyType as a receiver to readin the json information
// from the file specified by the path
func (tp *ThirdPartyType) read(path string) (err error) {
	file, err := os.OpenFile(path, os.O_RDONLY, 0777)
	if err != nil {
		return err
	}
	if err := tp.decode(file); err != nil {
		return err
	}

	return nil
}

// ReadURLs reads in the URLs from the sources.json file and stores them in the
// receiver ThirdPartyType's field Dependencies.
func (tp *ThirdPartyType) ReadURLs() (err error) {
	absPath, err := util.AbsolutePathHelper(thirdpartyswdir, sourceconfigname)
	glog.V(2).Infoln(absPath)
	if err != nil {
		return err
	}
	if err := tp.read(absPath); err != nil {
		return err
	}
	for i, el := range tp.Dependencies {
		glog.V(2).Infof("%d: %s\n", i, el.URL)
	}
	return nil
}
<|endoftext|>


<commit_before>// Package webfist implements WebFist.
package webfist

type WebFingerResponse struct {
  JSON map[string]interface{}
}

// Storage is the interface implemented by backends.
type Storage interface {
	PutEmail(*EmailAddr, *Email) error
	Emails(*EmailAddr) ([]*Email, error)
  WebFinger(emailAddr *EmailAddr) *WebFingerResponse
}
<commit_msg>Better doc of webfinger response<commit_after>// Package webfist implements WebFist.
package webfist

// Payload from: tools.ietf.org/html/draft-ietf-appsawg-webfinger-14
// TODO: Consider restricting to only delegation to another WebFinger server.
type WebFingerResponse struct {
  JSON map[string]interface{}
}

// Storage is the interface implemented by backends.
type Storage interface {
	PutEmail(*EmailAddr, *Email) error
	Emails(*EmailAddr) ([]*Email, error)
  WebFinger(emailAddr *EmailAddr) *WebFingerResponse
}
<|endoftext|>


<commit_before>package discgo

type Webhook struct {
	ID        string
	GuildID   *string
	ChannelID string
	User      *User
	Name      *string
	Avatar    *string
	Token     string
}
<commit_msg>TODO webhook, gonna polish the REST API now.<commit_after>package discgo

// TODO not needed for now, but maybe later?
type Webhook struct {
	ID        string  `json:"id"`
	GuildID   *string `json:"guild_id"`
	ChannelID string  `json:"channel_id"`
	User      *User   `json:"user"`
	Name      *string `json:"name"`
	Avatar    *string `json:"avatar"`
	Token     string  `json:"token"`
}
<|endoftext|>


<commit_before>package tachyon

import (
	"bufio"
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
)

func captureCmd(c *exec.Cmd, show bool) ([]byte, []byte, error) {
	stdout, err := c.StdoutPipe()

	if err != nil {
		return nil, nil, err
	}

	defer stdout.Close()

	var wg sync.WaitGroup

	var bout bytes.Buffer
	var berr bytes.Buffer

	prefix := []byte(`| `)

	wg.Add(1)
	go func() {
		defer wg.Done()
		buf := bufio.NewReader(stdout)

		for {
			line, err := buf.ReadSlice('\n')

			if err != nil {
				break
			}

			bout.Write(line)

			if show {
				os.Stdout.Write(prefix)
				os.Stdout.Write(line)
			}
		}
	}()

	stderr, err := c.StderrPipe()

	if err != nil {
		stdout.Close()
		return nil, nil, err
	}

	defer stderr.Close()

	wg.Add(1)
	go func() {
		defer wg.Done()
		buf := bufio.NewReader(stderr)

		for {
			line, err := buf.ReadSlice('\n')

			if err != nil {
				break
			}

			berr.Write(line)

			if show {
				os.Stdout.Write(prefix)
				os.Stdout.Write(line)
			}
		}
	}()

	c.Start()

	wg.Wait()

	err = c.Wait()

	return bout.Bytes(), berr.Bytes(), err
}

type CommandResult struct {
	ReturnCode int
	Stdout     []byte
	Stderr     []byte
}

func RunCommand(env *CommandEnv, parts ...string) (*CommandResult, error) {
	c := exec.Command(parts[0], parts[1:]...)

	if env.Env.config.ShowCommandOutput {
		fmt.Printf("RUN: %s\n", strings.Join(parts, " "))
	}

	rc := 0

	stdout, stderr, err := captureCmd(c, env.Env.config.ShowCommandOutput)
	if err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			rc = 1
		} else {
			return nil, err
		}
	}

	return &CommandResult{rc, stdout, stderr}, nil
}

func RunCommandInEnv(env *CommandEnv, unixEnv []string, parts ...string) (*CommandResult, error) {
	c := exec.Command(parts[0], parts[1:]...)
	c.Env = unixEnv

	if env.Env.config.ShowCommandOutput {
		fmt.Printf("RUN: %s\n", strings.Join(parts, " "))
	}

	rc := 0

	stdout, stderr, err := captureCmd(c, env.Env.config.ShowCommandOutput)
	if err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			rc = 1
		} else {
			return nil, err
		}
	}

	return &CommandResult{rc, stdout, stderr}, nil
}

func runCmd(env *CommandEnv, ignore bool, parts ...string) (*Result, error) {
	cmd, err := RunCommand(env, parts...)
	if !ignore && err != nil {
		return nil, err
	}

	r := NewResult(true)

	r.Add("rc", cmd.ReturnCode)
	r.Add("stdout", strings.TrimSpace(string(cmd.Stdout)))
	r.Add("stderr", strings.TrimSpace(string(cmd.Stderr)))

	if str, ok := renderShellResult(r); ok {
		r.Add("_result", str)
	}

	return r, nil
}

type CommandCmd struct {
	Command    string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *CommandCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	parts, err := shlex.Split(cmd.Command)

	if err != nil {
		return nil, err
	}

	return runCmd(env, cmd.IgnoreFail, parts...)
}

func (cmd *CommandCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

type ShellCmd struct {
	Command    string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *ShellCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	return runCmd(env, cmd.IgnoreFail, "sh", "-c", cmd.Command)
}

func (cmd *ShellCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

func renderShellResult(res *Result) (string, bool) {
	rcv, ok := res.Get("rc")
	if !ok {
		return "", false
	}

	stdoutv, ok := res.Get("stdout")
	if !ok {
		return "", false
	}

	stderrv, ok := res.Get("stderr")
	if !ok {
		return "", false
	}

	rc := rcv.Read().(int)
	stdout := stdoutv.Read().(string)
	stderr := stderrv.Read().(string)

	if rc == 0 && len(stdout) == 0 && len(stderr) == 0 {
		return "", true
	} else if len(stderr) == 0 && len(stdout) < 60 {
		stdout = strings.Replace(stdout, "\n", " ", -1)
		return fmt.Sprintf(`rc: %d, stdout: "%s"`, rc, stdout), true
	}

	return "", false
}

type CopyCmd struct {
	Src  string `tachyon:"src,required"`
	Dest string `tachyon:"dest,required"`
}

func md5file(path string) ([]byte, error) {
	h := md5.New()

	i, err := os.Open(path)
	if err != nil {
		return nil, err
	}

	if _, err := io.Copy(h, i); err != nil {
		return nil, err
	}

	return h.Sum(nil), nil
}

func (cmd *CopyCmd) Run(env *CommandEnv) (*Result, error) {
	input, err := os.Open(cmd.Src)

	if err != nil {
		return nil, err
	}

	srcStat, err := os.Stat(cmd.Src)
	if err != nil {
		return nil, err
	}

	srcDigest, err := md5file(cmd.Src)
	if err != nil {
		return nil, err
	}

	var dstDigest []byte

	defer input.Close()

	dest := cmd.Dest

	link := false

	if stat, err := os.Lstat(dest); err == nil {
		if stat.IsDir() {
			dest = filepath.Join(dest, filepath.Base(cmd.Src))
		} else {
			dstDigest, _ = md5file(dest)
		}

		link = stat.Mode()&os.ModeSymlink != 0
	}

	rd := ResultData{
		"md5sum": Any(hex.Dump(srcDigest)),
		"src":    Any(cmd.Src),
		"dest":   Any(dest),
	}

	if dstDigest != nil && bytes.Equal(srcDigest, dstDigest) {
		return WrapResult(false, rd), nil
	}

	tmp := fmt.Sprintf("%s.tmp.%d", cmd.Dest, os.Getpid())

	output, err := os.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0644)

	if err != nil {
		return nil, err
	}

	defer output.Close()

	if _, err = io.Copy(output, input); err != nil {
		os.Remove(tmp)
		return nil, err
	}

	if link {
		os.Remove(dest)
	}

	if err := os.Chmod(tmp, srcStat.Mode()); err != nil {
		os.Remove(tmp)
		return nil, err
	}

	if ostat, ok := srcStat.Sys().(*syscall.Stat_t); ok {
		os.Chown(tmp, int(ostat.Uid), int(ostat.Gid))
	}

	err = os.Rename(tmp, dest)
	if err != nil {
		os.Remove(tmp)
		return nil, err
	}

	return WrapResult(true, rd), nil
}

type ScriptCmd struct {
	Script     string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *ScriptCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

func (cmd *ScriptCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	script := cmd.Script

	parts, err := shlex.Split(cmd.Script)
	if err == nil {
		script = parts[0]
	}

	path := env.Paths.File(script)

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

	runArgs := append([]string{"sh", path}, parts[1:]...)

	return runCmd(env, cmd.IgnoreFail, runArgs...)
}

func init() {
	RegisterCommand("command", &CommandCmd{})
	RegisterCommand("shell", &ShellCmd{})
	RegisterCommand("copy", &CopyCmd{})
	RegisterCommand("script", &ScriptCmd{})
}
<commit_msg>Fix copy to refer to files/<commit_after>package tachyon

import (
	"bufio"
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
	"syscall"
)

func captureCmd(c *exec.Cmd, show bool) ([]byte, []byte, error) {
	stdout, err := c.StdoutPipe()

	if err != nil {
		return nil, nil, err
	}

	defer stdout.Close()

	var wg sync.WaitGroup

	var bout bytes.Buffer
	var berr bytes.Buffer

	prefix := []byte(`| `)

	wg.Add(1)
	go func() {
		defer wg.Done()
		buf := bufio.NewReader(stdout)

		for {
			line, err := buf.ReadSlice('\n')

			if err != nil {
				break
			}

			bout.Write(line)

			if show {
				os.Stdout.Write(prefix)
				os.Stdout.Write(line)
			}
		}
	}()

	stderr, err := c.StderrPipe()

	if err != nil {
		stdout.Close()
		return nil, nil, err
	}

	defer stderr.Close()

	wg.Add(1)
	go func() {
		defer wg.Done()
		buf := bufio.NewReader(stderr)

		for {
			line, err := buf.ReadSlice('\n')

			if err != nil {
				break
			}

			berr.Write(line)

			if show {
				os.Stdout.Write(prefix)
				os.Stdout.Write(line)
			}
		}
	}()

	c.Start()

	wg.Wait()

	err = c.Wait()

	return bout.Bytes(), berr.Bytes(), err
}

type CommandResult struct {
	ReturnCode int
	Stdout     []byte
	Stderr     []byte
}

func RunCommand(env *CommandEnv, parts ...string) (*CommandResult, error) {
	c := exec.Command(parts[0], parts[1:]...)

	if env.Env.config.ShowCommandOutput {
		fmt.Printf("RUN: %s\n", strings.Join(parts, " "))
	}

	rc := 0

	stdout, stderr, err := captureCmd(c, env.Env.config.ShowCommandOutput)
	if err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			rc = 1
		} else {
			return nil, err
		}
	}

	return &CommandResult{rc, stdout, stderr}, nil
}

func RunCommandInEnv(env *CommandEnv, unixEnv []string, parts ...string) (*CommandResult, error) {
	c := exec.Command(parts[0], parts[1:]...)
	c.Env = unixEnv

	if env.Env.config.ShowCommandOutput {
		fmt.Printf("RUN: %s\n", strings.Join(parts, " "))
	}

	rc := 0

	stdout, stderr, err := captureCmd(c, env.Env.config.ShowCommandOutput)
	if err != nil {
		if _, ok := err.(*exec.ExitError); ok {
			rc = 1
		} else {
			return nil, err
		}
	}

	return &CommandResult{rc, stdout, stderr}, nil
}

func runCmd(env *CommandEnv, ignore bool, parts ...string) (*Result, error) {
	cmd, err := RunCommand(env, parts...)
	if !ignore && err != nil {
		return nil, err
	}

	r := NewResult(true)

	r.Add("rc", cmd.ReturnCode)
	r.Add("stdout", strings.TrimSpace(string(cmd.Stdout)))
	r.Add("stderr", strings.TrimSpace(string(cmd.Stderr)))

	if str, ok := renderShellResult(r); ok {
		r.Add("_result", str)
	}

	return r, nil
}

type CommandCmd struct {
	Command    string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *CommandCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	parts, err := shlex.Split(cmd.Command)

	if err != nil {
		return nil, err
	}

	return runCmd(env, cmd.IgnoreFail, parts...)
}

func (cmd *CommandCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

type ShellCmd struct {
	Command    string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *ShellCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	return runCmd(env, cmd.IgnoreFail, "sh", "-c", cmd.Command)
}

func (cmd *ShellCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

func renderShellResult(res *Result) (string, bool) {
	rcv, ok := res.Get("rc")
	if !ok {
		return "", false
	}

	stdoutv, ok := res.Get("stdout")
	if !ok {
		return "", false
	}

	stderrv, ok := res.Get("stderr")
	if !ok {
		return "", false
	}

	rc := rcv.Read().(int)
	stdout := stdoutv.Read().(string)
	stderr := stderrv.Read().(string)

	if rc == 0 && len(stdout) == 0 && len(stderr) == 0 {
		return "", true
	} else if len(stderr) == 0 && len(stdout) < 60 {
		stdout = strings.Replace(stdout, "\n", " ", -1)
		return fmt.Sprintf(`rc: %d, stdout: "%s"`, rc, stdout), true
	}

	return "", false
}

type CopyCmd struct {
	Src  string `tachyon:"src,required"`
	Dest string `tachyon:"dest,required"`
}

func md5file(path string) ([]byte, error) {
	h := md5.New()

	i, err := os.Open(path)
	if err != nil {
		return nil, err
	}

	if _, err := io.Copy(h, i); err != nil {
		return nil, err
	}

	return h.Sum(nil), nil
}

func (cmd *CopyCmd) Run(env *CommandEnv) (*Result, error) {
	var src string

	if cmd.Src[0] == '/' {
		src = cmd.Src
	} else {
		src = env.Paths.File(cmd.Src)
	}

	input, err := os.Open(src)

	if err != nil {
		return nil, err
	}

	srcStat, err := os.Stat(src)
	if err != nil {
		return nil, err
	}

	srcDigest, err := md5file(src)
	if err != nil {
		return nil, err
	}

	var dstDigest []byte

	defer input.Close()

	dest := cmd.Dest

	link := false

	if stat, err := os.Lstat(dest); err == nil {
		if stat.IsDir() {
			dest = filepath.Join(dest, filepath.Base(src))
		} else {
			dstDigest, _ = md5file(dest)
		}

		link = stat.Mode()&os.ModeSymlink != 0
	}

	rd := ResultData{
		"md5sum": Any(hex.EncodeToString(srcDigest)),
		"src":    Any(src),
		"dest":   Any(dest),
	}

	if dstDigest != nil && bytes.Equal(srcDigest, dstDigest) {
		return WrapResult(false, rd), nil
	}

	tmp := fmt.Sprintf("%s.tmp.%d", cmd.Dest, os.Getpid())

	output, err := os.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0644)

	if err != nil {
		return nil, err
	}

	defer output.Close()

	if _, err = io.Copy(output, input); err != nil {
		os.Remove(tmp)
		return nil, err
	}

	if link {
		os.Remove(dest)
	}

	if err := os.Chmod(tmp, srcStat.Mode()); err != nil {
		os.Remove(tmp)
		return nil, err
	}

	if ostat, ok := srcStat.Sys().(*syscall.Stat_t); ok {
		os.Chown(tmp, int(ostat.Uid), int(ostat.Gid))
	}

	err = os.Rename(tmp, dest)
	if err != nil {
		os.Remove(tmp)
		return nil, err
	}

	return WrapResult(true, rd), nil
}

type ScriptCmd struct {
	Script     string `tachyon:"command,required"`
	Creates    string `tachyon:"creates"`
	IgnoreFail bool   `tachyon:"ignore_failure"`
}

func (cmd *ScriptCmd) ParseArgs(s Scope, args string) (Vars, error) {
	if args == "" {
		return Vars{}, nil
	}

	return Vars{"command": Any(args)}, nil
}

func (cmd *ScriptCmd) Run(env *CommandEnv) (*Result, error) {
	if cmd.Creates != "" {
		if _, err := os.Stat(cmd.Creates); err == nil {
			r := NewResult(false)
			r.Add("rc", 0)
			r.Add("exists", cmd.Creates)

			return r, nil
		}
	}

	script := cmd.Script

	parts, err := shlex.Split(cmd.Script)
	if err == nil {
		script = parts[0]
	}

	path := env.Paths.File(script)

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

	runArgs := append([]string{"sh", path}, parts[1:]...)

	return runCmd(env, cmd.IgnoreFail, runArgs...)
}

func init() {
	RegisterCommand("command", &CommandCmd{})
	RegisterCommand("shell", &ShellCmd{})
	RegisterCommand("copy", &CopyCmd{})
	RegisterCommand("script", &ScriptCmd{})
}
<|endoftext|>


<commit_before>package golog

// All of Golog's builtin, foreign-implemented predicates
// are defined here.

import "fmt"
import "math/big"
import "sort"
import "strings"
import "github.com/mndrix/golog/term"
import . "github.com/mndrix/golog/util"

// !/0
func BuiltinCut(m Machine, args []term.Term) ForeignReturn {
	// if were anything to cut, !/0 would have already been
	// replaced with '$cut_to/1'  Since this goal wasn't there
	// must be nothing cut, so treat it as an alias for "true/0"
	return ForeignTrue()
}

// $cut_to/1
//
// An internal system predicate which might be removed at any time
// in the future.  It cuts all disjunctions on top of a specific cut
// barrier.
func BuiltinCutTo(m Machine, args []term.Term) ForeignReturn {
	barrierId := args[0].(*term.Integer).Value().Int64()
	return m.CutTo(barrierId)
}

// ,/2
func BuiltinComma(m Machine, args []term.Term) ForeignReturn {
	return m.PushConj(args[1]).PushConj(args[0])
}

// ground/1
func BuiltinGround(m Machine, args []term.Term) ForeignReturn {
	switch x := args[0].(type) {
	case *term.Variable:
		return ForeignFail()
	case *term.Atom,
		*term.Integer,
		*term.Float,
		*term.Error:
		return ForeignTrue()
	case *term.Compound:
		// recursively evaluate compound term's arguments
		for _, arg := range x.Arguments() {
			f := BuiltinGround(m, []term.Term{arg})
			switch f.(type) {
			case *foreignFail:
				return ForeignFail()
			}
		}
		return ForeignTrue()
	}
	msg := fmt.Sprintf("Unexpected term type: %#v", args[0])
	panic(msg)
}

// ->/2
func BuiltinIfThen(m Machine, args []term.Term) ForeignReturn {
	cond := args[0]
	then := args[1]

	// CUT_BARRIER, (cond, !, then)
	cut := term.NewTerm("!")
	goal := term.NewTerm(",", cond, term.NewTerm(",", cut, then))
	return m.DemandCutBarrier().PushConj(goal)
}

// ;/2
//
// Implements disjunction and if-then-else.
func BuiltinSemicolon(m Machine, args []term.Term) ForeignReturn {
	arity := args[0].Arity()
	functor := args[0].Functor()
	if arity == 2 && functor == "->" { // §7.8.8
		return ifThenElse(m, args)
	}

	cp := NewSimpleChoicePoint(m, args[1])
	return m.PushDisj(cp).PushConj(args[0])
}
func ifThenElse(m Machine, args []term.Term) ForeignReturn {
	cond := args[0].Arguments()[0]
	then := args[0].Arguments()[1]
	els := args[1]

	// CUT_BARRIER, (call(cond), !, then; else)
	cut := term.NewTerm("!")
	cond = term.NewTerm("call", cond)
	goal := term.NewTerm(",", cond, term.NewTerm(",", cut, then))
	goal = term.NewTerm(";", goal, els)
	return m.DemandCutBarrier().PushConj(goal)
}

// =/2
func BuiltinUnify(m Machine, args []term.Term) ForeignReturn {
	return ForeignUnify(args[0], args[1])
}

// (\+)/1
func BuiltinNot(m Machine, args []term.Term) ForeignReturn {
	var answer term.Bindings
	var err error
	m = m.ClearConjs().PushConj(args[0])

	for {
		m, answer, err = m.Step()
		if err == MachineDone {
			return ForeignTrue()
		}
		MaybePanic(err)
		if answer != nil {
			return ForeignFail()
		}
	}
	panic("impossible")
}

// atom_codes/2 see ISO §8.16.5
func BuiltinAtomCodes2(m Machine, args []term.Term) ForeignReturn {
	atom := args[0]
	list := args[1]

	if !term.IsVariable(atom) {
		list = term.NewCodeList(atom.Functor())
		return ForeignUnify(args[1], list)
	} else if !term.IsVariable(list) {
		runes := make([]rune, 0)
		for {
			switch list.Arity() {
			case 2:
				if list.Functor() == "." {
					args := list.Arguments()
					code := args[0].(*term.Integer)
					runes = append(runes, code.Code())
					list = args[1]
				}
			case 0:
				if list.Functor() == "[]" {
					atom = term.NewAtom(string(runes))
					return ForeignUnify(args[0], atom)
				}
			default:
				msg := fmt.Sprintf("unexpected code list %s", args[1])
				panic(msg)
			}
		}
	}

	msg := fmt.Sprintf("atom_codes/2: error with the arguments %s and %s", args[0], args[1])
	panic(msg)
}

// atom_number/2 as defined in SWI-Prolog
func BuiltinAtomNumber2(m Machine, args []term.Term) (ret ForeignReturn) {
	atom := args[0]
	number := args[1]

	if !term.IsVariable(atom) {
		defer func() { // convert parsing panics into fail
			if x := recover(); x != nil {
				ret = ForeignFail()
			}
		}()
		if strings.Contains(atom.Functor(), ".") {
			number = term.NewFloat(atom.Functor())
		} else {
			number = term.NewInt(atom.Functor())
		}
		return ForeignUnify(args[1], number)
	} else if !term.IsVariable(number) {
		atom = term.NewAtom(number.String())
		return ForeignUnify(args[0], atom)
	}

	msg := fmt.Sprintf("atom_number/2: Arguments are not sufficiently instantiated: %s and %s", args[0], args[1])
	panic(msg)
}

// call/*
func BuiltinCall(m Machine, args []term.Term) ForeignReturn {
	// which goal is being called?
	bodyTerm := args[0]
	if term.IsVariable(bodyTerm) {
		bindings := m.Bindings()
		bodyTerm = bindings.Resolve_(bodyTerm.(*term.Variable))
	}

	// build a new goal with extra arguments attached
	functor := bodyTerm.Functor()
	newArgs := make([]term.Term, 0)
	newArgs = append(newArgs, bodyTerm.Arguments()...)
	newArgs = append(newArgs, args[1:]...)
	goal := term.NewTerm(functor, newArgs...)

	// construct a machine that will prove this goal next
	return m.DemandCutBarrier().PushConj(goal)
}

// downcase_atom(+AnyCase, -LowerCase)
//
// Converts the characters of AnyCase into lowercase and unifies the
// lowercase atom with LowerCase.
func BuiltinDowncaseAtom2(m Machine, args []term.Term) ForeignReturn {
	anycase := args[0]
	if term.IsVariable(anycase) {
		panic("downcase_atom/2: instantiation_error")
	}
	if anycase.Arity() != 0 {
		msg := fmt.Sprintf("downcase_atom/2: type_error(atom, %s)", anycase)
		panic(msg)
	}

	lowercase := term.NewAtom(strings.ToLower(anycase.Functor()))
	return ForeignUnify(args[1], lowercase)
}

// fail/0
func BuiltinFail(m Machine, args []term.Term) ForeignReturn {
	return ForeignFail()
}

// findall/3
func BuiltinFindall3(m Machine, args []term.Term) ForeignReturn {
	template := args[0]
	goal := args[1]

	// call(Goal), X=Template
	x := term.NewVar("_")
	call := term.NewTerm("call", goal)
	unify := term.NewTerm("=", x, template)
	prove := term.NewTerm(",", call, unify)
	proofs := m.ClearConjs().ProveAll(prove)

	// build a list from the results
	instances := make([]term.Term, 0)
	for _, proof := range proofs {
		t, err := proof.Resolve(x)
		MaybePanic(err)
		instances = append(instances, t)
	}

	return ForeignUnify(args[2], term.NewTermList(instances))
}

// listing/0
// This should be implemented in pure Prolog, but for debugging purposes,
// I'm doing it for now as a foreign predicate.  This will go away.
func BuiltinListing0(m Machine, args []term.Term) ForeignReturn {
	fmt.Println(m.String())
	return ForeignTrue()
}

// msort(+Unsorted:list, -Sorted:list) is det.
//
// True if Sorted is a sorted version of Unsorted.  Duplicates are
// not removed.
//
// This is currently implemented using Go's sort.Sort.
// The exact implementation is subject to change.  I make no
// guarantees about sort stability.
func BuiltinMsort2(m Machine, args []term.Term) ForeignReturn {
	terms := term.ProperListToTermSlice(args[0])
	sort.Sort((*term.TermSlice)(&terms))
	list := term.NewTermList(terms)
	return ForeignUnify(args[1], list)
}

// A temporary hack for debugging.  This will disappear once Golog has
// proper support for format/2
func BuiltinPrintf(m Machine, args []term.Term) ForeignReturn {
	template := args[0].Functor()
	template = strings.Replace(template, "~n", "\n", -1)
	if len(args) == 1 {
		fmt.Printf(template)
	} else if len(args) == 2 {
		fmt.Printf(template, args[1])
	}
	return ForeignTrue()
}

// succ(?A:integer, ?B:integer) is det.
//
// True if B is one greater than A and A >= 0.
func BuiltinSucc2(m Machine, args []term.Term) ForeignReturn {
	x := args[0]
	y := args[1]
	zero := big.NewInt(0)

	if term.IsInteger(x) {
		a := x.(*term.Integer)
		if a.Value().Cmp(zero) < 0 {
			panic("succ/2: first argument must be 0 or greater")
		}
		result := new(big.Int).Add(a.Value(), big.NewInt(1))
		return ForeignUnify(y, term.NewBigInt(result))
	} else if term.IsInteger(y) {
		b := y.(*term.Integer)
		result := new(big.Int).Add(b.Value(), big.NewInt(-1))
		if result.Cmp(zero) < 0 {
			panic("succ/2: first argument must be 0 or greater")
		}
		return ForeignUnify(x, term.NewBigInt(result))
	}

	panic("succ/2: one argument must be an integer")
}
<commit_msg>Delete outdated, dead code<commit_after>package golog

// All of Golog's builtin, foreign-implemented predicates
// are defined here.

import "fmt"
import "math/big"
import "sort"
import "strings"
import "github.com/mndrix/golog/term"
import . "github.com/mndrix/golog/util"

// !/0
func BuiltinCut(m Machine, args []term.Term) ForeignReturn {
	// if were anything to cut, !/0 would have already been
	// replaced with '$cut_to/1'  Since this goal wasn't there
	// must be nothing cut, so treat it as an alias for "true/0"
	return ForeignTrue()
}

// $cut_to/1
//
// An internal system predicate which might be removed at any time
// in the future.  It cuts all disjunctions on top of a specific cut
// barrier.
func BuiltinCutTo(m Machine, args []term.Term) ForeignReturn {
	barrierId := args[0].(*term.Integer).Value().Int64()
	return m.CutTo(barrierId)
}

// ,/2
func BuiltinComma(m Machine, args []term.Term) ForeignReturn {
	return m.PushConj(args[1]).PushConj(args[0])
}

// ground/1
func BuiltinGround(m Machine, args []term.Term) ForeignReturn {
	switch x := args[0].(type) {
	case *term.Variable:
		return ForeignFail()
	case *term.Atom,
		*term.Integer,
		*term.Float,
		*term.Error:
		return ForeignTrue()
	case *term.Compound:
		// recursively evaluate compound term's arguments
		for _, arg := range x.Arguments() {
			f := BuiltinGround(m, []term.Term{arg})
			switch f.(type) {
			case *foreignFail:
				return ForeignFail()
			}
		}
		return ForeignTrue()
	}
	msg := fmt.Sprintf("Unexpected term type: %#v", args[0])
	panic(msg)
}

// ->/2
func BuiltinIfThen(m Machine, args []term.Term) ForeignReturn {
	cond := args[0]
	then := args[1]

	// CUT_BARRIER, (cond, !, then)
	cut := term.NewTerm("!")
	goal := term.NewTerm(",", cond, term.NewTerm(",", cut, then))
	return m.DemandCutBarrier().PushConj(goal)
}

// ;/2
//
// Implements disjunction and if-then-else.
func BuiltinSemicolon(m Machine, args []term.Term) ForeignReturn {
	arity := args[0].Arity()
	functor := args[0].Functor()
	if arity == 2 && functor == "->" { // §7.8.8
		return ifThenElse(m, args)
	}

	cp := NewSimpleChoicePoint(m, args[1])
	return m.PushDisj(cp).PushConj(args[0])
}
func ifThenElse(m Machine, args []term.Term) ForeignReturn {
	cond := args[0].Arguments()[0]
	then := args[0].Arguments()[1]
	els := args[1]

	// CUT_BARRIER, (call(cond), !, then; else)
	cut := term.NewTerm("!")
	cond = term.NewTerm("call", cond)
	goal := term.NewTerm(",", cond, term.NewTerm(",", cut, then))
	goal = term.NewTerm(";", goal, els)
	return m.DemandCutBarrier().PushConj(goal)
}

// =/2
func BuiltinUnify(m Machine, args []term.Term) ForeignReturn {
	return ForeignUnify(args[0], args[1])
}

// (\+)/1
func BuiltinNot(m Machine, args []term.Term) ForeignReturn {
	var answer term.Bindings
	var err error
	m = m.ClearConjs().PushConj(args[0])

	for {
		m, answer, err = m.Step()
		if err == MachineDone {
			return ForeignTrue()
		}
		MaybePanic(err)
		if answer != nil {
			return ForeignFail()
		}
	}
	panic("impossible")
}

// atom_codes/2 see ISO §8.16.5
func BuiltinAtomCodes2(m Machine, args []term.Term) ForeignReturn {
	atom := args[0]
	list := args[1]

	if !term.IsVariable(atom) {
		list = term.NewCodeList(atom.Functor())
		return ForeignUnify(args[1], list)
	} else if !term.IsVariable(list) {
		runes := make([]rune, 0)
		for {
			switch list.Arity() {
			case 2:
				if list.Functor() == "." {
					args := list.Arguments()
					code := args[0].(*term.Integer)
					runes = append(runes, code.Code())
					list = args[1]
				}
			case 0:
				if list.Functor() == "[]" {
					atom = term.NewAtom(string(runes))
					return ForeignUnify(args[0], atom)
				}
			default:
				msg := fmt.Sprintf("unexpected code list %s", args[1])
				panic(msg)
			}
		}
	}

	msg := fmt.Sprintf("atom_codes/2: error with the arguments %s and %s", args[0], args[1])
	panic(msg)
}

// atom_number/2 as defined in SWI-Prolog
func BuiltinAtomNumber2(m Machine, args []term.Term) (ret ForeignReturn) {
	atom := args[0]
	number := args[1]

	if !term.IsVariable(atom) {
		defer func() { // convert parsing panics into fail
			if x := recover(); x != nil {
				ret = ForeignFail()
			}
		}()
		if strings.Contains(atom.Functor(), ".") {
			number = term.NewFloat(atom.Functor())
		} else {
			number = term.NewInt(atom.Functor())
		}
		return ForeignUnify(args[1], number)
	} else if !term.IsVariable(number) {
		atom = term.NewAtom(number.String())
		return ForeignUnify(args[0], atom)
	}

	msg := fmt.Sprintf("atom_number/2: Arguments are not sufficiently instantiated: %s and %s", args[0], args[1])
	panic(msg)
}

// call/*
func BuiltinCall(m Machine, args []term.Term) ForeignReturn {

	// build a new goal with extra arguments attached
	functor := bodyTerm.Functor()
	newArgs := make([]term.Term, 0)
	newArgs = append(newArgs, bodyTerm.Arguments()...)
	newArgs = append(newArgs, args[1:]...)
	goal := term.NewTerm(functor, newArgs...)

	// construct a machine that will prove this goal next
	return m.DemandCutBarrier().PushConj(goal)
}

// downcase_atom(+AnyCase, -LowerCase)
//
// Converts the characters of AnyCase into lowercase and unifies the
// lowercase atom with LowerCase.
func BuiltinDowncaseAtom2(m Machine, args []term.Term) ForeignReturn {
	anycase := args[0]
	if term.IsVariable(anycase) {
		panic("downcase_atom/2: instantiation_error")
	}
	if anycase.Arity() != 0 {
		msg := fmt.Sprintf("downcase_atom/2: type_error(atom, %s)", anycase)
		panic(msg)
	}

	lowercase := term.NewAtom(strings.ToLower(anycase.Functor()))
	return ForeignUnify(args[1], lowercase)
}

// fail/0
func BuiltinFail(m Machine, args []term.Term) ForeignReturn {
	return ForeignFail()
}

// findall/3
func BuiltinFindall3(m Machine, args []term.Term) ForeignReturn {
	template := args[0]
	goal := args[1]

	// call(Goal), X=Template
	x := term.NewVar("_")
	call := term.NewTerm("call", goal)
	unify := term.NewTerm("=", x, template)
	prove := term.NewTerm(",", call, unify)
	proofs := m.ClearConjs().ProveAll(prove)

	// build a list from the results
	instances := make([]term.Term, 0)
	for _, proof := range proofs {
		t, err := proof.Resolve(x)
		MaybePanic(err)
		instances = append(instances, t)
	}

	return ForeignUnify(args[2], term.NewTermList(instances))
}

// listing/0
// This should be implemented in pure Prolog, but for debugging purposes,
// I'm doing it for now as a foreign predicate.  This will go away.
func BuiltinListing0(m Machine, args []term.Term) ForeignReturn {
	fmt.Println(m.String())
	return ForeignTrue()
}

// msort(+Unsorted:list, -Sorted:list) is det.
//
// True if Sorted is a sorted version of Unsorted.  Duplicates are
// not removed.
//
// This is currently implemented using Go's sort.Sort.
// The exact implementation is subject to change.  I make no
// guarantees about sort stability.
func BuiltinMsort2(m Machine, args []term.Term) ForeignReturn {
	terms := term.ProperListToTermSlice(args[0])
	sort.Sort((*term.TermSlice)(&terms))
	list := term.NewTermList(terms)
	return ForeignUnify(args[1], list)
}

// A temporary hack for debugging.  This will disappear once Golog has
// proper support for format/2
func BuiltinPrintf(m Machine, args []term.Term) ForeignReturn {
	template := args[0].Functor()
	template = strings.Replace(template, "~n", "\n", -1)
	if len(args) == 1 {
		fmt.Printf(template)
	} else if len(args) == 2 {
		fmt.Printf(template, args[1])
	}
	return ForeignTrue()
}

// succ(?A:integer, ?B:integer) is det.
//
// True if B is one greater than A and A >= 0.
func BuiltinSucc2(m Machine, args []term.Term) ForeignReturn {
	x := args[0]
	y := args[1]
	zero := big.NewInt(0)

	if term.IsInteger(x) {
		a := x.(*term.Integer)
		if a.Value().Cmp(zero) < 0 {
			panic("succ/2: first argument must be 0 or greater")
		}
		result := new(big.Int).Add(a.Value(), big.NewInt(1))
		return ForeignUnify(y, term.NewBigInt(result))
	} else if term.IsInteger(y) {
		b := y.(*term.Integer)
		result := new(big.Int).Add(b.Value(), big.NewInt(-1))
		if result.Cmp(zero) < 0 {
			panic("succ/2: first argument must be 0 or greater")
		}
		return ForeignUnify(x, term.NewBigInt(result))
	}

	panic("succ/2: one argument must be an integer")
}
<|endoftext|>


<commit_before>package hystrix

import (
	"testing"
	"time"
)

func TestOpen(t *testing.T) {
	c := NewCircuitBreaker()

	for i := 0; i < 10; i++ {
		c.Health.Updates <- false
	}

	c.toggleOpenFromHealth(time.Now())

	if !c.IsOpen() {
		t.Fail()
	}
}

// TODO: circuit re-closes when failures stop
func TestClose(t *testing.T) {

}
<commit_msg>test for circuit toggling into closed state<commit_after>package hystrix

import (
	"testing"
	"time"
)

func TestOpen(t *testing.T) {
	c := NewCircuitBreaker()

	for i := 0; i < 10; i++ {
		c.Health.Updates <- false
	}

	c.toggleOpenFromHealth(time.Now())

	if !c.IsOpen() {
		t.Fail()
	}
}

func TestClose(t *testing.T) {
	c := NewCircuitBreaker()
	c.Open = true

	for i := 0; i < 10; i++ {
		c.Health.Updates <- true
	}

	c.toggleOpenFromHealth(time.Now())

	if c.IsOpen() {
		t.Fail()
	}
}
<|endoftext|>