<commit_before>package seq

import (
	"bytes"
	"fmt"
	"math"
	"text/tabwriter"
)

// Profile represents a sequence profile in terms of log-odds scores.
type Profile struct {
	// The columns of a profile.
	Emissions []EProbs

	// The alphabet of the profile. The length of the alphabet should be
	// equal to the number of rows in the profile.
	// There are no restrictions on the alphabet. (i.e., Gap characters are
	// allowed but they are not treated specially.)
	Alphabet Alphabet
}

// NewProfile initializes a profile with a default
// alphabet that is compatible with this package's BLOSUM62 matrix.
// Emission probabilities are set to the minimum log-odds probability.
func NewProfile(columns int) *Profile {
	return NewProfileAlphabet(columns, AlphaBlosum62)
}

// NewProfileAlphabet initializes a profile with the given alphabet.
// Emission probabilities are set to the minimum log-odds probability.
func NewProfileAlphabet(columns int, alphabet Alphabet) *Profile {
	emits := make([]EProbs, columns)
	for i := 0; i < columns; i++ {
		emits[i] = NewEProbs(alphabet)
	}
	return &Profile{emits, alphabet}
}

func (p *Profile) Len() int {
	return len(p.Emissions)
}

func (p *Profile) String() string {
	buf := new(bytes.Buffer)
	tabw := tabwriter.NewWriter(buf, 4, 0, 3, ' ', 0)
	pf := func(ft string, v ...interface{}) { fmt.Fprintf(tabw, ft, v...) }
	for _, r := range p.Alphabet {
		pf("%c", rune(r))
		for _, eprobs := range p.Emissions {
			pf("\t%0.4f", eprobs.Lookup(r))
		}
		pf("\n")
	}
	tabw.Flush()
	return buf.String()
}

// FrequencyProfile represents a sequence profile in terms of raw frequencies.
// A FrequencyProfile is useful as an intermediate representation. It can be
// used to incrementally build a Profile.
type FrequencyProfile struct {
	// The columns of a frequency profile.
	Freqs []map[Residue]int

	// The alphabet of the profile. The length of the alphabet should be
	// equal to the number of rows in the frequency profile.
	// There are no restrictions on the alphabet. (i.e., Gap characters are
	// allowed but they are not treated specially.)
	Alphabet Alphabet
}

func (fp *FrequencyProfile) String() string {
	buf := new(bytes.Buffer)
	tabw := tabwriter.NewWriter(buf, 4, 0, 3, ' ', 0)
	pf := func(ft string, v ...interface{}) { fmt.Fprintf(tabw, ft, v...) }
	for _, r := range fp.Alphabet {
		pf("%c", rune(r))
		for _, column := range fp.Freqs {
			pf("\t%d", column[r])
		}
		pf("\n")
	}
	tabw.Flush()
	return buf.String()
}

// NewNullProfile initializes a frequency profile that can be used to tabulate
// a null model. This is equivalent to calling NewFrequencyProfile with the
// number of columns set to 1.
func NewNullProfile() *FrequencyProfile {
	return NewFrequencyProfile(1)
}

// NewFrequencyProfile initializes a frequency profile with a default
// alphabet that is compatible with this package's BLOSUM62 matrix.
func NewFrequencyProfile(columns int) *FrequencyProfile {
	return NewFrequencyProfileAlphabet(columns, AlphaBlosum62)
}

// NewFrequencyProfileAlphabet initializes a frequency profile with the
// given alphabet.
func NewFrequencyProfileAlphabet(
	columns int,
	alphabet Alphabet,
) *FrequencyProfile {
	freqs := make([]map[Residue]int, columns)
	for i := 0; i < columns; i++ {
		freqs[i] = make(map[Residue]int, len(alphabet))
		for _, residue := range alphabet {
			freqs[i][residue] = 0
		}
	}
	return &FrequencyProfile{freqs, alphabet}
}

// Len returns the number of columns in the frequency profile.
func (fp *FrequencyProfile) Len() int {
	return len(fp.Freqs)
}

// Add adds the sequence to the given profile. The sequence must have length
// equivalent to the number of columns in the profile. The sequence must also
// only contain residues that are in the alphabet for the profile.
//
// As a special case, if the alphabet contains the 'X' residue, then any
// unrecognized residues in the sequence with respect to the profile's alphabet
// will be considered as an 'X' residue.
func (fp *FrequencyProfile) Add(s Sequence) {
	if fp.Len() != s.Len() {
		panic(fmt.Sprintf("Profile has length %d but sequence has length %d",
			fp.Len(), s.Len()))
	}
	for column := 0; column < fp.Len(); column++ {
		r := s.Residues[column]
		if _, ok := fp.Freqs[column][r]; ok {
			fp.Freqs[column][r] += 1
		} else if _, ok := fp.Freqs[column]['X']; ok {
			fp.Freqs[column]['X'] += 1
		} else {
			panic(fmt.Sprintf("Unrecognized residue %c while using an "+
				"alphabet without a wildcard: '%s'.", r, fp.Alphabet))
		}
	}
}

// Profile converts a raw frequency profile to a profile that uses a log-odds
// representation. The log-odds scores are computed with the given null model,
// which is itself just a raw frequency profile with a single column.
func (fp *FrequencyProfile) Profile(null *FrequencyProfile) *Profile {
	if null.Len() != 1 {
		panic(fmt.Sprintf("null model has %d columns; should have 1",
			null.Len()))
	}
	if !fp.Alphabet.Equals(null.Alphabet) {
		panic(fmt.Sprintf("freq profile alphabet '%s' is not equal to "+
			"null profile alphabet '%s'.", fp.Alphabet, null.Alphabet))
	}
	p := NewProfileAlphabet(fp.Len(), fp.Alphabet)

	// Compute the background emission probabilities.
	nulltot := freqTotal(null.Freqs[0])
	nullemit := make(map[Residue]float64, fp.Alphabet.Len())
	for _, residue := range null.Alphabet {
		nullemit[residue] = float64(null.Freqs[0][residue]) / float64(nulltot)
	}

	// Now compute the emission probabilities and convert to log-odds.
	for column := 0; column < fp.Len(); column++ {
		tot := freqTotal(fp.Freqs[column])
		for _, residue := range fp.Alphabet {
			if null.Freqs[0][residue] == 0 || fp.Freqs[column][residue] == 0 {
				p.Emissions[column].Set(residue, MinProb)
			} else {
				prob := float64(fp.Freqs[column][residue]) / float64(tot)
				logOdds := -Prob(math.Log(prob / nullemit[residue]))
				p.Emissions[column].Set(residue, logOdds)
			}
		}
	}
	return p
}

// freqTotal computes the total frequency in a single column.
func freqTotal(column map[Residue]int) int {
	tot := 0
	for _, freq := range column {
		tot += freq
	}
	return tot
}
<commit_msg>Add a method for combining frequency profiles.<commit_after>package seq

import (
	"bytes"
	"fmt"
	"math"
	"text/tabwriter"
)

// Profile represents a sequence profile in terms of log-odds scores.
type Profile struct {
	// The columns of a profile.
	Emissions []EProbs

	// The alphabet of the profile. The length of the alphabet should be
	// equal to the number of rows in the profile.
	// There are no restrictions on the alphabet. (i.e., Gap characters are
	// allowed but they are not treated specially.)
	Alphabet Alphabet
}

// NewProfile initializes a profile with a default
// alphabet that is compatible with this package's BLOSUM62 matrix.
// Emission probabilities are set to the minimum log-odds probability.
func NewProfile(columns int) *Profile {
	return NewProfileAlphabet(columns, AlphaBlosum62)
}

// NewProfileAlphabet initializes a profile with the given alphabet.
// Emission probabilities are set to the minimum log-odds probability.
func NewProfileAlphabet(columns int, alphabet Alphabet) *Profile {
	emits := make([]EProbs, columns)
	for i := 0; i < columns; i++ {
		emits[i] = NewEProbs(alphabet)
	}
	return &Profile{emits, alphabet}
}

func (p *Profile) Len() int {
	return len(p.Emissions)
}

func (p *Profile) String() string {
	buf := new(bytes.Buffer)
	tabw := tabwriter.NewWriter(buf, 4, 0, 3, ' ', 0)
	pf := func(ft string, v ...interface{}) { fmt.Fprintf(tabw, ft, v...) }
	for _, r := range p.Alphabet {
		pf("%c", rune(r))
		for _, eprobs := range p.Emissions {
			pf("\t%0.4f", eprobs.Lookup(r))
		}
		pf("\n")
	}
	tabw.Flush()
	return buf.String()
}

// FrequencyProfile represents a sequence profile in terms of raw frequencies.
// A FrequencyProfile is useful as an intermediate representation. It can be
// used to incrementally build a Profile.
type FrequencyProfile struct {
	// The columns of a frequency profile.
	Freqs []map[Residue]int

	// The alphabet of the profile. The length of the alphabet should be
	// equal to the number of rows in the frequency profile.
	// There are no restrictions on the alphabet. (i.e., Gap characters are
	// allowed but they are not treated specially.)
	Alphabet Alphabet
}

func (fp *FrequencyProfile) String() string {
	buf := new(bytes.Buffer)
	tabw := tabwriter.NewWriter(buf, 4, 0, 3, ' ', 0)
	pf := func(ft string, v ...interface{}) { fmt.Fprintf(tabw, ft, v...) }
	for _, r := range fp.Alphabet {
		pf("%c", rune(r))
		for _, column := range fp.Freqs {
			pf("\t%d", column[r])
		}
		pf("\n")
	}
	tabw.Flush()
	return buf.String()
}

// NewNullProfile initializes a frequency profile that can be used to tabulate
// a null model. This is equivalent to calling NewFrequencyProfile with the
// number of columns set to 1.
func NewNullProfile() *FrequencyProfile {
	return NewFrequencyProfile(1)
}

// NewFrequencyProfile initializes a frequency profile with a default
// alphabet that is compatible with this package's BLOSUM62 matrix.
func NewFrequencyProfile(columns int) *FrequencyProfile {
	return NewFrequencyProfileAlphabet(columns, AlphaBlosum62)
}

// NewFrequencyProfileAlphabet initializes a frequency profile with the
// given alphabet.
func NewFrequencyProfileAlphabet(
	columns int,
	alphabet Alphabet,
) *FrequencyProfile {
	freqs := make([]map[Residue]int, columns)
	for i := 0; i < columns; i++ {
		freqs[i] = make(map[Residue]int, len(alphabet))
		for _, residue := range alphabet {
			freqs[i][residue] = 0
		}
	}
	return &FrequencyProfile{freqs, alphabet}
}

// Len returns the number of columns in the frequency profile.
func (fp *FrequencyProfile) Len() int {
	return len(fp.Freqs)
}

// Combine adds the given frequency profile to the current one.
// Both profiles must have the same number of columns.
func (fp1 *FrequencyProfile) Combine(fp2 *FrequencyProfile) {
	if fp1.Len() != fp2.Len() {
		panic(fmt.Sprintf("Profile has length %d but other profile has "+
			"length %d", fp1.Len(), fp2.Len()))
	}
	for c := 0; c < fp1.Len(); c++ {
		for residue := range fp1.Freqs[c] {
			fp1.Freqs[c][residue] += fp2.Freqs[c][residue]
		}
	}
}

