<commit_before>package mailgun

import (
	"fmt"
	"github.com/mbanzon/simplehttp"
	"time"
)

// TODO(sfalvo):
// Abstract Paging/Links into an interface type or something which lets you page through
// data.  Borrow from Gophercloud's data interpreters.

// Events are open-ended, loosely-defined JSON documents.
// They will always have an event and a timestamp field, however.
type Event map[string]interface{}

// Links encapsulates navigation opportunities to find more information
// about things.
// TODO(sfalvo): Rename to Paging
type Links map[string]string

// noTime always equals an uninitialized Time structure.
// It's used to detect when a time parameter is provided.
var noTime time.Time

// GetEventsOptions lets the caller of GetEvents() specify how the results are to be returned.
// Begin and End time-box the results returned.
// ForceAscending and ForceDescending are used to force Mailgun to use a given traversal order of the events.
// If both ForceAscending and ForceDescending are true, an error will result.
// If none, the default will be inferred from the Begin and End parameters.
// Limit caps the number of results returned.  If left unspecified, Mailgun assumes 100.
// Compact, if true, compacts the returned JSON to minimize transmission bandwidth.
// Otherwise, the JSON is spaced appropriately for human consumption.
// Filter allows the caller to provide more specialized filters on the query.
// Consult the Mailgun documentation for more details.
type GetEventsOptions struct {
	Begin, End                               time.Time
	ForceAscending, ForceDescending, Compact bool
	Limit                                    int
	Filter                                   map[string]string
}

// GetEvents provides the caller with a list of log entries.
// See the GetEventsOptions structure for information on how to customize the list returned.
// Note that the API responds with events with open definitions;
// that is, no specific standard structure exists for them.
// Thus, you'll need to provide your own accessors to the information of interest.
func (mg *MailgunImpl) GetEvents(opts GetEventsOptions) ([]Event, Links, error) {
	if opts.ForceAscending && opts.ForceDescending {
		return nil, nil, fmt.Errorf("collation cannot at once be both ascending and descending")
	}

	payload := simplehttp.NewUrlEncodedPayload()
	if opts.Limit != 0 {
		payload.AddValue("limit", fmt.Sprintf("%d", opts.Limit))
	}
	if opts.Compact {
		payload.AddValue("pretty", "no")
	}
	if opts.ForceAscending {
		payload.AddValue("ascending", "yes")
	}
	if opts.ForceDescending {
		payload.AddValue("ascending", "no")
	}
	if opts.Begin != noTime {
		payload.AddValue("begin", formatMailgunTime(&opts.Begin))
	}
	if opts.End != noTime {
		payload.AddValue("end", formatMailgunTime(&opts.End))
	}
	if opts.Filter != nil {
		for k, v := range opts.Filter {
			payload.AddValue(k, v)
		}
	}

	url, err := generateParameterizedUrl(mg, eventsEndpoint, payload)
	if err != nil {
		return nil, nil, err
	}
	r := simplehttp.NewHTTPRequest(url)
	r.SetBasicAuth(basicAuthUser, mg.ApiKey())
	var response map[string]interface{}
	err = getResponseFromJSON(r, &response)
	if err != nil {
		return nil, nil, err
	}

	items := response["items"].([]interface{})
	events := make([]Event, len(items))
	for i, item := range items {
		events[i] = item.(map[string]interface{})
	}

	pagings := response["paging"].(map[string]interface{})
	var links = make(Links, len(pagings))
	for key, page := range pagings {
		links[key] = page.(string)
	}

	return events, links, err
}
<commit_msg>Create EventIterator object.<commit_after>package mailgun

import (
	"fmt"
	"github.com/mbanzon/simplehttp"
	"time"
)

// TODO(sfalvo):
// Abstract Paging/Links into an interface type or something which lets you page through
// data.  Borrow from Gophercloud's data interpreters.

// Events are open-ended, loosely-defined JSON documents.
// They will always have an event and a timestamp field, however.
type Event map[string]interface{}

// Links encapsulates navigation opportunities to find more information
// about things.
// TODO(sfalvo): Rename to Paging
type Links map[string]string

// noTime always equals an uninitialized Time structure.
// It's used to detect when a time parameter is provided.
var noTime time.Time

// GetEventsOptions lets the caller of GetEvents() specify how the results are to be returned.
// Begin and End time-box the results returned.
// ForceAscending and ForceDescending are used to force Mailgun to use a given traversal order of the events.
// If both ForceAscending and ForceDescending are true, an error will result.
// If none, the default will be inferred from the Begin and End parameters.
// Limit caps the number of results returned.  If left unspecified, Mailgun assumes 100.
// Compact, if true, compacts the returned JSON to minimize transmission bandwidth.
// Otherwise, the JSON is spaced appropriately for human consumption.
// Filter allows the caller to provide more specialized filters on the query.
// Consult the Mailgun documentation for more details.
type GetEventsOptions struct {
	Begin, End                               time.Time
	ForceAscending, ForceDescending, Compact bool
	Limit                                    int
	Filter                                   map[string]string
}

type EventIterator struct {
	events []Event
	nextURL, prevURL string
	mg Mailgun
}

// GetEvents provides the caller with a list of log entries.
// See the GetEventsOptions structure for information on how to customize the list returned.
// Note that the API responds with events with open definitions;
// that is, no specific standard structure exists for them.
// Thus, you'll need to provide your own accessors to the information of interest.
//
// DEPRECATED.  Use GetEventsIterator() instead.
func (mg *MailgunImpl) GetEvents(opts GetEventsOptions) ([]Event, Links, error) {
	ei, err := mg.GetEventsIterator(opts)
	if err != nil {
		return nil, nil, err
	}
	return ei.Events(), nil, nil
}

func (mg *MailgunImpl) GetEventsIterator(opts GetEventsOptions) (*EventIterator, error) {
	ei := mg.NewEventIterator()
	err := ei.GetFirstPage(opts)
	return ei, err
}

func (mg *MailgunImpl) NewEventIterator() *EventIterator {
	return &EventIterator{mg: mg}
}

func (ei *EventIterator) Events() []Event {
	return ei.events
}

func (ei *EventIterator) IsAtBeginning() bool {
	return ei.prevURL == ""
}

func (ei *EventIterator) IsAtEnd() bool {
	return ei.nextURL == ""
}

