<commit_before>// Package text contains utility functions for manipulating raw text strings
package text

import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"

	"github.com/fatih/camelcase"
)

// taken from https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702
var commonInitialisms = map[string]bool{
	"API":   true,
	"ASCII": true,
	"CPU":   true,
	"CSS":   true,
	"DNS":   true,
	"EOF":   true,
	"GUID":  true,
	"HTML":  true,
	"HTTP":  true,
	"HTTPS": true,
	"ID":    true,
	"IP":    true,
	"JSON":  true,
	"LHS":   true,
	"QPS":   true,
	"RAM":   true,
	"RHS":   true,
	"RPC":   true,
	"SLA":   true,
	"SMTP":  true,
	"SQL":   true,
	"SSH":   true,
	"TCP":   true,
	"TLS":   true,
	"TTL":   true,
	"UDP":   true,
	"UI":    true,
	"UID":   true,
	"UUID":  true,
	"URI":   true,
	"URL":   true,
	"UTF8":  true,
	"VM":    true,
	"XML":   true,
	"XSRF":  true,
	"XSS":   true,
}

// Indent indents a block of text with an indent string. It does this by
// placing the given indent string at the front of every line, except on the
// last line, if the last line has no characters. This special treatment
// simplifies the generation of nested text structures.
func Indent(text, indent string) string {
	if text == "" {
		return text
	}
	if text[len(text)-1:] == "\n" {
		result := ""
		for _, j := range strings.Split(text[:len(text)-1], "\n") {
			result += indent + j + "\n"
		}
		return result
	}
	result := ""
	for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") {
		result += indent + j + "\n"
	}
	return result[:len(result)-1]
}

// Underline returns the provided text together with a new line character and a
// line of "=" characters whose length is equal to the maximum line length in
// the provided text, followed by a final newline character.
func Underline(text string) string {
	var maxlen int
	for _, j := range strings.Split(text, "\n") {
		if len(j) > maxlen {
			maxlen = len(j)
		}
	}
	return text + "\n" + strings.Repeat("=", maxlen) + "\n"
}

// Returns a string of the same length, filled with "*"s.
func StarOut(text string) string {
	return strings.Repeat("*", len(text))
}

// GoIdentifierFrom provides a mechanism to mutate an arbitrary descriptive
// string (name) into an _exported_ Go identifier (variable name, function
// name, etc) that e.g. can be used in generated code, taking into account a
// blacklist of names that have already been used, in order to guarantee that a
// new name is created which will not conflict with an existing type.
//
// Identifier syntax: https://golang.org/ref/spec#Identifiers
//
// Strategy to convert arbitrary unicode string to a valid identifier:
//
// 1) Ensure name is valid UTF-8; if not, replace it with empty string
//
// 2) Split name into arrays of allowed runes (words), discarding disallowed
// unicode points
//
// 3) Upper case first rune in each word (see
// https://golang.org/pkg/strings/#Title)
//
// 4) Set appropriate case (upper/lower) of first char
//
// 5) Split words further into sub words, by decomposing camel case words
//
// 6) Replace subwords that when uppercase'd are a common "initialism" as per
// https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702
// such that the case of each character in the subword has the same case as the
// initial character (e.g. Url -> URL)
//
// 7) Rejoin subwords to form a single word
//
// 8) Rejoin words into a single string
//
// 9) If the string starts with a number, add a leading `_`
//
// 10) If the string is the empty string or "_", set as "Identifier"
//
// 11) If the resulting identifier is in the blacklist, append the lowest
// integer possible, >= 1, that results in no blacklist conflict
//
// 12) Add the new name to the given blacklist
//
// Note, the `map[string]bool` construction is simply a mechanism to implement
// set semantics; a value of `true` signifies inclusion in the set.
// Non-existence is equivalent to existence with a value of `false`; therefore
// it is recommended to only store `true` values.
func GoIdentifierFrom(name string, exported bool, blacklist map[string]bool) (identifier string) {
	if !utf8.ValidString(name) {
		name = ""
	}
	for i, word := range strings.FieldsFunc(
		name,
		func(c rune) bool {
			return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_'
		},
	) {
		if i == 0 {
			if len(word) > 0 {
				firstRune, size := utf8.DecodeRuneInString(word)
				remainingString := word[size:]
				if exported {
					word = string(unicode.ToUpper(firstRune)) + remainingString
				} else {
					word = string(unicode.ToLower(firstRune)) + remainingString
				}
			}
		} else {
			word = strings.Title(word)
		}
		caseAdaptedWord := ""
		for _, subWord := range camelcase.Split(word) {
			if u, l := strings.ToUpper(subWord), strings.ToLower(subWord); commonInitialisms[u] {
				if subWord[0] >= 'a' && subWord[0] <= 'z' {
					subWord = l
				} else {
					subWord = u
				}
			}
			caseAdaptedWord += subWord
		}
		identifier += caseAdaptedWord
	}

	if strings.IndexFunc(
		identifier,
		func(c rune) bool {
			return unicode.IsNumber(c)
		},
	) == 0 {
		identifier = "_" + identifier
	}

	if identifier == "" || identifier == "_" {
		identifier = "Identifier"
	}

	// If name already exists, add an integer suffix to name. Start with "1" and increment
	// by 1 until an unused name is found. Example: if name FooBar was generated four times
	// , the first instance would be called FooBar, then the next would be FooBar1, the next
	// FooBar2 and the last would be assigned a name of FooBar3. We do this to guarantee we
	// don't use duplicate names for different logical entities.
	for k, baseName := 1, identifier; blacklist[identifier]; {
		identifier = fmt.Sprintf("%v%v", baseName, k)
		k++
	}
	blacklist[identifier] = true
	return
}

// Returns the indefinite article (in English) for a the given noun, which is
// 'an' for nouns beginning with a vowel, otherwise 'a'.
func IndefiniteArticle(noun string) string {
	if strings.ContainsRune("AEIOUaeiou", rune(noun[0])) {
		return "an"
	} else {
		return "a"
	}
}
<commit_msg>Syntax simplification<commit_after>// Package text contains utility functions for manipulating raw text strings
package text

import (
	"fmt"
	"strings"
	"unicode"
	"unicode/utf8"

	"github.com/fatih/camelcase"
)

// taken from https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702
var commonInitialisms = map[string]bool{
	"API":   true,
	"ASCII": true,
	"CPU":   true,
	"CSS":   true,
	"DNS":   true,
	"EOF":   true,
	"GUID":  true,
	"HTML":  true,
	"HTTP":  true,
	"HTTPS": true,
	"ID":    true,
	"IP":    true,
	"JSON":  true,
	"LHS":   true,
	"QPS":   true,
	"RAM":   true,
	"RHS":   true,
	"RPC":   true,
	"SLA":   true,
	"SMTP":  true,
	"SQL":   true,
	"SSH":   true,
	"TCP":   true,
	"TLS":   true,
	"TTL":   true,
	"UDP":   true,
	"UI":    true,
	"UID":   true,
	"UUID":  true,
	"URI":   true,
	"URL":   true,
	"UTF8":  true,
	"VM":    true,
	"XML":   true,
	"XSRF":  true,
	"XSS":   true,
}

// Indent indents a block of text with an indent string. It does this by
// placing the given indent string at the front of every line, except on the
// last line, if the last line has no characters. This special treatment
// simplifies the generation of nested text structures.
func Indent(text, indent string) string {
	if text == "" {
		return text
	}
	if text[len(text)-1:] == "\n" {
		result := ""
		for _, j := range strings.Split(text[:len(text)-1], "\n") {
			result += indent + j + "\n"
		}
		return result
	}
	result := ""
	for _, j := range strings.Split(strings.TrimRight(text, "\n"), "\n") {
		result += indent + j + "\n"
	}
	return result[:len(result)-1]
}

// Underline returns the provided text together with a new line character and a
// line of "=" characters whose length is equal to the maximum line length in
// the provided text, followed by a final newline character.
func Underline(text string) string {
	var maxlen int
	for _, j := range strings.Split(text, "\n") {
		if len(j) > maxlen {
			maxlen = len(j)
		}
	}
	return text + "\n" + strings.Repeat("=", maxlen) + "\n"
}

// Returns a string of the same length, filled with "*"s.
func StarOut(text string) string {
	return strings.Repeat("*", len(text))
}

// GoIdentifierFrom provides a mechanism to mutate an arbitrary descriptive
// string (name) into an _exported_ Go identifier (variable name, function
// name, etc) that e.g. can be used in generated code, taking into account a
// blacklist of names that have already been used, in order to guarantee that a
// new name is created which will not conflict with an existing type.
//
// Identifier syntax: https://golang.org/ref/spec#Identifiers
//
// Strategy to convert arbitrary unicode string to a valid identifier:
//
// 1) Ensure name is valid UTF-8; if not, replace it with empty string
//
// 2) Split name into arrays of allowed runes (words), discarding disallowed
// unicode points
//
// 3) Upper case first rune in each word (see
// https://golang.org/pkg/strings/#Title)
//
// 4) Set appropriate case (upper/lower) of first char
//
// 5) Split words further into sub words, by decomposing camel case words
//
// 6) Replace subwords that when uppercase'd are a common "initialism" as per
// https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702
// such that the case of each character in the subword has the same case as the
// initial character (e.g. Url -> URL)
//
// 7) Rejoin subwords to form a single word
//
// 8) Rejoin words into a single string
//
// 9) If the string starts with a number, add a leading `_`
//
// 10) If the string is the empty string or "_", set as "Identifier"
//
// 11) If the resulting identifier is in the blacklist, append the lowest
// integer possible, >= 1, that results in no blacklist conflict
//
// 12) Add the new name to the given blacklist
//
// Note, the `map[string]bool` construction is simply a mechanism to implement
// set semantics; a value of `true` signifies inclusion in the set.
// Non-existence is equivalent to existence with a value of `false`; therefore
// it is recommended to only store `true` values.
func GoIdentifierFrom(name string, exported bool, blacklist map[string]bool) (identifier string) {
	if !utf8.ValidString(name) {
		name = ""
	}
	for i, word := range strings.FieldsFunc(
		name,
		func(c rune) bool {
			return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_'
		},
	) {
		if i == 0 {
			if len(word) > 0 {
				firstRune, size := utf8.DecodeRuneInString(word)
				remainingString := word[size:]
				if exported {
					word = string(unicode.ToUpper(firstRune)) + remainingString
				} else {
					word = string(unicode.ToLower(firstRune)) + remainingString
				}
			}
		} else {
			word = strings.Title(word)
		}
		caseAdaptedWord := ""
		for _, subWord := range camelcase.Split(word) {
			u, l := strings.ToUpper(subWord), strings.ToLower(subWord)
			if commonInitialisms[u] {
				if subWord[0] >= 'a' && subWord[0] <= 'z' {
					subWord = l
				} else {
					subWord = u
				}
			}
			caseAdaptedWord += subWord
		}
		identifier += caseAdaptedWord
	}

	if strings.IndexFunc(
		identifier,
		func(c rune) bool {
			return unicode.IsNumber(c)
		},
	) == 0 {
		identifier = "_" + identifier
	}

	if identifier == "" || identifier == "_" {
		identifier = "Identifier"
	}

	// If name already exists, add an integer suffix to name. Start with "1" and increment
	// by 1 until an unused name is found. Example: if name FooBar was generated four times
	// , the first instance would be called FooBar, then the next would be FooBar1, the next
	// FooBar2 and the last would be assigned a name of FooBar3. We do this to guarantee we
	// don't use duplicate names for different logical entities.
	for k, baseName := 1, identifier; blacklist[identifier]; {
		identifier = fmt.Sprintf("%v%v", baseName, k)
		k++
	}
	blacklist[identifier] = true
	return
}

// Returns the indefinite article (in English) for a the given noun, which is
// 'an' for nouns beginning with a vowel, otherwise 'a'.
func IndefiniteArticle(noun string) string {
	if strings.ContainsRune("AEIOUaeiou", rune(noun[0])) {
		return "an"
	} else {
		return "a"
	}
}
<|endoftext|>


<commit_before>package pgtype

import (
	"database/sql/driver"
	"encoding/binary"
	"fmt"
	"time"

	"github.com/jackc/pgio"
)

const pgTimestampFormat = "2006-01-02 15:04:05.999999999"

// Timestamp represents the PostgreSQL timestamp type. The PostgreSQL
// timestamp does not have a time zone. This presents a problem when
// translating to and from time.Time which requires a time zone. It is highly
// recommended to use timestamptz whenever possible. Timestamp methods either
// convert to UTC or return an error on non-UTC times.
type Timestamp struct {
	Time             time.Time // Time must always be in UTC.
	Status           Status
	InfinityModifier InfinityModifier
}