// Add adds the sequence to the given profile. The sequence must have length
// equivalent to the number of columns in the profile. The sequence must also
// only contain residues that are in the alphabet for the profile.
//
// As a special case, if the alphabet contains the 'X' residue, then any
// unrecognized residues in the sequence with respect to the profile's alphabet
// will be considered as an 'X' residue.
func (fp *FrequencyProfile) Add(s Sequence) {
	if fp.Len() != s.Len() {
		panic(fmt.Sprintf("Profile has length %d but sequence has length %d",
			fp.Len(), s.Len()))
	}
	for column := 0; column < fp.Len(); column++ {
		r := s.Residues[column]
		if _, ok := fp.Freqs[column][r]; ok {
			fp.Freqs[column][r] += 1
		} else if _, ok := fp.Freqs[column]['X']; ok {
			fp.Freqs[column]['X'] += 1
		} else {
			panic(fmt.Sprintf("Unrecognized residue %c while using an "+
				"alphabet without a wildcard: '%s'.", r, fp.Alphabet))
		}
	}
}

// Profile converts a raw frequency profile to a profile that uses a log-odds
// representation. The log-odds scores are computed with the given null model,
// which is itself just a raw frequency profile with a single column.
func (fp *FrequencyProfile) Profile(null *FrequencyProfile) *Profile {
	if null.Len() != 1 {
		panic(fmt.Sprintf("null model has %d columns; should have 1",
			null.Len()))
	}
	if !fp.Alphabet.Equals(null.Alphabet) {
		panic(fmt.Sprintf("freq profile alphabet '%s' is not equal to "+
			"null profile alphabet '%s'.", fp.Alphabet, null.Alphabet))
	}
	p := NewProfileAlphabet(fp.Len(), fp.Alphabet)

	// Compute the background emission probabilities.
	nulltot := freqTotal(null.Freqs[0])
	nullemit := make(map[Residue]float64, fp.Alphabet.Len())
	for _, residue := range null.Alphabet {
		nullemit[residue] = float64(null.Freqs[0][residue]) / float64(nulltot)
	}

	// Now compute the emission probabilities and convert to log-odds.
	for column := 0; column < fp.Len(); column++ {
		tot := freqTotal(fp.Freqs[column])
		for _, residue := range fp.Alphabet {
			if null.Freqs[0][residue] == 0 || fp.Freqs[column][residue] == 0 {
				p.Emissions[column].Set(residue, MinProb)
			} else {
				prob := float64(fp.Freqs[column][residue]) / float64(tot)
				logOdds := -Prob(math.Log(prob / nullemit[residue]))
				p.Emissions[column].Set(residue, logOdds)
			}
		}
	}
	return p
}

// freqTotal computes the total frequency in a single column.
func freqTotal(column map[Residue]int) int {
	tot := 0
	for _, freq := range column {
		tot += freq
	}
	return tot
}
<|endoftext|>


<commit_before>package oz

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path"

	"github.com/subgraph/oz/network"
)

type Profile struct {
	// Name of this profile
	Name string
	// Path to binary to launch
	Path string
	// List of path to binaries matching this sandbox
	Paths []string
	// Path of the config file
	ProfilePath string `json:"-"`
	// Optional path of binary to watch for watchdog purposes if different than Path
	Watchdog string
	// Optional wrapper binary to use when launching command (ex: tsocks)
	Wrapper string
	// If true launch one sandbox per instance, otherwise run all instances in same sandbox
	Multi bool
	// Disable mounting of sys and proc inside the sandbox
	NoSysProc bool
	// Disable bind mounting of default directories (etc,usr,bin,lib,lib64)
	// Also disables default blacklist items (/sbin, /usr/sbin, /usr/bin/sudo)
	// Normally not used
	NoDefaults bool
	// Allow bind mounting of files passed as arguments inside the sandbox
	AllowFiles bool `json:"allow_files"`
	// List of paths to bind mount inside jail
	Whitelist []WhitelistItem
	// List of paths to blacklist inside jail
	Blacklist []BlacklistItem
	// Optional XServer config
	XServer XServerConf
	// List of environment variables
	Environment []EnvVar
	// Networking
	Networking NetworkProfile
}

type AudioMode string
const (
	PROFILE_AUDIO_NONE    AudioMode = "none"
	PROFILE_AUDIO_SPEAKER AudioMode = "speaker"
	PROFILE_AUDIO_FULL    AudioMode = "full"
)

type XServerConf struct {
	Enabled             bool
	TrayIcon            string   `json:"tray_icon"`
	WindowIcon          string   `json:"window_icon"`
	EnableTray          bool     `json:"enable_tray"`
	EnableNotifications bool     `json:"enable_notifications"`
	UsePulseAudio       bool     `json:"use_pulse_audio"`
	DisableClipboard    bool     `json:"disable_clipboard"`
	AudioMode           AudioMode `json:"audio_mode"`
}

type WhitelistItem struct {
	Path     string
	ReadOnly bool `json:"read_only"`
}

type BlacklistItem struct {
	Path string
}

type EnvVar struct {
	Name  string
	Value string
}

// Sandbox network definition
type NetworkProfile struct {
	// One of empty, host, bridge
	Nettype network.NetType `json:"type"`

	// Name of the bridge to attach to
	//Bridge string

	// List of Sockets we want to attach to the jail
	//  Applies to Nettype: bridge and empty only
	Sockets []network.ProxyConfig
}

const defaultProfileDirectory = "/var/lib/oz/cells.d"

var loadedProfiles []*Profile

type Profiles []*Profile

func NewDefaultProfile() *Profile {
	return &Profile{
		Multi:      false,
		AllowFiles: false,
		XServer: XServerConf{
			Enabled:             true,
			EnableTray:          false,
			EnableNotifications: false,
			UsePulseAudio:       false,
			AudioMode:           PROFILE_AUDIO_NONE,
		},
	}
}

func (ps Profiles) GetProfileByName(name string) (*Profile, error) {
	if loadedProfiles == nil {
		ps, err := LoadProfiles(defaultProfileDirectory)
		if err != nil {
			return nil, err
		}
		loadedProfiles = ps
	}

	for _, p := range loadedProfiles {
		if p.Name == name {
			return p, nil
		}
	}
	return nil, nil
}

func (ps Profiles) GetProfileByPath(bpath string) (*Profile, error) {
	if loadedProfiles == nil {
		ps, err := LoadProfiles(defaultProfileDirectory)
		if err != nil {
			return nil, err
		}
		loadedProfiles = ps
	}

	for _, p := range loadedProfiles {
		if p.Path == bpath {
			return p, nil
		}
		for _, pp := range p.Paths {
			if pp == bpath {
				return p, nil
			}
		}
	}
	return nil, nil
}

func LoadProfiles(dir string) (Profiles, error) {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	ps := []*Profile{}
	for _, f := range fs {
		if !f.IsDir() {
			name := path.Join(dir, f.Name())
			p, err := loadProfileFile(name)
			if err != nil {
				return nil, fmt.Errorf("error loading '%s': %v", f.Name(), err)
			}
			ps = append(ps, p)
		}
	}

	loadedProfiles = ps
	return ps, nil
}

func loadProfileFile(file string) (*Profile, error) {
	bs, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	p := new(Profile)
	if err := json.Unmarshal(bs, p); err != nil {
		return nil, err
	}
	if p.Name == "" {
		p.Name = path.Base(p.Path)
	}
	p.ProfilePath = file
	return p, nil
}
<commit_msg>Add seccomp configuration params to the Oz profile specification/parser<commit_after>package oz

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path"
	"strings"

	"github.com/subgraph/oz/network"
)

type Profile struct {
	// Name of this profile
	Name string
	// Path to binary to launch
	Path string
	// List of path to binaries matching this sandbox
	Paths []string
	// Path of the config file
	ProfilePath string `json:"-"`
	// Optional path of binary to watch for watchdog purposes if different than Path
	Watchdog string
	// Optional wrapper binary to use when launching command (ex: tsocks)
	Wrapper string
	// If true launch one sandbox per instance, otherwise run all instances in same sandbox
	Multi bool
	// Disable mounting of sys and proc inside the sandbox
	NoSysProc bool
	// Disable bind mounting of default directories (etc,usr,bin,lib,lib64)
	// Also disables default blacklist items (/sbin, /usr/sbin, /usr/bin/sudo)
	// Normally not used
	NoDefaults bool
	// Allow bind mounting of files passed as arguments inside the sandbox
	AllowFiles bool `json:"allow_files"`
	// List of paths to bind mount inside jail
	Whitelist []WhitelistItem
	// List of paths to blacklist inside jail
	Blacklist []BlacklistItem
	// Optional XServer config
	XServer XServerConf
	// List of environment variables
	Environment []EnvVar
	// Networking
	Networking NetworkProfile
	// Seccomp
	Seccomp SeccompConf
}

type AudioMode string

const (
	PROFILE_AUDIO_NONE    AudioMode = "none"
	PROFILE_AUDIO_SPEAKER AudioMode = "speaker"
	PROFILE_AUDIO_FULL    AudioMode = "full"
)

type XServerConf struct {
	Enabled             bool
	TrayIcon            string    `json:"tray_icon"`
	WindowIcon          string    `json:"window_icon"`
	EnableTray          bool      `json:"enable_tray"`
	EnableNotifications bool      `json:"enable_notifications"`
	UsePulseAudio       bool      `json:"use_pulse_audio"`
	DisableClipboard    bool      `json:"disable_clipboard"`
	AudioMode           AudioMode `json:"audio_mode"`
}

type SeccompConf struct {
	Mode              string
	Enforce           bool
	Seccomp_Whitelist string
	Seccomp_Blacklist string
}

type WhitelistItem struct {
	Path     string
	ReadOnly bool `json:"read_only"`
}

type BlacklistItem struct {
	Path string
}

type EnvVar struct {
	Name  string
	Value string
}

// Sandbox network definition
type NetworkProfile struct {
	// One of empty, host, bridge
	Nettype network.NetType `json:"type"`

	// Name of the bridge to attach to
	//Bridge string

	// List of Sockets we want to attach to the jail
	//  Applies to Nettype: bridge and empty only
	Sockets []network.ProxyConfig
}

const defaultProfileDirectory = "/var/lib/oz/cells.d"

var loadedProfiles []*Profile

type Profiles []*Profile

func NewDefaultProfile() *Profile {
	return &Profile{
		Multi:      false,
		AllowFiles: false,
		XServer: XServerConf{
			Enabled:             true,
			EnableTray:          false,
			EnableNotifications: false,
			UsePulseAudio:       false,
			AudioMode:           PROFILE_AUDIO_NONE,
		},
	}
}

func (ps Profiles) GetProfileByName(name string) (*Profile, error) {
	if loadedProfiles == nil {
		ps, err := LoadProfiles(defaultProfileDirectory)
		if err != nil {
			return nil, err
		}
		loadedProfiles = ps
	}

	for _, p := range loadedProfiles {
		if p.Name == name {
			return p, nil
		}
	}
	return nil, nil
}

func (ps Profiles) GetProfileByPath(bpath string) (*Profile, error) {
	if loadedProfiles == nil {
		ps, err := LoadProfiles(defaultProfileDirectory)
		if err != nil {
			return nil, err
		}
		loadedProfiles = ps
	}

	for _, p := range loadedProfiles {
		if p.Path == bpath {
			return p, nil
		}
		for _, pp := range p.Paths {
			if pp == bpath {
				return p, nil
			}
		}
	}
	return nil, nil
}

func LoadProfiles(dir string) (Profiles, error) {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	ps := []*Profile{}
	for _, f := range fs {
		if !f.IsDir() {
			name := path.Join(dir, f.Name())
			if strings.Contains(f.Name(), ".json") {

				p, err := loadProfileFile(name)
				if err != nil {
					return nil, fmt.Errorf("error loading '%s': %v", f.Name(), err)
				}
				ps = append(ps, p)
			}
		}
	}

	loadedProfiles = ps
	return ps, nil
}