func (ei *EventIterator) GetFirstPage(opts GetEventsOptions) error {
	if opts.ForceAscending && opts.ForceDescending {
		return fmt.Errorf("collation cannot at once be both ascending and descending")
	}

	payload := simplehttp.NewUrlEncodedPayload()
	if opts.Limit != 0 {
		payload.AddValue("limit", fmt.Sprintf("%d", opts.Limit))
	}
	if opts.Compact {
		payload.AddValue("pretty", "no")
	}
	if opts.ForceAscending {
		payload.AddValue("ascending", "yes")
	}
	if opts.ForceDescending {
		payload.AddValue("ascending", "no")
	}
	if opts.Begin != noTime {
		payload.AddValue("begin", formatMailgunTime(&opts.Begin))
	}
	if opts.End != noTime {
		payload.AddValue("end", formatMailgunTime(&opts.End))
	}
	if opts.Filter != nil {
		for k, v := range opts.Filter {
			payload.AddValue(k, v)
		}
	}

	url, err := generateParameterizedUrl(ei.mg, eventsEndpoint, payload)
	if err != nil {
		return err
	}
	r := simplehttp.NewHTTPRequest(url)
	r.SetBasicAuth(basicAuthUser, ei.mg.ApiKey())
	var response map[string]interface{}
	err = getResponseFromJSON(r, &response)
	if err != nil {
		return err
	}

	items := response["items"].([]interface{})
	ei.events = make([]Event, len(items))
	for i, item := range items {
		ei.events[i] = item.(map[string]interface{})
	}

	pagings := response["paging"].(map[string]interface{})
	links := make(map[string]string, len(pagings))
	for key, page := range pagings {
		links[key] = page.(string)
	}
	ei.nextURL = links["next"]
	ei.prevURL = links["previous"]
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdExport = &Command{
	Run:   runExport,
	Usage: "export [dir]",
	Short: "Export metadata to a local directory",
	Long: `
Export metadata to a local directory

Examples:

  force export

  force export org/schema
`,
}

func runExport(cmd *Command, args []string) {
	wd, _ := os.Getwd()
	root := filepath.Join(wd, "metadata")
	if len(args) == 1 {
		root, _ = filepath.Abs(args[0])
	}
	force, _ := ActiveForce()
	sobjects, err := force.ListSobjects()
	if err != nil {
		ErrorAndExit(err.Error())
	}
	stdObjects := make([]string, 1, len(sobjects)+1)
	stdObjects[0] = "*"
	for _, sobject := range sobjects {
		name := sobject["name"].(string)
		if !sobject["custom"].(bool) && !strings.HasSuffix(name, "__Tag") && !strings.HasSuffix(name, "__History") && !strings.HasSuffix(name, "__Share") {
			stdObjects = append(stdObjects, name)
		}
	}
	query := ForceMetadataQuery{
		{Name: "AccountSettings", Members: []string{"*"}},
		{Name: "ActivitiesSettings", Members: []string{"*"}},
		{Name: "AddressSettings", Members: []string{"*"}},
		{Name: "AnalyticSnapshot", Members: []string{"*"}},
		{Name: "ApexClass", Members: []string{"*"}},
		{Name: "ApexComponent", Members: []string{"*"}},
		{Name: "ApexPage", Members: []string{"*"}},
		{Name: "ApexTrigger", Members: []string{"*"}},
		{Name: "ApprovalProcess", Members: []string{"*"}},
		{Name: "AssignmentRules", Members: []string{"*"}},
		{Name: "AuthProvider", Members: []string{"*"}},
		{Name: "AutoResponseRules", Members: []string{"*"}},
		{Name: "BusinessHoursSettings", Members: []string{"*"}},
		{Name: "BusinessProcess", Members: []string{"*"}},
		{Name: "CallCenter", Members: []string{"*"}},
		{Name: "CaseSettings", Members: []string{"*"}},
		{Name: "ChatterAnswersSettings", Members: []string{"*"}},
		{Name: "CompanySettings", Members: []string{"*"}},
		{Name: "Community", Members: []string{"*"}},
		{Name: "CompactLayout", Members: []string{"*"}},
		{Name: "ConnectedApp", Members: []string{"*"}},
		{Name: "ContractSettings", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomApplicationComponent", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomField", Members: []string{"*"}},
		{Name: "CustomLabels", Members: []string{"*"}},
		{Name: "CustomObject", Members: stdObjects},
		{Name: "CustomObjectTranslation", Members: []string{"*"}},
		{Name: "CustomPageWebLink", Members: []string{"*"}},
		{Name: "CustomSite", Members: []string{"*"}},
		{Name: "CustomTab", Members: []string{"*"}},
		{Name: "Dashboard", Members: []string{"*"}},
		{Name: "DataCategoryGroup", Members: []string{"*"}},
		{Name: "Document", Members: []string{"*"}},
		{Name: "EmailTemplate", Members: []string{"*"}},
		{Name: "EntitlementProcess", Members: []string{"*"}},
		{Name: "EntitlementSettings", Members: []string{"*"}},
		{Name: "EntitlementTemplate", Members: []string{"*"}},
		{Name: "ExternalDataSource", Members: []string{"*"}},
		{Name: "FieldSet", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
		{Name: "Folder", Members: []string{"*"}},
		{Name: "ForecastingSettings", Members: []string{"*"}},
		{Name: "Group", Members: []string{"*"}},
		{Name: "HomePageComponent", Members: []string{"*"}},
		{Name: "HomePageLayout", Members: []string{"*"}},
		{Name: "IdeasSettings", Members: []string{"*"}},
		{Name: "KnowledgeSettings", Members: []string{"*"}},
		{Name: "Layout", Members: []string{"*"}},
		{Name: "Letterhead", Members: []string{"*"}},
		{Name: "ListView", Members: []string{"*"}},
		{Name: "LiveAgentSettings", Members: []string{"*"}},
		{Name: "LiveChatAgentConfig", Members: []string{"*"}},
		{Name: "LiveChatButton", Members: []string{"*"}},
		{Name: "LiveChatDeployment", Members: []string{"*"}},
		{Name: "MilestoneType", Members: []string{"*"}},
		{Name: "MobileSettings", Members: []string{"*"}},
		{Name: "NamedFilter", Members: []string{"*"}},
		{Name: "Network", Members: []string{"*"}},
		{Name: "OpportunitySettings", Members: []string{"*"}},
		{Name: "PermissionSet", Members: []string{"*"}},
		{Name: "Portal", Members: []string{"*"}},
		{Name: "PostTemplate", Members: []string{"*"}},
		{Name: "ProductSettings", Members: []string{"*"}},
		{Name: "Profile", Members: []string{"*"}},
		{Name: "Queue", Members: []string{"*"}},
		{Name: "QuickAction", Members: []string{"*"}},
		{Name: "QuoteSettings", Members: []string{"*"}},
		{Name: "RecordType", Members: []string{"*"}},
		{Name: "RemoteSiteSetting", Members: []string{"*"}},
		{Name: "Report", Members: []string{"*"}},
		{Name: "ReportType", Members: []string{"*"}},
		{Name: "Role", Members: []string{"*"}},
		{Name: "SamlSsoConfig", Members: []string{"*"}},
		{Name: "Scontrol", Members: []string{"*"}},
		{Name: "SecuritySettings", Members: []string{"*"}},
		{Name: "SharingReason", Members: []string{"*"}},
		{Name: "Skill", Members: []string{"*"}},
		{Name: "StaticResource", Members: []string{"*"}},
		{Name: "Territory", Members: []string{"*"}},
		{Name: "Translations", Members: []string{"*"}},
		{Name: "ValidationRule", Members: []string{"*"}},
		{Name: "Workflow", Members: []string{"*"}},
	}
	files, err := force.Metadata.Retrieve(query)
	if err != nil {
		fmt.Printf("Encountered and error with retrieve...\n")
		ErrorAndExit(err.Error())
	}
	for name, data := range files {
		file := filepath.Join(root, name)
		dir := filepath.Dir(file)
		if err := os.MkdirAll(dir, 0755); err != nil {
			ErrorAndExit(err.Error())
		}
		if err := ioutil.WriteFile(filepath.Join(root, name), data, 0644); err != nil {
			ErrorAndExit(err.Error())
		}
	}
	fmt.Printf("Exported to %s\n", root)
}
<commit_msg>Export SharingRules<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdExport = &Command{
	Run:   runExport,
	Usage: "export [dir]",
	Short: "Export metadata to a local directory",
	Long: `
Export metadata to a local directory

Examples:

  force export

  force export org/schema
`,
}

func runExport(cmd *Command, args []string) {
	wd, _ := os.Getwd()
	root := filepath.Join(wd, "metadata")
	if len(args) == 1 {
		root, _ = filepath.Abs(args[0])
	}
	force, _ := ActiveForce()
	sobjects, err := force.ListSobjects()
	if err != nil {
		ErrorAndExit(err.Error())
	}
	stdObjects := make([]string, 1, len(sobjects)+1)
	stdObjects[0] = "*"
	for _, sobject := range sobjects {
		name := sobject["name"].(string)
		if !sobject["custom"].(bool) && !strings.HasSuffix(name, "__Tag") && !strings.HasSuffix(name, "__History") && !strings.HasSuffix(name, "__Share") {
			stdObjects = append(stdObjects, name)
		}
	}
	query := ForceMetadataQuery{
		{Name: "AccountSettings", Members: []string{"*"}},
		{Name: "ActivitiesSettings", Members: []string{"*"}},
		{Name: "AddressSettings", Members: []string{"*"}},
		{Name: "AnalyticSnapshot", Members: []string{"*"}},
		{Name: "ApexClass", Members: []string{"*"}},
		{Name: "ApexComponent", Members: []string{"*"}},
		{Name: "ApexPage", Members: []string{"*"}},
		{Name: "ApexTrigger", Members: []string{"*"}},
		{Name: "ApprovalProcess", Members: []string{"*"}},
		{Name: "AssignmentRules", Members: []string{"*"}},
		{Name: "AuthProvider", Members: []string{"*"}},
		{Name: "AutoResponseRules", Members: []string{"*"}},
		{Name: "BusinessHoursSettings", Members: []string{"*"}},
		{Name: "BusinessProcess", Members: []string{"*"}},
		{Name: "CallCenter", Members: []string{"*"}},
		{Name: "CaseSettings", Members: []string{"*"}},
		{Name: "ChatterAnswersSettings", Members: []string{"*"}},
		{Name: "CompanySettings", Members: []string{"*"}},
		{Name: "Community", Members: []string{"*"}},
		{Name: "CompactLayout", Members: []string{"*"}},
		{Name: "ConnectedApp", Members: []string{"*"}},
		{Name: "ContractSettings", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomApplicationComponent", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomField", Members: []string{"*"}},
		{Name: "CustomLabels", Members: []string{"*"}},
		{Name: "CustomObject", Members: stdObjects},
		{Name: "CustomObjectTranslation", Members: []string{"*"}},
		{Name: "CustomPageWebLink", Members: []string{"*"}},
		{Name: "CustomSite", Members: []string{"*"}},
		{Name: "CustomTab", Members: []string{"*"}},
		{Name: "Dashboard", Members: []string{"*"}},
		{Name: "DataCategoryGroup", Members: []string{"*"}},
		{Name: "Document", Members: []string{"*"}},
		{Name: "EmailTemplate", Members: []string{"*"}},
		{Name: "EntitlementProcess", Members: []string{"*"}},
		{Name: "EntitlementSettings", Members: []string{"*"}},
		{Name: "EntitlementTemplate", Members: []string{"*"}},
		{Name: "ExternalDataSource", Members: []string{"*"}},
		{Name: "FieldSet", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
		{Name: "Folder", Members: []string{"*"}},
		{Name: "ForecastingSettings", Members: []string{"*"}},
		{Name: "Group", Members: []string{"*"}},
		{Name: "HomePageComponent", Members: []string{"*"}},
		{Name: "HomePageLayout", Members: []string{"*"}},
		{Name: "IdeasSettings", Members: []string{"*"}},
		{Name: "KnowledgeSettings", Members: []string{"*"}},
		{Name: "Layout", Members: []string{"*"}},
		{Name: "Letterhead", Members: []string{"*"}},
		{Name: "ListView", Members: []string{"*"}},
		{Name: "LiveAgentSettings", Members: []string{"*"}},
		{Name: "LiveChatAgentConfig", Members: []string{"*"}},
		{Name: "LiveChatButton", Members: []string{"*"}},
		{Name: "LiveChatDeployment", Members: []string{"*"}},
		{Name: "MilestoneType", Members: []string{"*"}},
		{Name: "MobileSettings", Members: []string{"*"}},
		{Name: "NamedFilter", Members: []string{"*"}},
		{Name: "Network", Members: []string{"*"}},
		{Name: "OpportunitySettings", Members: []string{"*"}},
		{Name: "PermissionSet", Members: []string{"*"}},
		{Name: "Portal", Members: []string{"*"}},
		{Name: "PostTemplate", Members: []string{"*"}},
		{Name: "ProductSettings", Members: []string{"*"}},
		{Name: "Profile", Members: []string{"*"}},
		{Name: "Queue", Members: []string{"*"}},
		{Name: "QuickAction", Members: []string{"*"}},
		{Name: "QuoteSettings", Members: []string{"*"}},
		{Name: "RecordType", Members: []string{"*"}},
		{Name: "RemoteSiteSetting", Members: []string{"*"}},
		{Name: "Report", Members: []string{"*"}},
		{Name: "ReportType", Members: []string{"*"}},
		{Name: "Role", Members: []string{"*"}},
		{Name: "SamlSsoConfig", Members: []string{"*"}},
		{Name: "Scontrol", Members: []string{"*"}},
		{Name: "SecuritySettings", Members: []string{"*"}},
		{Name: "SharingReason", Members: []string{"*"}},
		{Name: "SharingRules", Members: []string{"*"}},
		{Name: "Skill", Members: []string{"*"}},
		{Name: "StaticResource", Members: []string{"*"}},
		{Name: "Territory", Members: []string{"*"}},
		{Name: "Translations", Members: []string{"*"}},
		{Name: "ValidationRule", Members: []string{"*"}},
		{Name: "Workflow", Members: []string{"*"}},
	}
	files, err := force.Metadata.Retrieve(query)
	if err != nil {
		fmt.Printf("Encountered and error with retrieve...\n")
		ErrorAndExit(err.Error())
	}
	for name, data := range files {
		file := filepath.Join(root, name)
		dir := filepath.Dir(file)
		if err := os.MkdirAll(dir, 0755); err != nil {
			ErrorAndExit(err.Error())
		}
		if err := ioutil.WriteFile(filepath.Join(root, name), data, 0644); err != nil {
			ErrorAndExit(err.Error())
		}
	}
	fmt.Printf("Exported to %s\n", root)
}
<|endoftext|>


<commit_before>package form

import (
	"math"
	"reflect"
	"strconv"
	"strings"
)

type processor interface {
	process(reflect.Value, []string) error
}

type inum struct {
	min, max int64
	bits     int
}

func newInum(tags reflect.StructTag, bits int) inum {
	i := inum{
		min:  math.MinInt64,
		max:  math.MaxInt64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		im, err := strconv.ParseInt(m, 10, bits)
		if err == nil {
			i.min = im
		}
	}
	if m := tags.Get("max"); m != "" {
		im, err := strconv.ParseInt(m, 10, bits)
		if err == nil {
			i.max = im
		}
	}
	return i
}

func (i inum) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseInt(data[0], 10, i.bits)
	if err != nil {
		return err
	}
	if num < i.min || num > i.max {
		return ErrNotInRange
	}
	v.SetInt(num)
	return nil
}

type unum struct {
	min, max uint64
	bits     int
}

func newUnum(tags reflect.StructTag, bits int) unum {
	u := unum{
		max:  math.MaxUint64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		um, err := strconv.ParseUint(m, 10, bits)
		if err == nil {
			u.min = um
		}
	}
	if m := tags.Get("max"); m != "" {
		um, err := strconv.ParseUint(m, 10, bits)
		if err == nil {
			u.max = um
		}
	}
	return u
}

func (u unum) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseUint(data[0], 10, u.bits)
	if err != nil {
		return err
	}
	if num < u.min || num > u.max {
		return ErrNotInRange
	}
	v.SetUint(num)
	return nil
}

type float struct {
	min, max float64
	bits     int
}

func newFloat(tags reflect.StructTag, bits int) float {
	f := float{
		min:  -math.MaxFloat64,
		max:  math.MaxFloat64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		um, err := strconv.ParseFloat(m, bits)
		if err == nil {
			f.min = um
		}
	}
	if m := tags.Get("max"); m != "" {
		um, err := strconv.ParseFloat(m, bits)
		if err == nil {
			f.max = um
		}
	}
	return f
}

func (f float) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseFloat(data[0], f.bits)
	if err != nil {
		return err
	}
	if num < f.min || num > f.max {
		return ErrNotInRange
	}
	v.SetFloat(num)
	return nil
}

type str struct{}

func (str) process(v reflect.Value, data []string) error {
	v.SetString(data[0])
	return nil
}

type boolean struct{}

func (boolean) process(v reflect.Value, data []string) error {
	switch strings.ToLower(data[0]) {
	case "on", "yes", "y", "1", "t", "true":
		v.SetBool(true)
	case "off", "no", "n", "0", "f", "false":
		v.SetBool(false)
	default:
		return ErrInvalidBoolean
	}
	return nil
}

type slice struct {
	processor
	typ reflect.Type
}

func (s slice) process(v reflect.Value, data []string) error {
	v.Set(reflect.MakeSlice(s.typ, 1, len(data)))
	l := 0
	errs := make(Errors, 0)
	for n := range data {
		if err := s.processor.process(v.Index(l), data[n:]); err != nil {
			errs = append(errs, err)
		} else if l < len(data) {
			l++
			v.SetLen(l + 1)
		}
	}
	if len(errs) > 0 {
		return errs
	}
	return nil
}

type pointer struct {
	processor
	typ reflect.Type
}