// Set converts src into a Timestamp and stores in dst. If src is a
// time.Time in a non-UTC time zone, the time zone is discarded.
func (dst *Timestamp) Set(src interface{}) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	if value, ok := src.(interface{ Get() interface{} }); ok {
		value2 := value.Get()
		if value2 != value {
			return dst.Set(value2)
		}
	}

	switch value := src.(type) {
	case time.Time:
		*dst = Timestamp{Time: time.Date(value.Year(), value.Month(), value.Day(), value.Hour(), value.Minute(), value.Second(), value.Nanosecond(), time.UTC), Status: Present}
	case *time.Time:
		if value == nil {
			*dst = Timestamp{Status: Null}
		} else {
			return dst.Set(*value)
		}
	case InfinityModifier:
		*dst = Timestamp{InfinityModifier: value, Status: Present}
	default:
		if originalSrc, ok := underlyingTimeType(src); ok {
			return dst.Set(originalSrc)
		}
		return fmt.Errorf("cannot convert %v to Timestamp", value)
	}

	return nil
}

func (dst Timestamp) Get() interface{} {
	switch dst.Status {
	case Present:
		if dst.InfinityModifier != None {
			return dst.InfinityModifier
		}
		return dst.Time
	case Null:
		return nil
	default:
		return dst.Status
	}
}

func (src *Timestamp) AssignTo(dst interface{}) error {
	switch src.Status {
	case Present:
		switch v := dst.(type) {
		case *time.Time:
			if src.InfinityModifier != None {
				return fmt.Errorf("cannot assign %v to %T", src, dst)
			}
			*v = src.Time
			return nil
		default:
			if nextDst, retry := GetAssignToDstType(dst); retry {
				return src.AssignTo(nextDst)
			}
			return fmt.Errorf("unable to assign to %T", dst)
		}
	case Null:
		return NullAssignTo(dst)
	}

	return fmt.Errorf("cannot decode %#v into %T", src, dst)
}

// DecodeText decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeText(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	sbuf := string(src)
	switch sbuf {
	case "infinity":
		*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
	case "-infinity":
		*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
	default:
		tim, err := time.Parse(pgTimestampFormat, sbuf)
		if err != nil {
			return err
		}

		*dst = Timestamp{Time: tim, Status: Present}
	}

	return nil
}

// DecodeBinary decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeBinary(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	if len(src) != 8 {
		return fmt.Errorf("invalid length for timestamp: %v", len(src))
	}

	microsecSinceY2K := int64(binary.BigEndian.Uint64(src))

	switch microsecSinceY2K {
	case infinityMicrosecondOffset:
		*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
	case negativeInfinityMicrosecondOffset:
		*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
	default:
		tim := time.Unix(
			microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000,
			(microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000),
		)
		*dst = Timestamp{Time: tim, Status: Present}
	}

	return nil
}

// EncodeText writes the text encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
	switch src.Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}
	if src.Time.Location() != time.UTC {
		return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
	}

	var s string

	switch src.InfinityModifier {
	case None:
		s = src.Time.Truncate(time.Microsecond).Format(pgTimestampFormat)
	case Infinity:
		s = "infinity"
	case NegativeInfinity:
		s = "-infinity"
	}

	return append(buf, s...), nil
}

// EncodeBinary writes the binary encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
	switch src.Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}
	if src.Time.Location() != time.UTC {
		return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
	}

	var microsecSinceY2K int64
	switch src.InfinityModifier {
	case None:
		microsecSinceUnixEpoch := src.Time.Unix()*1000000 + int64(src.Time.Nanosecond())/1000
		microsecSinceY2K = microsecSinceUnixEpoch - microsecFromUnixEpochToY2K
	case Infinity:
		microsecSinceY2K = infinityMicrosecondOffset
	case NegativeInfinity:
		microsecSinceY2K = negativeInfinityMicrosecondOffset
	}

	return pgio.AppendInt64(buf, microsecSinceY2K), nil
}

// Scan implements the database/sql Scanner interface.
func (dst *Timestamp) Scan(src interface{}) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	switch src := src.(type) {
	case string:
		return dst.DecodeText(nil, []byte(src))
	case []byte:
		srcCopy := make([]byte, len(src))
		copy(srcCopy, src)
		return dst.DecodeText(nil, srcCopy)
	case time.Time:
		*dst = Timestamp{Time: src, Status: Present}
		return nil
	}

	return fmt.Errorf("cannot scan %T", src)
}

// Value implements the database/sql/driver Valuer interface.
func (src Timestamp) Value() (driver.Value, error) {
	switch src.Status {
	case Present:
		if src.InfinityModifier != None {
			return src.InfinityModifier.String(), nil
		}
		return src.Time, nil
	case Null:
		return nil, nil
	default:
		return nil, errUndefined
	}
}
<commit_msg>Fix: Timestamp DecodeBinary is in UTC<commit_after>package pgtype

import (
	"database/sql/driver"
	"encoding/binary"
	"fmt"
	"time"

	"github.com/jackc/pgio"
)

const pgTimestampFormat = "2006-01-02 15:04:05.999999999"

// Timestamp represents the PostgreSQL timestamp type. The PostgreSQL
// timestamp does not have a time zone. This presents a problem when
// translating to and from time.Time which requires a time zone. It is highly
// recommended to use timestamptz whenever possible. Timestamp methods either
// convert to UTC or return an error on non-UTC times.
type Timestamp struct {
	Time             time.Time // Time must always be in UTC.
	Status           Status
	InfinityModifier InfinityModifier
}

// Set converts src into a Timestamp and stores in dst. If src is a
// time.Time in a non-UTC time zone, the time zone is discarded.
func (dst *Timestamp) Set(src interface{}) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	if value, ok := src.(interface{ Get() interface{} }); ok {
		value2 := value.Get()
		if value2 != value {
			return dst.Set(value2)
		}
	}

	switch value := src.(type) {
	case time.Time:
		*dst = Timestamp{Time: time.Date(value.Year(), value.Month(), value.Day(), value.Hour(), value.Minute(), value.Second(), value.Nanosecond(), time.UTC), Status: Present}
	case *time.Time:
		if value == nil {
			*dst = Timestamp{Status: Null}
		} else {
			return dst.Set(*value)
		}
	case InfinityModifier:
		*dst = Timestamp{InfinityModifier: value, Status: Present}
	default:
		if originalSrc, ok := underlyingTimeType(src); ok {
			return dst.Set(originalSrc)
		}
		return fmt.Errorf("cannot convert %v to Timestamp", value)
	}

	return nil
}

func (dst Timestamp) Get() interface{} {
	switch dst.Status {
	case Present:
		if dst.InfinityModifier != None {
			return dst.InfinityModifier
		}
		return dst.Time
	case Null:
		return nil
	default:
		return dst.Status
	}
}

func (src *Timestamp) AssignTo(dst interface{}) error {
	switch src.Status {
	case Present:
		switch v := dst.(type) {
		case *time.Time:
			if src.InfinityModifier != None {
				return fmt.Errorf("cannot assign %v to %T", src, dst)
			}
			*v = src.Time
			return nil
		default:
			if nextDst, retry := GetAssignToDstType(dst); retry {
				return src.AssignTo(nextDst)
			}
			return fmt.Errorf("unable to assign to %T", dst)
		}
	case Null:
		return NullAssignTo(dst)
	}

	return fmt.Errorf("cannot decode %#v into %T", src, dst)
}

// DecodeText decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeText(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	sbuf := string(src)
	switch sbuf {
	case "infinity":
		*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
	case "-infinity":
		*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
	default:
		tim, err := time.Parse(pgTimestampFormat, sbuf)
		if err != nil {
			return err
		}

		*dst = Timestamp{Time: tim, Status: Present}
	}

	return nil
}

// DecodeBinary decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeBinary(ci *ConnInfo, src []byte) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	if len(src) != 8 {
		return fmt.Errorf("invalid length for timestamp: %v", len(src))
	}

	microsecSinceY2K := int64(binary.BigEndian.Uint64(src))

	switch microsecSinceY2K {
	case infinityMicrosecondOffset:
		*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
	case negativeInfinityMicrosecondOffset:
		*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
	default:
		tim := time.Unix(
			microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000,
			(microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000),
		).UTC()
		*dst = Timestamp{Time: tim, Status: Present}
	}

	return nil
}

// EncodeText writes the text encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
	switch src.Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}
	if src.Time.Location() != time.UTC {
		return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
	}

	var s string

	switch src.InfinityModifier {
	case None:
		s = src.Time.Truncate(time.Microsecond).Format(pgTimestampFormat)
	case Infinity:
		s = "infinity"
	case NegativeInfinity:
		s = "-infinity"
	}

	return append(buf, s...), nil
}

// EncodeBinary writes the binary encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
	switch src.Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}
	if src.Time.Location() != time.UTC {
		return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
	}

	var microsecSinceY2K int64
	switch src.InfinityModifier {
	case None:
		microsecSinceUnixEpoch := src.Time.Unix()*1000000 + int64(src.Time.Nanosecond())/1000
		microsecSinceY2K = microsecSinceUnixEpoch - microsecFromUnixEpochToY2K
	case Infinity:
		microsecSinceY2K = infinityMicrosecondOffset
	case NegativeInfinity:
		microsecSinceY2K = negativeInfinityMicrosecondOffset
	}

	return pgio.AppendInt64(buf, microsecSinceY2K), nil
}

// Scan implements the database/sql Scanner interface.
func (dst *Timestamp) Scan(src interface{}) error {
	if src == nil {
		*dst = Timestamp{Status: Null}
		return nil
	}

	switch src := src.(type) {
	case string:
		return dst.DecodeText(nil, []byte(src))
	case []byte:
		srcCopy := make([]byte, len(src))
		copy(srcCopy, src)
		return dst.DecodeText(nil, srcCopy)
	case time.Time:
		*dst = Timestamp{Time: src, Status: Present}
		return nil
	}

	return fmt.Errorf("cannot scan %T", src)
}