func loadProfileFile(file string) (*Profile, error) {
	bs, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}
	p := new(Profile)
	if err := json.Unmarshal(bs, p); err != nil {
		return nil, err
	}
	if p.Name == "" {
		p.Name = path.Base(p.Path)
	}
	p.ProfilePath = file
	return p, nil
}
<|endoftext|>


<commit_before>package command

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"sync"
)

type CommandsInfo struct {
	Port int
}

type CommandInfo map[string]*struct {
	Token string
}

type CommandRuntimeInfo struct {
	Token   string
	Handler interface{}
}

type CommandServer struct {
	Common   CommandsInfo
	Command  CommandInfo
	Handlers map[string]*CommandRuntimeInfo
}

type Color struct {
	r, g, b uint8
}

func (color Color) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf(`"`+"#%02x%02x%02x"+`"`, color.r, color.g, color.b)), nil
}

type AttachmentField struct {
	title string
	value string
	short bool
}

type Attachment struct {
	Fallback string `json:"fallback"`
	Color    Color  `json:"color"`
	Pretext  string `json:"pretext"`

	AuthorName string `json:"author_name"`
	AuthorLink string `json:"author_link"`
	AuthorIcon string `json:"author_icon"`

	Title     string `json:"title"`
	TitleLink string `json:"title_link"`

	Text string `json:"text"`

	ImageUrl string `json:"image_url"`
	ThumbUrl string `json:"thumb_url"`
}

type ResponseTypeEnum int

const (
	in_channel = iota
	ephemeral
	deffered_in_channel
)

func (e ResponseTypeEnum) MarshalJSON() ([]byte, error) {
	var str string
	switch e {
	case deffered_in_channel:
		str = "in_channel"
		break
	case in_channel:
		str = "in_channel"
		break
	case ephemeral:
		str = "ephemeral"
		break
	default:
		return nil, errors.New("Invalid value")
	}
	return []byte(`"` + str + `"`), nil
}

type Response struct {
	ResponseType ResponseTypeEnum `json:"response_type"`
	Text         string           `json:"text"`
	Attachments  []Attachment     `json:"attachments"`
}

type Request struct {
	Token       string `param:"token"`
	TeamId      string `param:"team_id"`
	TeamDomain  string `param:"team_domain"`
	ChannelId   string `param:"channel_id"`
	ChannelName string `param:"channel_name"`
	UserId      string `param:"user_id"`
	UserName    string `param:"user_name"`
	Command     string `param:"command"`
	Text        string `param:"text"`
	ResponseUrl string `param:"response_url"`
}

func NewServer(commands CommandsInfo, command CommandInfo) *CommandServer {
	server := &CommandServer{commands, command, map[string]*CommandRuntimeInfo{}}

	for k, v := range command {
		server.Handlers[k] = &CommandRuntimeInfo{v.Token, nil}
	}

	server.Handlers["/echo"].Handler = EchoCommand

	return server
}

func requestFormToRequestObj(r *http.Request) *Request {
	ret := new(Request)

	val := reflect.Indirect(reflect.ValueOf(ret))
	typ := reflect.TypeOf(*ret)

	for i := 0; i < typ.NumField(); i++ {
		field := val.Field(i)
		field_info := typ.Field(i)
		field_name := field_info.Tag.Get("param")
		field.Set(reflect.ValueOf(r.FormValue(field_name)))
	}

	return ret
}

func (server *CommandServer) commandHandler(w http.ResponseWriter, r *http.Request) {
	req := requestFormToRequestObj(r)
	handlerInfo := server.Handlers[req.Command]

	if handlerInfo != nil {
		if handlerInfo.Token == "" || handlerInfo.Token == req.Token {
			fun := reflect.ValueOf(handlerInfo.Handler)
			in := make([]reflect.Value, 1)
			in[0] = reflect.ValueOf(*req)
			response := fun.Call(in)[0].Interface().(*Response)

			var e error
			w.Header().Set("Content-Type", "application/json")
			if response.ResponseType != deffered_in_channel {
				encoder := json.NewEncoder(w)
				e = encoder.Encode(response)
			} else {
				var buf []byte
				buf, e = json.Marshal(response)
				http.Post(req.ResponseUrl, "application/json", bytes.NewBuffer(buf))
			}

			if e != nil {
				fmt.Println("Error occured : ", req, e)
			}
		}
	}
}

func (server *CommandServer) Start(wg *sync.WaitGroup) {
	http.HandleFunc("/", server.commandHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Common.Port), nil)

	wg.Done()
}
<commit_msg>command log<commit_after>package command

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"reflect"
	"sync"
)

type CommandsInfo struct {
	Port int
}

type CommandInfo map[string]*struct {
	Token string
}

type CommandRuntimeInfo struct {
	Token   string
	Handler interface{}
}

type CommandServer struct {
	Common   CommandsInfo
	Command  CommandInfo
	Handlers map[string]*CommandRuntimeInfo
}

type Color struct {
	r, g, b uint8
}

func (color Color) MarshalJSON() ([]byte, error) {
	return []byte(fmt.Sprintf(`"`+"#%02x%02x%02x"+`"`, color.r, color.g, color.b)), nil
}

type AttachmentField struct {
	title string
	value string
	short bool
}

type Attachment struct {
	Fallback string `json:"fallback"`
	Color    Color  `json:"color"`
	Pretext  string `json:"pretext"`

	AuthorName string `json:"author_name"`
	AuthorLink string `json:"author_link"`
	AuthorIcon string `json:"author_icon"`

	Title     string `json:"title"`
	TitleLink string `json:"title_link"`

	Text string `json:"text"`

	ImageUrl string `json:"image_url"`
	ThumbUrl string `json:"thumb_url"`
}

type ResponseTypeEnum int

const (
	in_channel = iota
	ephemeral
	deffered_in_channel
)

func (e ResponseTypeEnum) MarshalJSON() ([]byte, error) {
	var str string
	switch e {
	case deffered_in_channel:
		str = "in_channel"
		break
	case in_channel:
		str = "in_channel"
		break
	case ephemeral:
		str = "ephemeral"
		break
	default:
		return nil, errors.New("Invalid value")
	}
	return []byte(`"` + str + `"`), nil
}

type Response struct {
	ResponseType ResponseTypeEnum `json:"response_type"`
	Text         string           `json:"text"`
	Attachments  []Attachment     `json:"attachments"`
}

type Request struct {
	Token       string `param:"token"`
	TeamId      string `param:"team_id"`
	TeamDomain  string `param:"team_domain"`
	ChannelId   string `param:"channel_id"`
	ChannelName string `param:"channel_name"`
	UserId      string `param:"user_id"`
	UserName    string `param:"user_name"`
	Command     string `param:"command"`
	Text        string `param:"text"`
	ResponseUrl string `param:"response_url"`
}

func NewServer(commands CommandsInfo, command CommandInfo) *CommandServer {
	server := &CommandServer{commands, command, map[string]*CommandRuntimeInfo{}}

	for k, v := range command {
		server.Handlers[k] = &CommandRuntimeInfo{v.Token, nil}
	}

	server.Handlers["/echo"].Handler = EchoCommand

	return server
}

func requestFormToRequestObj(r *http.Request) *Request {
	ret := new(Request)

	val := reflect.Indirect(reflect.ValueOf(ret))
	typ := reflect.TypeOf(*ret)

	for i := 0; i < typ.NumField(); i++ {
		field := val.Field(i)
		field_info := typ.Field(i)
		field_name := field_info.Tag.Get("param")
		field.Set(reflect.ValueOf(r.FormValue(field_name)))
	}

	return ret
}

func (server *CommandServer) commandHandler(w http.ResponseWriter, r *http.Request) {
	req := requestFormToRequestObj(r)
	handlerInfo := server.Handlers[req.Command]

	if handlerInfo != nil {
		if handlerInfo.Token == "" || handlerInfo.Token == req.Token {
			fun := reflect.ValueOf(handlerInfo.Handler)
			in := make([]reflect.Value, 1)
			in[0] = reflect.ValueOf(*req)
			response := fun.Call(in)[0].Interface().(*Response)

			var e error
			w.Header().Set("Content-Type", "application/json")
			if response.ResponseType != deffered_in_channel {
				encoder := json.NewEncoder(w)
				e = encoder.Encode(response)
			} else {
				var buf []byte
				buf, e = json.Marshal(response)
				http.Post(req.ResponseUrl, "application/json", bytes.NewBuffer(buf))
				log.Println("Deffered : ", string(buf))
			}

			if e != nil {
				log.Println("Error occured : ", req, e)
			}
		}
	}
}

func (server *CommandServer) Start(wg *sync.WaitGroup) {
	http.HandleFunc("/", server.commandHandler)
	http.ListenAndServe(fmt.Sprintf(":%d", server.Common.Port), nil)

	wg.Done()
}
<|endoftext|>


<commit_before>package command

import (
	"encoding/json"
	"fmt"
	"strconv"
)

type exportData struct {
	projectId uint64
	deviceId  string
	series    string
	limit     uint64
}

func (e *exportData) IsValid() bool {
	return e.projectId > 0 && e.limit > 0
}

// NewExportCommand returns the base 'export' command.
func NewExportCommand(ctx *Context) *Command {
	e := new(exportData)
	pid := ctx.Profile.ActiveProject

	cmd := &Command{
		Name:    "query",
		ApiPath: "/v1/exports",
		Usage:   "Get data for projects, devices, and series",
		Data:    e,
		Action:  getExport,
	}

	flags := cmd.NewFlagSet("iobeam query")
	flags.Uint64Var(&e.projectId, "projectId", pid, "Project ID (if omitted, defaults to active project)")
	flags.StringVar(&e.deviceId, "deviceId", "", "Device ID")
	flags.StringVar(&e.series, "series", "", "Series name")
	flags.Uint64Var(&e.limit, "limit", 10, "Max number of results")

	return cmd
}

// getExport fetches the requested data from the iobeam Cloud based on
// the provided projectID, deviceID, and series name.
func getExport(c *Command, ctx *Context) error {
	e := c.Data.(*exportData)

	reqPath := c.ApiPath + "/" + strconv.FormatUint(e.projectId, 10)
	device := "all"
	if len(e.deviceId) > 0 {
		device = e.deviceId
	}
	reqPath += "/" + device
	if len(e.series) > 0 {
		reqPath += "/" + e.series
	}

	x := make(map[string]interface{})
	_, err := ctx.Client.
		Get(reqPath).
		Expect(200).
		ProjectToken(ctx.Profile, e.projectId).
		ParamUint64("limit", e.limit).
		ResponseBody(&x).
		ResponseBodyHandler(func(token interface{}) error {
		fmt.Println("Results: ")
		output, err := json.MarshalIndent(token, "", "  ")
		fmt.Println(string(output))
		return err
	}).Execute()

	return err
}
<commit_msg>Adds some of the basic query params: from, to, lessThan, greaterThan, equalTo<commit_after>package command

import (
	"encoding/json"
	"fmt"
	"math"
	"strconv"
	"time"
)

type exportData struct {
	projectId uint64
	deviceId  string
	series    string

	limit       uint64
	from        uint64
	to          uint64
	lessThan    int64
	greaterThan int64
	equal       string
}

func (e *exportData) IsValid() bool {
	pidOk := e.projectId > 0
	limitOk := e.limit > 0
	rangeOk := e.from <= e.to
	valRangeOk := e.greaterThan <= e.greaterThan
	equalOk := len(e.equal) == 0
	if !equalOk {
		_, err := strconv.ParseInt(e.equal, 0, 64)
		equalOk = err == nil
	}
	return pidOk && limitOk && rangeOk && valRangeOk && equalOk
}