func (p pointer) process(v reflect.Value, data []string) error {
	pv := reflect.New(p.typ)
	if err := p.processor.process(pv.Elem(), data); err != nil {
		return err
	}
	v.Set(pv)
	return nil
}
<commit_msg>added a processor to run custom (interface'd) code on a value<commit_after>package form

import (
	"math"
	"reflect"
	"strconv"
	"strings"
)

type processor interface {
	process(reflect.Value, []string) error
}

type inum struct {
	min, max int64
	bits     int
}

func newInum(tags reflect.StructTag, bits int) inum {
	i := inum{
		min:  math.MinInt64,
		max:  math.MaxInt64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		im, err := strconv.ParseInt(m, 10, bits)
		if err == nil {
			i.min = im
		}
	}
	if m := tags.Get("max"); m != "" {
		im, err := strconv.ParseInt(m, 10, bits)
		if err == nil {
			i.max = im
		}
	}
	return i
}

func (i inum) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseInt(data[0], 10, i.bits)
	if err != nil {
		return err
	}
	if num < i.min || num > i.max {
		return ErrNotInRange
	}
	v.SetInt(num)
	return nil
}

type unum struct {
	min, max uint64
	bits     int
}

func newUnum(tags reflect.StructTag, bits int) unum {
	u := unum{
		max:  math.MaxUint64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		um, err := strconv.ParseUint(m, 10, bits)
		if err == nil {
			u.min = um
		}
	}
	if m := tags.Get("max"); m != "" {
		um, err := strconv.ParseUint(m, 10, bits)
		if err == nil {
			u.max = um
		}
	}
	return u
}

func (u unum) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseUint(data[0], 10, u.bits)
	if err != nil {
		return err
	}
	if num < u.min || num > u.max {
		return ErrNotInRange
	}
	v.SetUint(num)
	return nil
}

type float struct {
	min, max float64
	bits     int
}

func newFloat(tags reflect.StructTag, bits int) float {
	f := float{
		min:  -math.MaxFloat64,
		max:  math.MaxFloat64,
		bits: bits,
	}
	if m := tags.Get("min"); m != "" {
		um, err := strconv.ParseFloat(m, bits)
		if err == nil {
			f.min = um
		}
	}
	if m := tags.Get("max"); m != "" {
		um, err := strconv.ParseFloat(m, bits)
		if err == nil {
			f.max = um
		}
	}
	return f
}

func (f float) process(v reflect.Value, data []string) error {
	num, err := strconv.ParseFloat(data[0], f.bits)
	if err != nil {
		return err
	}
	if num < f.min || num > f.max {
		return ErrNotInRange
	}
	v.SetFloat(num)
	return nil
}

type str struct{}

func (str) process(v reflect.Value, data []string) error {
	v.SetString(data[0])
	return nil
}

type boolean struct{}

func (boolean) process(v reflect.Value, data []string) error {
	switch strings.ToLower(data[0]) {
	case "on", "yes", "y", "1", "t", "true":
		v.SetBool(true)
	case "off", "no", "n", "0", "f", "false":
		v.SetBool(false)
	default:
		return ErrInvalidBoolean
	}
	return nil
}

type slice struct {
	processor
	typ reflect.Type
}

func (s slice) process(v reflect.Value, data []string) error {
	v.Set(reflect.MakeSlice(s.typ, 1, len(data)))
	l := 0
	errs := make(Errors, 0)
	for n := range data {
		if err := s.processor.process(v.Index(l), data[n:]); err != nil {
			errs = append(errs, err)
		} else if l < len(data) {
			l++
			v.SetLen(l + 1)
		}
	}
	if len(errs) > 0 {
		return errs
	}
	return nil
}

type pointer struct {
	processor
	typ reflect.Type
}

func (p pointer) process(v reflect.Value, data []string) error {
	pv := reflect.New(p.typ)
	if err := p.processor.process(pv.Elem(), data); err != nil {
		return err
	}
	v.Set(pv)
	return nil
}

type formParser interface {
	ParseForm([]string) error
}

type inter bool

func (i inter) process(v reflect.Value, data []string) error {
	if i {
		v = v.Addr()
	}
	return v.Interface().(formParser).ParseForm(data)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"
)

type Processor struct {
	Func func(page *Page, args []string)
	Desc string
	// Preprocessor is a processor which will be executed during initialization
	// stage
	Pre bool
}

var Processors map[string]*Processor

// it is necessary to wrap assignment in a function since go compiler is strict
// enough to throw error when there can be an assignment loop, but not smart
// enough to determine if it's actually truth (Processors definition loops with
// ProcessTags, which is strange)
func InitProcessors() {
	Processors = map[string]*Processor{
		"inner-template": &Processor{
			ProcessInnerTemplate,
			"process content as a Go template",
			false,
		},
		"template": &Processor{
			ProcessTemplate,
			"put content in a template (argument - template name)",
			false,
		},
		"markdown": &Processor{
			ProcessMarkdown,
			"process content as a markdown",
			false,
		},
		"rename": &Processor{
			ProcessRename,
			"rename resulting file (argument - pattern for renaming, " +
				"relative to current file location)",
			true,
		},
		"ext": &Processor{
			ProcessExt,
			"change extension",
			true,
		},
		"ignore": &Processor{
			ProcessIgnore,
			"ignore file",
			true,
		},
		"directorify": &Processor{
			ProcessDirectorify,
			"path/name.html -> path/name/index.html",
			false,
		},
		"external": &Processor{
			ProcessExternal,
			"run external command to process content (shortcut ':')",
			false,
		},
		"config": &Processor{
			ProcessConfig,
			"read config from content (separated by '----\\n')",
			true,
		},
		"tags": &Processor{
			ProcessTags,
			"generate tags pages for tags mentioned in page header " +
				"(argument - tag template)",
			true,
		},
		"relativize": &Processor{
			ProcessRelativize,
			"make all urls bound at root relative " +
				"(allows deploying resulting site in a subdirectory)",
			false,
		},
	}
}

func ProcessorSummary() {
	keys := make([]string, 0)
	for k := range Processors {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		p := Processors[k]
		pre := ""
		if p.Pre {
			pre = "(preprocessor)"
		}
		fmt.Printf("%s %s\n\t%s\n", k, pre, p.Desc)
	}
}

func ProcessCommand(page *Page, cmd *Command, pre bool) {
	c := string(*cmd)
	if strings.HasPrefix(c, ":") {
		c = "external " + c[1:]
	}
	bits := strings.Split(c, " ")

	processor := Processors[bits[0]]
	if processor.Pre != pre {
		return
	}
	if processor == nil {
		errhandle(fmt.Errorf("processor '%s' not found", bits[0]))
	}
	processor.Func(page, bits[1:])
}

func ProcessInnerTemplate(page *Page, args []string) {
	defer func() {
		if err := recover(); err != nil {
			errhandle(fmt.Errorf("%s: %s", page.Source, err))
		}
	}()

	t, err := page.Site.Template.Clone()
	errhandle(err)
	t, err = t.New("ad-hoc").Parse(page.Content())
	if err != nil {
		errhandle(fmt.Errorf("Page %s: %s", page.Source, err))
	}

	var buffer bytes.Buffer
	err = t.ExecuteTemplate(&buffer, "ad-hoc", page)
	if err != nil {
		errhandle(fmt.Errorf("Page %s: %s", page.Source, err))
	}

	page.SetContent(buffer.String())
}

func ProcessTemplate(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New("'template' rule needs an argument"))
	}
	pagetype := args[0]

	defer func() {
		if err := recover(); err != nil {
			errhandle(fmt.Errorf("%s: %s", page.Source, err))
		}
	}()

	var buffer bytes.Buffer
	err := page.Site.Template.ExecuteTemplate(&buffer, pagetype, page)
	if err != nil {
		errhandle(fmt.Errorf("%s: %s", page.Source, err))
	}

	page.SetContent(buffer.String())
}

func ProcessMarkdown(page *Page, args []string) {
	result := Markdown(page.Content())
	page.SetContent(result)
}

func ProcessRename(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(fmt.Errorf("'rename' rule needs an argument"))
	}

	dest := args[0]

	if strings.Contains(dest, "*") {
		if !strings.Contains(page.Pattern, "*") {
			errhandle(fmt.Errorf(
				"'rename' rule cannot rename '%s' to '%s'",
				page.Pattern, dest))
		}

		group := fmt.Sprintf("([^%c]*)", filepath.Separator)
		base := filepath.Base(page.Pattern)
		pat := strings.Replace(regexp.QuoteMeta(base), "\\*", group, 1)

		re, err := regexp.Compile(pat)
		errhandle(err)
		m := re.FindStringSubmatch(filepath.Base(page.Path))

		dest = strings.Replace(dest, "*", m[1], 1)
	}

	page.Path = filepath.Join(filepath.Dir(page.Path), dest)
}

func ProcessExt(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New(
			"'ext' rule requires an extension prefixed with dot"))
	}
	ext := filepath.Ext(page.Path)
	if ext == "" {
		page.Path = page.Path + args[0]
	} else {
		page.Path = strings.Replace(page.Path, ext, args[0], 1)
	}
}

func ProcessIgnore(page *Page, args []string) {
	page.state = StateIgnored
}

func ProcessDirectorify(page *Page, args []string) {
	if filepath.Base(page.Path) != "index.html" {
		page.Path = strings.Replace(page.Path, ".html", "/index.html", 1)
	}
}

func ProcessExternal(page *Page, args []string) {
	path, err := exec.LookPath(args[0])
	if err != nil {
		path, err = exec.LookPath(filepath.Join(page.Site.Base, args[0]))
		if err != nil {
			errhandle(fmt.Errorf(
				"command '%s' not found", args[0]))
		}
	}
	cmd := exec.Command(path, args[1:]...)
	cmd.Stdin = strings.NewReader(page.Content())
	cmd.Dir = page.Site.Base
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	data, err := cmd.Output()
	if err != nil {
		errhandle(fmt.Errorf("'%s' failed: %s\n%s",
			strings.Join(args, " "), err, stderr.String()))
	}

	page.SetContent(string(data))
}

func ProcessConfig(page *Page, args []string) {
	parts := TrimSplitN(page.Content(), "\n----\n", 2)
	if len(parts) != 2 {
		// no configuration, well then...
		page.PageHeader = *NewPageHeader()
		return
	}

	page.PageHeader = *ParseHeader(parts[0])
	page.SetContent(parts[1])
}

func ProcessTags(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New("'tags' rule needs an argument"))
	}

	if page.Tags == nil {
		return
	}

	site := page.Site

	for _, tag := range page.Tags {
		tagpath := strings.Replace(args[0], "*", tag, 1)

		if !site.Pages.HasPage(func(inner *Page) bool {
			return inner.Source == tagpath
		}) {
			pattern, rule := site.Rules.MatchedRule(tagpath)
			tagpage := &Page{
				PageHeader: PageHeader{Title: tag},
				Site:       site,
				Pattern:    pattern,
				Rule:       rule,
				Source:     tagpath,
				Path:       tagpath,
				wasread:    true,
				// tags are never new, because they only depend on pages and
				// have not a bit of original content
				ModTime: time.Unix(0, 0),
			}
			page.Site.Pages = append(page.Site.Pages, tagpage)
			tagpage.peek()
		}
	}

}

var RelRe = regexp.MustCompile(`(href|src)=["']/([^"']*)["']`)
var NonProtoRe = regexp.MustCompile(`(href|src)=["']//`)

func ProcessRelativize(page *Page, args []string) {
	repl := `$1="` + page.Rel("/") + `$2"`
	rv := RelRe.ReplaceAllStringFunc(page.Content(), func(inp string) string {
		if NonProtoRe.MatchString(inp) {
			return inp
		}
		return RelRe.ReplaceAllString(inp, repl)
	})
	page.SetContent(rv)
}
<commit_msg>processors: name all arguments<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"
)

type Processor struct {
	Func func(page *Page, args []string)
	Desc string
	// Preprocessor is a processor which will be executed during initialization
	// stage
	Pre bool
}

var Processors map[string]*Processor