// Value implements the database/sql/driver Valuer interface.
func (src Timestamp) Value() (driver.Value, error) {
	switch src.Status {
	case Present:
		if src.InfinityModifier != None {
			return src.InfinityModifier.String(), nil
		}
		return src.Time, nil
	case Null:
		return nil, nil
	default:
		return nil, errUndefined
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strconv"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/glacier"
)

// partSize the size of each part of the multipart upload except the last, in
// bytes. The last part can be smaller than this part size.
const partSize int64 = 4096 // 4 MB will limit the archive in 40GB

func main() {
	archive, err := buildArchive(os.Getenv("TOGLACIER_PATH"))
	if err != nil {
		log.Fatal(err)
	}
	defer archive.Close()

	archiveID, location, err := sendArchive(archive, os.Getenv("AWS_ACCOUNT_ID"), os.Getenv("AWS_REGION"), os.Getenv("AWS_VAULT_NAME"))
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Archive ID: %s", archiveID)
	log.Printf("Location: %s", location)
}

func buildArchive(backupPath string) (*os.File, error) {
	tarFile, err := ioutil.TempFile("", "toglacier-")
	if err != nil {
		return nil, fmt.Errorf("error creating the tar file. details: %s", err)
	}

	tarArchive := tar.NewWriter(tarFile)

	if err := buildArchiveLevels(tarArchive, backupPath); err != nil {
		tarFile.Close()
		return nil, err
	}

	if err := tarArchive.Close(); err != nil {
		tarFile.Close()
		return nil, fmt.Errorf("error generating tar file. details: %s", err)
	}

	return tarFile, nil
}

func buildArchiveLevels(tarArchive *tar.Writer, pathLevel string) error {
	files, err := ioutil.ReadDir(pathLevel)
	if err != nil {
		return fmt.Errorf("error reading path “%s”. details: %s", pathLevel, err)
	}

	for _, file := range files {
		if file.IsDir() {
			buildArchiveLevels(tarArchive, path.Join(pathLevel, file.Name()))
			continue
		}

		tarHeader := tar.Header{
			Name: file.Name(),
			Mode: 0600,
			Size: file.Size(),
		}

		if err := tarArchive.WriteHeader(&tarHeader); err != nil {
			return fmt.Errorf("error writing header in tar for file %s. details: %s", file.Name(), err)
		}

		filename := path.Join(pathLevel, file.Name())

		fd, err := os.Open(filename)
		if err != nil {
			return fmt.Errorf("error opening file %s. details: %s", filename, err)
		}

		if n, err := io.Copy(tarArchive, fd); err != nil {
			return fmt.Errorf("error writing content in tar for file %s. details: %s", filename, err)

		} else if n != file.Size() {
			return fmt.Errorf("wrong number of bytes writen in file %s", filename)
		}

		if err := fd.Close(); err != nil {
			return fmt.Errorf("error closing file %s. details: %s", filename, err)
		}
	}

	return nil
}

func sendArchive(archive *os.File, awsAccountID, awsRegion, awsVaultName string) (archiveID, location string, err error) {
	archiveInfo, err := archive.Stat()
	if err != nil {
		return "", "", fmt.Errorf("error retrieving archive information. details: %s", err)
	}

	if archiveInfo.Size() <= 1024100 {
		return sendSmallArchive(archive, awsAccountID, awsRegion, awsVaultName)
	}

	return sendBigArchive(archive, archiveInfo.Size(), awsAccountID, awsRegion, awsVaultName)
}

func sendSmallArchive(archive *os.File, awsAccountID, awsRegion, awsVaultName string) (archiveID, location string, err error) {
	// ComputeHashes already rewind the file seek at the beginning and at the end
	// of the function, so we don't need to wore about it
	hash := glacier.ComputeHashes(archive)

	awsArchive := glacier.UploadArchiveInput{
		AccountId:          aws.String(awsAccountID),
		ArchiveDescription: aws.String(fmt.Sprintf("backup file from %s", time.Now().Format(time.RFC3339))),
		Body:               archive,
		Checksum:           aws.String(hex.EncodeToString(hash.TreeHash)),
		VaultName:          aws.String(awsVaultName),
	}

	awsSession, err := session.NewSession()
	if err != nil {
		return "", "", fmt.Errorf("error creating aws session. details: %s", err)
	}

	awsGlacier := glacier.New(awsSession, &aws.Config{
		Region: aws.String(awsRegion),
	})

	// Uncomment the line bellow to understand what is going on
	//awsGlacier.Config.WithLogLevel(aws.LogDebugWithHTTPBody | aws.LogDebugWithRequestErrors | aws.LogDebugWithRequestRetries | aws.LogDebugWithSigning)

	response, err := awsGlacier.UploadArchive(&awsArchive)
	if err != nil {
		return "", "", fmt.Errorf("error sending archive to aws glacier. details: %s", err)
	}

	return *response.ArchiveId, *response.Location, nil
}

func sendBigArchive(archive *os.File, archiveSize int64, awsAccountID, awsRegion, awsVaultName string) (archiveID, location string, err error) {
	awsSession, err := session.NewSession()
	if err != nil {
		return "", "", fmt.Errorf("error creating aws session. details: %s", err)
	}

	awsGlacier := glacier.New(awsSession, &aws.Config{
		Region: aws.String(awsRegion),
	})

	// Uncomment the line bellow to understand what is going on
	//awsGlacier.Config.WithLogLevel(aws.LogDebugWithHTTPBody | aws.LogDebugWithRequestErrors | aws.LogDebugWithRequestRetries | aws.LogDebugWithSigning)

	awsInitiate := glacier.InitiateMultipartUploadInput{
		AccountId:          aws.String(awsAccountID),
		ArchiveDescription: aws.String(fmt.Sprintf("backup file from %s", time.Now().Format(time.RFC3339))),
		PartSize:           aws.String(strconv.FormatInt(partSize, 10)),
		VaultName:          aws.String(awsVaultName),
	}

	awsInitiateResponse, err := awsGlacier.InitiateMultipartUpload(&awsInitiate)
	if err != nil {
		return "", "", fmt.Errorf("error initializing multipart upload. details: %s", err)
	}

	var offset int64
	var part = make([]byte, partSize)

	for offset = 0; offset < archiveSize; offset += partSize {
		n, err := archive.Read(part)
		if err != nil {
			return "", "", fmt.Errorf("error reading an archive part (%d). details: %s", offset, err)
		}

		body := bytes.NewReader(part[:n])
		hash := glacier.ComputeHashes(body)

		awsArchivePart := glacier.UploadMultipartPartInput{
			AccountId: aws.String(awsAccountID),
			Body:      body,
			Checksum:  aws.String(hex.EncodeToString(hash.TreeHash)),
			Range:     aws.String(fmt.Sprintf("%d-%d/%d", offset, offset+int64(n), archiveSize)),
			UploadId:  awsInitiateResponse.UploadId,
			VaultName: aws.String(awsVaultName),
		}

		if _, err := awsGlacier.UploadMultipartPart(&awsArchivePart); err != nil {
			return "", "", fmt.Errorf("error sending an archive part (%d). details: %s", offset, err)
		}
	}

	// ComputeHashes already rewind the file seek at the beginning and at the end
	// of the function, so we don't need to wore about it
	hash := glacier.ComputeHashes(archive)

	awsComplete := glacier.CompleteMultipartUploadInput{
		AccountId:   aws.String(awsAccountID),
		ArchiveSize: aws.String(strconv.FormatInt(archiveSize, 10)),
		Checksum:    aws.String(hex.EncodeToString(hash.TreeHash)),
		UploadId:    awsInitiateResponse.UploadId,
		VaultName:   aws.String(awsVaultName),
	}

	awsCompleteResponse, err := awsGlacier.CompleteMultipartUpload(&awsComplete)
	if err != nil {
		return "", "", fmt.Errorf("error completing multipart upload. details: %s", err)
	}

	return *awsCompleteResponse.ArchiveId, *awsCompleteResponse.Location, nil
}
<commit_msg>Remove AWS_REGION reference.<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strconv"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/glacier"
)

// partSize the size of each part of the multipart upload except the last, in
// bytes. The last part can be smaller than this part size.
const partSize int64 = 4096 // 4 MB will limit the archive in 40GB

func main() {
	archive, err := buildArchive(os.Getenv("TOGLACIER_PATH"))
	if err != nil {
		log.Fatal(err)
	}
	defer archive.Close()

	archiveID, location, err := sendArchive(archive, os.Getenv("AWS_ACCOUNT_ID"), os.Getenv("AWS_VAULT_NAME"))
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Archive ID: %s", archiveID)
	log.Printf("Location: %s", location)
}

func buildArchive(backupPath string) (*os.File, error) {
	tarFile, err := ioutil.TempFile("", "toglacier-")
	if err != nil {
		return nil, fmt.Errorf("error creating the tar file. details: %s", err)
	}

	tarArchive := tar.NewWriter(tarFile)

	if err := buildArchiveLevels(tarArchive, backupPath); err != nil {
		tarFile.Close()
		return nil, err
	}

	if err := tarArchive.Close(); err != nil {
		tarFile.Close()
		return nil, fmt.Errorf("error generating tar file. details: %s", err)
	}

	return tarFile, nil
}

func buildArchiveLevels(tarArchive *tar.Writer, pathLevel string) error {
	files, err := ioutil.ReadDir(pathLevel)
	if err != nil {
		return fmt.Errorf("error reading path “%s”. details: %s", pathLevel, err)
	}

	for _, file := range files {
		if file.IsDir() {
			buildArchiveLevels(tarArchive, path.Join(pathLevel, file.Name()))
			continue
		}

		tarHeader := tar.Header{
			Name: file.Name(),
			Mode: 0600,
			Size: file.Size(),
		}

		if err := tarArchive.WriteHeader(&tarHeader); err != nil {
			return fmt.Errorf("error writing header in tar for file %s. details: %s", file.Name(), err)
		}

		filename := path.Join(pathLevel, file.Name())

		fd, err := os.Open(filename)
		if err != nil {
			return fmt.Errorf("error opening file %s. details: %s", filename, err)
		}

		if n, err := io.Copy(tarArchive, fd); err != nil {
			return fmt.Errorf("error writing content in tar for file %s. details: %s", filename, err)

		} else if n != file.Size() {
			return fmt.Errorf("wrong number of bytes writen in file %s", filename)
		}

		if err := fd.Close(); err != nil {
			return fmt.Errorf("error closing file %s. details: %s", filename, err)
		}
	}

	return nil
}

func sendArchive(archive *os.File, awsAccountID, awsVaultName string) (archiveID, location string, err error) {
	archiveInfo, err := archive.Stat()
	if err != nil {
		return "", "", fmt.Errorf("error retrieving archive information. details: %s", err)
	}

	if archiveInfo.Size() <= 1024100 {
		return sendSmallArchive(archive, awsAccountID, awsVaultName)
	}

	return sendBigArchive(archive, archiveInfo.Size(), awsAccountID, awsVaultName)
}

func sendSmallArchive(archive *os.File, awsAccountID, awsVaultName string) (archiveID, location string, err error) {
	// ComputeHashes already rewind the file seek at the beginning and at the end
	// of the function, so we don't need to wore about it
	hash := glacier.ComputeHashes(archive)

	awsArchive := glacier.UploadArchiveInput{
		AccountId:          aws.String(awsAccountID),
		ArchiveDescription: aws.String(fmt.Sprintf("backup file from %s", time.Now().Format(time.RFC3339))),
		Body:               archive,
		Checksum:           aws.String(hex.EncodeToString(hash.TreeHash)),
		VaultName:          aws.String(awsVaultName),
	}

	awsSession, err := session.NewSession()
	if err != nil {
		return "", "", fmt.Errorf("error creating aws session. details: %s", err)
	}

	awsGlacier := glacier.New(awsSession)

	// Uncomment the line bellow to understand what is going on
	//awsGlacier.Config.WithLogLevel(aws.LogDebugWithHTTPBody | aws.LogDebugWithRequestErrors | aws.LogDebugWithRequestRetries | aws.LogDebugWithSigning)

	response, err := awsGlacier.UploadArchive(&awsArchive)
	if err != nil {
		return "", "", fmt.Errorf("error sending archive to aws glacier. details: %s", err)
	}

	return *response.ArchiveId, *response.Location, nil
}

func sendBigArchive(archive *os.File, archiveSize int64, awsAccountID, awsVaultName string) (archiveID, location string, err error) {
	awsSession, err := session.NewSession()
	if err != nil {
		return "", "", fmt.Errorf("error creating aws session. details: %s", err)
	}

	awsGlacier := glacier.New(awsSession)

	// Uncomment the line bellow to understand what is going on
	//awsGlacier.Config.WithLogLevel(aws.LogDebugWithHTTPBody | aws.LogDebugWithRequestErrors | aws.LogDebugWithRequestRetries | aws.LogDebugWithSigning)

	awsInitiate := glacier.InitiateMultipartUploadInput{
		AccountId:          aws.String(awsAccountID),
		ArchiveDescription: aws.String(fmt.Sprintf("backup file from %s", time.Now().Format(time.RFC3339))),
		PartSize:           aws.String(strconv.FormatInt(partSize, 10)),
		VaultName:          aws.String(awsVaultName),
	}

	awsInitiateResponse, err := awsGlacier.InitiateMultipartUpload(&awsInitiate)
	if err != nil {
		return "", "", fmt.Errorf("error initializing multipart upload. details: %s", err)
	}

	var offset int64
	var part = make([]byte, partSize)

	for offset = 0; offset < archiveSize; offset += partSize {
		n, err := archive.Read(part)
		if err != nil {
			return "", "", fmt.Errorf("error reading an archive part (%d). details: %s", offset, err)
		}

		body := bytes.NewReader(part[:n])
		hash := glacier.ComputeHashes(body)

		awsArchivePart := glacier.UploadMultipartPartInput{
			AccountId: aws.String(awsAccountID),
			Body:      body,
			Checksum:  aws.String(hex.EncodeToString(hash.TreeHash)),
			Range:     aws.String(fmt.Sprintf("%d-%d/%d", offset, offset+int64(n), archiveSize)),
			UploadId:  awsInitiateResponse.UploadId,
			VaultName: aws.String(awsVaultName),
		}

		if _, err := awsGlacier.UploadMultipartPart(&awsArchivePart); err != nil {
			return "", "", fmt.Errorf("error sending an archive part (%d). details: %s", offset, err)
		}
	}

	// ComputeHashes already rewind the file seek at the beginning and at the end
	// of the function, so we don't need to wore about it
	hash := glacier.ComputeHashes(archive)

	awsComplete := glacier.CompleteMultipartUploadInput{
		AccountId:   aws.String(awsAccountID),
		ArchiveSize: aws.String(strconv.FormatInt(archiveSize, 10)),
		Checksum:    aws.String(hex.EncodeToString(hash.TreeHash)),
		UploadId:    awsInitiateResponse.UploadId,
		VaultName:   aws.String(awsVaultName),
	}

	awsCompleteResponse, err := awsGlacier.CompleteMultipartUpload(&awsComplete)
	if err != nil {
		return "", "", fmt.Errorf("error completing multipart upload. details: %s", err)
	}

	return *awsCompleteResponse.ArchiveId, *awsCompleteResponse.Location, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/termie/go-shutil"
)