// NewExportCommand returns the base 'export' command.
func NewExportCommand(ctx *Context) *Command {
	e := new(exportData)
	pid := ctx.Profile.ActiveProject

	cmd := &Command{
		Name:    "query",
		ApiPath: "/v1/exports",
		Usage:   "Get data for projects, devices, and series",
		Data:    e,
		Action:  getExport,
	}

	flags := cmd.NewFlagSet("iobeam query")
	maxTime := uint64((time.Now().UnixNano() / int64(time.Millisecond)) + (1000 * 60 * 60 * 24))
	flags.Uint64Var(&e.projectId, "projectId", pid, "Project ID (if omitted, defaults to active project)")
	flags.StringVar(&e.deviceId, "deviceId", "", "Device ID")
	flags.StringVar(&e.series, "series", "", "Series name")

	flags.Uint64Var(&e.limit, "limit", 10, "Max number of results")
	flags.Uint64Var(&e.from, "from", 0, "Min timestamp (unix time in milliseconds)")
	flags.Uint64Var(&e.to, "to", maxTime, "Max timestamp (unix time in milliseconds, default is now + a day)")
	flags.Int64Var(&e.lessThan, "lessThan", math.MaxInt64, "Max value for datapoints")
	flags.Int64Var(&e.greaterThan, "greaterThan", math.MinInt64, "Min value for datapoints")
	flags.StringVar(&e.equal, "equalTo", "", "Datapoints with this value")
	return cmd
}

// getExport fetches the requested data from the iobeam Cloud based on
// the provided projectID, deviceID, and series name.
func getExport(c *Command, ctx *Context) error {
	e := c.Data.(*exportData)

	reqPath := c.ApiPath + "/" + strconv.FormatUint(e.projectId, 10)
	device := "all"
	if len(e.deviceId) > 0 {
		device = e.deviceId
	}
	reqPath += "/" + device
	if len(e.series) > 0 {
		reqPath += "/" + e.series
	}

	req := ctx.Client.Get(reqPath).Expect(200).ProjectToken(ctx.Profile, e.projectId)
	req = req.
		ParamUint64("limit", e.limit).
		ParamUint64("from", e.from).
		ParamUint64("to", e.to).
		ParamInt64("less_than", e.lessThan).
		ParamInt64("greater_than", e.greaterThan)
	if len(e.equal) > 0 {
		temp, _ := strconv.ParseInt(e.equal, 0, 64)
		fmt.Println(temp)
		req = req.ParamInt64("equals", temp)
	}

	x := make(map[string]interface{})
	_, err := req.ResponseBody(&x).
		ResponseBodyHandler(func(token interface{}) error {
		fmt.Println("Results: ")
		output, err := json.MarshalIndent(token, "", "  ")
		fmt.Println(string(output))
		return err
	}).Execute()

	return err
}
<|endoftext|>


<commit_before>package main
/*
*  File: project.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 20:28:54 PDT 2011
*/
import (
    "os"
    "log"
    "fmt"
    "exec"
    "path/filepath"
    "io/ioutil"
    "time"
    "github.com/hoisie/mustache.go"
)

var (
    DirPermissions  uint32 = 0755
    FilePermissions uint32 = 0644
)

type RepoType int
const(
    NilRepoType RepoType = iota
    GitType
    // MercurialType
    // ...
)

type RepoHost int
const (
    NilRepoHost RepoHost = iota
    GitHubHost
    //GoogleHost
    //...
)

type ProjectType int
const (
    NilProjectType ProjectType = iota
    CmdType
    PkgType
    //LibType
    //MainType
)
func (ptype ProjectType) String() string {
    switch ptype {
    case CmdType:
        return "cmd"
    case PkgType:
        return "pkg"
    }
    return ""
}

func DefaultTarget(pname string) string {
    // TODO strip special characters from the prjoect name.
    return pname
}

type Project struct {
    Name   string
    Target string
    User   string
    Type   ProjectType
    Host   RepoHost
    Repo   RepoType
}

func GetGoroot() string {
    goroot, err := os.Getenverror("GOROOT")
    if err != nil {
        panic("goroot")
    }
    return goroot
}
func GetTemplateRoot() string {
    var goroot = GetGoroot()
    return filepath.Join(goroot, "src", "pkg",
            "github.com", "bmatsuo", "gonew", "templates")
}

func (p Project) MakefileTemplatePath() string {
    return filepath.Join(GetTemplateRoot(), "makefiles", p.Type.String() + ".t")
}
func (p Project) CreateMakefile(dict map[string]string) os.Error {
    var (
        templatePath = p.MakefileTemplatePath()
        template = mustache.RenderFile(templatePath, dict, map[string]string{"file":"Makefile"})
    )
	if DEBUG || VERBOSE {
		fmt.Print("Creating Makefile\n")
    }
    if DEBUG && DEBUG_LEVEL > 0 {
        log.Printf("template: %s", templatePath)
        if DEBUG_LEVEL > 1 {
	     log.Print("\n", template, "\n")
        }
    }
    var templout = make([]byte, len(template))
    copy(templout, template)
    var errWrite = ioutil.WriteFile("Makefile", templout, FilePermissions)
    return errWrite
}

func (p Project) MainFilename() string {
    return p.Name + ".go"
    /*
    switch p.Type {
    case CmdType:
    case PkgType:
    }
    */
}

func (p Project) MainTemplatePath() []string {
    switch p.Type {
    case CmdType:
        return []string{GetTemplateRoot(), "gofiles", "cmd.t"}
    case PkgType:
        return []string{GetTemplateRoot(), "gofiles", "pkg.t"}
    }
    return []string{""}
}
func (p Project) CreateMainFile(dict map[string]string) os.Error {
    var (
        mainfile = p.MainFilename()
        templatePath = p.MainTemplatePath()
        errWrite = WriteTemplate(mainfile, "main file", dict, templatePath...)
    )
    return errWrite
}

func (p Project) TestTemplatePath() []string {
    return []string{GetTemplateRoot(), "gofiles", "test.t"}
}
func (p Project) TestFilename() string {
    switch p.Type {
    case CmdType:
        return "main_test.go"
    case PkgType:
        return p.Name + "_test.go"
    }
    return p.Name + "_test.go"
}

func (p Project) CreateTestFile(dict map[string]string) os.Error {
    var (
        testfile = p.TestFilename()
        templatePath = p.TestTemplatePath()
		errWrite = WriteTemplate(testfile, "test file", dict, templatePath...)
    )
    return errWrite
}

func (p Project) ReadmeTemplatePath() []string {
    var root = GetTemplateRoot()
    var useMarkdown = p.Host == GitHubHost
    if useMarkdown {
        return []string{root, "README", p.Type.String() + ".md.t"}
    }
    return []string{root, "README", p.Type.String() + ".t"}
}
func (p Project) CreateReadme(dict map[string]string) os.Error {
    var (
        templatePath = p.ReadmeTemplatePath()
        readme = "README"
        useMarkdown = p.Host == GitHubHost
    )
    if useMarkdown {
        readme += ".md"
    }
	var errWrite = WriteTemplate(readme, "README", dict, templatePath...)
    return errWrite
}

func (p Project) DocTemplatePath() []string {
    var root = GetTemplateRoot()
    return []string{root, "gofiles", "doc.t"}
}
func (p Project) CreateDocFile(dict map[string]string) os.Error {
    if p.Type == PkgType {
        return nil
    }
	var (
		doc = "doc.go"
        templatePath = p.DocTemplatePath()
		errWrite = WriteTemplate(doc, "documentation files", dict, templatePath...)
	)
    return errWrite
}

func (p Project) OtherTemplatePaths() []string {
    var root = GetTemplateRoot()
    var others = make([]string, 0, 1)
    switch p.Repo {
    case GitType:
        others = append(others, filepath.Join(root, "otherfiles", "gitignore.t"))
    }
    if len(others) == 0 {
        return nil
    }
    return others
}
func (p Project) CreateOtherFiles(dict map[string]string) os.Error {
    if DEBUG || VERBOSE {
        fmt.Printf("Creating any other necessary files\n")
    }
    var templatePaths = p.OtherTemplatePaths()
    if templatePaths == nil {
        return nil
    }
    for _, path := range templatePaths {
        var template = mustache.RenderFile(path, dict)
        if DEBUG && DEBUG_LEVEL > 0 {
            log.Printf("template: %s", path)
            if DEBUG_LEVEL > 1 {
                log.Print("\n", template, "\n")
            }
        }
        var templout = make([]byte, len(template))
        copy(templout, template)
        var errWrite = ioutil.WriteFile(path, templout, FilePermissions)
        if errWrite != nil {
            return errWrite
        }
    }
    return nil
}

func (p Project) InitializeRepo(commit bool) os.Error {
    switch p.Repo {
    case GitType:
        var (
            initcmd = exec.Command("git", "init")
            addcmd = exec.Command("git", "add", ".")
            commitcmd = exec.Command("git", "commit",
                    "-a", "-m", "Empty project generated by gonew.")
        )
        errInit := initcmd.Run()
        if errInit != nil {
            return errInit
        }
        errAdd := addcmd.Run()
        if errAdd != nil {
            return errAdd
        }
        if commit {
            errCommit := commitcmd.Run()
            if errCommit != nil {
                return errCommit
            }
        }
    }
    return nil
}

// fix this method.
func (p Project) HostString() string {
    switch p.Repo {
    case GitType:
        return "github.com/" + AppConfig.HostUser
    }
    return "<INSERT REPO HOST HERE>"
}

func YearString() string {
    return time.LocalTime().Format("2006")
}

// fix the formatting of this method.
func DateString() string {
    return time.LocalTime().String()
}

func (p Project) GenerateDictionary() map[string]string {
    var td = make(map[string]string, 9)
    td["project"]   = p.Name
    td["name"]   = AppConfig.Name
    td["email"]  = AppConfig.Email
    td["gotarget"] = p.Target
    td["main"]   = p.MainFilename()
    td["type"]   = p.Type.String()
    td["repo"]   = p.HostString()
    td["year"]   = YearString()
    td["date"]   = DateString()
    return td
}

func (p Project) Create() os.Error {
    var dict = p.GenerateDictionary()
    var errMkdir, errChdir, errRepo, errChdirBack os.Error
    var errMake, errMain, errDoc, errTest, errReadme, errOther os.Error

    // Make the directory and change the working directory.
    if DEBUG || VERBOSE {
        fmt.Print("Creating project directory.\n")
    }
    errMkdir = os.Mkdir(p.Name, DirPermissions)
    if errMkdir != nil {
        return errMkdir
    }
    if DEBUG || VERBOSE {
        fmt.Print("Entering project directory.\n")
    }
    errChdir = os.Chdir(p.Name)
    if errChdir != nil {
        return errChdir
    }

    // Create the project files.
    errMake = p.CreateMakefile(dict)
    if errMake != nil {
        return errMake
    }
    errMain = p.CreateMainFile(dict)
    if errMain != nil {
        return errMain
    }
    errDoc = p.CreateDocFile(dict)
    if errDoc != nil {
        return errDoc
    }
    errTest = p.CreateTestFile(dict)
    if errTest != nil {
        return errTest
    }
    errReadme = p.CreateReadme(dict)
    if errReadme != nil {
        return errReadme
    }
    errOther = p.CreateOtherFiles(dict)
    if errOther != nil {
        return errOther
    }
    errRepo = p.InitializeRepo(true)
    if errRepo != nil {
        return errRepo
    }

    // Change the working directory back.
    if DEBUG || VERBOSE {
        fmt.Print("Leaving project directory.\n")
    }
    errChdirBack = os.Chdir("..")
    return errChdirBack
}
<commit_msg>Fix bug emitting template for 'other files'<commit_after>package main
/*
*  File: project.go
*  Author: Bryan Matsuo [bmatsuo@soe.ucsc.edu]
*  Created: Sat Jul  2 20:28:54 PDT 2011
*/
import (
    "os"
    "log"
    "fmt"
    "exec"
    "path/filepath"
    "io/ioutil"
    "time"
    "github.com/hoisie/mustache.go"
)