// it is necessary to wrap assignment in a function since go compiler is strict
// enough to throw error when there can be an assignment loop, but not smart
// enough to determine if it's actually truth (Processors definition loops with
// ProcessTags, which is strange)
func InitProcessors() {
	Processors = map[string]*Processor{
		"inner-template": &Processor{
			ProcessInnerTemplate,
			"process content as a Go template",
			false,
		},
		"template": &Processor{
			ProcessTemplate,
			"put content in a template (argument - template name)",
			false,
		},
		"markdown": &Processor{
			ProcessMarkdown,
			"process content as a markdown",
			false,
		},
		"rename": &Processor{
			ProcessRename,
			"rename resulting file (argument - pattern for renaming, " +
				"relative to current file location)",
			true,
		},
		"ext": &Processor{
			ProcessExt,
			"change extension",
			true,
		},
		"ignore": &Processor{
			ProcessIgnore,
			"ignore file",
			true,
		},
		"directorify": &Processor{
			ProcessDirectorify,
			"path/name.html -> path/name/index.html",
			false,
		},
		"external": &Processor{
			ProcessExternal,
			"run external command to process content (shortcut ':')",
			false,
		},
		"config": &Processor{
			ProcessConfig,
			"read config from content (separated by '----\\n')",
			true,
		},
		"tags": &Processor{
			ProcessTags,
			"generate tags pages for tags mentioned in page header " +
				"(argument - tag template)",
			true,
		},
		"relativize": &Processor{
			ProcessRelativize,
			"make all urls bound at root relative " +
				"(allows deploying resulting site in a subdirectory)",
			false,
		},
	}
}

func ProcessorSummary() {
	keys := make([]string, 0, len(Processors))
	for k := range Processors {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, k := range keys {
		p := Processors[k]
		pre := ""
		if p.Pre {
			pre = "(preprocessor)"
		}
		fmt.Printf("%s %s\n\t%s\n", k, pre, p.Desc)
	}
}

func ProcessCommand(page *Page, cmd *Command, pre bool) {
	c := string(*cmd)
	if strings.HasPrefix(c, ":") {
		c = "external " + c[1:]
	}
	bits := strings.Split(c, " ")

	processor := Processors[bits[0]]
	if processor.Pre != pre {
		return
	}
	if processor == nil {
		errhandle(fmt.Errorf("processor '%s' not found", bits[0]))
	}
	processor.Func(page, bits[1:])
}

func ProcessInnerTemplate(page *Page, args []string) {
	defer func() {
		if err := recover(); err != nil {
			errhandle(fmt.Errorf("%s: %s", page.Source, err))
		}
	}()

	t, err := page.Site.Template.Clone()
	errhandle(err)
	t, err = t.New("ad-hoc").Parse(page.Content())
	if err != nil {
		errhandle(fmt.Errorf("Page %s: %s", page.Source, err))
	}

	var buffer bytes.Buffer
	err = t.ExecuteTemplate(&buffer, "ad-hoc", page)
	if err != nil {
		errhandle(fmt.Errorf("Page %s: %s", page.Source, err))
	}

	page.SetContent(buffer.String())
}

func ProcessTemplate(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New("'template' rule needs an argument"))
	}
	pagetype := args[0]

	defer func() {
		if err := recover(); err != nil {
			errhandle(fmt.Errorf("%s: %s", page.Source, err))
		}
	}()

	var buffer bytes.Buffer
	err := page.Site.Template.ExecuteTemplate(&buffer, pagetype, page)
	if err != nil {
		errhandle(fmt.Errorf("%s: %s", page.Source, err))
	}

	page.SetContent(buffer.String())
}

func ProcessMarkdown(page *Page, args []string) {
	result := Markdown(page.Content())
	page.SetContent(result)
}

func ProcessRename(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(fmt.Errorf("'rename' rule needs an argument"))
	}
	dest := args[0]

	if strings.Contains(dest, "*") {
		if !strings.Contains(page.Pattern, "*") {
			errhandle(fmt.Errorf(
				"'rename' rule cannot rename '%s' to '%s'",
				page.Pattern, dest))
		}

		group := fmt.Sprintf("([^%c]*)", filepath.Separator)
		base := filepath.Base(page.Pattern)
		pat := strings.Replace(regexp.QuoteMeta(base), "\\*", group, 1)

		re, err := regexp.Compile(pat)
		errhandle(err)
		m := re.FindStringSubmatch(filepath.Base(page.Path))

		dest = strings.Replace(dest, "*", m[1], 1)
	}

	page.Path = filepath.Join(filepath.Dir(page.Path), dest)
}

func ProcessExt(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New(
			"'ext' rule requires an extension prefixed with dot"))
	}
	newExt := args[0]

	ext := filepath.Ext(page.Path)
	if ext == "" {
		page.Path = page.Path + newExt
	} else {
		page.Path = page.Path[0:len(page.Path) - len(ext)] + newExt
	}
}

func ProcessIgnore(page *Page, args []string) {
	page.state = StateIgnored
}

func ProcessDirectorify(page *Page, args []string) {
	if filepath.Base(page.Path) != "index.html" {
		page.Path = strings.Replace(page.Path, ".html", "/index.html", 1)
	}
}

func ProcessExternal(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New("'external' rule needs a command name"))
	}
	cmdName := args[0]
	cmdArgs := args[1:]

	path, err := exec.LookPath(cmdName)
	if err != nil {
		path, err = exec.LookPath(filepath.Join(page.Site.Base, cmdName))
		if err != nil {
			errhandle(fmt.Errorf("command '%s' not found", cmdName))
		}
	}

	cmd := exec.Command(path, cmdArgs...)
	cmd.Stdin = strings.NewReader(page.Content())
	cmd.Dir = page.Site.Base
	var stderr bytes.Buffer
	cmd.Stderr = &stderr
	data, err := cmd.Output()
	if err != nil {
		errhandle(fmt.Errorf("'%s' failed: %s\n%s",
			strings.Join(args, " "), err, stderr.String()))
	}

	page.SetContent(string(data))
}

func ProcessConfig(page *Page, args []string) {
	parts := TrimSplitN(page.Content(), "\n----\n", 2)
	if len(parts) != 2 {
		// no configuration, well then...
		page.PageHeader = *NewPageHeader()
		return
	}

	page.PageHeader = *ParseHeader(parts[0])
	page.SetContent(parts[1])
}

func ProcessTags(page *Page, args []string) {
	if len(args) < 1 {
		errhandle(errors.New("'tags' rule needs an argument"))
	}
	pathTemplate := args[0]

	if page.Tags == nil {
		return
	}

	site := page.Site

	for _, tag := range page.Tags {
		tagpath := strings.Replace(pathTemplate, "*", tag, 1)

		if !site.Pages.HasPage(func(inner *Page) bool {
			return inner.Source == tagpath
		}) {
			pattern, rule := site.Rules.MatchedRule(tagpath)
			tagpage := &Page{
				PageHeader: PageHeader{Title: tag},
				Site:       site,
				Pattern:    pattern,
				Rule:       rule,
				Source:     tagpath,
				Path:       tagpath,
				wasread:    true,
				// tags are never new, because they only depend on pages and
				// have not a bit of original content
				ModTime: time.Unix(0, 0),
			}
			page.Site.Pages = append(page.Site.Pages, tagpage)
			tagpage.peek()
		}
	}

}

var RelRe = regexp.MustCompile(`(href|src)=["']/([^"']*)["']`)
var NonProtoRe = regexp.MustCompile(`(href|src)=["']//`)

func ProcessRelativize(page *Page, args []string) {
	repl := `$1="` + page.Rel("/") + `$2"`
	rv := RelRe.ReplaceAllStringFunc(page.Content(), func(inp string) string {
		if NonProtoRe.MatchString(inp) {
			return inp
		}
		return RelRe.ReplaceAllString(inp, repl)
	})
	page.SetContent(rv)
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"os"

	"github.com/github/hub/git"
	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
)

var Version = "2.2.0"

var cmdVersion = &Command{
	Run:   runVersion,
	Usage: "version",
	Short: "Show hub version",
	Long:  `Shows git version and hub client version.`,
}

func init() {
	CmdRunner.Use(cmdVersion)
}

func runVersion(cmd *Command, args *Args) {
	gitVersion, err := git.Version()
	utils.Check(err)

	ghVersion := fmt.Sprintf("hub version %s", Version)

	ui.Println(gitVersion)
	ui.Println(ghVersion)

	os.Exit(0)
}
<commit_msg>Bump 2.2.1<commit_after>package commands

import (
	"fmt"
	"os"

	"github.com/github/hub/git"
	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
)

var Version = "2.2.1"

var cmdVersion = &Command{
	Run:   runVersion,
	Usage: "version",
	Short: "Show hub version",
	Long:  `Shows git version and hub client version.`,
}

func init() {
	CmdRunner.Use(cmdVersion)
}

func runVersion(cmd *Command, args *Args) {
	gitVersion, err := git.Version()
	utils.Check(err)

	ghVersion := fmt.Sprintf("hub version %s", Version)

	ui.Println(gitVersion)
	ui.Println(ghVersion)

	os.Exit(0)
}
<|endoftext|>


<commit_before>package procevents

import (
	"syscall"
)

type Conn struct {
	sock  int
	evbuf []Event
}

func Dial() (*Conn, error) {

	sock, err := cnSocket()
	if err != nil {
		return nil, err
	}

	if err := cnBind(sock, cnIdxProc); err != nil {
		return nil, err
	}

	if err := cnProcMcastListen(sock); err != nil {
		return nil, err
	}

	return &Conn{sock: sock}, nil
}

func (c *Conn) Read() (Event, error) {

	for len(c.evbuf) == 0 {
		buf := make([]byte, 1<<16)
		n, _, err := syscall.Recvfrom(c.sock, buf, 0)
		if err != nil {
			return nil, err
		}
		if n < syscall.NLMSG_HDRLEN {
			continue
		}

		msgs, err := syscall.ParseNetlinkMessage(buf[:n])
		if err != nil {
			return nil, err
		}

		for i := range msgs {
			switch msgs[i].Header.Type {
			case syscall.NLMSG_ERROR, syscall.NLMSG_NOOP, syscall.NLMSG_OVERRUN:
				continue
			}

			ev, err := parseProcEvent(&msgs[i])
			if err != nil {
				return nil, err
			}
			c.evbuf = append(c.evbuf, ev)
		}
	}

	ev := c.evbuf[0]
	c.evbuf = c.evbuf[1:]

	return ev, nil
}

func (c *Conn) Close() error {
	cnProcMcastIgnore(c.sock)
	return syscall.Close(c.sock)
}

type Event interface {
	What() uint32
	Cpu() uint32
	Timestamp() uint64
	Pid() int32
	Tgid() int32
}

type Header struct {
	what      uint32
	cpu       uint32
	timestamp uint64
	pid       int32
	tgid      int32
}

func (h Header) What() uint32      { return h.what }
func (h Header) Cpu() uint32       { return h.cpu }
func (h Header) Timestamp() uint64 { return h.timestamp }
func (h Header) Pid() int32        { return h.pid }
func (h Header) Tgid() int32       { return h.tgid }

type Fork struct {
	Header
	ChildPid  int32
	ChildTgid int32
}

type Exec struct {
	Header
}

type Uid struct {
	Header
	Ruid uint32
	Euid uint32
}

type Gid struct {
	Header
	Rgid uint32
	Egid uint32
}

type Sid struct {
	Header
}

type Ptrace struct {
	Header
	TracerPid  int32
	TracerTgid int32
}

type Comm struct {
	Header
	Comm [16]byte
}

type Coredump struct {
	Header
}

type Exit struct {
	Header
	Code   uint32
	Signal uint32
}
<commit_msg>return []Event<commit_after>package procevents

import (
	"syscall"
)

type Conn struct {
	sock int
}

func Dial() (*Conn, error) {

	sock, err := cnSocket()
	if err != nil {
		return nil, err
	}

	if err := cnBind(sock, cnIdxProc); err != nil {
		return nil, err
	}

	if err := cnProcMcastListen(sock); err != nil {
		return nil, err
	}

	return &Conn{sock: sock}, nil
}

func (c *Conn) Read() ([]Event, error) {

	buf := make([]byte, 1<<16)
	n, _, err := syscall.Recvfrom(c.sock, buf, 0)
	if err != nil {
		return nil, err
	}

	msgs, err := syscall.ParseNetlinkMessage(buf[:n])
	if err != nil {
		return nil, err
	}

	events := make([]Event, 0, len(msgs))
	for i := range msgs {
		switch msgs[i].Header.Type {
		case syscall.NLMSG_ERROR, syscall.NLMSG_NOOP, syscall.NLMSG_OVERRUN:
			continue
		}

		ev, err := parseProcEvent(&msgs[i])
		if err != nil {
			return nil, err
		}
		events = append(events, ev)
	}

	return events, nil
}