func start(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/startup.sh")
	return cmd.Run()
}

func stop(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/shutdown.sh")
	return cmd.Run()
}

func restart(path string) {
	err := stop(path)
	if err != nil {
		fmt.Println("TomEE isn't started...")
	}

	fmt.Printf("Starting server..")
	err = start(path)
	if err != nil {
		fmt.Println("Error during start")
		return
	}

	fmt.Println("TomEE started")
}

func deploy(tomeePath, packageForDeploy string) error {

	_, packageName := path.Split(packageForDeploy)
	deployPath := tomeePath + "/webapps/"
	if strings.HasSuffix(packageForDeploy, ".ear") {
		deployPath = tomeePath + "/apps/"
	}

	err := shutil.CopyFile(packageForDeploy, deployPath+packageName, true)
	if err != nil {
		return err
	}

	return nil
}

func createCommands() []cli.Command {

	pathFlag := cli.StringFlag{
		Name:   "path",
		Usage:  "path of the TomEE server. Default value: $TOMEE_HOME",
		EnvVar: "TOMEE_HOME",
	}

	startCommand := cli.Command{
		Name:  "start",
		Usage: "start the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			start(c.String("path"))
		},
	}

	stopCommand := cli.Command{
		Name:  "stop",
		Usage: "stop the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			stop(c.String("path"))
		},
	}

	restartCommand := cli.Command{
		Name:  "restart",
		Usage: "restart the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			restart(c.String("path"))
		},
	}

	deployCommand := cli.Command{
		Name:  "deploy",
		Usage: "deploy war/ear in TomEE",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			err := deploy(c.String("path"), c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Deployed in: " + c.String("path"))
		},
	}

	return []cli.Command{startCommand, stopCommand, restartCommand, deployCommand}
}

func main() {
	app := cli.NewApp()
	app.Name = "tomee-cli"
	app.Version = "1.0.0"
	app.Commands = createCommands()
	app.Run(os.Args)
}
<commit_msg>Fixed ear deploy<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"

	"github.com/codegangsta/cli"
	"github.com/termie/go-shutil"
)

func start(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/startup.sh")
	return cmd.Run()
}

func stop(path string) error {
	cmd := exec.Command("sh", "-c", path+"/bin/shutdown.sh")
	return cmd.Run()
}

func restart(path string) {
	err := stop(path)
	if err != nil {
		fmt.Println("TomEE isn't started...")
	}

	fmt.Printf("Starting server..")
	err = start(path)
	if err != nil {
		fmt.Println("Error during start")
		return
	}

	fmt.Println("TomEE started")
}

func deploy(tomeePath, packageForDeploy string) error {

	_, packageName := path.Split(packageForDeploy)
	deployPath := tomeePath + "/webapps/"
	if strings.HasSuffix(packageForDeploy, ".ear") {
		deployPath = tomeePath + "/apps/"
		os.Mkdir(deployPath, 0744)
	}

	err := shutil.CopyFile(packageForDeploy, deployPath+packageName, true)
	if err != nil {
		return err
	}

	return nil
}

func createCommands() []cli.Command {

	pathFlag := cli.StringFlag{
		Name:   "path",
		Usage:  "path of the TomEE server. Default value: $TOMEE_HOME",
		EnvVar: "TOMEE_HOME",
	}

	startCommand := cli.Command{
		Name:  "start",
		Usage: "start the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			start(c.String("path"))
		},
	}

	stopCommand := cli.Command{
		Name:  "stop",
		Usage: "stop the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			stop(c.String("path"))
		},
	}

	restartCommand := cli.Command{
		Name:  "restart",
		Usage: "restart the TomEE server",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			restart(c.String("path"))
		},
	}

	deployCommand := cli.Command{
		Name:  "deploy",
		Usage: "deploy war/ear in TomEE",
		Flags: []cli.Flag{pathFlag},
		Action: func(c *cli.Context) {
			err := deploy(c.String("path"), c.Args().First())
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Deployed in: " + c.String("path"))
		},
	}

	return []cli.Command{startCommand, stopCommand, restartCommand, deployCommand}
}

func main() {
	app := cli.NewApp()
	app.Name = "tomee-cli"
	app.Version = "1.0.0"
	app.Commands = createCommands()
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/libswarm/beam"
	"github.com/docker/libswarm/beam/inmem"
	beamutils "github.com/docker/libswarm/beam/utils"
	"github.com/docker/libswarm/backends"
	_ "github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"strings"
	"sync"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func EngineAsSender(eng *engine.Engine) beam.Sender {
	r, w := inmem.Pipe()
	go func() {
		for {
			msg, msgr, msgw, err := r.Receive(beam.R | beam.W)
			if err != nil {
				return
			}
			go func(msg *beam.Message, in beam.Receiver, out beam.Sender) {
				job := eng.Job(msg.Name, msg.Args...)
				stdout, _ := job.Stdout.AddPipe() // can't fail
				stderr, _ := job.Stderr.AddPipe() // can't fail
				stdinR, stdinW := io.Pipe()
				defer stdinR.Close()
				defer stdinW.Close()
				job.Stdin.Add(stdinR)
				log := func(src io.Reader) {
					scanner := bufio.NewScanner(src)
					for scanner.Scan() {
						if scanner.Err() != nil {
							return
						}
						if _, _, err := out.Send(&beam.Message{Name: "log", Args: []string{scanner.Text()}}, 0); err != nil {
							return
						}
					}
				}
				var tasks sync.WaitGroup
				tasks.Add(3)
				go func() {
					// Read from stdout, send "log" events
					defer tasks.Done()
					log(stdout)
				}()
				go func() {
					// Read from stderr, send "log" events
					// FIXME: how to differentiate stderr/stdout logs?
					defer tasks.Done()
					log(stderr)
				}()
				go func() {
					// Receive events, send "log" events to stdin
					defer tasks.Done()
					for {
						m, _, _, err := in.Receive(0)
						if err != nil {
							return
						}
						if m.Name == "log" {
							if len(m.Args) < 1 {
								continue
							}
							fmt.Fprintf(stdinW, "%s\n", strings.TrimRight(m.Args[0], "\r\n"))
						}
					}
				}()
				err := job.Run()
				if err != nil {
					out.Send(&beam.Message{Name: "error", Args: []string{err.Error()}}, 0)
				}
			}(msg, msgr, msgw)
		}
	}()
	return w
}

func SenderAsEngine(s beam.Sender) *engine.Engine {
	eng := engine.New()
	eng.RegisterCatchall(func(job *engine.Job) engine.Status {
		msg := &beam.Message{
			Name: job.Name,
			Args: job.Args,
		}
		// FIXME: serialize job.Env into a trailing argument
		r, w, err := s.Send(msg, beam.R|beam.W)
		if err != nil {
			return job.Errorf("beam send: %v", err)
		}
		var tasks sync.WaitGroup
		tasks.Add(1)
		go func() {
			defer tasks.Done()
			in := bufio.NewScanner(job.Stdin)
			for in.Scan() {
				_, _, err := w.Send(&beam.Message{Name: "log", Args: []string{in.Text()}}, 0)
				if err != nil {
					return
				}
			}
		}()
		tasks.Add(1)
		var status engine.Status = engine.StatusOK
		go func() {
			defer tasks.Done()
			for {
				msg, _, _, err := r.Receive(0)
				if err != nil {
					return
				}
				if msg.Name == "log" {
					if len(msg.Args) < 1 {
						continue
					}
					fmt.Fprintf(job.Stdout, "%s\n", strings.TrimRight(msg.Args[0], "\r\n"))
				} else if msg.Name == "error" {
					status = engine.StatusErr
					if len(msg.Args) < 1 {
						continue
					}
					fmt.Fprintf(job.Stderr, "%s\n", strings.TrimRight(msg.Args[0], "\r\n"))
				}
			}
		}()
		tasks.Wait()
		return status
	})
	return eng
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	hub := beamutils.NewHub()
	back := backends.New()
	// Load backends
	for _, cmd := range c.Args() {
		bName, bArgs, err := parseCmd(cmd)
		if err != nil {
			Fatalf("%v", err)
		}
		fmt.Printf("---> Loading backend '%s'\n", strings.Join(append([]string{bName}, bArgs...), " "))
		backendr, _, err := back.Send(&beam.Message{Name: "cd", Args: []string{bName}}, beam.R)
		if err != nil {
			Fatalf("%s: %v\n", bName, err)
		}
		// backendr will return either 'error' or 'register'.
		for {
			m, mr, mw, err := backendr.Receive(beam.R|beam.W)
			if err == io.EOF {
				break
			}
			if err != nil {
				Fatalf("%v", err)
			}
			if m.Name == "error" {
				Fatalf("%v", strings.Join(m.Args, " "))
			}
			if m.Name == "register" {
				// FIXME: adapt the beam interface to allow the caller to
				// (optionally) pass their own Sender/Receiver?
				// Would make proxying/splicing easier.
				hubr, hubw, err := hub.Send(m, beam.R|beam.W)
				if err != nil {
					Fatalf("%v", err)
				}
				fmt.Printf("successfully registered\n")
				go beamutils.Copy(hubw, mr)
				go beamutils.Copy(mw, hubr)
			}
		}
	}
	in, _, err := hub.Send(&beam.Message{Name: "start"}, beam.R)
	if err != nil {
		Fatalf("%v", err)
	}
	for {
		msg, _, _, err := in.Receive(0)
		if err == io.EOF {
			break
		}
		if err != nil {
			Fatalf("%v", err)
		}
		fmt.Printf("--> %s %s\n", msg.Name, strings.Join(msg.Args, " "))
	}
}

func parseCmd(txt string) (string, []string, error) {
	l, err := shlex.NewLexer(strings.NewReader(txt))
	if err != nil {
		return "", nil, err
	}
	var cmd []string
	for {
		word, err := l.NextWord()
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", nil, err
		}
		cmd = append(cmd, word)
	}
	if len(cmd) == 0 {
		return "", nil, fmt.Errorf("parse error: empty command")
	}
	return cmd[0], cmd[1:], nil
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<commit_msg>swarmd: more informative error messages<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/docker/libswarm/beam"
	"github.com/docker/libswarm/beam/inmem"
	beamutils "github.com/docker/libswarm/beam/utils"
	"github.com/docker/libswarm/backends"
	_ "github.com/dotcloud/docker/api/server"
	"github.com/dotcloud/docker/engine"
	"github.com/flynn/go-shlex"
	"io"
	"os"
	"strings"
	"sync"
)

func main() {
	app := cli.NewApp()
	app.Name = "swarmd"
	app.Usage = "Control a heterogenous distributed system with the Docker API"
	app.Version = "0.0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{"backend", "debug", "load a backend"},
	}
	app.Action = cmdDaemon
	app.Run(os.Args)
}

func EngineAsSender(eng *engine.Engine) beam.Sender {
	r, w := inmem.Pipe()
	go func() {
		for {
			msg, msgr, msgw, err := r.Receive(beam.R | beam.W)
			if err != nil {
				return
			}
			go func(msg *beam.Message, in beam.Receiver, out beam.Sender) {
				job := eng.Job(msg.Name, msg.Args...)
				stdout, _ := job.Stdout.AddPipe() // can't fail
				stderr, _ := job.Stderr.AddPipe() // can't fail
				stdinR, stdinW := io.Pipe()
				defer stdinR.Close()
				defer stdinW.Close()
				job.Stdin.Add(stdinR)
				log := func(src io.Reader) {
					scanner := bufio.NewScanner(src)
					for scanner.Scan() {
						if scanner.Err() != nil {
							return
						}
						if _, _, err := out.Send(&beam.Message{Name: "log", Args: []string{scanner.Text()}}, 0); err != nil {
							return
						}
					}
				}
				var tasks sync.WaitGroup
				tasks.Add(3)
				go func() {
					// Read from stdout, send "log" events
					defer tasks.Done()
					log(stdout)
				}()
				go func() {
					// Read from stderr, send "log" events
					// FIXME: how to differentiate stderr/stdout logs?
					defer tasks.Done()
					log(stderr)
				}()
				go func() {
					// Receive events, send "log" events to stdin
					defer tasks.Done()
					for {
						m, _, _, err := in.Receive(0)
						if err != nil {
							return
						}
						if m.Name == "log" {
							if len(m.Args) < 1 {
								continue
							}
							fmt.Fprintf(stdinW, "%s\n", strings.TrimRight(m.Args[0], "\r\n"))
						}
					}
				}()
				err := job.Run()
				if err != nil {
					out.Send(&beam.Message{Name: "error", Args: []string{err.Error()}}, 0)
				}
			}(msg, msgr, msgw)
		}
	}()
	return w
}