var (
    DirPermissions  uint32 = 0755
    FilePermissions uint32 = 0644
)

type RepoType int
const(
    NilRepoType RepoType = iota
    GitType
    // MercurialType
    // ...
)

type RepoHost int
const (
    NilRepoHost RepoHost = iota
    GitHubHost
    //GoogleHost
    //...
)

type ProjectType int
const (
    NilProjectType ProjectType = iota
    CmdType
    PkgType
    //LibType
    //MainType
)
func (ptype ProjectType) String() string {
    switch ptype {
    case CmdType:
        return "cmd"
    case PkgType:
        return "pkg"
    }
    return ""
}

func DefaultTarget(pname string) string {
    // TODO strip special characters from the prjoect name.
    return pname
}

type Project struct {
    Name   string
    Target string
    User   string
    Type   ProjectType
    Host   RepoHost
    Repo   RepoType
}

func GetGoroot() string {
    goroot, err := os.Getenverror("GOROOT")
    if err != nil {
        panic("goroot")
    }
    return goroot
}
func GetTemplateRoot() string {
    var goroot = GetGoroot()
    return filepath.Join(goroot, "src", "pkg",
            "github.com", "bmatsuo", "gonew", "templates")
}

func (p Project) MakefileTemplatePath() string {
    return filepath.Join(GetTemplateRoot(), "makefiles", p.Type.String() + ".t")
}
func (p Project) CreateMakefile(dict map[string]string) os.Error {
    var (
        templatePath = p.MakefileTemplatePath()
        template = mustache.RenderFile(templatePath, dict, map[string]string{"file":"Makefile"})
    )
	if DEBUG || VERBOSE {
		fmt.Print("Creating Makefile\n")
    }
    if DEBUG && DEBUG_LEVEL > 0 {
        log.Printf("template: %s", templatePath)
        if DEBUG_LEVEL > 1 {
	     log.Print("\n", template, "\n")
        }
    }
    var templout = make([]byte, len(template))
    copy(templout, template)
    var errWrite = ioutil.WriteFile("Makefile", templout, FilePermissions)
    return errWrite
}

func (p Project) MainFilename() string {
    return p.Name + ".go"
    /*
    switch p.Type {
    case CmdType:
    case PkgType:
    }
    */
}

func (p Project) MainTemplatePath() []string {
    switch p.Type {
    case CmdType:
        return []string{GetTemplateRoot(), "gofiles", "cmd.t"}
    case PkgType:
        return []string{GetTemplateRoot(), "gofiles", "pkg.t"}
    }
    return []string{""}
}
func (p Project) CreateMainFile(dict map[string]string) os.Error {
    var (
        mainfile = p.MainFilename()
        templatePath = p.MainTemplatePath()
        errWrite = WriteTemplate(mainfile, "main file", dict, templatePath...)
    )
    return errWrite
}

func (p Project) TestTemplatePath() []string {
    return []string{GetTemplateRoot(), "gofiles", "test.t"}
}
func (p Project) TestFilename() string {
    switch p.Type {
    case CmdType:
        return "main_test.go"
    case PkgType:
        return p.Name + "_test.go"
    }
    return p.Name + "_test.go"
}

func (p Project) CreateTestFile(dict map[string]string) os.Error {
    var (
        testfile = p.TestFilename()
        templatePath = p.TestTemplatePath()
		errWrite = WriteTemplate(testfile, "test file", dict, templatePath...)
    )
    return errWrite
}

func (p Project) ReadmeTemplatePath() []string {
    var root = GetTemplateRoot()
    var useMarkdown = p.Host == GitHubHost
    if useMarkdown {
        return []string{root, "README", p.Type.String() + ".md.t"}
    }
    return []string{root, "README", p.Type.String() + ".t"}
}
func (p Project) CreateReadme(dict map[string]string) os.Error {
    var (
        templatePath = p.ReadmeTemplatePath()
        readme = "README"
        useMarkdown = p.Host == GitHubHost
    )
    if useMarkdown {
        readme += ".md"
    }
	var errWrite = WriteTemplate(readme, "README", dict, templatePath...)
    return errWrite
}

func (p Project) DocTemplatePath() []string {
    var root = GetTemplateRoot()
    return []string{root, "gofiles", "doc.t"}
}
func (p Project) CreateDocFile(dict map[string]string) os.Error {
    if p.Type == PkgType {
        return nil
    }
	var (
		doc = "doc.go"
        templatePath = p.DocTemplatePath()
		errWrite = WriteTemplate(doc, "documentation files", dict, templatePath...)
	)
    return errWrite
}

func (p Project) OtherTemplatePaths() [][]string {
    var root = GetTemplateRoot()
    var others = make([][]string, 0, 1)
    switch p.Repo {
    case GitType:
        others = append(others, []string{".gitignore", root, "otherfiles", "gitignore.t"})
    }
    if len(others) == 0 {
        return nil
    }
    return others
}
func (p Project) CreateOtherFiles(dict map[string]string) os.Error {
    var templatePaths = p.OtherTemplatePaths()
    if templatePaths == nil {
        return nil
    }
    for _, path := range templatePaths {
        var errWrite = WriteTemplate(path[0], "other file", dict, path[1:]...)
        if errWrite != nil {
            return errWrite
        }
    }
    return nil
}

func (p Project) InitializeRepo(commit bool) os.Error {
    switch p.Repo {
    case GitType:
        var (
            initcmd = exec.Command("git", "init")
            addcmd = exec.Command("git", "add", ".")
            commitcmd = exec.Command("git", "commit",
                    "-a", "-m", "Empty project generated by gonew.")
        )
        errInit := initcmd.Run()
        if errInit != nil {
            return errInit
        }
        errAdd := addcmd.Run()
        if errAdd != nil {
            return errAdd
        }
        if commit {
            errCommit := commitcmd.Run()
            if errCommit != nil {
                return errCommit
            }
        }
    }
    return nil
}

// fix this method.
func (p Project) HostString() string {
    switch p.Repo {
    case GitType:
        return "github.com/" + AppConfig.HostUser
    }
    return "<INSERT REPO HOST HERE>"
}

func YearString() string {
    return time.LocalTime().Format("2006")
}

// fix the formatting of this method.
func DateString() string {
    return time.LocalTime().String()
}

func (p Project) GenerateDictionary() map[string]string {
    var td = make(map[string]string, 9)
    td["project"]   = p.Name
    td["name"]   = AppConfig.Name
    td["email"]  = AppConfig.Email
    td["gotarget"] = p.Target
    td["main"]   = p.MainFilename()
    td["type"]   = p.Type.String()
    td["repo"]   = p.HostString()
    td["year"]   = YearString()
    td["date"]   = DateString()
    return td
}

func (p Project) Create() os.Error {
    var dict = p.GenerateDictionary()
    var errMkdir, errChdir, errRepo, errChdirBack os.Error
    var errMake, errMain, errDoc, errTest, errReadme, errOther os.Error

    // Make the directory and change the working directory.
    if DEBUG || VERBOSE {
        fmt.Print("Creating project directory.\n")
    }
    errMkdir = os.Mkdir(p.Name, DirPermissions)
    if errMkdir != nil {
        return errMkdir
    }
    if DEBUG || VERBOSE {
        fmt.Print("Entering project directory.\n")
    }
    errChdir = os.Chdir(p.Name)
    if errChdir != nil {
        return errChdir
    }

    // Create the project files.
    errMake = p.CreateMakefile(dict)
    if errMake != nil {
        return errMake
    }
    errMain = p.CreateMainFile(dict)
    if errMain != nil {
        return errMain
    }
    errDoc = p.CreateDocFile(dict)
    if errDoc != nil {
        return errDoc
    }
    errTest = p.CreateTestFile(dict)
    if errTest != nil {
        return errTest
    }
    errReadme = p.CreateReadme(dict)
    if errReadme != nil {
        return errReadme
    }
    errOther = p.CreateOtherFiles(dict)
    if errOther != nil {
        return errOther
    }
    errRepo = p.InitializeRepo(true)
    if errRepo != nil {
        return errRepo
    }

    // Change the working directory back.
    if DEBUG || VERBOSE {
        fmt.Print("Leaving project directory.\n")
    }
    errChdirBack = os.Chdir("..")
    return errChdirBack
}
<|endoftext|>


<commit_before>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.3"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<commit_msg>functions: 0.0.31 release<commit_after>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.31"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"net"
	"net/http"
	"os"
	"sync"
	"time"
)

type statusHandler struct {
	// Mutex for locking
	mu *sync.Mutex
	// Backend dialer to check if target is up and running
	dial func() (net.Conn, error)
	// Current status
	listening bool
	reloading bool
}

type statusResponse struct {
	Ok            bool      `json:"ok"`
	Status        string    `json:"status"`
	BackendOk     bool      `json:"backend_ok"`
	BackendStatus string    `json:"backend_status"`
	BackendError  string    `json:"backend_error,omitempty"`
	Time          time.Time `json:"time,omitempty"`
	Hostname      string    `json:"hostname,omitempty"`
	Message       string    `json:"message,omitempty"`
	Revision      string    `json:"revision,omitempty"`
	Compiler      string    `json:"compiler,omitempty"`
}

func newStatusHandler(dial func() (net.Conn, error)) *statusHandler {
	return &statusHandler{&sync.Mutex{}, dial, false, false}
}

func (s *statusHandler) Listening() {
	s.mu.Lock()
	s.listening = true
	s.reloading = false
	s.mu.Unlock()
}

func (s *statusHandler) Reloading() {
	s.mu.Lock()
	s.reloading = true
	s.mu.Unlock()
}