func (c *Conn) Close() error {
	cnProcMcastIgnore(c.sock)
	return syscall.Close(c.sock)
}

type Event interface {
	What() uint32
	Cpu() uint32
	Timestamp() uint64
	Pid() int32
	Tgid() int32
}

type Header struct {
	what      uint32
	cpu       uint32
	timestamp uint64
	pid       int32
	tgid      int32
}

func (h Header) What() uint32      { return h.what }
func (h Header) Cpu() uint32       { return h.cpu }
func (h Header) Timestamp() uint64 { return h.timestamp }
func (h Header) Pid() int32        { return h.pid }
func (h Header) Tgid() int32       { return h.tgid }

type Fork struct {
	Header
	ChildPid  int32
	ChildTgid int32
}

type Exec struct {
	Header
}

type Uid struct {
	Header
	Ruid uint32
	Euid uint32
}

type Gid struct {
	Header
	Rgid uint32
	Egid uint32
}

type Sid struct {
	Header
}

type Ptrace struct {
	Header
	TracerPid  int32
	TracerTgid int32
}

type Comm struct {
	Header
	Comm [16]byte
}

type Coredump struct {
	Header
}

type Exit struct {
	Header
	Code   uint32
	Signal uint32
}
<|endoftext|>


<commit_before>package mchan

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"gopkg.in/logex.v1"

	"github.com/chzyer/flow"
	"github.com/chzyer/next/util/clock"
)

type Server struct {
	cfg    *SvrConf
	flow   *flow.Flow
	key    []byte
	server *http.Server
	ct     *clock.Clock
	router map[string]HandlerFunc
}

type SvrConf struct {
	CertFile string
	KeyFile  string
}

func NewServer(f *flow.Flow, listen string, ct *clock.Clock, key []byte, cfg *SvrConf) *Server {
	httpserver := &http.Server{
		Addr:           listen,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 10,
	}
	httpserver.SetKeepAlivesEnabled(false)
	svr := &Server{
		flow:   f,
		cfg:    cfg,
		key:    key,
		server: httpserver,
		ct:     ct,
		router: make(map[string]HandlerFunc),
	}
	svr.server.Handler = svr
	return svr
}

type Req struct {
	payload []byte
}

func (r *Req) Unmarshal(obj interface{}) error {
	return json.Unmarshal(r.payload, obj)
}

type HandlerFunc func(*Req) interface{}

func (s *Server) HandleFunc(path string, f HandlerFunc) {
	s.router[path] = f
}

func (s *Server) write(w http.ResponseWriter, data []byte) {
	w.Header().Set("Content-Length", fmt.Sprintf("%v", len(data)))
	n, err := w.Write(data)
	logex.Debugf("write %v bytes", n)
	if n != len(data) {
		logex.Errorf("short write: %v, %v", n, len(data))
		return
	}
	if err != nil {
		logex.Error("on write error:", err)
	}
	return
}

func (s *Server) DecodeRequest(w http.ResponseWriter, body []byte) error {
	reply, err := Decode(s.key, body)
	if err != nil {
		return err
	}
	if f := s.router[reply.Path]; f != nil {
		ret := f(&Req{reply.Payload})
		logex.Debug("got reply:", ret)
		if ret == nil {
			return nil
		}
		switch t := ret.(type) {
		case error:
			s.write(w, ReplyError(s.key, t))
		default:
			s.write(w, Reply(s.key, ret))
		}
		return nil
	}
	return fmt.Errorf("not found")
}

func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		logex.Error(err)
		return
	}
	if err := s.DecodeRequest(w, body); err == nil {
		return
	}
	logex.Warn("invalid request from:", req.RemoteAddr)

	w.Header().Set("Content-Type", "text/html")
	w.Write([]byte(`
		<title>Hello World!</title>

Hello

`))
}

func (s *Server) Run() error {
	return s.server.ListenAndServe()
}
<commit_msg>[mchan] increase timeout<commit_after>package mchan

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"gopkg.in/logex.v1"

	"github.com/chzyer/flow"
	"github.com/chzyer/next/util/clock"
)

type Server struct {
	cfg    *SvrConf
	flow   *flow.Flow
	key    []byte
	server *http.Server
	ct     *clock.Clock
	router map[string]HandlerFunc
}

type SvrConf struct {
	CertFile string
	KeyFile  string
}

func NewServer(f *flow.Flow, listen string, ct *clock.Clock, key []byte, cfg *SvrConf) *Server {
	httpserver := &http.Server{
		Addr:           listen,
		ReadTimeout:    30 * time.Second,
		WriteTimeout:   30 * time.Second,
		MaxHeaderBytes: 1 << 10,
	}
	httpserver.SetKeepAlivesEnabled(false)
	svr := &Server{
		flow:   f,
		cfg:    cfg,
		key:    key,
		server: httpserver,
		ct:     ct,
		router: make(map[string]HandlerFunc),
	}
	svr.server.Handler = svr
	return svr
}

type Req struct {
	payload []byte
}

func (r *Req) Unmarshal(obj interface{}) error {
	return json.Unmarshal(r.payload, obj)
}

type HandlerFunc func(*Req) interface{}

func (s *Server) HandleFunc(path string, f HandlerFunc) {
	s.router[path] = f
}

func (s *Server) write(w http.ResponseWriter, data []byte) {
	w.Header().Set("Content-Length", fmt.Sprintf("%v", len(data)))
	n, err := w.Write(data)
	logex.Debugf("write %v bytes", n)
	if n != len(data) {
		logex.Errorf("short write: %v, %v", n, len(data))
		return
	}
	if err != nil {
		logex.Error("on write error:", err)
	}
	return
}

func (s *Server) DecodeRequest(w http.ResponseWriter, body []byte) error {
	reply, err := Decode(s.key, body)
	if err != nil {
		return err
	}
	if f := s.router[reply.Path]; f != nil {
		ret := f(&Req{reply.Payload})
		logex.Debug("got reply:", ret)
		if ret == nil {
			return nil
		}
		switch t := ret.(type) {
		case error:
			s.write(w, ReplyError(s.key, t))
		default:
			s.write(w, Reply(s.key, ret))
		}
		return nil
	}
	return fmt.Errorf("not found")
}

func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		logex.Error(err)
		return
	}
	if err := s.DecodeRequest(w, body); err == nil {
		return
	}
	logex.Warn("invalid request from:", req.RemoteAddr)

	w.Header().Set("Content-Type", "text/html")
	w.Write([]byte(`
		<title>Hello World!</title>

Hello

`))
}

func (s *Server) Run() error {
	return s.server.ListenAndServe()
}
<|endoftext|>


<commit_before>package backends

import (
	"github.com/docker/libswarm/beam"

	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"reflect"
	"strings"
	"testing"
)

type requestStub struct {
	reqMethod string
	reqPath   string
	reqBody   string

	resStatus int
	resBody   string
}

func TestBackendSpawn(t *testing.T) {
	instance(t, nil)
}

func TestAttachAndStart(t *testing.T) {
	i := instance(t, nil)
	_, _, err := i.Attach("")
	if err != nil {
		t.Fatal(err)
	}
	err = i.Start()
	if err != nil {
		t.Fatal(err)
	}
}

func TestLs(t *testing.T) {
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   "/containers/json",
		resBody: `
      [
        {"Names": ["/foo"]},
        {"Names": ["/bar"]}
      ]
    `,
	})
	i := instance(t, server)
	names, err := i.Ls()
	if err != nil {
		t.Fatal(err)
	}
	expected := []string{"foo", "bar"}
	if !reflect.DeepEqual(names, expected) {
		t.Fatalf("expected %#v, got %#v", expected, names)
	}
}

func TestSpawn(t *testing.T) {
	server := makeServer(t, &requestStub{
		reqMethod: "POST",
		reqPath:   "/containers/create",
		reqBody:   "{}",

		resStatus: 201,
		resBody:   "{}",
	})
	i := instance(t, server)
	_, err := i.Spawn("{}")
	if err != nil {
		t.Fatal(err)
	}
}

func TestAttachToChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	})
	i := instance(t, server)
	child(t, server, i, name)
}

func TestStartChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	}, &requestStub{
		reqMethod: "POST",
		reqPath:   fmt.Sprintf("/containers/%s/start", name),
		reqBody:   "{}",

		resStatus: 204,
	})
	i := instance(t, server)
	c := child(t, server, i, name)
	err := c.Start()
	if err != nil {
		t.Fatal(err)
	}
}

func TestStopChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	}, &requestStub{
		reqMethod: "POST",
		reqPath:   fmt.Sprintf("/containers/%s/stop", name),

		resStatus: 204,
	})
	i := instance(t, server)
	c := child(t, server, i, name)
	err := c.Stop()
	if err != nil {
		t.Fatal(err)
	}
}

func makeServer(t *testing.T, stubs ...*requestStub) *httptest.Server {
	for _, stub := range stubs {
		stub.reqPath = fmt.Sprintf("/v1.11%s", stub.reqPath)
	}

	stubSummaries := []string{}
	for _, stub := range stubs {
		stubSummaries = append(stubSummaries, fmt.Sprintf("%s %s", stub.reqMethod, stub.reqPath))
	}

	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		for _, stub := range stubs {
			if r.Method == stub.reqMethod && r.URL.Path == stub.reqPath {
				body, err := ioutil.ReadAll(r.Body)
				if err != nil {
					t.Fatal(err)
				}
				if string(body) != stub.reqBody {
					t.Fatalf("expected body: %#v, got body: %#v", stub.reqBody, string(body))
				}

				if stub.resStatus > 0 {
					w.WriteHeader(stub.resStatus)
				}
				w.Write([]byte(stub.resBody))
				return
			}
		}

		t.Fatalf("Unexpected request: '%s %s'.\nStubs: %#v", r.Method, r.URL.Path, stubSummaries)
	}))
}

func instance(t *testing.T, server *httptest.Server) *beam.Object {
	url := "tcp://localhost:4243"
	if server != nil {
		url = strings.Replace(server.URL, "http://", "tcp://", 1)
	}

	backend := DockerClient()
	instance, err := beam.Obj(backend).Spawn(url)
	if err != nil {
		t.Fatal(err)
	}
	return instance
}

func child(t *testing.T, server *httptest.Server, i *beam.Object, name string) *beam.Object {
	_, child, err := i.Attach(name)
	if err != nil {
		t.Fatal(err)
	}
	return child
}
<commit_msg>Assert that stubbed requests are actually called in dockerclient test<commit_after>package backends

import (
	"github.com/docker/libswarm/beam"

	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"reflect"
	"strings"
	"testing"
)

type requestStub struct {
	reqMethod string
	reqPath   string
	reqBody   string

	resStatus int
	resBody   string
}

func TestBackendSpawn(t *testing.T) {
	instance(t, nil)
}

func TestAttachAndStart(t *testing.T) {
	i := instance(t, nil)
	_, _, err := i.Attach("")
	if err != nil {
		t.Fatal(err)
	}
	err = i.Start()
	if err != nil {
		t.Fatal(err)
	}
}

func TestLs(t *testing.T) {
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   "/containers/json",
		resBody: `
      [
        {"Names": ["/foo"]},
        {"Names": ["/bar"]}
      ]
    `,
	})
	i := instance(t, server)
	names, err := i.Ls()
	if err != nil {
		t.Fatal(err)
	}
	expected := []string{"foo", "bar"}
	if !reflect.DeepEqual(names, expected) {
		t.Fatalf("expected %#v, got %#v", expected, names)
	}
	server.Check()
}

func TestSpawn(t *testing.T) {
	server := makeServer(t, &requestStub{
		reqMethod: "POST",
		reqPath:   "/containers/create",
		reqBody:   "{}",

		resStatus: 201,
		resBody:   "{}",
	})
	i := instance(t, server)
	_, err := i.Spawn("{}")
	if err != nil {
		t.Fatal(err)
	}
	server.Check()
}

func TestAttachToChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	})
	i := instance(t, server)
	child(t, server, i, name)
	server.Check()
}

func TestStartChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	}, &requestStub{
		reqMethod: "POST",
		reqPath:   fmt.Sprintf("/containers/%s/start", name),
		reqBody:   "{}",

		resStatus: 204,
	})
	i := instance(t, server)
	c := child(t, server, i, name)
	err := c.Start()
	if err != nil {
		t.Fatal(err)
	}
	server.Check()
}