func SenderAsEngine(s beam.Sender) *engine.Engine {
	eng := engine.New()
	eng.RegisterCatchall(func(job *engine.Job) engine.Status {
		msg := &beam.Message{
			Name: job.Name,
			Args: job.Args,
		}
		// FIXME: serialize job.Env into a trailing argument
		r, w, err := s.Send(msg, beam.R|beam.W)
		if err != nil {
			return job.Errorf("beam send: %v", err)
		}
		var tasks sync.WaitGroup
		tasks.Add(1)
		go func() {
			defer tasks.Done()
			in := bufio.NewScanner(job.Stdin)
			for in.Scan() {
				_, _, err := w.Send(&beam.Message{Name: "log", Args: []string{in.Text()}}, 0)
				if err != nil {
					return
				}
			}
		}()
		tasks.Add(1)
		var status engine.Status = engine.StatusOK
		go func() {
			defer tasks.Done()
			for {
				msg, _, _, err := r.Receive(0)
				if err != nil {
					return
				}
				if msg.Name == "log" {
					if len(msg.Args) < 1 {
						continue
					}
					fmt.Fprintf(job.Stdout, "%s\n", strings.TrimRight(msg.Args[0], "\r\n"))
				} else if msg.Name == "error" {
					status = engine.StatusErr
					if len(msg.Args) < 1 {
						continue
					}
					fmt.Fprintf(job.Stderr, "%s\n", strings.TrimRight(msg.Args[0], "\r\n"))
				}
			}
		}()
		tasks.Wait()
		return status
	})
	return eng
}

func cmdDaemon(c *cli.Context) {
	if len(c.Args()) == 0 {
		Fatalf("Usage: %s <proto>://<address> [<proto>://<address>]...\n", c.App.Name)
	}

	hub := beamutils.NewHub()
	back := backends.New()
	// Load backends
	for _, cmd := range c.Args() {
		bName, bArgs, err := parseCmd(cmd)
		if err != nil {
			Fatalf("%v", err)
		}
		fmt.Printf("---> Loading backend '%s'\n", strings.Join(append([]string{bName}, bArgs...), " "))
		backendr, _, err := back.Send(&beam.Message{Name: "cd", Args: []string{bName}}, beam.R)
		if err != nil {
			Fatalf("%s: %v\n", bName, err)
		}
		// backendr will return either 'error' or 'register'.
		for {
			m, mr, mw, err := backendr.Receive(beam.R|beam.W)
			if err == io.EOF {
				break
			}
			if err != nil {
				Fatalf("error reading from backend: %v", err)
			}
			if m.Name == "error" {
				Fatalf("backend sent error: %v", strings.Join(m.Args, " "))
			}
			if m.Name == "register" {
				// FIXME: adapt the beam interface to allow the caller to
				// (optionally) pass their own Sender/Receiver?
				// Would make proxying/splicing easier.
				hubr, hubw, err := hub.Send(m, beam.R|beam.W)
				if err != nil {
					Fatalf("error binding backend to hub: %v", err)
				}
				fmt.Printf("successfully registered\n")
				go beamutils.Copy(hubw, mr)
				go beamutils.Copy(mw, hubr)
			}
		}
	}
	in, _, err := hub.Send(&beam.Message{Name: "start"}, beam.R)
	if err != nil {
		Fatalf("%v", err)
	}
	for {
		msg, _, _, err := in.Receive(0)
		if err == io.EOF {
			break
		}
		if err != nil {
			Fatalf("%v", err)
		}
		fmt.Printf("--> %s %s\n", msg.Name, strings.Join(msg.Args, " "))
	}
}

func parseCmd(txt string) (string, []string, error) {
	l, err := shlex.NewLexer(strings.NewReader(txt))
	if err != nil {
		return "", nil, err
	}
	var cmd []string
	for {
		word, err := l.NextWord()
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", nil, err
		}
		cmd = append(cmd, word)
	}
	if len(cmd) == 0 {
		return "", nil, fmt.Errorf("parse error: empty command")
	}
	return cmd[0], cmd[1:], nil
}