func (s *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	resp := statusResponse{
		Time: time.Now(),
	}

	conn, err := s.dial()
	resp.BackendOk = err == nil
	resp.Revision = buildRevision
	resp.Compiler = buildCompiler

	if resp.BackendOk {
		defer conn.Close()
		resp.BackendStatus = "ok"
	} else {
		resp.BackendError = err.Error()
		resp.BackendStatus = "critical"
	}

	s.mu.Lock()
	resp.Ok = s.listening && resp.BackendOk
	if !s.listening {
		resp.Message = "initializing"
	} else if s.reloading {
		resp.Message = "reloading"
	} else {
		resp.Message = "listening"
	}
	s.mu.Unlock()

	if resp.Ok && resp.BackendOk {
		resp.Status = "ok"
	} else {
		resp.Status = "critical"
	}

	hostname, err := os.Hostname()
	if err == nil {
		resp.Hostname = hostname
	}

	out, err := json.Marshal(resp)
	if err != nil {
		panic(err)
	}

	w.Write(out)
}
<commit_msg>Remove omitempty from fields that are never empty<commit_after>/*-
 * Copyright 2015 Square Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"encoding/json"
	"net"
	"net/http"
	"os"
	"sync"
	"time"
)

type statusHandler struct {
	// Mutex for locking
	mu *sync.Mutex
	// Backend dialer to check if target is up and running
	dial func() (net.Conn, error)
	// Current status
	listening bool
	reloading bool
}

type statusResponse struct {
	Ok            bool      `json:"ok"`
	Status        string    `json:"status"`
	BackendOk     bool      `json:"backend_ok"`
	BackendStatus string    `json:"backend_status"`
	BackendError  string    `json:"backend_error,omitempty"`
	Time          time.Time `json:"time"`
	Hostname      string    `json:"hostname,omitempty"`
	Message       string    `json:"message"`
	Revision      string    `json:"revision"`
	Compiler      string    `json:"compiler"`
}

func newStatusHandler(dial func() (net.Conn, error)) *statusHandler {
	return &statusHandler{&sync.Mutex{}, dial, false, false}
}

func (s *statusHandler) Listening() {
	s.mu.Lock()
	s.listening = true
	s.reloading = false
	s.mu.Unlock()
}

func (s *statusHandler) Reloading() {
	s.mu.Lock()
	s.reloading = true
	s.mu.Unlock()
}

func (s *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	resp := statusResponse{
		Time: time.Now(),
	}

	conn, err := s.dial()
	resp.BackendOk = err == nil
	resp.Revision = buildRevision
	resp.Compiler = buildCompiler

	if resp.BackendOk {
		defer conn.Close()
		resp.BackendStatus = "ok"
	} else {
		resp.BackendError = err.Error()
		resp.BackendStatus = "critical"
	}

	s.mu.Lock()
	resp.Ok = s.listening && resp.BackendOk
	if !s.listening {
		resp.Message = "initializing"
	} else if s.reloading {
		resp.Message = "reloading"
	} else {
		resp.Message = "listening"
	}
	s.mu.Unlock()

	if resp.Ok && resp.BackendOk {
		resp.Status = "ok"
	} else {
		resp.Status = "critical"
	}

	hostname, err := os.Hostname()
	if err == nil {
		resp.Hostname = hostname
	}

	out, err := json.Marshal(resp)
	if err != nil {
		panic(err)
	}

	w.Write(out)
}
<|endoftext|>


<commit_before>package leetcode

// 199. Binary Tree Right Side View
func rightSideView(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}
	res := []int{}
	list := []*TreeNode{root}
	for len(list) > 0 {
		res = append(res, list[len(list)-1].Val)
		nextList := make([]*TreeNode, 0)
		for _, node := range list {
			if node.Left != nil {
				nextList = append(nextList, node.Left)
			}
			if node.Right != nil {
				nextList = append(nextList, node.Right)
			}
		}
		list = nextList
	}

	return res
}
<commit_msg>Add 199. Binary Tree Right Side View with list<commit_after>package leetcode

import "container/list"

// 199. Binary Tree Right Side View
func rightSideView(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}
	res := []int{}
	list := []*TreeNode{root}
	for len(list) > 0 {
		res = append(res, list[len(list)-1].Val)
		nextList := make([]*TreeNode, 0)
		for _, node := range list {
			if node.Left != nil {
				nextList = append(nextList, node.Left)
			}
			if node.Right != nil {
				nextList = append(nextList, node.Right)
			}
		}
		list = nextList
	}

	return res
}

// 199. Binary Tree Right Side View by container/list
func rightSideView2(root *TreeNode) []int {
	if root == nil {
		return []int{}
	}
	res := []int{}
	l := list.New()
	l.PushBack(root)
	for l.Len() > 0 {
		front := l.Front().Value.(*TreeNode)
		res = append(res, front.Val)
		nextList := list.New()
		for el := l.Front(); el != nil; el = l.Front() {
			node := el.Value.(*TreeNode)
			if node.Right != nil {
				nextList.PushBack(node.Right)
			}
			if node.Left != nil {
				nextList.PushBack(node.Left)
			}
			l.Remove(el)
		}
		l = nextList
	}

	return res
}
<|endoftext|>


<commit_before>package ini

import (
	"strings"
	"testing"
)

func assertIsSection(sectionName string, t *testing.T) {
	if !isSection(sectionName) {
		t.Errorf("%q is not a valid section name", sectionName)
	}
}

func assertIsNotSection(sectionName string, t *testing.T) {
	if isSection(sectionName) {
		t.Errorf("%q is a valid section name", sectionName)
	}
}

func expectLine(expectedLine, actualLine string, t *testing.T) {
	if actualLine != expectedLine {
		t.Errorf("expected line %q, got %q", actualLine, expectedLine)
	}
}

func expectProperty(expectedProperty, actualProperty string, t *testing.T) {
	if actualProperty != expectedProperty {
		errmsg := "expected property %q, got %q"
		t.Errorf(errmsg, expectedProperty, actualProperty)
	}
}

func expectValue(expectedValue, actualValue string, t *testing.T) {
	if actualValue != expectedValue {
		errmsg := "expected value %q, got %q"
		t.Errorf(errmsg, expectedValue, actualValue)
	}
}

func TestReadlineEmpty(t *testing.T) {
	linereader := newLineReader(strings.NewReader(""))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("", line, t)
}

func TestReadlineNoNewline(t *testing.T) {
	linereader := newLineReader(strings.NewReader("line without nl"))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("line without nl", line, t)
}

func TestReadline(t *testing.T) {
	reader := strings.NewReader("first line\nsecond line")
	linereader := newLineReader(reader)
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("first line\n", line, t)
}

func TestIsSectionEmptyString(t *testing.T) {
	assertIsNotSection("", t)
}

func TestIsSectionEmptySection(t *testing.T) {
	assertIsNotSection("[]", t)
}

func TestIsSectionOneLetterName(t *testing.T) {
	assertIsSection("[a]", t)
}

func TestIsSectionValid(t *testing.T) {
	assertIsSection("[validsection]", t)
}

func TestParseItemEmptyString(t *testing.T) {
	line := ""
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestParseItemSimpleValid(t *testing.T) {
	line := "foo=bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemWithWhitespace(t *testing.T) {
	line := "foo  = 	bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemUnescapedEqualSign(t *testing.T) {
	line := "foo = bar = baz"
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != TooManyEqualSignsError {
		t.Errorf("expected TooManyEqualSignsError, got %v", err)
	}
}

func TestParseItemWithEscapedEqualSign(t *testing.T) {
	line := "foo = bar \\= baz"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar \\= baz", item.Value, t)
}

// TODO: test parseItem with quoted values!

func TestParseINIEmpty(t *testing.T) {
	config, err := NewConfigFromString("")
	assertErrorIsNil(err, t)
	expectedConfig := make(Config)
	assertConfigMapsEqual(config, &expectedConfig, t)
}

func TestParseINIOneSection(t *testing.T) {
	config, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	section := make(map[string]string)
	expectedConfig := &Config{"section": section}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINITwoSections(t *testing.T) {
	config, err := NewConfigFromString("[section one]\n[section two]")
	assertErrorIsNil(err, t)
	sectionOne := make(map[string]string)
	sectionTwo := make(map[string]string)
	expectedConfig := &Config{
		"section one": sectionOne,
		"section two": sectionTwo}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINISectionWithOneAssignment(t *testing.T) {
	config, err := NewConfigFromString("[section]\nproperty=value")
	assertErrorIsNil(err, t)
	expectedConfig := &Config{"section": {"property": "value"}}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINIAssignmentBeforeSection(t *testing.T) {
	_, err := NewConfigFromString("property=value\n[section]")
	assertErrorIsNotNil(err, t)
	if err != AssignmentOutsideSectionError {
		t.Errorf("expected AssignmentOutsideSectionError, got %v", err)
	}
}

func TestParseINIBrokenAssignment(t *testing.T) {
	_, err := NewConfigFromString("[section]\nproperty value")
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestConfigStringEmpty(t *testing.T) {
	stringedConfig := NewConfig().String()
	if expectedStr := ""; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestConfigStringOneSection(t *testing.T) {
	c, err := parseINI(newLineReader(strings.NewReader("[section]")))
	assertErrorIsNil(err, t)
	stringedConfig := c.String()
	if expectedStr := "[section]"; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestStringSectionWithItem(t *testing.T) {
	filecontent := "[section]\nfoo	=bar"
	c, err := parseINI(newLineReader(strings.NewReader(filecontent)))
	assertErrorIsNil(err, t)
	expectedStr := "[section]\nfoo = bar"
	if stringedConfig := c.String(); stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}
<commit_msg>completely get rid of parseINI calls in the tests<commit_after>package ini

import (
	"strings"
	"testing"
)

func assertIsSection(sectionName string, t *testing.T) {
	if !isSection(sectionName) {
		t.Errorf("%q is not a valid section name", sectionName)
	}
}

func assertIsNotSection(sectionName string, t *testing.T) {
	if isSection(sectionName) {
		t.Errorf("%q is a valid section name", sectionName)
	}
}

func expectLine(expectedLine, actualLine string, t *testing.T) {
	if actualLine != expectedLine {
		t.Errorf("expected line %q, got %q", actualLine, expectedLine)
	}
}

func expectProperty(expectedProperty, actualProperty string, t *testing.T) {
	if actualProperty != expectedProperty {
		errmsg := "expected property %q, got %q"
		t.Errorf(errmsg, expectedProperty, actualProperty)
	}
}

func expectValue(expectedValue, actualValue string, t *testing.T) {
	if actualValue != expectedValue {
		errmsg := "expected value %q, got %q"
		t.Errorf(errmsg, expectedValue, actualValue)
	}
}

func TestReadlineEmpty(t *testing.T) {
	linereader := newLineReader(strings.NewReader(""))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("", line, t)
}

func TestReadlineNoNewline(t *testing.T) {
	linereader := newLineReader(strings.NewReader("line without nl"))
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("line without nl", line, t)
}

func TestReadline(t *testing.T) {
	reader := strings.NewReader("first line\nsecond line")
	linereader := newLineReader(reader)
	line, err := linereader.ReadLine()
	assertErrorIsNil(err, t)
	expectLine("first line\n", line, t)
}

func TestIsSectionEmptyString(t *testing.T) {
	assertIsNotSection("", t)
}

func TestIsSectionEmptySection(t *testing.T) {
	assertIsNotSection("[]", t)
}

func TestIsSectionOneLetterName(t *testing.T) {
	assertIsSection("[a]", t)
}

func TestIsSectionValid(t *testing.T) {
	assertIsSection("[validsection]", t)
}

func TestParseItemEmptyString(t *testing.T) {
	line := ""
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestParseItemSimpleValid(t *testing.T) {
	line := "foo=bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemWithWhitespace(t *testing.T) {
	line := "foo  = 	bar"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar", item.Value, t)
}

func TestParseItemUnescapedEqualSign(t *testing.T) {
	line := "foo = bar = baz"
	_, err := parseItem(line)
	assertErrorIsNotNil(err, t)
	if err != TooManyEqualSignsError {
		t.Errorf("expected TooManyEqualSignsError, got %v", err)
	}
}

func TestParseItemWithEscapedEqualSign(t *testing.T) {
	line := "foo = bar \\= baz"
	item, err := parseItem(line)
	assertErrorIsNil(err, t)
	expectProperty("foo", item.Property, t)
	expectValue("bar \\= baz", item.Value, t)
}

// TODO: test parseItem with quoted values!

func TestParseINIEmpty(t *testing.T) {
	config, err := NewConfigFromString("")
	assertErrorIsNil(err, t)
	expectedConfig := make(Config)
	assertConfigMapsEqual(config, &expectedConfig, t)
}

func TestParseINIOneSection(t *testing.T) {
	config, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	section := make(map[string]string)
	expectedConfig := &Config{"section": section}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINITwoSections(t *testing.T) {
	config, err := NewConfigFromString("[section one]\n[section two]")
	assertErrorIsNil(err, t)
	sectionOne := make(map[string]string)
	sectionTwo := make(map[string]string)
	expectedConfig := &Config{
		"section one": sectionOne,
		"section two": sectionTwo}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINISectionWithOneAssignment(t *testing.T) {
	config, err := NewConfigFromString("[section]\nproperty=value")
	assertErrorIsNil(err, t)
	expectedConfig := &Config{"section": {"property": "value"}}
	assertConfigMapsEqual(config, expectedConfig, t)
}

func TestParseINIAssignmentBeforeSection(t *testing.T) {
	_, err := NewConfigFromString("property=value\n[section]")
	assertErrorIsNotNil(err, t)
	if err != AssignmentOutsideSectionError {
		t.Errorf("expected AssignmentOutsideSectionError, got %v", err)
	}
}

func TestParseINIBrokenAssignment(t *testing.T) {
	_, err := NewConfigFromString("[section]\nproperty value")
	assertErrorIsNotNil(err, t)
	if err != MissingEqualSignError {
		t.Errorf("expected MissingEqualSignError, got %v", err)
	}
}

func TestConfigStringEmpty(t *testing.T) {
	stringedConfig := NewConfig().String()
	if expectedStr := ""; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestConfigStringOneSection(t *testing.T) {
	c, err := NewConfigFromString("[section]")
	assertErrorIsNil(err, t)
	stringedConfig := c.String()
	if expectedStr := "[section]"; stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}

func TestStringSectionWithItem(t *testing.T) {
	c, err := NewConfigFromString("[section]\nfoo	=bar")
	assertErrorIsNil(err, t)
	expectedStr := "[section]\nfoo = bar"
	if stringedConfig := c.String(); stringedConfig != expectedStr {
		t.Errorf("expected %q, got %q", expectedStr, stringedConfig)
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 Thomas de Zeeuw.
//
// Licensed onder the MIT license that can be found in the LICENSE file.

package ini

// todo: test io stuff: http://localhost:6060/pkg/testing/iotest/.

import (
	"strings"
	"testing"
)

func TestSectionLine(t *testing.T) {
	tests := []struct {
		line    string
		section string
	}{
		{"[section]", "section"},
		{"[section];comment", "section"},
		{"[section] ; comment", "section"},
		{"[sec;tion]", "sec;tion"},
		{"[ s e c t i o n ]", "s e c t i o n"},
	}

	for _, test := range tests {
		section, err := parseSection([]byte(test.line))
		if err != nil {
			t.Fatalf("Didn't expect parseSection(%s) to return error: '%s'",
				test.line, err.Error())
		}

		if section != test.section {
			t.Fatalf("Expected parseSection(%s) to return section: %q, but got %q",
				test.line, test.section, section)
		}
	}
}

func TestSectionLineError(t *testing.T) {
	tests := []struct {
		line   string
		errMsg string
	}{
		{"section]", "section should start with \"[\""},
		{"[section] something", "unexpected \"s\" after section closed"},
		{"[section", "unclosed section"},
	}

	for _, test := range tests {
		_, err := parseSection([]byte(test.line))
		if err == nil {
			t.Fatalf("Expected parseSection(%s) to return an error, but didn't get one",
				test.line)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected parseSection(%s) to return error: %q, but got %q",
				test.line, test.errMsg, err.Error())
		}
	}
}

func TestKeyValueLine(t *testing.T) {
	tests := []struct {
		line  string
		key   string
		value string
	}{
		{"key=value", "key", "value"}, // Simple.
		{"k e y=v a l u e", "k e y", "v a l u e"},
		{"key = value", "key", "value"},
		{"key=", "key", ""},
		{"key=value; comment", "key", "value"}, // Simple with comment.
		{"key=value ; comment", "key", "value"},
		{"key = value; comment", "key", "value"},
		{"key = value ; comment", "key", "value"},
		{"key=; comment", "key", ""}, // Simple only comment.
		{"key= ; comment", "key", ""},
		{"key=;", "key", ""}, // Simple empty comment.
		{"key= ;", "key", ""},
		{"key = ;", "key", ""},
		{"key =  ;", "key", ""},

		{`"key"=value`, "key", "value"}, // Double qoute.
		{`"key" = value`, "key", "value"},
		{`key="value"`, "key", "value"},
		{`key = "value"`, "key", "value"},
		{`"key"="value"`, "key", "value"},
		{`"key" = "value"`, "key", "value"},
		{`"key"=value; comment`, "key", "value"}, // Double qoute with comment.
		{`"key"=value ; comment`, "key", "value"},
		{`"key" = value; comment`, "key", "value"},
		{`"key" = value ; comment`, "key", "value"},
		{`key="value"; comment`, "key", "value"},
		{`key="value" ; comment`, "key", "value"},
		{`key = "value"; comment`, "key", "value"},
		{`key = "value" ; comment`, "key", "value"},
		{`"key"="value"; comment`, "key", "value"},
		{`"key"="value" ; comment`, "key", "value"},
		{`"key" = "value"; comment`, "key", "value"},
		{`"key" = "value" ; comment`, "key", "value"},
		{`"key"=; comment`, "key", ""}, // Double qoute only comment.
		{`"key"= ; comment`, "key", ""},
		{`"key" = ; comment`, "key", ""},
		{`key=""; comment`, "key", ""},
		{`key="" ; comment`, "key", ""},
		{`key = ""; comment`, "key", ""},
		{`key = "" ; comment`, "key", ""},
		{`"key"=""; comment`, "key", ""},
		{`"key"="" ; comment`, "key", ""},
		{`"key" = ""; comment`, "key", ""},
		{`"key" = "" ; comment`, "key", ""},
		{`"key"=;`, "key", ""}, // Double quote empty comment.
		{`"key"= ;`, "key", ""},
		{`"key" = ;`, "key", ""},
		{`key="";`, "key", ""},
		{`key="" ;`, "key", ""},
		{`key = "";`, "key", ""},
		{`key = "" ;`, "key", ""},
		{`"key"="";`, "key", ""},
		{`"key"="" ;`, "key", ""},
		{`"key" = "";`, "key", ""},
		{`"key" = "" ;`, "key", ""},

		{"'key'=value", "key", "value"}, // Single qoute.
		{"'key' = value", "key", "value"},
		{"key='value'", "key", "value"},
		{"key = 'value'", "key", "value"},
		{"'key'='value'", "key", "value"},
		{"'key' = 'value'", "key", "value"},
		{"'key'=value; comment", "key", "value"}, // Single qoute with comment.
		{"'key'=value ; comment", "key", "value"},
		{"'key' = value; comment", "key", "value"},
		{"'key' = value ; comment", "key", "value"},
		{"key='value'; comment", "key", "value"},
		{"key='value' ; comment", "key", "value"},
		{"key = 'value'; comment", "key", "value"},
		{"key = 'value' ; comment", "key", "value"},
		{"'key'='value'; comment", "key", "value"},
		{"'key'='value' ; comment", "key", "value"},
		{"'key' = 'value'; comment", "key", "value"},
		{"'key' = 'value' ; comment", "key", "value"},
		{"'key'=; comment", "key", ""}, // Single qoute only comment.
		{"'key'= ; comment", "key", ""},
		{"'key' = ; comment", "key", ""},
		{"key=''; comment", "key", ""},
		{"key='' ; comment", "key", ""},
		{"key = ''; comment", "key", ""},
		{"key = '' ; comment", "key", ""},
		{"'key'=''; comment", "key", ""},
		{"'key'='' ; comment", "key", ""},
		{"'key' = ''; comment", "key", ""},
		{"'key' = '' ; comment", "key", ""},
		{"'key'=;", "key", ""}, // Single quote empty comment.
		{"'key'= ;", "key", ""},
		{"'key' = ;", "key", ""},
		{"key='';", "key", ""},
		{"key='' ;", "key", ""},
		{"key = '';", "key", ""},
		{"key = '' ;", "key", ""},
		{"'key'='';", "key", ""},
		{"'key'='' ;", "key", ""},
		{"'key' = '';", "key", ""},
		{"'key' = '' ;", "key", ""},

		{`"=key"=value`, "=key", "value"}, // Escaped qoutes.
		{`"k\"ey"=value`, `k"ey`, "value"},
		{`key="val\"ue="`, "key", `val"ue=`},

		{"ke;y=value", "ke;y", "value"}, // Misc.
		{`k\\ey=val\\ue`, `k\ey`, `val\ue`},
		{`k\"ey=val\"ue`, `k"ey`, `val"ue`},
		{`key=val\"ue\"`, `key`, `val"ue"`},
		{`key="val\"ue\""`, `key`, `val"ue"`},
		{`\\key=value`, `\key`, "value"},
		{`"ke;y"=value`, "ke;y", "value"},
		{`key="val;ue"`, "key", "val;ue"},
		{`"ke;y"="val;ue"`, "ke;y", "val;ue"},
		{`key==value`, "key", `=value`},
		{`key=value=`, "key", `value=`},
	}

	for _, test := range tests {
		key, value, err := parseKeyValue([]byte(test.line))
		if err != nil {
			t.Fatalf("Didn't expect parseKeyValue(%s) to return error: '%s'",
				test.line, err.Error())
		}

		if key != test.key {
			t.Fatalf("Expected parseKeyValue(%s) to return key: %q, but got %q",
				test.line, test.key, key)
		}

		if value != test.value {
			t.Fatalf("Expected parseKeyValue(%s) to return value: %q, but got %q",
				test.line, test.key, value)
		}
	}
}

func TestKeyValueLineErrors(t *testing.T) {
	tests := []struct {
		line   string
		errMsg string
	}{
		{`"key'=value`, "qoute not closed"},
		{`"key=value`, "qoute not closed"},
		{`'key"=value`, "qoute not closed"},
		{`'key=value`, "qoute not closed"},
		{`key="value'`, "qoute not closed"},
		{`key="value`, "qoute not closed"},
		{`key='value"`, "qoute not closed"},
		{`key='value`, "qoute not closed"},

		{"key", "no separator found"},
		{"key value", "no separator found"},
		{`"key"`, "no separator found"},

		{`"key"value`, `unexpected "v", expected the seperator "="`},
		{`"key"val=ue`, `unexpected "v", expected the seperator "="`},
		{`"key" "2" = value`, `unexpected "\"", expected the seperator "="`},

		{"=value", "key can't be empty"},
	}

	for _, test := range tests {
		_, _, err := parseKeyValue([]byte(test.line))
		if err == nil {
			t.Fatalf("Expected parseKeyValue(%s) to return an error, but didn't get one",
				test.line)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected parseKeyValue(%s) to return error: %q, but got %q",
				test.line, test.errMsg, err.Error())
		}
	}
}

// todo: Add more test data.
func TestParse(t *testing.T) {
	tests := []struct {
		content string
		config  Config
	}{
		{"[section]", Config{Global: {}, "section": {}}},
		{"[section]\n\nkey=value", Config{Global: {}, "section": {"key": "value"}}},
	}

	for _, test := range tests {
		config, err := Parse(strings.NewReader(test.content))
		if err != nil {
			t.Fatalf("Unexpected error from Parse(%s): %s", test.content, err.Error())
		}

		if len(config) != len(test.config) {
			t.Fatalf("Expected Parse(%s) to return %q, but got %q",
				test.content, config, test.config)
		}

		for sectionName, expectedSection := range test.config {
			gotSection, ok := config[sectionName]
			if !ok {
				t.Fatalf("Expected Parse(%s) to return %q, but got %q",
					test.content, config, test.config)
			}

			for key, expected := range expectedSection {
				got := gotSection[key]

				if got != expected {
					t.Fatalf("Expected Parse(%s) to return %q, but got %q",
						test.content, config, test.config)
				}
			}
		}
	}
}

func TestParseError(t *testing.T) {
	tests := []struct {
		content string
		errMsg  string
	}{
		{"key=value\nkey=value2", `ini: synthax error on line 2. key=value2: ` +
			`key "key" already used in section "SUPERGLOBAL"`},
		{"=value", `ini: synthax error on line 1. =value: key can't be empty`},
		{"[section", `ini: synthax error on line 1. [section: unclosed section`},
	}

	for _, test := range tests {
		_, err := Parse(strings.NewReader(test.content))
		if err == nil {
			t.Fatalf("Expected Parse(%s) to return an error, but didn't get one",
				test.content)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected Parse(%s) to return error: %q, but got %q",
				test.content, test.errMsg, err.Error())
		}
	}
}
<commit_msg>Add parse io error test<commit_after>// Copyright (C) 2015 Thomas de Zeeuw.
//
// Licensed onder the MIT license that can be found in the LICENSE file.

package ini

// todo: test io stuff: http://localhost:6060/pkg/testing/iotest/.

import (
	"strings"
	"testing"
	"testing/iotest"
)

func TestSectionLine(t *testing.T) {
	tests := []struct {
		line    string
		section string
	}{
		{"[section]", "section"},
		{"[section];comment", "section"},
		{"[section] ; comment", "section"},
		{"[sec;tion]", "sec;tion"},
		{"[ s e c t i o n ]", "s e c t i o n"},
	}

	for _, test := range tests {
		section, err := parseSection([]byte(test.line))
		if err != nil {
			t.Fatalf("Didn't expect parseSection(%s) to return error: '%s'",
				test.line, err.Error())
		}

		if section != test.section {
			t.Fatalf("Expected parseSection(%s) to return section: %q, but got %q",
				test.line, test.section, section)
		}
	}
}

func TestSectionLineError(t *testing.T) {
	tests := []struct {
		line   string
		errMsg string
	}{
		{"section]", "section should start with \"[\""},
		{"[section] something", "unexpected \"s\" after section closed"},
		{"[section", "unclosed section"},
	}

	for _, test := range tests {
		_, err := parseSection([]byte(test.line))
		if err == nil {
			t.Fatalf("Expected parseSection(%s) to return an error, but didn't get one",
				test.line)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected parseSection(%s) to return error: %q, but got %q",
				test.line, test.errMsg, err.Error())
		}
	}
}

func TestKeyValueLine(t *testing.T) {
	tests := []struct {
		line  string
		key   string
		value string
	}{
		{"key=value", "key", "value"}, // Simple.
		{"k e y=v a l u e", "k e y", "v a l u e"},
		{"key = value", "key", "value"},
		{"key=", "key", ""},
		{"key=value; comment", "key", "value"}, // Simple with comment.
		{"key=value ; comment", "key", "value"},
		{"key = value; comment", "key", "value"},
		{"key = value ; comment", "key", "value"},
		{"key=; comment", "key", ""}, // Simple only comment.
		{"key= ; comment", "key", ""},
		{"key=;", "key", ""}, // Simple empty comment.
		{"key= ;", "key", ""},
		{"key = ;", "key", ""},
		{"key =  ;", "key", ""},

		{`"key"=value`, "key", "value"}, // Double qoute.
		{`"key" = value`, "key", "value"},
		{`key="value"`, "key", "value"},
		{`key = "value"`, "key", "value"},
		{`"key"="value"`, "key", "value"},
		{`"key" = "value"`, "key", "value"},
		{`"key"=value; comment`, "key", "value"}, // Double qoute with comment.
		{`"key"=value ; comment`, "key", "value"},
		{`"key" = value; comment`, "key", "value"},
		{`"key" = value ; comment`, "key", "value"},
		{`key="value"; comment`, "key", "value"},
		{`key="value" ; comment`, "key", "value"},
		{`key = "value"; comment`, "key", "value"},
		{`key = "value" ; comment`, "key", "value"},
		{`"key"="value"; comment`, "key", "value"},
		{`"key"="value" ; comment`, "key", "value"},
		{`"key" = "value"; comment`, "key", "value"},
		{`"key" = "value" ; comment`, "key", "value"},
		{`"key"=; comment`, "key", ""}, // Double qoute only comment.
		{`"key"= ; comment`, "key", ""},
		{`"key" = ; comment`, "key", ""},
		{`key=""; comment`, "key", ""},
		{`key="" ; comment`, "key", ""},
		{`key = ""; comment`, "key", ""},
		{`key = "" ; comment`, "key", ""},
		{`"key"=""; comment`, "key", ""},
		{`"key"="" ; comment`, "key", ""},
		{`"key" = ""; comment`, "key", ""},
		{`"key" = "" ; comment`, "key", ""},
		{`"key"=;`, "key", ""}, // Double quote empty comment.
		{`"key"= ;`, "key", ""},
		{`"key" = ;`, "key", ""},
		{`key="";`, "key", ""},
		{`key="" ;`, "key", ""},
		{`key = "";`, "key", ""},
		{`key = "" ;`, "key", ""},
		{`"key"="";`, "key", ""},
		{`"key"="" ;`, "key", ""},
		{`"key" = "";`, "key", ""},
		{`"key" = "" ;`, "key", ""},

		{"'key'=value", "key", "value"}, // Single qoute.
		{"'key' = value", "key", "value"},
		{"key='value'", "key", "value"},
		{"key = 'value'", "key", "value"},
		{"'key'='value'", "key", "value"},
		{"'key' = 'value'", "key", "value"},
		{"'key'=value; comment", "key", "value"}, // Single qoute with comment.
		{"'key'=value ; comment", "key", "value"},
		{"'key' = value; comment", "key", "value"},
		{"'key' = value ; comment", "key", "value"},
		{"key='value'; comment", "key", "value"},
		{"key='value' ; comment", "key", "value"},
		{"key = 'value'; comment", "key", "value"},
		{"key = 'value' ; comment", "key", "value"},
		{"'key'='value'; comment", "key", "value"},
		{"'key'='value' ; comment", "key", "value"},
		{"'key' = 'value'; comment", "key", "value"},
		{"'key' = 'value' ; comment", "key", "value"},
		{"'key'=; comment", "key", ""}, // Single qoute only comment.
		{"'key'= ; comment", "key", ""},
		{"'key' = ; comment", "key", ""},
		{"key=''; comment", "key", ""},
		{"key='' ; comment", "key", ""},
		{"key = ''; comment", "key", ""},
		{"key = '' ; comment", "key", ""},
		{"'key'=''; comment", "key", ""},
		{"'key'='' ; comment", "key", ""},
		{"'key' = ''; comment", "key", ""},
		{"'key' = '' ; comment", "key", ""},
		{"'key'=;", "key", ""}, // Single quote empty comment.
		{"'key'= ;", "key", ""},
		{"'key' = ;", "key", ""},
		{"key='';", "key", ""},
		{"key='' ;", "key", ""},
		{"key = '';", "key", ""},
		{"key = '' ;", "key", ""},
		{"'key'='';", "key", ""},
		{"'key'='' ;", "key", ""},
		{"'key' = '';", "key", ""},
		{"'key' = '' ;", "key", ""},

		{`"=key"=value`, "=key", "value"}, // Escaped qoutes.
		{`"k\"ey"=value`, `k"ey`, "value"},
		{`key="val\"ue="`, "key", `val"ue=`},

		{"ke;y=value", "ke;y", "value"}, // Misc.
		{`k\\ey=val\\ue`, `k\ey`, `val\ue`},
		{`k\"ey=val\"ue`, `k"ey`, `val"ue`},
		{`key=val\"ue\"`, `key`, `val"ue"`},
		{`key="val\"ue\""`, `key`, `val"ue"`},
		{`\\key=value`, `\key`, "value"},
		{`"ke;y"=value`, "ke;y", "value"},
		{`key="val;ue"`, "key", "val;ue"},
		{`"ke;y"="val;ue"`, "ke;y", "val;ue"},
		{`key==value`, "key", `=value`},
		{`key=value=`, "key", `value=`},
	}

	for _, test := range tests {
		key, value, err := parseKeyValue([]byte(test.line))
		if err != nil {
			t.Fatalf("Didn't expect parseKeyValue(%s) to return error: '%s'",
				test.line, err.Error())
		}

		if key != test.key {
			t.Fatalf("Expected parseKeyValue(%s) to return key: %q, but got %q",
				test.line, test.key, key)
		}

		if value != test.value {
			t.Fatalf("Expected parseKeyValue(%s) to return value: %q, but got %q",
				test.line, test.key, value)
		}
	}
}

func TestKeyValueLineErrors(t *testing.T) {
	tests := []struct {
		line   string
		errMsg string
	}{
		{`"key'=value`, "qoute not closed"},
		{`"key=value`, "qoute not closed"},
		{`'key"=value`, "qoute not closed"},
		{`'key=value`, "qoute not closed"},
		{`key="value'`, "qoute not closed"},
		{`key="value`, "qoute not closed"},
		{`key='value"`, "qoute not closed"},
		{`key='value`, "qoute not closed"},

		{"key", "no separator found"},
		{"key value", "no separator found"},
		{`"key"`, "no separator found"},

		{`"key"value`, `unexpected "v", expected the seperator "="`},
		{`"key"val=ue`, `unexpected "v", expected the seperator "="`},
		{`"key" "2" = value`, `unexpected "\"", expected the seperator "="`},

		{"=value", "key can't be empty"},
	}

	for _, test := range tests {
		_, _, err := parseKeyValue([]byte(test.line))
		if err == nil {
			t.Fatalf("Expected parseKeyValue(%s) to return an error, but didn't get one",
				test.line)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected parseKeyValue(%s) to return error: %q, but got %q",
				test.line, test.errMsg, err.Error())
		}
	}
}

// todo: Add more test data.
func TestParse(t *testing.T) {
	tests := []struct {
		content string
		config  Config
	}{
		{"[section]", Config{Global: {}, "section": {}}},
		{"[section]\n\nkey=value", Config{Global: {}, "section": {"key": "value"}}},
	}

	for _, test := range tests {
		config, err := Parse(strings.NewReader(test.content))
		if err != nil {
			t.Fatalf("Unexpected error from Parse(%s): %s", test.content, err.Error())
		}

		if len(config) != len(test.config) {
			t.Fatalf("Expected Parse(%s) to return %q, but got %q",
				test.content, config, test.config)
		}

		for sectionName, expectedSection := range test.config {
			gotSection, ok := config[sectionName]
			if !ok {
				t.Fatalf("Expected Parse(%s) to return %q, but got %q",
					test.content, config, test.config)
			}

			for key, expected := range expectedSection {
				got := gotSection[key]

				if got != expected {
					t.Fatalf("Expected Parse(%s) to return %q, but got %q",
						test.content, config, test.config)
				}
			}
		}
	}
}

func TestParseError(t *testing.T) {
	tests := []struct {
		content string
		errMsg  string
	}{
		{"key=value\nkey=value2", `ini: synthax error on line 2. key=value2: ` +
			`key "key" already used in section "SUPERGLOBAL"`},
		{"=value", `ini: synthax error on line 1. =value: key can't be empty`},
		{"[section", `ini: synthax error on line 1. [section: unclosed section`},
	}

	for _, test := range tests {
		_, err := Parse(strings.NewReader(test.content))
		if err == nil {
			t.Fatalf("Expected Parse(%s) to return an error, but didn't get one",
				test.content)
		}

		if err.Error() != test.errMsg {
			t.Fatalf("Expected Parse(%s) to return error: %q, but got %q",
				test.content, test.errMsg, err.Error())
		}
	}
}

func TestParseIOError(t *testing.T) {
	r := iotest.TimeoutReader(strings.NewReader("key=value\nkey2=value2"))

	_, err := Parse(r)
	if err == nil {
		t.Fatalf("Expected Parse() to return an error, but didn't get one")
	}

	errMsg := "ini: error reading: " + iotest.ErrTimeout.Error()
	if err.Error() != errMsg {
		t.Fatalf("Expected Parse() to return error: %q, but got %q",
			errMsg, err.Error())
	}
}
<|endoftext|>