func TestStopChild(t *testing.T) {
	name := "foo"
	server := makeServer(t, &requestStub{
		reqMethod: "GET",
		reqPath:   fmt.Sprintf("/containers/%s/json", name),

		resBody: "{}",
	}, &requestStub{
		reqMethod: "POST",
		reqPath:   fmt.Sprintf("/containers/%s/stop", name),

		resStatus: 204,
	})
	i := instance(t, server)
	c := child(t, server, i, name)
	err := c.Stop()
	if err != nil {
		t.Fatal(err)
	}
	server.Check()
}

type stubRecord struct {
	stub      *requestStub
	summary   string
	callCount int
}

type stubServer struct {
	*httptest.Server

	stubs []*stubRecord
	t     *testing.T
}

func makeServer(t *testing.T, stubs ...*requestStub) *stubServer {
	s := &stubServer{
		stubs: []*stubRecord{},
		t:     t,
	}

	s.Server = httptest.NewServer(http.HandlerFunc(s.ServeRequest))

	for _, stub := range stubs {
		stub.reqPath = fmt.Sprintf("/v1.11%s", stub.reqPath)
		s.stubs = append(s.stubs, &stubRecord{
			stub:      stub,
			summary:   fmt.Sprintf("%s %s", stub.reqMethod, stub.reqPath),
			callCount: 0,
		})
	}

	return s
}

func (s *stubServer) Check() {
	for _, record := range s.stubs {
		if record.callCount != 1 {
			s.t.Fatalf("Expected %#v to be called exactly once, but was called %d times",
				record.summary, record.callCount)
		}
	}
}

func (s *stubServer) ServeRequest(w http.ResponseWriter, r *http.Request) {
	for _, record := range s.stubs {
		stub := record.stub
		if r.Method == stub.reqMethod && r.URL.Path == stub.reqPath {
			body, err := ioutil.ReadAll(r.Body)
			if err != nil {
				s.t.Fatal(err)
			}
			if string(body) != stub.reqBody {
				s.t.Fatalf("expected body: %#v, got body: %#v", stub.reqBody, string(body))
			}

			if stub.resStatus > 0 {
				w.WriteHeader(stub.resStatus)
			}
			w.Write([]byte(stub.resBody))

			record.callCount += 1
			return
		}
	}

	s.t.Fatalf("Unexpected request: '%s %s'.\nStubs: %#v", r.Method, r.URL.Path, s.AllSummaries())
}

func (s *stubServer) AllSummaries() []string {
	summaries := []string{}
	for _, record := range s.stubs {
		summaries = append(summaries, record.summary)
	}
	return summaries
}

func instance(t *testing.T, server *stubServer) *beam.Object {
	url := "tcp://localhost:4243"
	if server != nil {
		url = strings.Replace(server.URL, "http://", "tcp://", 1)
	}

	backend := DockerClient()
	instance, err := beam.Obj(backend).Spawn(url)
	if err != nil {
		t.Fatal(err)
	}
	return instance
}

func child(t *testing.T, server *stubServer, i *beam.Object, name string) *beam.Object {
	_, child, err := i.Attach(name)
	if err != nil {
		t.Fatal(err)
	}
	return child
}
<|endoftext|>


<commit_before><commit_msg>update<commit_after><|endoftext|>


<commit_before><commit_msg>Added new functionality to ServeHTTP<commit_after><|endoftext|>


<commit_before>// +build acceptance

package v2

import (
	"testing"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/acceptance/tools"
	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
	oskey "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
	os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
	"github.com/rackspace/gophercloud/pagination"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
	th "github.com/rackspace/gophercloud/testhelper"
)

func createServerKeyPair(t *testing.T, client *gophercloud.ServiceClient) *oskey.KeyPair {
	name := tools.RandomString("importedkey-", 8)
	pubkey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDlIQ3r+zd97kb9Hzmujd3V6pbO53eb3Go4q2E8iqVGWQfZTrFdL9KACJnqJIm9HmncfRkUTxE37hqeGCCv8uD+ZPmPiZG2E60OX1mGDjbbzAyReRwYWXgXHopggZTLak5k4mwZYaxwaufbVBDRn847e01lZnaXaszEToLM37NLw+uz29sl3TwYy2R0RGHPwPc160aWmdLjSyd1Nd4c9pvvOP/EoEuBjIC6NJJwg2Rvg9sjjx9jYj0QUgc8CqKLN25oMZ69kNJzlFylKRUoeeVr89txlR59yehJWk6Uw6lYFTdJmcmQOFVAJ12RMmS1hLWCM8UzAgtw+EDa0eqBxBDl smash@winter"

	k, err := keypairs.Create(client, oskey.CreateOpts{
		Name:      name,
		PublicKey: pubkey,
	}).Extract()
	th.AssertNoErr(t, err)

	return k
}

func createServer(t *testing.T, client *gophercloud.ServiceClient, keyName string) *os.Server {
	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	options, err := optionsFromEnv()
	th.AssertNoErr(t, err)

	name := tools.RandomString("Gophercloud-", 8)

	opts := &servers.CreateOpts{
		Name:       name,
		ImageRef:   options.imageID,
		FlavorRef:  options.flavorID,
		DiskConfig: diskconfig.Manual,
	}

	if keyName != "" {
		opts.KeyPair = keyName
	}

	t.Logf("Creating server [%s].", name)
	s, err := servers.Create(client, opts).Extract()
	th.AssertNoErr(t, err)
	t.Logf("Creating server.")

	err = servers.WaitForStatus(client, s.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)
	t.Logf("Server created successfully.")

	return s
}

func logServer(t *testing.T, server *os.Server, index int) {
	if index == -1 {
		t.Logf("             id=[%s]", server.ID)
	} else {
		t.Logf("[%02d]             id=[%s]", index, server.ID)
	}
	t.Logf("           name=[%s]", server.Name)
	t.Logf("      tenant ID=[%s]", server.TenantID)
	t.Logf("        user ID=[%s]", server.UserID)
	t.Logf("        updated=[%s]", server.Updated)
	t.Logf("        created=[%s]", server.Created)
	t.Logf("        host ID=[%s]", server.HostID)
	t.Logf("    access IPv4=[%s]", server.AccessIPv4)
	t.Logf("    access IPv6=[%s]", server.AccessIPv6)
	t.Logf("          image=[%v]", server.Image)
	t.Logf("         flavor=[%v]", server.Flavor)
	t.Logf("      addresses=[%v]", server.Addresses)
	t.Logf("       metadata=[%v]", server.Metadata)
	t.Logf("          links=[%v]", server.Links)
	t.Logf("        keyname=[%s]", server.KeyName)
	t.Logf(" admin password=[%s]", server.AdminPass)
	t.Logf("         status=[%s]", server.Status)
	t.Logf("       progress=[%d]", server.Progress)
}

func getServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Get")

	details, err := servers.Get(client, server.ID).Extract()
	th.AssertNoErr(t, err)
	logServer(t, details, -1)
}

func listServers(t *testing.T, client *gophercloud.ServiceClient) {
	t.Logf("> servers.List")

	count := 0
	err := servers.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
		count++
		t.Logf("--- Page %02d ---", count)

		s, err := servers.ExtractServers(page)
		th.AssertNoErr(t, err)
		for index, server := range s {
			logServer(t, &server, index)
		}

		return true, nil
	})
	th.AssertNoErr(t, err)
}

func changeAdminPassword(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.ChangeAdminPassword")

	original := server.AdminPass

	t.Logf("Changing server password.")
	err := servers.ChangeAdminPassword(client, server.ID, tools.MakeNewPassword(original)).Extract()
	th.AssertNoErr(t, err)

	err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)
	t.Logf("Password changed successfully.")
}

func rebootServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Reboot")

	err := servers.Reboot(client, server.ID, os.HardReboot).Extract()
	th.AssertNoErr(t, err)

	err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)

	t.Logf("Server successfully rebooted.")
}

func rebuildServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Rebuild")

	options, err := optionsFromEnv()
	th.AssertNoErr(t, err)

	opts := servers.RebuildOpts{
		Name:       tools.RandomString("RenamedGopher", 16),
		AdminPass:  tools.MakeNewPassword(server.AdminPass),
		ImageID:    options.imageID,
		DiskConfig: diskconfig.Manual,
	}
	after, err := servers.Rebuild(client, server.ID, opts).Extract()
	th.AssertNoErr(t, err)
	th.CheckEquals(t, after.ID, server.ID)

	err = servers.WaitForStatus(client, after.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)

	t.Logf("Server successfully rebuilt.")
	logServer(t, after, -1)
}

func deleteServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Delete")

	res := servers.Delete(client, server.ID)
	th.AssertNoErr(t, res.Err)

	t.Logf("Server deleted successfully.")
}

func deleteServerKeyPair(t *testing.T, client *gophercloud.ServiceClient, k *oskey.KeyPair) {
	t.Logf("> keypairs.Delete")

	err := keypairs.Delete(client, k.Name).ExtractErr()
	th.AssertNoErr(t, err)

	t.Logf("Keypair deleted successfully.")
}

func TestServerOperations(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	kp := createServerKeyPair(t, client)
	defer deleteServerKeyPair(t, client, kp)

	server := createServer(t, client, kp.Name)
	defer deleteServer(t, client, server)

	getServer(t, client, server)
	listServers(t, client)
	changeAdminPassword(t, client, server)
	rebootServer(t, client, server)
	rebuildServer(t, client, server)
}
<commit_msg>rackspace servers acceptance test fix<commit_after>// +build acceptance

package v2

import (
	"testing"

	"github.com/rackspace/gophercloud"
	"github.com/rackspace/gophercloud/acceptance/tools"
	"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
	oskey "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
	os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
	"github.com/rackspace/gophercloud/pagination"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs"
	"github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
	th "github.com/rackspace/gophercloud/testhelper"
)

func createServerKeyPair(t *testing.T, client *gophercloud.ServiceClient) *oskey.KeyPair {
	name := tools.RandomString("importedkey-", 8)
	pubkey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDlIQ3r+zd97kb9Hzmujd3V6pbO53eb3Go4q2E8iqVGWQfZTrFdL9KACJnqJIm9HmncfRkUTxE37hqeGCCv8uD+ZPmPiZG2E60OX1mGDjbbzAyReRwYWXgXHopggZTLak5k4mwZYaxwaufbVBDRn847e01lZnaXaszEToLM37NLw+uz29sl3TwYy2R0RGHPwPc160aWmdLjSyd1Nd4c9pvvOP/EoEuBjIC6NJJwg2Rvg9sjjx9jYj0QUgc8CqKLN25oMZ69kNJzlFylKRUoeeVr89txlR59yehJWk6Uw6lYFTdJmcmQOFVAJ12RMmS1hLWCM8UzAgtw+EDa0eqBxBDl smash@winter"

	k, err := keypairs.Create(client, oskey.CreateOpts{
		Name:      name,
		PublicKey: pubkey,
	}).Extract()
	th.AssertNoErr(t, err)

	return k
}

func createServer(t *testing.T, client *gophercloud.ServiceClient, keyName string) *os.Server {
	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	options, err := optionsFromEnv()
	th.AssertNoErr(t, err)

	name := tools.RandomString("Gophercloud-", 8)

	opts := &servers.CreateOpts{
		Name:       name,
		ImageRef:   options.imageID,
		FlavorRef:  options.flavorID,
		DiskConfig: diskconfig.Manual,
	}

	if keyName != "" {
		opts.KeyPair = keyName
	}

	t.Logf("Creating server [%s].", name)
	s, err := servers.Create(client, opts).Extract()
	th.AssertNoErr(t, err)
	t.Logf("Creating server.")

	err = servers.WaitForStatus(client, s.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)
	t.Logf("Server created successfully.")

	return s
}