func Fatalf(msg string, args ...interface{}) {
	if !strings.HasSuffix(msg, "\n") {
		msg = msg + "\n"
	}
	fmt.Fprintf(os.Stderr, msg, args...)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package syntax

import (
	"regexp"
	"unicode/utf8"

	"github.com/kybin/tor/cell"
	term "github.com/nsf/termbox-go"
)

var Languages = make(map[string]*Language)

func init() {
	golang := NewLanguage()
	golang.AddSyntax(Syntax{"string", regexp.MustCompile(`^(?m)".*?(?:[^\\]?"|$)`)}, Color{term.ColorRed, term.ColorBlack})
	golang.AddSyntax(Syntax{"raw string", regexp.MustCompile(`^(?s)` + "`" + `.*?` + "(?:`|$)")}, Color{term.ColorRed, term.ColorBlack})
	golang.AddSyntax(Syntax{"rune", regexp.MustCompile(`^(?m)'.*?(?:[^\\]?'|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	golang.AddSyntax(Syntax{"comment", regexp.MustCompile(`^(?m)//.*`)}, Color{term.ColorMagenta, term.ColorBlack})
	golang.AddSyntax(Syntax{"multi line comment", regexp.MustCompile(`^(?s)/[*].*?(?:[*]/|$)`)}, Color{term.ColorMagenta, term.ColorBlack})
	golang.AddSyntax(Syntax{"trailing spaces", regexp.MustCompile(`^(?m)[ \t]+$`)}, Color{term.ColorBlack, term.ColorYellow})
	golang.AddSyntax(Syntax{"package", regexp.MustCompile(`^package\s`)}, Color{term.ColorYellow, term.ColorBlack})
	Languages["go"] = golang

	py := NewLanguage()
	py.AddSyntax(Syntax{"multi line string1", regexp.MustCompile(`^(?s)""".*?(?:"""|$)`)}, Color{term.ColorRed, term.ColorBlack})
	py.AddSyntax(Syntax{"multi line string2", regexp.MustCompile(`^(?s)'''.*?(?:'''|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	py.AddSyntax(Syntax{"string1", regexp.MustCompile(`^(?m)".*?(?:[^\\]?"|$)`)}, Color{term.ColorRed, term.ColorBlack})
	py.AddSyntax(Syntax{"string2", regexp.MustCompile(`^(?m)'.*?(?:[^\\]?'|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	py.AddSyntax(Syntax{"comment", regexp.MustCompile(`^(?m)#.*`)}, Color{term.ColorMagenta, term.ColorBlack})
	py.AddSyntax(Syntax{"trailing spaces", regexp.MustCompile(`^(?m)[ \t]+$`)}, Color{term.ColorBlack, term.ColorYellow})
	Languages["py"] = py
}

// Byter could converted to []bytes.
type Byter interface {
	Bytes() []byte
}

// Parser is syntax parser.
type Parser struct {
	text        Byter
	textChanged bool
	lang        *Language
	Matches     []Match
}

// NewParser creates a new Parser.
func NewParser(text Byter, langName string) *Parser {
	p := &Parser{}
	lang, ok := Languages[langName]
	if ok {
		p.lang = lang
	}
	p.SetText(text)
	return p
}

// SetText set it's text.
// After doing this, it should re-Parse-d entirely.
// Until then, TextChanged will return true.
func (p *Parser) SetText(text Byter) {
	p.text = text
	p.textChanged = true
}

// TextChanged returns status whether
// it's text changed but not Parsed yet.
func (p *Parser) TextChanged() bool {
	return p.textChanged
}

// Parse calculates it's matches entirely.
func (p *Parser) Parse() {
	if p.lang != nil {
		p.Matches = p.lang.Parse(p.text.Bytes())
	}
	p.textChanged = false
}

// Parse calulate it's partial matches.
// It will re-parse text from min to max range and
// replace current matches if there is an overwrap.
func (p *Parser) ParseRange(min, max cell.Pt) {
	if p.lang != nil {
		p.Matches = p.lang.ParseRange(p.Matches, p.text.Bytes(), min, max)
	}
}

// Color returns any match's syntax color name.
func (p *Parser) Color(synName string) Color {
	return p.lang.Color(synName)
}

type Syntax struct {
	Name string
	Re   *regexp.Regexp
}

func (s Syntax) NewMatch(start, end cell.Pt) Match {
	return Match{Name: s.Name, Range: cell.Range{start, end}}
}

type Color struct {
	Fg term.Attribute
	Bg term.Attribute
}

type Language struct {
	syntaxes []Syntax // should be ordered
	colors   map[string]Color
}

func NewLanguage() *Language {
	return &Language{
		syntaxes: []Syntax{},
		colors:   make(map[string]Color),
	}
}

func (l *Language) AddSyntax(s Syntax, c Color) {
	l.syntaxes = append(l.syntaxes, s)
	l.colors[s.Name] = c
}

func (l *Language) Color(synName string) Color {
	c, ok := l.colors[synName]
	if !ok {
		return Color{term.ColorWhite, term.ColorBlack}
	}
	return c
}

func (l *Language) Parse(text []byte) []Match {
	c := NewCursor(text)
	matches := []Match{}
Loop:
	for {
		for _, syn := range l.syntaxes {
			ms := syn.Re.FindSubmatch(c.Remain())
			if ms == nil {
				continue
			}
			m := ms[0]
			if len(ms) == 2 {
				m = ms[1]
			}
			if string(m) == "" {
				continue
			}
			start := c.Pos()
			c.Skip(len(m))
			end := c.Pos()
			matches = append(matches, syn.NewMatch(start, end))
			continue Loop
		}
		if !c.Advance() {
			break
		}
	}
	return matches
}

// ParseRange checks and replace matches from min to max.
// When there is an overwrap between old matches and min position,
// it will recaculate matches from the overwrap begins.
func (l *Language) ParseRange(matches []Match, text []byte, min, max cell.Pt) []Match {
	// check where parse acutally started.
	last := -1
	overwrap := false
	for i, m := range matches {
		if m.Range.Min().Compare(min) < 0 {
			if m.Range.Max().Compare(min) < 0 {
				continue
			}
			overwrap = true
			last = i
			break
		}
		last = i
		break
	}

	parseStart := min
	if last != -1 {
		if overwrap {
			parseStart = matches[last].Range.Min()
		}
		matches = matches[:last]
	}

	// move cursor to start position.
	c := NewCursor(text)
	for c.Pos().Compare(parseStart) < 0 {
		ok := c.Advance()
		if !ok {
			// already end of text. nothing to do.
			return matches
		}
	}

Loop:
	for {
		if c.Pos().Compare(max) >= 0 {
			break
		}
		for _, syn := range l.syntaxes {
			ms := syn.Re.FindSubmatch(c.Remain())
			if ms == nil {
				continue
			}
			m := ms[0]
			if len(ms) == 2 {
				m = ms[1]
			}
			if string(m) == "" {
				continue
			}
			start := c.Pos()
			c.Skip(len(m))
			end := c.Pos()
			matches = append(matches, syn.NewMatch(start, end))
			continue Loop
		}
		if !c.Advance() {
			break
		}
	}
	return matches
}

type Cursor struct {
	text []byte
	b    int // byte offset
	l    int // line offset
	o    int // byte in line offset
}

func NewCursor(text []byte) *Cursor {
	return &Cursor{text: text}
}

func (c *Cursor) Pos() cell.Pt {
	return cell.Pt{c.l, c.o}
}

func (c *Cursor) Remain() []byte {
	if c.l == len(c.text) {
		return []byte("")
	}
	return c.text[c.b:]
}

func (c *Cursor) Advance() bool {
	if c.b == len(c.text) {
		return false
	}
	c.next()
	return true
}

func (c *Cursor) Skip(b int) {
	i := 0
	for i < b {
		_, size := c.next()
		i += size
	}
}

func (c *Cursor) next() (r rune, size int) {
	r, size = utf8.DecodeRune(c.Remain())
	c.b += size
	c.o += size
	if r == '\n' {
		c.l += 1
		c.o = 0
	}
	return r, size
}

type Match struct {
	Name  string
	Range cell.Range
}
<commit_msg>syntax: fix some comments<commit_after>package syntax

import (
	"regexp"
	"unicode/utf8"

	"github.com/kybin/tor/cell"
	term "github.com/nsf/termbox-go"
)

var Languages = make(map[string]*Language)

func init() {
	golang := NewLanguage()
	golang.AddSyntax(Syntax{"string", regexp.MustCompile(`^(?m)".*?(?:[^\\]?"|$)`)}, Color{term.ColorRed, term.ColorBlack})
	golang.AddSyntax(Syntax{"raw string", regexp.MustCompile(`^(?s)` + "`" + `.*?` + "(?:`|$)")}, Color{term.ColorRed, term.ColorBlack})
	golang.AddSyntax(Syntax{"rune", regexp.MustCompile(`^(?m)'.*?(?:[^\\]?'|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	golang.AddSyntax(Syntax{"comment", regexp.MustCompile(`^(?m)//.*`)}, Color{term.ColorMagenta, term.ColorBlack})
	golang.AddSyntax(Syntax{"multi line comment", regexp.MustCompile(`^(?s)/[*].*?(?:[*]/|$)`)}, Color{term.ColorMagenta, term.ColorBlack})
	golang.AddSyntax(Syntax{"trailing spaces", regexp.MustCompile(`^(?m)[ \t]+$`)}, Color{term.ColorBlack, term.ColorYellow})
	golang.AddSyntax(Syntax{"package", regexp.MustCompile(`^package\s`)}, Color{term.ColorYellow, term.ColorBlack})
	Languages["go"] = golang

	py := NewLanguage()
	py.AddSyntax(Syntax{"multi line string1", regexp.MustCompile(`^(?s)""".*?(?:"""|$)`)}, Color{term.ColorRed, term.ColorBlack})
	py.AddSyntax(Syntax{"multi line string2", regexp.MustCompile(`^(?s)'''.*?(?:'''|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	py.AddSyntax(Syntax{"string1", regexp.MustCompile(`^(?m)".*?(?:[^\\]?"|$)`)}, Color{term.ColorRed, term.ColorBlack})
	py.AddSyntax(Syntax{"string2", regexp.MustCompile(`^(?m)'.*?(?:[^\\]?'|$)`)}, Color{term.ColorYellow, term.ColorBlack})
	py.AddSyntax(Syntax{"comment", regexp.MustCompile(`^(?m)#.*`)}, Color{term.ColorMagenta, term.ColorBlack})
	py.AddSyntax(Syntax{"trailing spaces", regexp.MustCompile(`^(?m)[ \t]+$`)}, Color{term.ColorBlack, term.ColorYellow})
	Languages["py"] = py
}

// Byter could converted to []bytes.
type Byter interface {
	Bytes() []byte
}

// Parser is syntax parser.
type Parser struct {
	text        Byter
	textChanged bool
	lang        *Language
	Matches     []Match
}

// NewParser creates a new Parser.
func NewParser(text Byter, langName string) *Parser {
	p := &Parser{}
	lang, ok := Languages[langName]
	if ok {
		p.lang = lang
	}
	p.SetText(text)
	return p
}

// SetText set it's text.
// After done this, it should Parse entirely again.
// Until then, TextChanged will return true.
func (p *Parser) SetText(text Byter) {
	p.text = text
	p.textChanged = true
}

// TextChanged returns status whether
// it's text changed but not Parsed yet.
func (p *Parser) TextChanged() bool {
	return p.textChanged
}

// Parse calculates it's matches entirely.
func (p *Parser) Parse() {
	if p.lang != nil {
		p.Matches = p.lang.Parse(p.text.Bytes())
	}
	p.textChanged = false
}

// ParseRange calulates it's partial matches.
// It will parse text from min to max range and
// replace current matches if there is an overwrap.
func (p *Parser) ParseRange(min, max cell.Pt) {
	if p.lang != nil {
		p.Matches = p.lang.ParseRange(p.Matches, p.text.Bytes(), min, max)
	}
}

// Color returns any match's syntax color name.
func (p *Parser) Color(synName string) Color {
	return p.lang.Color(synName)
}

type Syntax struct {
	Name string
	Re   *regexp.Regexp
}

func (s Syntax) NewMatch(start, end cell.Pt) Match {
	return Match{Name: s.Name, Range: cell.Range{start, end}}
}

type Color struct {
	Fg term.Attribute
	Bg term.Attribute
}

type Language struct {
	syntaxes []Syntax // should be ordered
	colors   map[string]Color
}

func NewLanguage() *Language {
	return &Language{
		syntaxes: []Syntax{},
		colors:   make(map[string]Color),
	}
}

func (l *Language) AddSyntax(s Syntax, c Color) {
	l.syntaxes = append(l.syntaxes, s)
	l.colors[s.Name] = c
}

func (l *Language) Color(synName string) Color {
	c, ok := l.colors[synName]
	if !ok {
		return Color{term.ColorWhite, term.ColorBlack}
	}
	return c
}

func (l *Language) Parse(text []byte) []Match {
	c := NewCursor(text)
	matches := []Match{}
Loop:
	for {
		for _, syn := range l.syntaxes {
			ms := syn.Re.FindSubmatch(c.Remain())
			if ms == nil {
				continue
			}
			m := ms[0]
			if len(ms) == 2 {
				m = ms[1]
			}
			if string(m) == "" {
				continue
			}
			start := c.Pos()
			c.Skip(len(m))
			end := c.Pos()
			matches = append(matches, syn.NewMatch(start, end))
			continue Loop
		}
		if !c.Advance() {
			break
		}
	}
	return matches
}

// ParseRange checks and replace matches from min to max.
// When there is an overwrap between old matches and min position,
// it will recaculate matches from the overwrap begins.
func (l *Language) ParseRange(matches []Match, text []byte, min, max cell.Pt) []Match {
	// check where parse acutally started.
	last := -1
	overwrap := false
	for i, m := range matches {
		if m.Range.Min().Compare(min) < 0 {
			if m.Range.Max().Compare(min) < 0 {
				continue
			}
			overwrap = true
			last = i
			break
		}
		last = i
		break
	}

	parseStart := min
	if last != -1 {
		if overwrap {
			parseStart = matches[last].Range.Min()
		}
		matches = matches[:last]
	}

	// move cursor to start position.
	c := NewCursor(text)
	for c.Pos().Compare(parseStart) < 0 {
		ok := c.Advance()
		if !ok {
			// already end of text. nothing to do.
			return matches
		}
	}

Loop:
	for {
		if c.Pos().Compare(max) >= 0 {
			break
		}
		for _, syn := range l.syntaxes {
			ms := syn.Re.FindSubmatch(c.Remain())
			if ms == nil {
				continue
			}
			m := ms[0]
			if len(ms) == 2 {
				m = ms[1]
			}
			if string(m) == "" {
				continue
			}
			start := c.Pos()
			c.Skip(len(m))
			end := c.Pos()
			matches = append(matches, syn.NewMatch(start, end))
			continue Loop
		}
		if !c.Advance() {
			break
		}
	}
	return matches
}

type Cursor struct {
	text []byte
	b    int // byte offset
	l    int // line offset
	o    int // byte in line offset
}

func NewCursor(text []byte) *Cursor {
	return &Cursor{text: text}
}

func (c *Cursor) Pos() cell.Pt {
	return cell.Pt{c.l, c.o}
}

func (c *Cursor) Remain() []byte {
	if c.l == len(c.text) {
		return []byte("")
	}
	return c.text[c.b:]
}

func (c *Cursor) Advance() bool {
	if c.b == len(c.text) {
		return false
	}
	c.next()
	return true
}

func (c *Cursor) Skip(b int) {
	i := 0
	for i < b {
		_, size := c.next()
		i += size
	}
}

func (c *Cursor) next() (r rune, size int) {
	r, size = utf8.DecodeRune(c.Remain())
	c.b += size
	c.o += size
	if r == '\n' {
		c.l += 1
		c.o = 0
	}
	return r, size
}

type Match struct {
	Name  string
	Range cell.Range
}
<|endoftext|>


<commit_before>package syntax

import (
	"crypto/sha1"

	"fm.tul.cz/dupl/suffixtree"
)

type Node struct {
	Type     int
	Filename string
	Pos, End int
	Children []*Node
	Owns     int
}

func NewNode() *Node {
	return &Node{}
}

func (n *Node) AddChildren(children ...*Node) {
	n.Children = append(n.Children, children...)
}

func (n *Node) Val() int {
	return n.Type
}

type Match struct {
	Hash  string
	Frags [][]*Node
}

func Serialize(n *Node) []*Node {
	stream := make([]*Node, 0, 10)
	serial(n, &stream)
	return stream
}

func serial(n *Node, stream *[]*Node) int {
	*stream = append(*stream, n)
	var count int
	for _, child := range n.Children {
		count += serial(child, stream)
	}
	n.Owns = count
	return count + 1
}

// FindSyntaxUnits finds all complete syntax units in the match group and returns them
// with the corresponding hash.
func FindSyntaxUnits(data []*Node, m suffixtree.Match, threshold int) Match {
	if len(m.Ps) == 0 {
		return Match{}
	}
	firstSeq := data[m.Ps[0] : m.Ps[0]+m.Len]
	indexes := getUnitsIndexes(firstSeq, threshold)

	// TODO: is this really working?
	indexCnt := len(indexes)
	if indexCnt > 0 {
		lasti := indexes[indexCnt-1]
		firstn := firstSeq[lasti]
		for i := 1; i < len(m.Ps); i++ {
			n := data[int(m.Ps[i])+lasti]
			if firstn.Owns != n.Owns {
				indexes = indexes[:indexCnt-1]
				break
			}
		}
	}
	if len(indexes) == 0 || isCyclic(indexes, firstSeq) {
		return Match{}
	}

	match := Match{Frags: make([][]*Node, len(m.Ps))}
	for i, pos := range m.Ps {
		match.Frags[i] = make([]*Node, len(indexes))
		for j, index := range indexes {
			match.Frags[i][j] = data[int(pos)+index]
		}
	}

	lastIndex := indexes[len(indexes)-1]
	match.Hash = hashSeq(firstSeq[indexes[0] : lastIndex+firstSeq[lastIndex].Owns])
	return match
}

func getUnitsIndexes(nodeSeq []*Node, threshold int) []int {
	var indexes []int
	var split bool
	for i := 0; i < len(nodeSeq); {
		n := nodeSeq[i]
		switch {
		case n.Owns >= len(nodeSeq)-i:
			// not complete syntax unit
			i++
			split = true
			continue
		case n.Owns+1 < threshold:
			split = true
		default:
			if split {
				indexes = indexes[:0]
				split = false
			}
			indexes = append(indexes, i)
		}
		i += n.Owns + 1
	}
	return indexes
}

// isCyclic finds out whether there is a repetive pattern in the found clone. If positive,
// it return false to point out that the clone would be redundant.
func isCyclic(indexes []int, nodes []*Node) bool {
	cnt := len(indexes)
	if cnt <= 1 {
		return false
	}

	alts := make(map[int]bool)
	for i := 1; i <= cnt/2; i++ {
		if cnt%i == 0 {
			alts[i] = true
		}
	}

	for i := 0; i < indexes[cnt/2]; i++ {
		nstart := nodes[i+indexes[0]]
	AltLoop:
		for alt := range alts {
			for j := alt; j < cnt; j += alt {
				index := i + indexes[j]
				if index < len(nodes) {
					nalt := nodes[index]
					if nstart.Owns == nalt.Owns && nstart.Type == nalt.Type {
						continue
					}
				} else if i >= indexes[alt] {
					return true
				}
				delete(alts, alt)
				continue AltLoop
			}
		}
		if len(alts) == 0 {
			return false
		}
	}
	return true
}

func hashSeq(nodes []*Node) string {
	h := sha1.New()
	bytes := make([]byte, len(nodes))
	for i, node := range nodes {
		bytes[i] = byte(node.Type)
	}
	h.Write(bytes)
	return string(h.Sum(nil))
}
<commit_msg>dupl can't span multiple files<commit_after>package syntax

import (
	"crypto/sha1"

	"fm.tul.cz/dupl/suffixtree"
)

type Node struct {
	Type     int
	Filename string
	Pos, End int
	Children []*Node
	Owns     int
}

func NewNode() *Node {
	return &Node{}
}

func (n *Node) AddChildren(children ...*Node) {
	n.Children = append(n.Children, children...)
}

func (n *Node) Val() int {
	return n.Type
}

type Match struct {
	Hash  string
	Frags [][]*Node
}

func Serialize(n *Node) []*Node {
	stream := make([]*Node, 0, 10)
	serial(n, &stream)
	return stream
}

func serial(n *Node, stream *[]*Node) int {
	*stream = append(*stream, n)
	var count int
	for _, child := range n.Children {
		count += serial(child, stream)
	}
	n.Owns = count
	return count + 1
}

// FindSyntaxUnits finds all complete syntax units in the match group and returns them
// with the corresponding hash.
func FindSyntaxUnits(data []*Node, m suffixtree.Match, threshold int) Match {
	if len(m.Ps) == 0 {
		return Match{}
	}
	firstSeq := data[m.Ps[0] : m.Ps[0]+m.Len]
	indexes := getUnitsIndexes(firstSeq, threshold)

	// TODO: is this really working?
	indexCnt := len(indexes)
	if indexCnt > 0 {
		lasti := indexes[indexCnt-1]
		firstn := firstSeq[lasti]
		for i := 1; i < len(m.Ps); i++ {
			n := data[int(m.Ps[i])+lasti]
			if firstn.Owns != n.Owns {
				indexes = indexes[:indexCnt-1]
				break
			}
		}
	}
	if len(indexes) == 0 || isCyclic(indexes, firstSeq) || spansMultipleFiles(indexes, firstSeq) {
		return Match{}
	}

	match := Match{Frags: make([][]*Node, len(m.Ps))}
	for i, pos := range m.Ps {
		match.Frags[i] = make([]*Node, len(indexes))
		for j, index := range indexes {
			match.Frags[i][j] = data[int(pos)+index]
		}
	}

	lastIndex := indexes[len(indexes)-1]
	match.Hash = hashSeq(firstSeq[indexes[0] : lastIndex+firstSeq[lastIndex].Owns])
	return match
}

func getUnitsIndexes(nodeSeq []*Node, threshold int) []int {
	var indexes []int
	var split bool
	for i := 0; i < len(nodeSeq); {
		n := nodeSeq[i]
		switch {
		case n.Owns >= len(nodeSeq)-i:
			// not complete syntax unit
			i++
			split = true
			continue
		case n.Owns+1 < threshold:
			split = true
		default:
			if split {
				indexes = indexes[:0]
				split = false
			}
			indexes = append(indexes, i)
		}
		i += n.Owns + 1
	}
	return indexes
}

// isCyclic finds out whether there is a repetive pattern in the found clone. If positive,
// it return false to point out that the clone would be redundant.
func isCyclic(indexes []int, nodes []*Node) bool {
	cnt := len(indexes)
	if cnt <= 1 {
		return false
	}

	alts := make(map[int]bool)
	for i := 1; i <= cnt/2; i++ {
		if cnt%i == 0 {
			alts[i] = true
		}
	}

	for i := 0; i < indexes[cnt/2]; i++ {
		nstart := nodes[i+indexes[0]]
	AltLoop:
		for alt := range alts {
			for j := alt; j < cnt; j += alt {
				index := i + indexes[j]
				if index < len(nodes) {
					nalt := nodes[index]
					if nstart.Owns == nalt.Owns && nstart.Type == nalt.Type {
						continue
					}
				} else if i >= indexes[alt] {
					return true
				}
				delete(alts, alt)
				continue AltLoop
			}
		}
		if len(alts) == 0 {
			return false
		}
	}
	return true
}

func spansMultipleFiles(indexes []int, nodes []*Node) bool {
	if len(indexes) < 2 {
		return false
	}
	f := nodes[indexes[0]].Filename
	for i := 1; i < len(indexes); i++ {
		if nodes[indexes[i]].Filename != f {
			return true
		}
	}
	return false
}

func hashSeq(nodes []*Node) string {
	h := sha1.New()
	bytes := make([]byte, len(nodes))
	for i, node := range nodes {
		bytes[i] = byte(node.Type)
	}
	h.Write(bytes)
	return string(h.Sum(nil))
}
<|endoftext|>


<commit_before>/*
 * turbomole.go, part of gochem.
 *
 *
 * Copyright 2012 Raul Mera <rmera{at}chemDOThelsinkiDOTfi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 *
 * Gochem is developed at the laboratory for instruction in Swedish, Department of Chemistry,
 * University of Helsinki, Finland.
 *
 *
 */
/***Dedicated to the long life of the Ven. Khenpo Phuntzok Tenzin Rinpoche***/

package chem

import "os"
import "io"
import "strings"
import "log"

//import "strconv"
import "bufio"
import "fmt"
import "os/exec"

type TMRunner struct {
	defmethod   string
	defbasis    string
	defauxbasis string
	previousMO  string
	command     string
	inputname   string
	gimic       bool
}

//Creates and initialized a new instance of TMRuner, with values set
//to its defaults.
func MakeTMRunner() *TMRunner {
	run := new(TMRunner)
	run.SetDefaults()
	return run
}

//TMRunner methods

//Just to satisfy the interface. It does nothing
func (O *TMRunner) SetnCPU(cpu int) {
	//It does nothing! :-D
}

//This set the name of the subdirectory, in the current directory
//where the calculation will be ran
func (O *TMRunner) SetName(name string) {
	O.inputname = name

}

//In TM the command is set according to the method. I just assume a normal installation.
//This method doesnt do anything.
func (O *TMRunner) SetCommand(name string) {
	//Does nothing again
}

//Sets some defaults for TMRunner. default is an optimization at
//  TPSS-D3 / def2-SVP
func (O *TMRunner) SetDefaults() {
	O.defmethod = "tpss"
	O.defbasis = "def2-SVP"
	O.defauxbasis = "def2-SVP"
	O.command = "ridft"
	O.inputname = "gochemturbo"

}

//Adds all the strings in toapend to the control file, just before the $symmetry keyword
func (O *TMRunner) addToControl(toappend []string, Q *QMCalc) error {
	f, err := os.Open("control")
	if err != nil {
		return err
	}
	lines := make([]string, 0, 200) //200 is just a guess for the number of lines in the control file
	c := bufio.NewReader(f)
	for err == nil {
		var line string
		line, err = c.ReadString('\n')
		lines = append(lines, line)
	}
	f.Close() //I cant defer it because I need it closed now.
	out, err := os.Create("control")
	if err != nil {
		return err
	}
	defer out.Close()
	var k string
	for _, i := range lines {
		k = i //May not be too efficient
		if strings.Contains(i, "$symmetry") {
			for _, j := range toappend {
				if _, err := fmt.Fprintf(out, j+"\n"); err != nil {
					return err
				}
			}
		}
		if Q.SCFConvHelp >= 1 {
			if strings.Contains(k, "$scfiterlimit") {
				k = "$scfiterlimit   100\n"
			}
			if strings.Contains(k, "$scfdamp") {
				k = "$scfdamp start=10 step=0.005 min=0.5\n"
			}
		}
		if _, err := fmt.Fprintf(out, k); err != nil {
			return err
		}
	}
	return nil
}

func (O *TMRunner) addCosmo(epsilon float64) error {
	//The ammount of newlines is wrong, must fix
	cosmostring := "" //a few newlines before the epsilon
	if epsilon == 0 {
		return nil
	}
	cosmostring = fmt.Sprintf("%s%3.1f\n\n\n\n\n\n\n\nr all b\n*\n\n", cosmostring, epsilon)
	def := exec.Command("cosmoprep")
	pipe, err := def.StdinPipe()
	if err != nil {
		return fmt.Errorf("Unable to run cosmoprep: %s", err.Error())
	}
	defer pipe.Close()
	pipe.Write([]byte(cosmostring))
	if err := def.Run(); err != nil {
		return fmt.Errorf("Unable to run run cosmoprep: %s", err.Error())
	}
	return nil

}

func (O *TMRunner) addBasis(basisOrEcp string, basiselems []string, basis, defstring string) string {
	if basiselems == nil { //no atoms to add basis to, do nothing
		return defstring
	}
	for _, elem := range basiselems {
		defstring = fmt.Sprintf("%s%s \"%s\" %s\n", defstring, basisOrEcp, strings.ToLower(elem), basis)
	}
	return defstring
}

//modifies the coord file such as to freeze the atoms in the slice frozen.
func (O *TMRunner) addFrozen(frozen []int) error {
	f, err := os.Open("coord")
	if err != nil {
		return err
	}
	lines := make([]string, 0, 200) //200 is just a guess for the number of lines in the coord file
	c := bufio.NewReader(f)
	for err == nil {
		var line string
		line, err = c.ReadString('\n')
		lines = append(lines, line)
	}
	f.Close() //I cant defer it because I need it closed now.
	out, err := os.Create("coord")
	defer out.Close()
	for key, i := range lines {
		if isInInt(frozen, key-1) {
			j := strings.Replace(i, "\n", " f\n", -1)
			if _, err := fmt.Fprintf(out, j); err != nil {
				return err
			}
		} else {
			if _, err := fmt.Fprintf(out, i); err != nil {
				return err
			}
		}
	}
	return nil
}

func copy2pipe(pipe io.ReadCloser, file *os.File, end chan bool) {
	io.Copy(file, pipe)
	end <- true
}

//BuildInput builds an input for TM based int the data in atoms, coords and C.
//returns only error.
func (O *TMRunner) BuildInput(atoms Ref, coords *CoordMatrix, Q *QMCalc) error {
	err := os.Mkdir(O.inputname, os.FileMode(0755))
	for i := 0; err != nil; i++ {
		if strings.Contains(err.Error(), "file exists") {
			O.inputname = fmt.Sprintf("%s%d", O.inputname, i)
			err = os.Mkdir(O.inputname, os.FileMode(0755))
		} else {
			return err
		}
	}
	_ = os.Chdir(O.inputname)
	//Set the coordinates in a slightly stupid way.
	XYZWrite("file.xyz", atoms, coords)
	x2t := exec.Command("x2t", "file.xyz")
	stdout, err := x2t.StdoutPipe()
	if err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	coord, err := os.Create("coord")
	if err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	if err := x2t.Start(); err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	//	var end chan bool
	//	go copy2pipe(stdout, coord, end)
	//	<-end
	io.Copy(coord, stdout)
	coord.Close() //not defearable
	defstring := "\n\na coord\n*\nno\n"
	if atoms == nil || coords == nil {
		return fmt.Errorf("Missing charges or coordinates")
	}
	if Q.Basis == "" {
		fmt.Fprintf(os.Stderr, "no basis set assigned for TM calculation, will used the default %s, \n", O.defbasis)
		Q.Basis = O.defbasis
	}
	defstring = defstring + "b all " + Q.Basis + "\n"
	defstring = O.addBasis("b", Q.LBElements, Q.LowBasis, defstring)
	defstring = O.addBasis("ecp", Q.ECPElements, Q.ECP, defstring)
	defstring = O.addBasis("b", Q.ECPElements, Q.ECP, defstring)      //we set a basis set compatible with the ECP. In TM they share the same name
	defstring = O.addBasis("b", Q.HBElements, Q.HighBasis, defstring) //The high basis will override the ECP basis, which can be rather small. Use under your own risk.
	defstring = defstring + "\n\n\n\n*\n"
	defstring = fmt.Sprintf("%seht\n\n\n%d\n\n", defstring, atoms.Charge())
	method, ok := tMMethods[Q.Method]
	if !ok {
		fmt.Fprintf(os.Stderr, "no method assigned for TM calculation, will used the default %s, \n", O.defmethod)
		Q.Method = O.defmethod
		Q.RI = true
	} else {
		Q.Method = method
	}
	//We only support HF and DFT
	//O.command = "dscf"
	if Q.Method != "hf" {
		grid := ""
		if Q.Grid != 0 && Q.Grid <= 7 {
			grid = fmt.Sprintf("grid\n m%d\n", Q.Grid)
		}
		defstring = defstring + "dft\non\nfunc " + Q.Method + "\n" + grid + "*\n"
		if Q.RI {
			mem := 500
			if Q.Memory != 0 {
				mem = Q.Memory
			}
			defstring = fmt.Sprintf("%sri\non\nm %d\n*\n", defstring, mem)
			O.command = "ridft"
		}
	}
	defstring = defstring + "*\n"
	log.Println(defstring)
	def := exec.Command("define")
	pipe, err := def.StdinPipe()
	if err != nil {
		return fmt.Errorf("Unable to run define: %s", err.Error())
	}
	defer pipe.Close()
	pipe.Write([]byte(defstring))
	if err := def.Run(); err != nil {
		return fmt.Errorf("Unable to run define: %s", err.Error())
	}
	if Q.Optimize {
		O.command = "jobex"
		if Q.RI {
			O.command = O.command + " -c 200 -ri"
		} else {
			O.command = O.command + " -c 200"
		}
	}
	//Now modify control
	args := make([]string, 1, 2)
	args[0], ok = tMDisp[Q.Disperssion]
	if !ok {
		fmt.Fprintf(os.Stderr, "Dispersion correction requested not supported, will used the default: D3, \n")
		args[0] = "$disp3"
	}
	if Q.Gimic {
		O.command = "mpshift"
		args = append(args, "$gimic")
	}
	if err := O.addToControl(args, Q); err != nil {
		return err
	}
	//set the frozen atoms (only cartesian constraints are supported)
	if err := O.addFrozen(Q.CConstraints); err != nil {
		return err
	}
	//Finally the cosmo business.
	err = O.addCosmo(Q.Dielectric)
	os.Chdir("../")
	return err
}

var tMMethods = map[string]string{
	"HF":     "hf",
	"hf":     "hf",
	"b3lyp":  "b3-lyp",
	"B3LYP":  "b3-lyp",
	"b3-lyp": "b3-lyp",
	"PBE":    "pbe",
	"pbe":    "pbe",
	"TPSS":   "tpss",
	"TPSSh":  "tpssh",
	"tpss":   "tpss",
	"tpssh":  "tpssh",
	"BP86":   "b-p",
	"b-p":    "b-p",
}

var tMDisp = map[string]string{
	"":       "",
	"nodisp": "",
	"D":      "$disp",
	"D2":     "$disp2",
	"D3":     "$disp3",
}

//Run runs the command given by the string O.command
//it waits or not for the result depending on wait.
//This is a Unix-only function.
func (O *TMRunner) Run(wait bool) (err error) {
	filename := strings.Fields(O.command)
	fmt.Println("nohup " + O.command + " > " + filename[0] + ".out")
	command := exec.Command("sh", "-c", "nohup "+O.command+" >"+filename[0]+".out")
	if wait == true {
		err = command.Run()
	} else {
		err = command.Start()
	}
	return err
}

//GetEnergy is NOT working yet
func (O *TMRunner) GetEnergy() (float64, error) {
	return 0, nil
}

//GetGeometry is NOT working yet
func (O *TMRunner) GetGeometry(atoms Ref) (*CoordMatrix, error) {
	return nil, nil

}
<commit_msg>fixed bug with turbomole interface always using charge 0<commit_after>/*
 * turbomole.go, part of gochem.
 *
 *
 * Copyright 2012 Raul Mera <rmera{at}chemDOThelsinkiDOTfi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 *
 * Gochem is developed at the laboratory for instruction in Swedish, Department of Chemistry,
 * University of Helsinki, Finland.
 *
 *
 */
/***Dedicated to the long life of the Ven. Khenpo Phuntzok Tenzin Rinpoche***/

package chem

import "os"
import "io"
import "strings"
import "log"

//import "strconv"
import "bufio"
import "fmt"
import "os/exec"

type TMRunner struct {
	defmethod   string
	defbasis    string
	defauxbasis string
	previousMO  string
	command     string
	inputname   string
	gimic       bool
}

//Creates and initialized a new instance of TMRuner, with values set
//to its defaults.
func MakeTMRunner() *TMRunner {
	run := new(TMRunner)
	run.SetDefaults()
	return run
}

//TMRunner methods

//Just to satisfy the interface. It does nothing
func (O *TMRunner) SetnCPU(cpu int) {
	//It does nothing! :-D
}

//This set the name of the subdirectory, in the current directory
//where the calculation will be ran
func (O *TMRunner) SetName(name string) {
	O.inputname = name

}

//In TM the command is set according to the method. I just assume a normal installation.
//This method doesnt do anything.
func (O *TMRunner) SetCommand(name string) {
	//Does nothing again
}

//Sets some defaults for TMRunner. default is an optimization at
//  TPSS-D3 / def2-SVP
func (O *TMRunner) SetDefaults() {
	O.defmethod = "tpss"
	O.defbasis = "def2-SVP"
	O.defauxbasis = "def2-SVP"
	O.command = "ridft"
	O.inputname = "gochemturbo"

}

//Adds all the strings in toapend to the control file, just before the $symmetry keyword
func (O *TMRunner) addToControl(toappend []string, Q *QMCalc) error {
	f, err := os.Open("control")
	if err != nil {
		return err
	}
	lines := make([]string, 0, 200) //200 is just a guess for the number of lines in the control file
	c := bufio.NewReader(f)
	for err == nil {
		var line string
		line, err = c.ReadString('\n')
		lines = append(lines, line)
	}
	f.Close() //I cant defer it because I need it closed now.
	out, err := os.Create("control")
	if err != nil {
		return err
	}
	defer out.Close()
	var k string
	for _, i := range lines {
		k = i //May not be too efficient
		if strings.Contains(i, "$symmetry") {
			for _, j := range toappend {
				if _, err := fmt.Fprintf(out, j+"\n"); err != nil {
					return err
				}
			}
		}
		if Q.SCFConvHelp >= 1 {
			if strings.Contains(k, "$scfiterlimit") {
				k = "$scfiterlimit   100\n"
			}
			if strings.Contains(k, "$scfdamp") {
				k = "$scfdamp start=10 step=0.005 min=0.5\n"
			}
		}
		if _, err := fmt.Fprintf(out, k); err != nil {
			return err
		}
	}
	return nil
}

func (O *TMRunner) addCosmo(epsilon float64) error {
	//The ammount of newlines is wrong, must fix
	cosmostring := "" //a few newlines before the epsilon
	if epsilon == 0 {
		return nil
	}
	cosmostring = fmt.Sprintf("%s%3.1f\n\n\n\n\n\n\n\nr all b\n*\n\n", cosmostring, epsilon)
	def := exec.Command("cosmoprep")
	pipe, err := def.StdinPipe()
	if err != nil {
		return fmt.Errorf("Unable to run cosmoprep: %s", err.Error())
	}
	defer pipe.Close()
	pipe.Write([]byte(cosmostring))
	if err := def.Run(); err != nil {
		return fmt.Errorf("Unable to run run cosmoprep: %s", err.Error())
	}
	return nil

}

func (O *TMRunner) addBasis(basisOrEcp string, basiselems []string, basis, defstring string) string {
	if basiselems == nil { //no atoms to add basis to, do nothing
		return defstring
	}
	for _, elem := range basiselems {
		defstring = fmt.Sprintf("%s%s \"%s\" %s\n", defstring, basisOrEcp, strings.ToLower(elem), basis)
	}
	return defstring
}

//modifies the coord file such as to freeze the atoms in the slice frozen.
func (O *TMRunner) addFrozen(frozen []int) error {
	f, err := os.Open("coord")
	if err != nil {
		return err
	}
	lines := make([]string, 0, 200) //200 is just a guess for the number of lines in the coord file
	c := bufio.NewReader(f)
	for err == nil {
		var line string
		line, err = c.ReadString('\n')
		lines = append(lines, line)
	}
	f.Close() //I cant defer it because I need it closed now.
	out, err := os.Create("coord")
	defer out.Close()
	for key, i := range lines {
		if isInInt(frozen, key-1) {
			j := strings.Replace(i, "\n", " f\n", -1)
			if _, err := fmt.Fprintf(out, j); err != nil {
				return err
			}
		} else {
			if _, err := fmt.Fprintf(out, i); err != nil {
				return err
			}
		}
	}
	return nil
}

func copy2pipe(pipe io.ReadCloser, file *os.File, end chan bool) {
	io.Copy(file, pipe)
	end <- true
}

//BuildInput builds an input for TM based int the data in atoms, coords and C.
//returns only error.
//Note that at this point the interface does not support multiplicities different from 1 and 2.
//The number in atoms is simply ignored.
func (O *TMRunner) BuildInput(atoms Ref, coords *CoordMatrix, Q *QMCalc) error {
	err := os.Mkdir(O.inputname, os.FileMode(0755))
	for i := 0; err != nil; i++ {
		if strings.Contains(err.Error(), "file exists") {
			O.inputname = fmt.Sprintf("%s%d", O.inputname, i)
			err = os.Mkdir(O.inputname, os.FileMode(0755))
		} else {
			return err
		}
	}
	_ = os.Chdir(O.inputname)
	//Set the coordinates in a slightly stupid way.
	XYZWrite("file.xyz", atoms, coords)
	x2t := exec.Command("x2t", "file.xyz")
	stdout, err := x2t.StdoutPipe()
	if err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	coord, err := os.Create("coord")
	if err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	if err := x2t.Start(); err != nil {
		return fmt.Errorf("Unable to run x2t: %s", err.Error())
	}
	//	var end chan bool
	//	go copy2pipe(stdout, coord, end)
	//	<-end
	io.Copy(coord, stdout)
	coord.Close() //not defearable
	defstring := "\n\na coord\n*\nno\n"
	if atoms == nil || coords == nil {
		return fmt.Errorf("Missing charges or coordinates")
	}
	if Q.Basis == "" {
		fmt.Fprintf(os.Stderr, "no basis set assigned for TM calculation, will used the default %s, \n", O.defbasis)
		Q.Basis = O.defbasis
	}
	defstring = defstring + "b all " + Q.Basis + "\n"
	defstring = O.addBasis("b", Q.LBElements, Q.LowBasis, defstring)
	defstring = O.addBasis("ecp", Q.ECPElements, Q.ECP, defstring)
	defstring = O.addBasis("b", Q.ECPElements, Q.ECP, defstring)      //we set a basis set compatible with the ECP. In TM they share the same name
	defstring = O.addBasis("b", Q.HBElements, Q.HighBasis, defstring) //The high basis will override the ECP basis, which can be rather small. Use under your own risk.
	defstring = defstring + "\n\n\n\n*\n"
	defstring = fmt.Sprintf("%seht\n\n%d\n\n", defstring, atoms.Charge())
	method, ok := tMMethods[Q.Method]
	if !ok {
		fmt.Fprintf(os.Stderr, "no method assigned for TM calculation, will used the default %s, \n", O.defmethod)
		Q.Method = O.defmethod
		Q.RI = true
	} else {
		Q.Method = method
	}
	//We only support HF and DFT
	//O.command = "dscf"
	if Q.Method != "hf" {
		grid := ""
		if Q.Grid != 0 && Q.Grid <= 7 {
			grid = fmt.Sprintf("grid\n m%d\n", Q.Grid)
		}
		defstring = defstring + "dft\non\nfunc " + Q.Method + "\n" + grid + "*\n"
		if Q.RI {
			mem := 500
			if Q.Memory != 0 {
				mem = Q.Memory
			}
			defstring = fmt.Sprintf("%sri\non\nm %d\n*\n", defstring, mem)
			O.command = "ridft"
		}
	}
	defstring = defstring + "*\n"
	log.Println(defstring)
	def := exec.Command("define")
	pipe, err := def.StdinPipe()
	if err != nil {
		return fmt.Errorf("Unable to run define: %s", err.Error())
	}
	defer pipe.Close()
	pipe.Write([]byte(defstring))
	if err := def.Run(); err != nil {
		return fmt.Errorf("Unable to run define: %s", err.Error())
	}
	if Q.Optimize {
		O.command = "jobex"
		if Q.RI {
			O.command = O.command + " -c 200 -ri"
		} else {
			O.command = O.command + " -c 200"
		}
	}
	//Now modify control
	args := make([]string, 1, 2)
	args[0], ok = tMDisp[Q.Disperssion]
	if !ok {
		fmt.Fprintf(os.Stderr, "Dispersion correction requested not supported, will used the default: D3, \n")
		args[0] = "$disp3"
	}
	if Q.Gimic {
		O.command = "mpshift"
		args = append(args, "$gimic")
	}
	if err := O.addToControl(args, Q); err != nil {
		return err
	}
	//set the frozen atoms (only cartesian constraints are supported)
	if err := O.addFrozen(Q.CConstraints); err != nil {
		return err
	}
	//Finally the cosmo business.
	err = O.addCosmo(Q.Dielectric)
	os.Chdir("../")
	return err
}

var tMMethods = map[string]string{
	"HF":     "hf",
	"hf":     "hf",
	"b3lyp":  "b3-lyp",
	"B3LYP":  "b3-lyp",
	"b3-lyp": "b3-lyp",
	"PBE":    "pbe",
	"pbe":    "pbe",
	"TPSS":   "tpss",
	"TPSSh":  "tpssh",
	"tpss":   "tpss",
	"tpssh":  "tpssh",
	"BP86":   "b-p",
	"b-p":    "b-p",
}

var tMDisp = map[string]string{
	"":       "",
	"nodisp": "",
	"D":      "$disp",
	"D2":     "$disp2",
	"D3":     "$disp3",
}

//Run runs the command given by the string O.command
//it waits or not for the result depending on wait.
//This is a Unix-only function.
func (O *TMRunner) Run(wait bool) (err error) {
	filename := strings.Fields(O.command)
	fmt.Println("nohup " + O.command + " > " + filename[0] + ".out")
	command := exec.Command("sh", "-c", "nohup "+O.command+" >"+filename[0]+".out")
	if wait == true {
		err = command.Run()
	} else {
		err = command.Start()
	}
	return err
}

//GetEnergy is NOT working yet
func (O *TMRunner) GetEnergy() (float64, error) {
	return 0, nil
}

//GetGeometry is NOT working yet
func (O *TMRunner) GetGeometry(atoms Ref) (*CoordMatrix, error) {
	return nil, nil

}
<|endoftext|>