func logServer(t *testing.T, server *os.Server, index int) {
	if index == -1 {
		t.Logf("             id=[%s]", server.ID)
	} else {
		t.Logf("[%02d]             id=[%s]", index, server.ID)
	}
	t.Logf("           name=[%s]", server.Name)
	t.Logf("      tenant ID=[%s]", server.TenantID)
	t.Logf("        user ID=[%s]", server.UserID)
	t.Logf("        updated=[%s]", server.Updated)
	t.Logf("        created=[%s]", server.Created)
	t.Logf("        host ID=[%s]", server.HostID)
	t.Logf("    access IPv4=[%s]", server.AccessIPv4)
	t.Logf("    access IPv6=[%s]", server.AccessIPv6)
	t.Logf("          image=[%v]", server.Image)
	t.Logf("         flavor=[%v]", server.Flavor)
	t.Logf("      addresses=[%v]", server.Addresses)
	t.Logf("       metadata=[%v]", server.Metadata)
	t.Logf("          links=[%v]", server.Links)
	t.Logf("        keyname=[%s]", server.KeyName)
	t.Logf(" admin password=[%s]", server.AdminPass)
	t.Logf("         status=[%s]", server.Status)
	t.Logf("       progress=[%d]", server.Progress)
}

func getServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Get")

	details, err := servers.Get(client, server.ID).Extract()
	th.AssertNoErr(t, err)
	logServer(t, details, -1)
}

func listServers(t *testing.T, client *gophercloud.ServiceClient) {
	t.Logf("> servers.List")

	count := 0
	err := servers.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
		count++
		t.Logf("--- Page %02d ---", count)

		s, err := servers.ExtractServers(page)
		th.AssertNoErr(t, err)
		for index, server := range s {
			logServer(t, &server, index)
		}

		return true, nil
	})
	th.AssertNoErr(t, err)
}

func changeAdminPassword(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.ChangeAdminPassword")

	original := server.AdminPass

	t.Logf("Changing server password.")
	err := servers.ChangeAdminPassword(client, server.ID, tools.MakeNewPassword(original)).ExtractErr()
	th.AssertNoErr(t, err)

	err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)
	t.Logf("Password changed successfully.")
}

func rebootServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Reboot")

	err := servers.Reboot(client, server.ID, os.HardReboot).ExtractErr()
	th.AssertNoErr(t, err)

	err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)

	t.Logf("Server successfully rebooted.")
}

func rebuildServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Rebuild")

	options, err := optionsFromEnv()
	th.AssertNoErr(t, err)

	opts := servers.RebuildOpts{
		Name:       tools.RandomString("RenamedGopher", 16),
		AdminPass:  tools.MakeNewPassword(server.AdminPass),
		ImageID:    options.imageID,
		DiskConfig: diskconfig.Manual,
	}
	after, err := servers.Rebuild(client, server.ID, opts).Extract()
	th.AssertNoErr(t, err)
	th.CheckEquals(t, after.ID, server.ID)

	err = servers.WaitForStatus(client, after.ID, "ACTIVE", 300)
	th.AssertNoErr(t, err)

	t.Logf("Server successfully rebuilt.")
	logServer(t, after, -1)
}

func deleteServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
	t.Logf("> servers.Delete")

	res := servers.Delete(client, server.ID)
	th.AssertNoErr(t, res.Err)

	t.Logf("Server deleted successfully.")
}

func deleteServerKeyPair(t *testing.T, client *gophercloud.ServiceClient, k *oskey.KeyPair) {
	t.Logf("> keypairs.Delete")

	err := keypairs.Delete(client, k.Name).ExtractErr()
	th.AssertNoErr(t, err)

	t.Logf("Keypair deleted successfully.")
}

func TestServerOperations(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	kp := createServerKeyPair(t, client)
	defer deleteServerKeyPair(t, client, kp)

	server := createServer(t, client, kp.Name)
	defer deleteServer(t, client, server)

	getServer(t, client, server)
	listServers(t, client)
	changeAdminPassword(t, client, server)
	rebootServer(t, client, server)
	rebuildServer(t, client, server)
}
<|endoftext|>


<commit_before><commit_msg>add "Labels" property for PullRequest (#855)<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed homedir expansion<commit_after><|endoftext|>


<commit_before><commit_msg>more api tracing (#12666)<commit_after><|endoftext|>


<commit_before>package mongo

import (
	"math/rand"
	"strconv"

	"gopkg.in/mgo.v2"
	"h12.me/realtest/container"
)

const (
	containerName = "realtest-mongo-79cb399e9230494cb475d8461a0183c7"
	internalPort  = 27017
)

type Mongo struct {
	ConnStr string
	*mgo.Session
	*mgo.Database
	c *container.Container
}

func New() (*Mongo, error) {
	c, err := container.FindOrCreate(containerName, "mongo:latest")
	if err != nil {
		return nil, err
	}
	connStr := "mongodb://" + c.Addr(internalPort)
	session, err := mgo.Dial(connStr)
	if err != nil {
		c.Close()
		return nil, err
	}
	return &Mongo{
		ConnStr: connStr,
		Session: session,
		c:       c,
	}, nil
}

func (m *Mongo) NewDB(dbName string) *mgo.Database {
	return m.Session.DB(dbName)
}

func (m *Mongo) NewRandomDB() *mgo.Database {
	return m.Session.DB("db_" + strconv.Itoa(rand.Int()))
}

func (s *Mongo) Close() {
	if s.Session != nil {
		s.Session.Close()
		s.Session = nil
	}
}

func (s *Mongo) Addr() string {
	return s.c.Addr(internalPort)
}
<commit_msg>update for MongoDB<commit_after>package mongo

import (
	"math/rand"
	"strconv"

	"gopkg.in/mgo.v2"
	"h12.me/realtest/container"
)

const (
	internalPort = 27017
)

var (
	containerName = container.ContainerName{
		Name: "realtest-mongo-79cb399e9230494cb475d8461a0183c7",
	}
)

type Mongo struct {
	ConnStr string
	*mgo.Session
	*mgo.Database
	c *container.Container
}

func New() (*Mongo, error) {
	c, err := containerName.FindOrCreate("mongo:latest")
	if err != nil {
		return nil, err
	}
	connStr := "mongodb://" + c.Addr(internalPort)
	session, err := mgo.Dial(connStr)
	if err != nil {
		c.Close()
		return nil, err
	}
	return &Mongo{
		ConnStr: connStr,
		Session: session,
		c:       c,
	}, nil
}

func (m *Mongo) NewDB(dbName string) *mgo.Database {
	return m.Session.DB(dbName)
}

func (m *Mongo) NewRandomDB() *mgo.Database {
	return m.Session.DB("db_" + strconv.Itoa(rand.Int()))
}

func (s *Mongo) Close() {
	if s.Session != nil {
		s.Session.Close()
		s.Session = nil
	}
}

func (s *Mongo) Addr() string {
	return s.c.Addr(internalPort)
}
<|endoftext|>


<commit_before><commit_msg>Refactor network tests in GQT<commit_after><|endoftext|>


<commit_before><commit_msg>Remove reactions.remove unit test due to API uncertanties<commit_after><|endoftext|>


<commit_before>package solver

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

// ParseSlice parse a slice of slice of lits and returns the equivalent problem.
// The argument is supposed to be a well-formed CNF.
func ParseSlice(cnf [][]int) *Problem {
	var pb Problem
	for _, line := range cnf {
		switch len(line) {
		case 0:
			pb.Status = Unsat
			return &pb
		case 1:
			if line[0] == 0 {
				panic("null unit clause")
			}
			lit := IntToLit(int32(line[0]))
			v := lit.Var()
			if int(v) >= pb.NbVars {
				pb.NbVars = int(v) + 1
			}
			pb.Units = append(pb.Units, lit)
		default:
			lits := make([]Lit, len(line))
			for j, val := range line {
				if val == 0 {
					panic("null literal in clause %q")
				}
				lits[j] = IntToLit(int32(val))
				if v := int(lits[j].Var()); v >= pb.NbVars {
					pb.NbVars = v + 1
				}
			}
			pb.Clauses = append(pb.Clauses, NewClause(lits))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplify()
	return &pb
}

// ParseCardConstrs parses the given cardinality constraints.
// Will panic if a zero value appears in the literals.
func ParseCardConstrs(constrs []CardConstr) *Problem {
	var pb Problem
	for _, constr := range constrs {
		card := constr.AtLeast
		if card <= 0 { // Clause is trivially SAT, ignore
			continue
		}
		if len(constr.Lits) < card { // Clause cannot be satsfied
			pb.Status = Unsat
			return &pb
		}
		if len(constr.Lits) == card { // All lits must be true
			for i := range constr.Lits {
				if constr.Lits[i] == 0 {
					panic("literal 0 found in clause")
				}
				lit := IntToLit(int32(constr.Lits[i]))
				v := lit.Var()
				if int(v) >= pb.NbVars {
					pb.NbVars = int(v) + 1
				}
				pb.Units = append(pb.Units, lit)
			}
		} else {
			lits := make([]Lit, len(constr.Lits))
			for j, val := range constr.Lits {
				if val == 0 {
					panic("literal 0 found in clause")
				}
				lits[j] = IntToLit(int32(val))
				if v := int(lits[j].Var()); v >= pb.NbVars {
					pb.NbVars = v + 1
				}
			}
			pb.Clauses = append(pb.Clauses, NewCardClause(lits, card))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplify()
	return &pb
}

// ParsePBConstrs parses and returns a PB problem from PBConstr values.
func ParsePBConstrs(constrs []PBConstr) *Problem {
	var pb Problem
	for _, constr := range constrs {
		for i := range constr.Lits {
			lit := IntToLit(int32(constr.Lits[i]))
			v := lit.Var()
			if int(v) >= pb.NbVars {
				pb.NbVars = int(v) + 1
			}
		}
		card := constr.AtLeast
		if card <= 0 { // Clause is trivially SAT, ignore
			continue
		}
		sumW := constr.WeightSum()
		if sumW < card { // Clause cannot be satsfied
			pb.Status = Unsat
			return &pb
		}
		if sumW == card { // All lits must be true
			for i := range constr.Lits {
				lit := IntToLit(int32(constr.Lits[i]))
				pb.Units = append(pb.Units, lit)
			}
		} else {
			lits := make([]Lit, len(constr.Lits))
			for j, val := range constr.Lits {
				lits[j] = IntToLit(int32(val))
			}
			pb.Clauses = append(pb.Clauses, NewPBClause(lits, constr.Weights, card))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplifyPB()
	return &pb
}

// Parses a CNF line containing a clause and adds it to the problem.
func (pb *Problem) parseClause(line string) error {
	fields := strings.Fields(line)
	lits := make([]Lit, len(fields)-1)
	for i, field := range fields {
		if i == len(fields)-1 { // Ignore last field: it is the 0 clause terminator
			break
		}
		if field == "" {
			continue
		}
		cnfLit, err := strconv.Atoi(field)
		if err != nil {
			return fmt.Errorf("Invalid literal %q in CNF clause %q", field, line)
		}
		lits[i] = IntToLit(int32(cnfLit))
	}
	switch len(lits) {
	case 0:
		pb.Status = Unsat
		pb.Clauses = nil
	case 1:
		lit := lits[0]
		pb.Units = append(pb.Units, lit)
		v := lit.Var()
		if pb.Model[v] == 0 {
			if lit.IsPositive() {
				pb.Model[lit.Var()] = 1
			} else {
				pb.Model[lit.Var()] = -1
			}
		} else if pb.Model[v] > 0 != lit.IsPositive() {
			pb.Status = Unsat
		}
	default:
		pb.Clauses = append(pb.Clauses, NewClause(lits))
	}
	return nil
}

// ParseCNF parses a CNF file and returns the corresponding Problem.
func ParseCNF(f io.Reader) (*Problem, error) {
	scanner := bufio.NewScanner(f)
	var nbClauses int
	var pb Problem
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			continue
		}
		if line[0] == 'p' {
			fields := strings.Split(line, " ")
			if len(fields) < 4 {
				return nil, fmt.Errorf("invalid syntax %q in CNF file", line)
			}
			var err error
			pb.NbVars, err = strconv.Atoi(fields[2])
			if err != nil {
				return nil, fmt.Errorf("nbvars not an int : '%s'", fields[2])
			}
			pb.Model = make([]decLevel, pb.NbVars)
			nbClauses, err = strconv.Atoi(fields[3])
			if err != nil {
				return nil, fmt.Errorf("nbClauses not an int : '%s'", fields[3])
			}
			pb.Clauses = make([]*Clause, 0, nbClauses)
		} else if line[0] != 'c' { // Not a header, not a comment : a clause
			if err := pb.parseClause(line); err != nil {
				return nil, err
			}
		}
	}
	pb.simplify()
	return &pb, nil
}

func (pb *Problem) parsePBLine(line string) error {
	if line == "" {
		return fmt.Errorf("empty line in file")
	}
	if line[len(line)-1] != ';' {
		return fmt.Errorf("line %q does not end with semicolon", line)
	}
	fields := strings.Fields(line[:len(line)-1])
	if len(fields) == 0 {
		return fmt.Errorf("empty line in file")
	}
	if len(fields) < 4 || len(fields)%2 != 0 {
		return fmt.Errorf("invalid syntax %q", line)
	}
	operator := fields[len(fields)-2]
	if operator != ">=" && operator != "=" {
		return fmt.Errorf("invalid operator %q in %q: expected \">=\" or \"=\"", operator, line)
	}
	rhs, err := strconv.Atoi(fields[len(fields)-1])
	if err != nil {
		return fmt.Errorf("invalid value %q in %q: %v", fields[len(fields)-1], line, err)
	}
	weights, lits, err := pb.parseTerms(fields, line)
	if err != nil {
		return err
	}
	if operator == ">=" {
		pb.Clauses = append(pb.Clauses, GtEq(lits, weights, rhs).Clause())
	} else {
		for _, constr := range Eq(lits, weights, rhs) {
			pb.Clauses = append(pb.Clauses, constr.Clause())
		}
	}
	return nil
}

func (pb *Problem) parseTerms(fields []string, line string) (weights []int, lits []int, err error) {
	terms := fields[:len(fields)-2]
	weights = make([]int, len(terms)/2)
	lits = make([]int, len(terms)/2)
	for i := range weights {
		w, err := strconv.Atoi(terms[i*2])
		if err != nil {
			return nil, nil, fmt.Errorf("invalid weight %q in %q: %v", terms[i*2], line, err)
		}
		weights[i] = w
		l := terms[i*2+1]
		if !strings.HasPrefix(l, "x") && !strings.HasPrefix(l, "~x") || len(l) < 2 {
			return nil, nil, fmt.Errorf("invalid variable name %q in %q", l, line)
		}
		if l[0] == '~' {
			lits[i], err = strconv.Atoi(l[2:])
		} else {
			lits[i], err = strconv.Atoi(l[1:])
		}
		if err != nil {
			return nil, nil, fmt.Errorf("invalid variable %q in %q: %v", l, line, err)
		}
		if lits[i] > pb.NbVars {
			pb.NbVars = lits[i]
		}
		if l[0] == '~' {
			lits[i] = -lits[i]
		}
	}
	return weights, lits, nil
}

// ParsePBS parses a file corresponding to the PBS syntax.
// See http://www.cril.univ-artois.fr/PB16/format.pdf for more details.
func ParsePBS(f io.Reader) (*Problem, error) {
	scanner := bufio.NewScanner(f)
	var pb Problem
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" || line[0] == '*' {
			continue
		}
		if err := pb.parsePBLine(line); err != nil {
			return nil, err
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("could not parse PBS: %v", err)
	}
	pb.Model = make([]decLevel, pb.NbVars)
	pb.simplifyPB()
	log.Printf("problem is %s", pb.PBString())
	return &pb, nil
}
<commit_msg>removed debugging logging<commit_after>package solver

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

// ParseSlice parse a slice of slice of lits and returns the equivalent problem.
// The argument is supposed to be a well-formed CNF.
func ParseSlice(cnf [][]int) *Problem {
	var pb Problem
	for _, line := range cnf {
		switch len(line) {
		case 0:
			pb.Status = Unsat
			return &pb
		case 1:
			if line[0] == 0 {
				panic("null unit clause")
			}
			lit := IntToLit(int32(line[0]))
			v := lit.Var()
			if int(v) >= pb.NbVars {
				pb.NbVars = int(v) + 1
			}
			pb.Units = append(pb.Units, lit)
		default:
			lits := make([]Lit, len(line))
			for j, val := range line {
				if val == 0 {
					panic("null literal in clause %q")
				}
				lits[j] = IntToLit(int32(val))
				if v := int(lits[j].Var()); v >= pb.NbVars {
					pb.NbVars = v + 1
				}
			}
			pb.Clauses = append(pb.Clauses, NewClause(lits))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplify()
	return &pb
}

// ParseCardConstrs parses the given cardinality constraints.
// Will panic if a zero value appears in the literals.
func ParseCardConstrs(constrs []CardConstr) *Problem {
	var pb Problem
	for _, constr := range constrs {
		card := constr.AtLeast
		if card <= 0 { // Clause is trivially SAT, ignore
			continue
		}
		if len(constr.Lits) < card { // Clause cannot be satsfied
			pb.Status = Unsat
			return &pb
		}
		if len(constr.Lits) == card { // All lits must be true
			for i := range constr.Lits {
				if constr.Lits[i] == 0 {
					panic("literal 0 found in clause")
				}
				lit := IntToLit(int32(constr.Lits[i]))
				v := lit.Var()
				if int(v) >= pb.NbVars {
					pb.NbVars = int(v) + 1
				}
				pb.Units = append(pb.Units, lit)
			}
		} else {
			lits := make([]Lit, len(constr.Lits))
			for j, val := range constr.Lits {
				if val == 0 {
					panic("literal 0 found in clause")
				}
				lits[j] = IntToLit(int32(val))
				if v := int(lits[j].Var()); v >= pb.NbVars {
					pb.NbVars = v + 1
				}
			}
			pb.Clauses = append(pb.Clauses, NewCardClause(lits, card))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplify()
	return &pb
}

// ParsePBConstrs parses and returns a PB problem from PBConstr values.
func ParsePBConstrs(constrs []PBConstr) *Problem {
	var pb Problem
	for _, constr := range constrs {
		for i := range constr.Lits {
			lit := IntToLit(int32(constr.Lits[i]))
			v := lit.Var()
			if int(v) >= pb.NbVars {
				pb.NbVars = int(v) + 1
			}
		}
		card := constr.AtLeast
		if card <= 0 { // Clause is trivially SAT, ignore
			continue
		}
		sumW := constr.WeightSum()
		if sumW < card { // Clause cannot be satsfied
			pb.Status = Unsat
			return &pb
		}
		if sumW == card { // All lits must be true
			for i := range constr.Lits {
				lit := IntToLit(int32(constr.Lits[i]))
				pb.Units = append(pb.Units, lit)
			}
		} else {
			lits := make([]Lit, len(constr.Lits))
			for j, val := range constr.Lits {
				lits[j] = IntToLit(int32(val))
			}
			pb.Clauses = append(pb.Clauses, NewPBClause(lits, constr.Weights, card))
		}
	}
	pb.Model = make([]decLevel, pb.NbVars)
	for _, unit := range pb.Units {
		v := unit.Var()
		if pb.Model[v] == 0 {
			if unit.IsPositive() {
				pb.Model[v] = 1
			} else {
				pb.Model[v] = -1
			}
		} else if pb.Model[v] > 0 != unit.IsPositive() {
			pb.Status = Unsat
			return &pb
		}
	}
	pb.simplifyPB()
	return &pb
}

// Parses a CNF line containing a clause and adds it to the problem.
func (pb *Problem) parseClause(line string) error {
	fields := strings.Fields(line)
	lits := make([]Lit, len(fields)-1)
	for i, field := range fields {
		if i == len(fields)-1 { // Ignore last field: it is the 0 clause terminator
			break
		}
		if field == "" {
			continue
		}
		cnfLit, err := strconv.Atoi(field)
		if err != nil {
			return fmt.Errorf("Invalid literal %q in CNF clause %q", field, line)
		}
		lits[i] = IntToLit(int32(cnfLit))
	}
	switch len(lits) {
	case 0:
		pb.Status = Unsat
		pb.Clauses = nil
	case 1:
		lit := lits[0]
		pb.Units = append(pb.Units, lit)
		v := lit.Var()
		if pb.Model[v] == 0 {
			if lit.IsPositive() {
				pb.Model[lit.Var()] = 1
			} else {
				pb.Model[lit.Var()] = -1
			}
		} else if pb.Model[v] > 0 != lit.IsPositive() {
			pb.Status = Unsat
		}
	default:
		pb.Clauses = append(pb.Clauses, NewClause(lits))
	}
	return nil
}

// ParseCNF parses a CNF file and returns the corresponding Problem.
func ParseCNF(f io.Reader) (*Problem, error) {
	scanner := bufio.NewScanner(f)
	var nbClauses int
	var pb Problem
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" {
			continue
		}
		if line[0] == 'p' {
			fields := strings.Split(line, " ")
			if len(fields) < 4 {
				return nil, fmt.Errorf("invalid syntax %q in CNF file", line)
			}
			var err error
			pb.NbVars, err = strconv.Atoi(fields[2])
			if err != nil {
				return nil, fmt.Errorf("nbvars not an int : '%s'", fields[2])
			}
			pb.Model = make([]decLevel, pb.NbVars)
			nbClauses, err = strconv.Atoi(fields[3])
			if err != nil {
				return nil, fmt.Errorf("nbClauses not an int : '%s'", fields[3])
			}
			pb.Clauses = make([]*Clause, 0, nbClauses)
		} else if line[0] != 'c' { // Not a header, not a comment : a clause
			if err := pb.parseClause(line); err != nil {
				return nil, err
			}
		}
	}
	pb.simplify()
	return &pb, nil
}

func (pb *Problem) parsePBLine(line string) error {
	if line == "" {
		return fmt.Errorf("empty line in file")
	}
	if line[len(line)-1] != ';' {
		return fmt.Errorf("line %q does not end with semicolon", line)
	}
	fields := strings.Fields(line[:len(line)-1])
	if len(fields) == 0 {
		return fmt.Errorf("empty line in file")
	}
	if len(fields) < 4 || len(fields)%2 != 0 {
		return fmt.Errorf("invalid syntax %q", line)
	}
	operator := fields[len(fields)-2]
	if operator != ">=" && operator != "=" {
		return fmt.Errorf("invalid operator %q in %q: expected \">=\" or \"=\"", operator, line)
	}
	rhs, err := strconv.Atoi(fields[len(fields)-1])
	if err != nil {
		return fmt.Errorf("invalid value %q in %q: %v", fields[len(fields)-1], line, err)
	}
	weights, lits, err := pb.parseTerms(fields, line)
	if err != nil {
		return err
	}
	if operator == ">=" {
		pb.Clauses = append(pb.Clauses, GtEq(lits, weights, rhs).Clause())
	} else {
		for _, constr := range Eq(lits, weights, rhs) {
			pb.Clauses = append(pb.Clauses, constr.Clause())
		}
	}
	return nil
}

func (pb *Problem) parseTerms(fields []string, line string) (weights []int, lits []int, err error) {
	terms := fields[:len(fields)-2]
	weights = make([]int, len(terms)/2)
	lits = make([]int, len(terms)/2)
	for i := range weights {
		w, err := strconv.Atoi(terms[i*2])
		if err != nil {
			return nil, nil, fmt.Errorf("invalid weight %q in %q: %v", terms[i*2], line, err)
		}
		weights[i] = w
		l := terms[i*2+1]
		if !strings.HasPrefix(l, "x") && !strings.HasPrefix(l, "~x") || len(l) < 2 {
			return nil, nil, fmt.Errorf("invalid variable name %q in %q", l, line)
		}
		if l[0] == '~' {
			lits[i], err = strconv.Atoi(l[2:])
		} else {
			lits[i], err = strconv.Atoi(l[1:])
		}
		if err != nil {
			return nil, nil, fmt.Errorf("invalid variable %q in %q: %v", l, line, err)
		}
		if lits[i] > pb.NbVars {
			pb.NbVars = lits[i]
		}
		if l[0] == '~' {
			lits[i] = -lits[i]
		}
	}
	return weights, lits, nil
}

// ParsePBS parses a file corresponding to the PBS syntax.
// See http://www.cril.univ-artois.fr/PB16/format.pdf for more details.
func ParsePBS(f io.Reader) (*Problem, error) {
	scanner := bufio.NewScanner(f)
	var pb Problem
	for scanner.Scan() {
		line := scanner.Text()
		if line == "" || line[0] == '*' {
			continue
		}
		if err := pb.parsePBLine(line); err != nil {
			return nil, err
		}
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("could not parse PBS: %v", err)
	}
	pb.Model = make([]decLevel, pb.NbVars)
	pb.simplifyPB()
	return &pb, nil
}
<|endoftext|>