<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/dustin/go-couchstore"
	"github.com/dustin/go-jsonpointer"
)

var timeoutError = errors.New("query timed out")

type ptrval struct {
	di       *couchstore.DocInfo
	val      *string
	included bool
}

type Reducer func(input chan ptrval) interface{}

type processOut struct {
	cacheKey    string
	key         int64
	value       []interface{}
	err         error
	cacheOpaque uint32
}

func (p processOut) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]interface{}{"v": p.value})
}

type processIn struct {
	cacheKey   string
	dbname     string
	key        int64
	infos      []*couchstore.DocInfo
	nextInfo   *couchstore.DocInfo
	ptrs       []string
	reds       []string
	before     time.Time
	filters    []string
	filtervals []string
	out        chan<- *processOut
}

type queryIn struct {
	dbname     string
	from       string
	to         string
	group      int
	ptrs       []string
	reds       []string
	start      time.Time
	before     time.Time
	filters    []string
	filtervals []string
	started    int32
	totalKeys  int32
	out        chan *processOut
	cherr      chan error
}

func processDoc(di *couchstore.DocInfo, chs []chan ptrval,
	doc []byte, ptrs []string,
	filters []string, filtervals []string,
	included bool) {

	pv := ptrval{di, nil, included}

	j := map[string]interface{}{}
	err := json.Unmarshal(doc, &j)
	if err != nil {
		for i := range ptrs {
			chs[i] <- pv
		}
		return
	}
	for i, p := range filters {
		val := jsonpointer.Get(j, p)
		checkVal := filtervals[i]
		switch val.(type) {
		case string:
			if val != checkVal {
				return
			}
		case int, uint, int64, float64, uint64, bool:
			v := fmt.Sprintf("%v", val)
			if v != checkVal {
				return
			}
		default:
			return
		}
	}

	for i, p := range ptrs {
		val := jsonpointer.Get(j, p)
		switch x := val.(type) {
		case string:
			pv.val = &x
			chs[i] <- pv
		case int, uint, int64, float64, uint64, bool:
			v := fmt.Sprintf("%v", val)
			pv.val = &v
			chs[i] <- pv
		default:
			log.Printf("Ignoring %T", val)
			chs[i] <- pv
		}
	}
}

func process_docs(pi *processIn) {

	result := processOut{pi.cacheKey, pi.key, nil, nil, 0}

	if len(pi.ptrs) == 0 {
		log.Panicf("No pointers specified in query: %#v", *pi)
	}

	db, err := dbopen(pi.dbname)
	if err != nil {
		result.err = err
		pi.out <- &result
		return
	}
	defer db.Close()

	chans := make([]chan ptrval, 0, len(pi.ptrs))
	resultchs := make([]chan interface{}, 0, len(pi.ptrs))
	for i, r := range pi.reds {
		chans = append(chans, make(chan ptrval))
		resultchs = append(resultchs, make(chan interface{}))

		go func(fi int, fr string) {
			resultchs[fi] <- reducers[fr](chans[fi])
		}(i, r)
	}

	go func() {
		defer closeAll(chans)

		dodoc := func(di *couchstore.DocInfo, included bool) {
			doc, err := db.GetFromDocInfo(di)
			if err == nil {
				processDoc(di, chans, doc.Value(), pi.ptrs,
					pi.filters, pi.filtervals, included)
			} else {
				for i := range pi.ptrs {
					chans[i] <- ptrval{di, nil, included}
				}
			}
		}

		for _, di := range pi.infos {
			dodoc(di, true)
		}
		if pi.nextInfo != nil {
			dodoc(pi.nextInfo, false)
		}
	}()

	results := make([]interface{}, len(pi.ptrs))
	for i := 0; i < len(pi.ptrs); i++ {
		results[i] = <-resultchs[i]
		if f, fok := results[i].(float64); fok && math.IsNaN(f) {
			results[i] = nil
		}
	}
	result.value = results

	if result.cacheOpaque == 0 && result.cacheKey != "" {
		// It's OK if we can't store our newly pulled item in
		// the cache, but it's most definitely not OK to stop
		// here because of this.
		select {
		case cacheInputSet <- &result:
		default:
		}
	}
	pi.out <- &result
}

func docProcessor(ch <-chan *processIn) {
	for pi := range ch {
		if time.Now().Before(pi.before) {
			process_docs(pi)
		} else {
			pi.out <- &processOut{"", pi.key, nil, timeoutError, 0}
		}
	}
}

func fetchDocs(dbname string, key int64, infos []*couchstore.DocInfo,
	nextInfo *couchstore.DocInfo, ptrs []string, reds []string,
	filters []string, filtervals []string,
	before time.Time, out chan<- *processOut) {

	i := processIn{"", dbname, key, infos, nextInfo,
		ptrs, reds, before, filters, filtervals, out}

	cacheInput <- &i
}

func runQuery(q *queryIn) {
	if len(q.ptrs) == 0 {
		q.cherr <- fmt.Errorf("At least one pointer is required")
		return
	}

	db, err := dbopen(q.dbname)
	if err != nil {
		log.Printf("Error opening db: %v - %v", q.dbname, err)
		q.cherr <- err
		return
	}
	defer db.Close()

	chunk := int64(time.Duration(q.group) * time.Millisecond)

	infos := []*couchstore.DocInfo{}
	g := int64(0)
	nextg := ""

	err = db.Walk(q.from, func(d *couchstore.Couchstore,
		di *couchstore.DocInfo) error {
		kstr := di.ID()
		var err error
		if q.to != "" && kstr >= q.to {
			err = couchstore.StopIteration
		}

		atomic.AddInt32(&q.totalKeys, 1)

		if kstr >= nextg {
			if len(infos) > 0 {
				atomic.AddInt32(&q.started, 1)
				fetchDocs(q.dbname, g, infos, di,
					q.ptrs, q.reds, q.filters, q.filtervals,
					q.before, q.out)

				infos = make([]*couchstore.DocInfo, 0, len(infos))
			}

			k := parseKey(kstr)
			g = (k / chunk) * chunk
			nextgi := g + chunk
			nextgt := time.Unix(nextgi/1e9, nextgi%1e9).UTC()
			nextg = nextgt.Format(time.RFC3339Nano)
		}
		infos = append(infos, di)

		return err
	})

	if err == nil && len(infos) > 0 {
		atomic.AddInt32(&q.started, 1)
		fetchDocs(q.dbname, g, infos, nil,
			q.ptrs, q.reds, q.filters, q.filtervals,
			q.before, q.out)
	}

	q.cherr <- err
}

func queryExecutor(ch <-chan *queryIn) {
	for q := range ch {
		if time.Now().Before(q.before) {
			runQuery(q)
		} else {
			log.Printf("Timed out query that's %v late",
				time.Since(q.before))
			q.cherr <- timeoutError
		}
	}
}

func executeQuery(dbname, from, to string, group int,
	ptrs []string, reds []string, filters []string, filtervals []string) *queryIn {

	now := time.Now()

	rv := &queryIn{
		dbname:     dbname,
		from:       from,
		to:         to,
		group:      group,
		ptrs:       ptrs,
		reds:       reds,
		start:      now,
		before:     now.Add(*queryTimeout),
		filters:    filters,
		filtervals: filtervals,
		out:        make(chan *processOut),
		cherr:      make(chan error),
	}
	queryInput <- rv
	return rv
}

var processorInput chan *processIn
var queryInput chan *queryIn

func convertTofloat64(in chan ptrval) chan float64 {
	ch := make(chan float64)
	go func() {
		defer close(ch)
		for v := range in {
			if v.included && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					ch <- x
				}
			}
		}
	}()

	return ch
}

func convertTofloat64Rate(in chan ptrval) chan float64 {
	ch := make(chan float64)
	go func() {
		defer close(ch)
		var prevts int64
		var preval float64

		// First, find a part of the stream that has usable data.
		for v := range in {
			if v.di != nil && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					prevts = parseKey(v.di.ID())
					preval = x
					break
				}
			}
		}
		// Then emit floats based on deltas from previous values.
		for v := range in {
			if v.di != nil && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					thists := parseKey(v.di.ID())

					val := ((x - preval) /
						(float64(thists-prevts) / 1e9))

					if !math.IsNaN(val) {
						ch <- val
					}

					prevts = thists
					preval = x
				}
			}
		}
	}()

	return ch
}

var reducers = map[string]Reducer{
	"identity": func(input chan ptrval) interface{} {
		rv := []*string{}
		for s := range input {
			if s.included {
				rv = append(rv, s.val)
			}
		}
		return rv
	},
	"any": func(input chan ptrval) interface{} {
		for v := range input {
			if v.included && v.val != nil {
				return *v.val
			}
		}
		return nil
	},
	"count": func(input chan ptrval) interface{} {
		rv := 0
		for v := range input {
			if v.included && v.val != nil {
				rv++
			}
		}
		return rv
	},
	"sum": func(input chan ptrval) interface{} {
		rv := float64(0)
		for v := range convertTofloat64(input) {
			rv += v
		}
		return rv
	},
	"sumsq": func(input chan ptrval) interface{} {
		rv := float64(0)
		for v := range convertTofloat64(input) {
			rv += (v * v)
		}
		return rv
	},
	"max": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64(input) {
			if v > rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"min": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64(input) {
			if v < rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"avg": func(input chan ptrval) interface{} {
		nums := float64(0)
		sum := float64(0)
		for v := range convertTofloat64(input) {
			nums++
			sum += v
		}
		if nums > 0 {
			return sum / nums
		}
		return math.NaN()
	},
	"c_min": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64Rate(input) {
			if v < rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"c_avg": func(input chan ptrval) interface{} {
		nums := float64(0)
		sum := float64(0)
		for v := range convertTofloat64Rate(input) {
			nums++
			sum += v
		}
		if nums > 0 {
			return sum / nums
		}
		return math.NaN()
	},
	"c_max": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64Rate(input) {
			if v > rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
}
<commit_msg>Use new streaming JSON pointer impl.<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math"
	"strconv"
	"sync/atomic"
	"time"

	"github.com/dustin/go-couchstore"
	"github.com/dustin/go-jsonpointer"
)

var timeoutError = errors.New("query timed out")

type ptrval struct {
	di       *couchstore.DocInfo
	val      *string
	included bool
}

type Reducer func(input chan ptrval) interface{}

type processOut struct {
	cacheKey    string
	key         int64
	value       []interface{}
	err         error
	cacheOpaque uint32
}

func (p processOut) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]interface{}{"v": p.value})
}

type processIn struct {
	cacheKey   string
	dbname     string
	key        int64
	infos      []*couchstore.DocInfo
	nextInfo   *couchstore.DocInfo
	ptrs       []string
	reds       []string
	before     time.Time
	filters    []string
	filtervals []string
	out        chan<- *processOut
}

type queryIn struct {
	dbname     string
	from       string
	to         string
	group      int
	ptrs       []string
	reds       []string
	start      time.Time
	before     time.Time
	filters    []string
	filtervals []string
	started    int32
	totalKeys  int32
	out        chan *processOut
	cherr      chan error
}

func pget(j []byte, s string) (rv interface{}) {
	b, err := jsonpointer.Find(j, s)
	if err != nil {
		return nil
	}
	err = json.Unmarshal(b, &rv)
	if err != nil {
		return nil
	}
	return
}

func processDoc(di *couchstore.DocInfo, chs []chan ptrval,
	doc []byte, ptrs []string,
	filters []string, filtervals []string,
	included bool) {

	pv := ptrval{di, nil, included}

	for i, p := range filters {
		val := pget(doc, p)
		checkVal := filtervals[i]
		switch val.(type) {
		case string:
			if val != checkVal {
				return
			}
		case int, uint, int64, float64, uint64, bool:
			v := fmt.Sprintf("%v", val)
			if v != checkVal {
				return
			}
		default:
			return
		}
	}

	for i, p := range ptrs {
		val := pget(doc, p)
		switch x := val.(type) {
		case string:
			pv.val = &x
			chs[i] <- pv
		case int, uint, int64, float64, uint64, bool:
			v := fmt.Sprintf("%v", val)
			pv.val = &v
			chs[i] <- pv
		default:
			log.Printf("Ignoring %T", val)
			chs[i] <- pv
		}
	}
}

func process_docs(pi *processIn) {

	result := processOut{pi.cacheKey, pi.key, nil, nil, 0}

	if len(pi.ptrs) == 0 {
		log.Panicf("No pointers specified in query: %#v", *pi)
	}

	db, err := dbopen(pi.dbname)
	if err != nil {
		result.err = err
		pi.out <- &result
		return
	}
	defer db.Close()

	chans := make([]chan ptrval, 0, len(pi.ptrs))
	resultchs := make([]chan interface{}, 0, len(pi.ptrs))
	for i, r := range pi.reds {
		chans = append(chans, make(chan ptrval))
		resultchs = append(resultchs, make(chan interface{}))

		go func(fi int, fr string) {
			resultchs[fi] <- reducers[fr](chans[fi])
		}(i, r)
	}

	go func() {
		defer closeAll(chans)

		dodoc := func(di *couchstore.DocInfo, included bool) {
			doc, err := db.GetFromDocInfo(di)
			if err == nil {
				processDoc(di, chans, doc.Value(), pi.ptrs,
					pi.filters, pi.filtervals, included)
			} else {
				for i := range pi.ptrs {
					chans[i] <- ptrval{di, nil, included}
				}
			}
		}

		for _, di := range pi.infos {
			dodoc(di, true)
		}
		if pi.nextInfo != nil {
			dodoc(pi.nextInfo, false)
		}
	}()

	results := make([]interface{}, len(pi.ptrs))
	for i := 0; i < len(pi.ptrs); i++ {
		results[i] = <-resultchs[i]
		if f, fok := results[i].(float64); fok && math.IsNaN(f) {
			results[i] = nil
		}
	}
	result.value = results

	if result.cacheOpaque == 0 && result.cacheKey != "" {
		// It's OK if we can't store our newly pulled item in
		// the cache, but it's most definitely not OK to stop
		// here because of this.
		select {
		case cacheInputSet <- &result:
		default:
		}
	}
	pi.out <- &result
}

func docProcessor(ch <-chan *processIn) {
	for pi := range ch {
		if time.Now().Before(pi.before) {
			process_docs(pi)
		} else {
			pi.out <- &processOut{"", pi.key, nil, timeoutError, 0}
		}
	}
}

func fetchDocs(dbname string, key int64, infos []*couchstore.DocInfo,
	nextInfo *couchstore.DocInfo, ptrs []string, reds []string,
	filters []string, filtervals []string,
	before time.Time, out chan<- *processOut) {

	i := processIn{"", dbname, key, infos, nextInfo,
		ptrs, reds, before, filters, filtervals, out}

	cacheInput <- &i
}

func runQuery(q *queryIn) {
	if len(q.ptrs) == 0 {
		q.cherr <- fmt.Errorf("At least one pointer is required")
		return
	}

	db, err := dbopen(q.dbname)
	if err != nil {
		log.Printf("Error opening db: %v - %v", q.dbname, err)
		q.cherr <- err
		return
	}
	defer db.Close()

	chunk := int64(time.Duration(q.group) * time.Millisecond)

	infos := []*couchstore.DocInfo{}
	g := int64(0)
	nextg := ""

	err = db.Walk(q.from, func(d *couchstore.Couchstore,
		di *couchstore.DocInfo) error {
		kstr := di.ID()
		var err error
		if q.to != "" && kstr >= q.to {
			err = couchstore.StopIteration
		}

		atomic.AddInt32(&q.totalKeys, 1)

		if kstr >= nextg {
			if len(infos) > 0 {
				atomic.AddInt32(&q.started, 1)
				fetchDocs(q.dbname, g, infos, di,
					q.ptrs, q.reds, q.filters, q.filtervals,
					q.before, q.out)

				infos = make([]*couchstore.DocInfo, 0, len(infos))
			}

			k := parseKey(kstr)
			g = (k / chunk) * chunk
			nextgi := g + chunk
			nextgt := time.Unix(nextgi/1e9, nextgi%1e9).UTC()
			nextg = nextgt.Format(time.RFC3339Nano)
		}
		infos = append(infos, di)

		return err
	})

	if err == nil && len(infos) > 0 {
		atomic.AddInt32(&q.started, 1)
		fetchDocs(q.dbname, g, infos, nil,
			q.ptrs, q.reds, q.filters, q.filtervals,
			q.before, q.out)
	}

	q.cherr <- err
}

func queryExecutor(ch <-chan *queryIn) {
	for q := range ch {
		if time.Now().Before(q.before) {
			runQuery(q)
		} else {
			log.Printf("Timed out query that's %v late",
				time.Since(q.before))
			q.cherr <- timeoutError
		}
	}
}

func executeQuery(dbname, from, to string, group int,
	ptrs []string, reds []string, filters []string, filtervals []string) *queryIn {

	now := time.Now()

	rv := &queryIn{
		dbname:     dbname,
		from:       from,
		to:         to,
		group:      group,
		ptrs:       ptrs,
		reds:       reds,
		start:      now,
		before:     now.Add(*queryTimeout),
		filters:    filters,
		filtervals: filtervals,
		out:        make(chan *processOut),
		cherr:      make(chan error),
	}
	queryInput <- rv
	return rv
}

var processorInput chan *processIn
var queryInput chan *queryIn

func convertTofloat64(in chan ptrval) chan float64 {
	ch := make(chan float64)
	go func() {
		defer close(ch)
		for v := range in {
			if v.included && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					ch <- x
				}
			}
		}
	}()

	return ch
}

func convertTofloat64Rate(in chan ptrval) chan float64 {
	ch := make(chan float64)
	go func() {
		defer close(ch)
		var prevts int64
		var preval float64

		// First, find a part of the stream that has usable data.
		for v := range in {
			if v.di != nil && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					prevts = parseKey(v.di.ID())
					preval = x
					break
				}
			}
		}
		// Then emit floats based on deltas from previous values.
		for v := range in {
			if v.di != nil && v.val != nil {
				x, err := strconv.ParseFloat(*v.val, 64)
				if err == nil {
					thists := parseKey(v.di.ID())

					val := ((x - preval) /
						(float64(thists-prevts) / 1e9))

					if !math.IsNaN(val) {
						ch <- val
					}

					prevts = thists
					preval = x
				}
			}
		}
	}()

	return ch
}

var reducers = map[string]Reducer{
	"identity": func(input chan ptrval) interface{} {
		rv := []*string{}
		for s := range input {
			if s.included {
				rv = append(rv, s.val)
			}
		}
		return rv
	},
	"any": func(input chan ptrval) interface{} {
		for v := range input {
			if v.included && v.val != nil {
				return *v.val
			}
		}
		return nil
	},
	"count": func(input chan ptrval) interface{} {
		rv := 0
		for v := range input {
			if v.included && v.val != nil {
				rv++
			}
		}
		return rv
	},
	"sum": func(input chan ptrval) interface{} {
		rv := float64(0)
		for v := range convertTofloat64(input) {
			rv += v
		}
		return rv
	},
	"sumsq": func(input chan ptrval) interface{} {
		rv := float64(0)
		for v := range convertTofloat64(input) {
			rv += (v * v)
		}
		return rv
	},
	"max": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64(input) {
			if v > rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"min": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64(input) {
			if v < rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"avg": func(input chan ptrval) interface{} {
		nums := float64(0)
		sum := float64(0)
		for v := range convertTofloat64(input) {
			nums++
			sum += v
		}
		if nums > 0 {
			return sum / nums
		}
		return math.NaN()
	},
	"c_min": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64Rate(input) {
			if v < rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
	"c_avg": func(input chan ptrval) interface{} {
		nums := float64(0)
		sum := float64(0)
		for v := range convertTofloat64Rate(input) {
			nums++
			sum += v
		}
		if nums > 0 {
			return sum / nums
		}
		return math.NaN()
	},
	"c_max": func(input chan ptrval) interface{} {
		rv := math.NaN()
		for v := range convertTofloat64Rate(input) {
			if v > rv || math.IsNaN(rv) {
				rv = v
			}
		}
		return rv
	},
}
<|endoftext|>


<commit_before>package GoSDK

import ()

// Filter is the atomic structure inside a query it contains
// A field a value and an operator
type Filter struct {
	Field    string
	Value    interface{}
	Operator string
}

type Ordering struct {
	SortOrder bool
	OrderKey  string
}

type Query struct {
	Filters    [][]Filter
	PageSize   int
	PageNumber int
	Order      []Ordering
}

func NewQuery() *Query {
	query := &Query{
		Filters: [][]Filter{[]Filter{}},
		Order:   []Ordering{},
	}
	return query
}

func (q *Query) EqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) GreaterThan(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: ">",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) GreaterThanEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: ">=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) LessThan(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "<",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) LessThanEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "<=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) NotEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "!=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) Matches(field, regex string) {
	f := Filter{
		Field:    field,
		Value:    regex,
		Operator: "~",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) Or(orQuery *Query) {
	q.Filters = append(q.Filters, orQuery.Filters...)
}

// Map will produce the kind of thing that is sent as a query
// either as the body of a request or as a queryString
func (q *Query) serialize() map[string]interface{} {
	qrMap := make(map[string]interface{})
	qrMap["PAGENUM"] = q.PageNumber
	qrMap["PAGESIZE"] = q.PageSize
	sortMap := make([]map[string]interface{}, len(q.Order))
	for i, ordering := range q.Order {
		sortMap[i] = make(map[string]interface{})
		if ordering.SortOrder {
			sortMap[i]["ASC"] = ordering.OrderKey
		} else {
			sortMap[i]["DESC"] = ordering.OrderKey
		}
	}
	qrMap["SORT"] = sortMap
	filterSlice := make([][]map[string]interface{}, len(q.Filters))
	for i, querySlice := range q.Filters {
		qm := make([]map[string]interface{}, len(querySlice))
		for j, query := range querySlice {
			mapForQuery := make(map[string]interface{})
			var op string
			switch query.Operator {
			case "=":
				op = "EQ"
			case ">":
				op = "GT"
			case "<":
				op = "LT"
			case ">=":
				op = "GTE"
			case "<=":
				op = "LTE"
			case "/=":
				op = "NEQ"
			case "~":
				op = "RE"
			default:
				op = "EQ"
			}
			mapForQuery[op] = []map[string]interface{}{map[string]interface{}{query.Field: query.Value}}
			qm[j] = mapForQuery
		}
		filterSlice[i] = qm
	}
	qrMap["FILTERS"] = filterSlice
	return qrMap
}
<commit_msg>Add changes to allow selecting of specific fields<commit_after>package GoSDK

import ()

// Filter is the atomic structure inside a query it contains
// A field a value and an operator
type Filter struct {
	Field    string
	Value    interface{}
	Operator string
}

type Ordering struct {
	SortOrder bool
	OrderKey  string
}

type Query struct {
	Filters    [][]Filter
	PageSize   int
	PageNumber int
	Order      []Ordering
	Columns    []string
}

func NewQuery() *Query {
	query := &Query{
		Filters: [][]Filter{[]Filter{}},
		Order:   []Ordering{},
	}
	return query
}

func (q *Query) EqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) GreaterThan(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: ">",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) GreaterThanEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: ">=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) LessThan(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "<",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) LessThanEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "<=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) NotEqualTo(field string, value interface{}) {
	f := Filter{
		Field:    field,
		Value:    value,
		Operator: "!=",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) Matches(field, regex string) {
	f := Filter{
		Field:    field,
		Value:    regex,
		Operator: "~",
	}
	q.Filters[0] = append(q.Filters[0], f)
}

func (q *Query) Or(orQuery *Query) {
	q.Filters = append(q.Filters, orQuery.Filters...)
}

// Map will produce the kind of thing that is sent as a query
// either as the body of a request or as a queryString
func (q *Query) serialize() map[string]interface{} {
	qrMap := make(map[string]interface{})
	qrMap["PAGENUM"] = q.PageNumber
	qrMap["PAGESIZE"] = q.PageSize
	qrMap["SELECTCOLUMNS"] = q.Columns
	sortMap := make([]map[string]interface{}, len(q.Order))
	for i, ordering := range q.Order {
		sortMap[i] = make(map[string]interface{})
		if ordering.SortOrder {
			sortMap[i]["ASC"] = ordering.OrderKey
		} else {
			sortMap[i]["DESC"] = ordering.OrderKey
		}
	}
	qrMap["SORT"] = sortMap
	filterSlice := make([][]map[string]interface{}, len(q.Filters))
	for i, querySlice := range q.Filters {
		qm := make([]map[string]interface{}, len(querySlice))
		for j, query := range querySlice {
			mapForQuery := make(map[string]interface{})
			var op string
			switch query.Operator {
			case "=":
				op = "EQ"
			case ">":
				op = "GT"
			case "<":
				op = "LT"
			case ">=":
				op = "GTE"
			case "<=":
				op = "LTE"
			case "/=":
				op = "NEQ"
			case "~":
				op = "RE"
			default:
				op = "EQ"
			}
			mapForQuery[op] = []map[string]interface{}{map[string]interface{}{query.Field: query.Value}}
			qm[j] = mapForQuery
		}
		filterSlice[i] = qm
	}
	qrMap["FILTERS"] = filterSlice
	return qrMap
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package miniprofiler_gae

import (
	"appengine"
	"appengine/memcache"
	"appengine/user"
	"appengine_internal"
	"fmt"
	"github.com/mjibson/MiniProfiler/go/miniprofiler"
	"github.com/mjibson/appstats"
	"net/http"
)

func init() {
	miniprofiler.Enable = EnableIfAdminOrDev
	miniprofiler.Get = GetMemcache
	miniprofiler.Store = StoreMemcache
	miniprofiler.MachineName = Instance
}

// EnableIfAdminOrDev returns true if this is the dev server or the current
// user is an admin. This is the default for miniprofiler.Enable.
func EnableIfAdminOrDev(r *http.Request) bool {
	if appengine.IsDevAppServer() {
		return true
	}
	c := appengine.NewContext(r)
	if u := user.Current(c); u != nil {
		return u.Admin
	}
	return false
}

// Instance returns the app engine instance id, or the hostname on dev.
// This is the default for miniprofiler.MachineName.
func Instance() string {
	if i := appengine.InstanceID(); i != "" {
		return i[len(i)-8:]
	}
	return miniprofiler.Hostname()
}

// StoreMemcache stores the Profile in memcache. This is the default for
// miniprofiler.Store.
func StoreMemcache(r *http.Request, p *miniprofiler.Profile) {
	item := &memcache.Item{
		Key:   mp_key(string(p.Id)),
		Value: p.Json(),
	}
	c := appengine.NewContext(r)
	memcache.Set(c, item)
}

// GetMemcache gets the Profile from memcache. This is the default for
// miniprofiler.Get.
func GetMemcache(r *http.Request, id string) *miniprofiler.Profile {
	c := appengine.NewContext(r)
	item, err := memcache.Get(c, mp_key(id))
	if err != nil {
		return nil
	}
	return miniprofiler.ProfileFromJson(item.Value)
}

type Context struct {
	appstats.Context
	P *miniprofiler.Profile
}

func (c Context) Call(service, method string, in, out appengine_internal.ProtoMessage, opts *appengine_internal.CallOptions) error {
	err := c.Context.Call(service, method, in, out, opts)
	if service == "__go__" {
		v := c.Context.Stats.RPCStats[len(c.Context.Stats.RPCStats)-1]
		c.P.AddCustomTiming("RPC", &miniprofiler.CustomTiming{
			StartMilliseconds:    float64(v.Offset.Nanoseconds()) / 1000000,
			DurationMilliseconds: float64(v.Duration.Nanoseconds()) / 1000000,
		})
	}
	return err
}

// NewHandler returns a profiled, appstats-aware appengine.Context.
func NewHandler(f func(Context, http.ResponseWriter, *http.Request)) appstats.Handler {
	return appstats.NewHandler(func(c appengine.Context, w http.ResponseWriter, r *http.Request) {
		pc := Context{
			Context: c.(appstats.Context),
		}
		pc.P = miniprofiler.NewProfile(w, r, miniprofiler.FuncName(f))
		f(pc, w, r)

		if pc.P.Root != nil {
			pc.P.CustomLink = pc.URL()
			pc.P.CustomLinkName = "appstats"
			pc.P.Finalize()
		}
	})
}

func mp_key(id string) string {
	return fmt.Sprintf("mini-profiler-results:%s", id)
}
<commit_msg>Oops, fix compare<commit_after>/*
 * Copyright (c) 2013 Matt Jibson <matt.jibson@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package miniprofiler_gae

import (
	"appengine"
	"appengine/memcache"
	"appengine/user"
	"appengine_internal"
	"fmt"
	"github.com/mjibson/MiniProfiler/go/miniprofiler"
	"github.com/mjibson/appstats"
	"net/http"
)

func init() {
	miniprofiler.Enable = EnableIfAdminOrDev
	miniprofiler.Get = GetMemcache
	miniprofiler.Store = StoreMemcache
	miniprofiler.MachineName = Instance
}

// EnableIfAdminOrDev returns true if this is the dev server or the current
// user is an admin. This is the default for miniprofiler.Enable.
func EnableIfAdminOrDev(r *http.Request) bool {
	if appengine.IsDevAppServer() {
		return true
	}
	c := appengine.NewContext(r)
	if u := user.Current(c); u != nil {
		return u.Admin
	}
	return false
}

// Instance returns the app engine instance id, or the hostname on dev.
// This is the default for miniprofiler.MachineName.
func Instance() string {
	if i := appengine.InstanceID(); i != "" {
		return i[len(i)-8:]
	}
	return miniprofiler.Hostname()
}

// StoreMemcache stores the Profile in memcache. This is the default for
// miniprofiler.Store.
func StoreMemcache(r *http.Request, p *miniprofiler.Profile) {
	item := &memcache.Item{
		Key:   mp_key(string(p.Id)),
		Value: p.Json(),
	}
	c := appengine.NewContext(r)
	memcache.Set(c, item)
}

// GetMemcache gets the Profile from memcache. This is the default for
// miniprofiler.Get.
func GetMemcache(r *http.Request, id string) *miniprofiler.Profile {
	c := appengine.NewContext(r)
	item, err := memcache.Get(c, mp_key(id))
	if err != nil {
		return nil
	}
	return miniprofiler.ProfileFromJson(item.Value)
}

type Context struct {
	appstats.Context
	P *miniprofiler.Profile
}

func (c Context) Call(service, method string, in, out appengine_internal.ProtoMessage, opts *appengine_internal.CallOptions) error {
	err := c.Context.Call(service, method, in, out, opts)
	if service != "__go__" {
		v := c.Context.Stats.RPCStats[len(c.Context.Stats.RPCStats)-1]
		c.P.AddCustomTiming("RPC", &miniprofiler.CustomTiming{
			StartMilliseconds:    float64(v.Offset.Nanoseconds()) / 1000000,
			DurationMilliseconds: float64(v.Duration.Nanoseconds()) / 1000000,
		})
	}
	return err
}

// NewHandler returns a profiled, appstats-aware appengine.Context.
func NewHandler(f func(Context, http.ResponseWriter, *http.Request)) appstats.Handler {
	return appstats.NewHandler(func(c appengine.Context, w http.ResponseWriter, r *http.Request) {
		pc := Context{
			Context: c.(appstats.Context),
		}
		pc.P = miniprofiler.NewProfile(w, r, miniprofiler.FuncName(f))
		f(pc, w, r)

		if pc.P.Root != nil {
			pc.P.CustomLink = pc.URL()
			pc.P.CustomLinkName = "appstats"
			pc.P.Finalize()
		}
	})
}

func mp_key(id string) string {
	return fmt.Sprintf("mini-profiler-results:%s", id)
}
<|endoftext|>


<commit_before>package bongo

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"github.com/jinzhu/gorm"
)

func (b *Bongo) Fetch(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.First(i.Self(), i.GetId()).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	return b.DB.
		Table(i.TableName()).
		Where(ids).
		Find(data).
		Error

}

func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	return b.Create(i)
}

// selector, set
func (b *Bongo) UpdatePartial(i Modellable, rest ...map[string]interface{}) error {
	var set, selector map[string]interface{}

	switch len(rest) {
	case 1:
		set = rest[0]
		selector = nil
	case 2:
		selector = rest[0]
		set = rest[1]
	default:
		return errors.New("Update partial parameter list is wrong")
	}

	query := b.DB.Table(i.TableName())

	if i.GetId() != 0 {
		query = query.Where(i.GetId())
	} else {
		//add selector
		query = addWhere(query, selector)
	}

	if err := query.Model(i.Self()).Update(set).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Delete(i.Self()).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

func (b *Bongo) Some(i Modellable, data interface{}, rest ...map[string]interface{}) error {

	var selector, options, plucked map[string]interface{}
	switch len(rest) {

	case 1: // just filter
		selector = rest[0]
	case 2: //filter and sort
		selector = rest[0]
		options = rest[1]
	case 3: // filter, sort and only get some data of the result set
		selector = rest[0]
		options = rest[1]
		plucked = rest[2]
	default:
		return errors.New("Some parameter list is wrong")
	}

	// init query
	query := b.DB

	// add pluck data
	query = addPluck(query, plucked)

	// add sort options
	query = addSort(query, options)

	// add table name
	query = query.Table(i.TableName())

	// add selector
	query = addWhere(query, selector)
	err := query.Find(data).Error
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, selector map[string]interface{}) error {

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add selector
	query = addWhere(query, selector)

	// add limit
	query.Limit(1)

	return query.Find(data).Error
}

func (b *Bongo) AfterCreate(i Modellable) {
	eventName := fmt.Sprintf("%s_created", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func (b *Bongo) AfterUpdate(i Modellable) {
	eventName := fmt.Sprintf("%s_updated", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func (b *Bongo) AfterDelete(i Modellable) {
	eventName := fmt.Sprintf("%s_deleted", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func addSort(query *gorm.DB, options map[string]interface{}) *gorm.DB {

	if options == nil {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

func addPluck(query *gorm.DB, plucked map[string]interface{}) *gorm.DB {

	if plucked == nil {
		return query
	}

	var opts []string
	for key := range plucked {
		opts = append(opts, fmt.Sprintf("%s", key))
	}
	fmt.Println(strings.Join(opts, ","))
	return query.Select(strings.Join(opts, ","))
}

func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}
	return query.Where(selector)
}
<commit_msg>Social: add documentation<commit_after>package bongo

import (
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"github.com/jinzhu/gorm"
)

func (b *Bongo) Fetch(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.First(i.Self(), i.GetId()).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) FetchByIds(i Modellable, data interface{}, ids []int64) error {
	if len(ids) == 0 {
		return nil
	}

	return b.DB.
		Table(i.TableName()).
		Where(ids).
		Find(data).
		Error

}

func (b *Bongo) Create(i Modellable) error {
	if err := b.DB.Save(i).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Update(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	// Update and Create is using the Save method, so they are
	// same functions but GORM handles, AfterCreate and AfterUpdate
	// in correct manner
	return b.Create(i)
}

// selector, set
func (b *Bongo) UpdatePartial(i Modellable, rest ...map[string]interface{}) error {
	var set, selector map[string]interface{}

	switch len(rest) {
	case 1:
		set = rest[0]
		selector = nil
	case 2:
		selector = rest[0]
		set = rest[1]
	default:
		return errors.New("Update partial parameter list is wrong")
	}

	query := b.DB.Table(i.TableName())

	if i.GetId() != 0 {
		query = query.Where(i.GetId())
	} else {
		//add selector
		query = addWhere(query, selector)
	}

	if err := query.Model(i.Self()).Update(set).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Delete(i Modellable) error {
	if i.GetId() == 0 {
		return errors.New(fmt.Sprintf("Id is not set for %s", i.TableName()))
	}

	if err := b.DB.Delete(i.Self()).Error; err != nil {
		return err
	}

	return nil
}

func (b *Bongo) Count(i Modellable, where ...interface{}) (int, error) {
	var count int

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add query
	query = query.Where(where[0], where[1:len(where)]...)

	return count, query.Count(&count).Error
}

func (b *Bongo) Some(i Modellable, data interface{}, rest ...map[string]interface{}) error {

	var selector, options, plucked map[string]interface{}
	switch len(rest) {

	case 1: // just filter
		selector = rest[0]
	case 2: //filter and sort
		selector = rest[0]
		options = rest[1]
	case 3: // filter, sort and only get some data of the result set
		selector = rest[0]
		options = rest[1]
		plucked = rest[2]
	default:
		return errors.New("Some parameter list is wrong")
	}

	// init query
	query := b.DB

	// add pluck data
	query = addPluck(query, plucked)

	// add sort options
	query = addSort(query, options)

	// add table name
	query = query.Table(i.TableName())

	// add selector
	query = addWhere(query, selector)
	err := query.Find(data).Error
	if err == gorm.RecordNotFound {
		return nil
	}
	return err
}

func (b *Bongo) One(i Modellable, data interface{}, selector map[string]interface{}) error {

	// init query
	query := b.DB

	// add table name
	query = query.Table(i.TableName())

	// add selector
	query = addWhere(query, selector)

	// add limit
	query.Limit(1)

	return query.Find(data).Error
}

func (b *Bongo) AfterCreate(i Modellable) {
	eventName := fmt.Sprintf("%s_created", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func (b *Bongo) AfterUpdate(i Modellable) {
	eventName := fmt.Sprintf("%s_updated", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func (b *Bongo) AfterDelete(i Modellable) {
	eventName := fmt.Sprintf("%s_deleted", i.TableName())
	data, err := json.Marshal(i.Self())
	if err != nil {
		// here try to resend this message to RMQ again, than
		// persist it to somewhere!#!##@$%#?
		// those messages are really important now
		fmt.Println("Error occured", err)
		return
	}
	err = b.Broker.Publish(eventName, data)
	if err != nil {
		fmt.Println("jhasdjhadsjdasj", err)
	}
}

func addSort(query *gorm.DB, options map[string]interface{}) *gorm.DB {

	if options == nil {
		return query
	}

	var opts []string
	for key, val := range options {
		opts = append(opts, fmt.Sprintf("%s %v", key, val))
	}
	return query.Order(strings.Join(opts, ","))
}

func addPluck(query *gorm.DB, plucked map[string]interface{}) *gorm.DB {

	if plucked == nil {
		return query
	}

	var opts []string
	for key := range plucked {
		opts = append(opts, fmt.Sprintf("%s", key))
	}
	fmt.Println(strings.Join(opts, ","))
	return query.Select(strings.Join(opts, ","))
}

func addWhere(query *gorm.DB, selector map[string]interface{}) *gorm.DB {
	if selector == nil {
		return query
	}
	return query.Where(selector)
}
<|endoftext|>


<commit_before>package main

const (
	postInstall = `#!/bin/bash

KITE_PLIST="/Library/LaunchAgents/com.koding.kite.{{.}}.plist"
chown root:wheel ${KITE_PLIST}
chmod 644 ${KITE_PLIST}

echo $USER
su $USER -c "/bin/launchctl load ${KITE_PLIST}"

exit 0
`

	preInstall = `#!/bin/sh

echo "Checking for plist"
if /bin/launchctl list "com.koding.kite.{{.}}.plist" &> /dev/null; then
    echo "Unloading plist"
    /bin/launchctl unload "/Library/LaunchAgents/com.koding.kite.{{.}}.plist"
fi

KDFILE=/usr/local/bin/{{.}}

echo "Removing previous installation"
if [ -f $KDFILE  ]; then
    rm -r $KDFILE
fi

exit 0
`

	distribution = `<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-script minSpecVersion="1.000000">
    <title>Koding Kite</title>
    <background mime-type="image/png" file="bg.png"/>
    <options customize="never" allow-external-scripts="no"/>
    <!-- <domains enable_localSystem="true" /> -->
    <options rootVolumeOnly="true" />
    <installation-check script="installCheck();"/>
    <script>
function installCheck() {
    if(system.files.fileExistsAtPath('/usr/local/bin/{{.}}')) {
        my.result.title = 'Previous Installation Detected';
        my.result.message = 'A previous installation of Koding {{.}} Kite exists at /usr/local/bin. This installer will remove the previous installation prior to installing. Please back up any data before proceeding.';
        my.result.type = 'Warning';
        return false;
    }
    return true;
}
    </script>
    <!-- List all component packages -->
    <pkg-ref
        id="com.koding.kite.{{.}}.pkg"
        auth="root">com.koding.kite.{{.}}.pkg</pkg-ref>
    <choices-outline>
        <line choice="com.koding.kite.{{.}}.choice"/>
    </choices-outline>
    <choice
        id="com.koding.kite.{{.}}.choice"
        title="Koding Kite"
        customLocation="/">
        <pkg-ref id="com.koding.kite.{{.}}.pkg"/>
    </choice>
</installer-script>
`

	launchAgent = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>KeepAlive</key>
    <dict>
        <key>NetworkState</key>
        <true/>
    </dict>
    <key>Label</key>
    <string>com.koding.kite.{{.}}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/{{.}}</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
`
)
<commit_msg>kd/build: fix reloading of launchAgents, now it stops and starts the agent<commit_after>package main

const (
	preInstall = `#!/bin/sh

KITE_PLIST="/Library/LaunchAgents/com.koding.kite.{{.}}.plist"

# see: https://lists.macosforge.org/pipermail/launchd-dev/2011-January/000890.html
echo "Checking to unload plist"
for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do
    pid=$(echo $pid_uid | cut -d, -f1)
    uid=$(echo $pid_uid | cut -d, -f2)
    echo "unloading launch agent"
    launchctl bsexec "$pid" chroot -u "$uid" / launchctl unload ${KITE_PLIST}
done

KDFILE=/usr/local/bin/{{.}}

echo "Removing previous installation"
if [ -f $KDFILE  ]; then
    rm -r $KDFILE
fi

exit 0
`
	postInstall = `#!/bin/bash

KITE_PLIST="/Library/LaunchAgents/com.koding.kite.{{.}}.plist"
chown root:wheel ${KITE_PLIST}
chmod 644 ${KITE_PLIST}

# this is simpler than below, but it doesn't get the USER env always, don't know why.
# echo $USER
# su $USER -c "/bin/launchctl load ${KITE_PLIST}"

# see: https://lists.macosforge.org/pipermail/launchd-dev/2011-January/000890.html
echo "running postinstall actions for all logged in users."
for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do
    pid=$(echo $pid_uid | cut -d, -f1)
    uid=$(echo $pid_uid | cut -d, -f2)
    echo "loading launch agent"
    launchctl bsexec "$pid" chroot -u "$uid" / launchctl load ${KITE_PLIST}
done

exit 0
`

	distribution = `<?xml version="1.0" encoding="utf-8" standalone="no"?>
<installer-script minSpecVersion="1.000000">
    <title>Koding Kite</title>
    <background mime-type="image/png" file="bg.png"/>
    <options customize="never" allow-external-scripts="no"/>
    <!-- <domains enable_localSystem="true" /> -->
    <options rootVolumeOnly="true" />
    <installation-check script="installCheck();"/>
    <script>
function installCheck() {
    if(system.files.fileExistsAtPath('/usr/local/bin/{{.}}')) {
        my.result.title = 'Previous Installation Detected';
        my.result.message = 'A previous installation of Koding {{.}} Kite exists at /usr/local/bin. This installer will remove the previous installation prior to installing. Please back up any data before proceeding.';
        my.result.type = 'Warning';
        return false;
    }
    return true;
}
    </script>
    <!-- List all component packages -->
    <pkg-ref
        id="com.koding.kite.{{.}}.pkg"
        auth="root">com.koding.kite.{{.}}.pkg</pkg-ref>
    <choices-outline>
        <line choice="com.koding.kite.{{.}}.choice"/>
    </choices-outline>
    <choice
        id="com.koding.kite.{{.}}.choice"
        title="Koding Kite"
        customLocation="/">
        <pkg-ref id="com.koding.kite.{{.}}.pkg"/>
    </choice>
</installer-script>
`

	launchAgent = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>KeepAlive</key>
    <dict>
        <key>NetworkState</key>
        <true/>
    </dict>
    <key>Label</key>
    <string>com.koding.kite.{{.}}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/{{.}}</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
`
)
<|endoftext|>


<commit_before>/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strings"
	"sync"
	"text/template"
)

type label struct {
	Name string `json:"name"`
}

type prInfo struct {
	Labels []label `json:"labels"`
	Number int     `json:"number"`
	Title  string  `json:"title"`
}

const (
	markdownTemplate = `
{{- range $typeName, $components := . }}
## {{ $typeName }}
{{- range $componentName, $component := $components }}
### {{ $componentName}}
{{- range $prInfo := $component }}
 - {{ $prInfo.Title }} #{{ $prInfo.Number }}
{{- end }}
{{- end }}
{{- end }}
`

	prefixType      = "Type: "
	prefixComponent = "Component: "
)

func loadMergedPRs(from, to string) ([]string, error) {
	cmd := exec.Command("git", "log", "--oneline", fmt.Sprintf("%s...%s", from, to))
	out, err := cmd.Output()
	if err != nil {
		execErr := err.(*exec.ExitError)
		return nil, fmt.Errorf("%s:\nstderr: %s\nstdout: %s", err.Error(), execErr.Stderr, out)
	}

	var prs []string
	rgx := regexp.MustCompile(`Merge pull request #(\d+)`)
	lines := strings.Split(string(out), "\n")
	for _, line := range lines {
		lineInfo := rgx.FindStringSubmatch(line)
		if len(lineInfo) == 2 {
			prs = append(prs, lineInfo[1])
		}
	}

	sort.Strings(prs)
	return prs, nil
}

func loadPRinfo(pr string) (prInfo, error) {
	cmd := exec.Command("gh", "pr", "view", pr, "--json", "title,number,labels")
	out, err := cmd.Output()
	if err != nil {
		execErr := err.(*exec.ExitError)
		return prInfo{}, fmt.Errorf("%s:\nstderr: %s\nstdout: %s", err.Error(), execErr.Stderr, out)
	}
	var prInfo prInfo
	err = json.Unmarshal(out, &prInfo)
	return prInfo, err
}

func loadAllPRs(prs []string) ([]prInfo, error) {
	errChan := make(chan error)
	wgDone := make(chan bool)
	prChan := make(chan string, len(prs))
	// fill the work queue
	for _, s := range prs {
		prChan <- s
	}
	close(prChan)

	var prInfos []prInfo

	wg := sync.WaitGroup{}
	mu := sync.Mutex{}
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			// load meta data about PRs
			defer wg.Done()
			for b := range prChan {
				fmt.Print(".")
				prInfo, err := loadPRinfo(b)
				if err != nil {
					errChan <- err
					break
				}
				mu.Lock()
				prInfos = append(prInfos, prInfo)
				mu.Unlock()
			}
		}()
	}

	go func() {
		// wait for the loading to finish
		wg.Wait()
		close(wgDone)
	}()

	var err error
	select {
	case <-wgDone:
		break
	case err = <-errChan:
		break
	}

	fmt.Println()
	return prInfos, err
}

func groupPRs(prInfos []prInfo) map[string]map[string][]prInfo {
	prPerType := map[string]map[string][]prInfo{}

	for _, info := range prInfos {
		var typ, component string
		for _, lbl := range info.Labels {
			switch {
			case strings.HasPrefix(lbl.Name, prefixType):
				typ = strings.TrimPrefix(lbl.Name, prefixType)
			case strings.HasPrefix(lbl.Name, prefixComponent):
				component = strings.TrimPrefix(lbl.Name, prefixComponent)
			}
		}
		if typ == "" {
			typ = "Other"
		}
		if component == "" {
			component = "Other"
		}
		components, exists := prPerType[typ]
		if !exists {
			components = map[string][]prInfo{}
			prPerType[typ] = components
		}

		prsPerComponentAndType := components[component]
		components[component] = append(prsPerComponentAndType, info)
	}
	return prPerType
}

func writePrInfos(fileout string, prPerType map[string]map[string][]prInfo) (err error) {
	writeTo := os.Stdout
	if fileout != "" {
		writeTo, err = os.OpenFile(fileout, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
		if err != nil {
			return err
		}
	}

	t := template.Must(template.New("markdownTemplate").Parse(markdownTemplate))
	err = t.ExecuteTemplate(writeTo, "markdownTemplate", prPerType)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	from := flag.String("from", "", "from sha/tag/branch")
	to := flag.String("to", "HEAD", "to sha/tag/branch")
	fileout := flag.String("file", "", "file on which to write release notes, stdout if empty")

	flag.Parse()

	prs, err := loadMergedPRs(*from, *to)
	if err != nil {
		log.Fatal(err)
	}

	prInfos, err := loadAllPRs(prs)
	if err != nil {
		log.Fatal(err)
	}

	prPerType := groupPRs(prInfos)

	err = writePrInfos(*fileout, prPerType)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>best commit ever<commit_after>/*
Copyright 2021 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"regexp"
	"sort"
	"strings"
	"sync"
	"text/template"
)

type label struct {
	Name string `json:"name"`
}

type prInfo struct {
	Labels []label `json:"labels"`
	Number int     `json:"number"`
	Title  string  `json:"title"`
}

const (
	markdownTemplate = `
{{- range $typeName, $components := . }}
## {{ $typeName }}
{{- range $componentName, $component := $components }}
### {{ $componentName}}
{{- range $prInfo := $component }}
 - {{ $prInfo.Title }} #{{ $prInfo.Number }}
{{- end }}
{{- end }}
{{- end }}
`

	prefixType      = "Type: "
	prefixComponent = "Component: "
)

func loadMergedPRs(from, to string) ([]string, error) {
	cmd := exec.Command("git", "log", "--oneline", fmt.Sprintf("%s..%s", from, to))
	out, err := cmd.Output()
	if err != nil {
		execErr := err.(*exec.ExitError)
		return nil, fmt.Errorf("%s:\nstderr: %s\nstdout: %s", err.Error(), execErr.Stderr, out)
	}

	var prs []string
	rgx := regexp.MustCompile(`Merge pull request #(\d+)`)
	lines := strings.Split(string(out), "\n")
	for _, line := range lines {
		lineInfo := rgx.FindStringSubmatch(line)
		if len(lineInfo) == 2 {
			prs = append(prs, lineInfo[1])
		}
	}

	sort.Strings(prs)
	return prs, nil
}

func loadPRinfo(pr string) (prInfo, error) {
	cmd := exec.Command("gh", "pr", "view", pr, "--json", "title,number,labels")
	out, err := cmd.Output()
	if err != nil {
		execErr := err.(*exec.ExitError)
		return prInfo{}, fmt.Errorf("%s:\nstderr: %s\nstdout: %s", err.Error(), execErr.Stderr, out)
	}
	var prInfo prInfo
	err = json.Unmarshal(out, &prInfo)
	return prInfo, err
}

func loadAllPRs(prs []string) ([]prInfo, error) {
	errChan := make(chan error)
	wgDone := make(chan bool)
	prChan := make(chan string, len(prs))
	// fill the work queue
	for _, s := range prs {
		prChan <- s
	}
	close(prChan)

	var prInfos []prInfo

	wg := sync.WaitGroup{}
	mu := sync.Mutex{}
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			// load meta data about PRs
			defer wg.Done()
			for b := range prChan {
				fmt.Print(".")
				prInfo, err := loadPRinfo(b)
				if err != nil {
					errChan <- err
					break
				}
				mu.Lock()
				prInfos = append(prInfos, prInfo)
				mu.Unlock()
			}
		}()
	}

	go func() {
		// wait for the loading to finish
		wg.Wait()
		close(wgDone)
	}()

	var err error
	select {
	case <-wgDone:
		break
	case err = <-errChan:
		break
	}

	fmt.Println()
	return prInfos, err
}

func groupPRs(prInfos []prInfo) map[string]map[string][]prInfo {
	prPerType := map[string]map[string][]prInfo{}

	for _, info := range prInfos {
		var typ, component string
		for _, lbl := range info.Labels {
			switch {
			case strings.HasPrefix(lbl.Name, prefixType):
				typ = strings.TrimPrefix(lbl.Name, prefixType)
			case strings.HasPrefix(lbl.Name, prefixComponent):
				component = strings.TrimPrefix(lbl.Name, prefixComponent)
			}
		}
		if typ == "" {
			typ = "Other"
		}
		if component == "" {
			component = "Other"
		}
		components, exists := prPerType[typ]
		if !exists {
			components = map[string][]prInfo{}
			prPerType[typ] = components
		}

		prsPerComponentAndType := components[component]
		components[component] = append(prsPerComponentAndType, info)
	}
	return prPerType
}

func writePrInfos(fileout string, prPerType map[string]map[string][]prInfo) (err error) {
	writeTo := os.Stdout
	if fileout != "" {
		writeTo, err = os.OpenFile(fileout, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
		if err != nil {
			return err
		}
	}

	t := template.Must(template.New("markdownTemplate").Parse(markdownTemplate))
	err = t.ExecuteTemplate(writeTo, "markdownTemplate", prPerType)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	from := flag.String("from", "", "from sha/tag/branch")
	to := flag.String("to", "HEAD", "to sha/tag/branch")
	fileout := flag.String("file", "", "file on which to write release notes, stdout if empty")

	flag.Parse()

	prs, err := loadMergedPRs(*from, *to)
	if err != nil {
		log.Fatal(err)
	}

	prInfos, err := loadAllPRs(prs)
	if err != nil {
		log.Fatal(err)
	}

	prPerType := groupPRs(prInfos)

	err = writePrInfos(*fileout, prPerType)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package golang

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"sync"
	"text/template"

	"github.com/sourcegraph/go-vcsurl"
	"sourcegraph.com/sourcegraph/srcgraph/buildstore"
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/container"
	"sourcegraph.com/sourcegraph/srcgraph/dep2"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	// Register the Go toolchain.
	toolchain.Register("golang", defaultGoVersion)
}

// goVersion represents a Go release: where to download it, how to create graph
// references to it, etc.
type goVersion struct {
	// VersionString is the version string for this Go version, as listed at
	// https://code.google.com/p/go/downloads/list. (E.g., "go1.2.1" or
	// "go1.2rc5".)
	VersionString string

	RepositoryCloneURL string
	RepositoryURI      repo.URI
	RepositoryVCS      vcsurl.VCS
	VCSRevision        string
	BaseImportPath     string
	BasePkgDir         string

	resolveCache   map[string]*dep2.ResolvedTarget
	resolveCacheMu sync.Mutex
}

var goVersions = map[string]*goVersion{
	"1.2.1": &goVersion{
		VersionString:      "go1.2.1",
		RepositoryCloneURL: "https://code.google.com/p/go",
		RepositoryURI:      "code.google.com/p/go",
		RepositoryVCS:      vcsurl.Mercurial,
		VCSRevision:        "go1.2.1",
		BaseImportPath:     "code.google.com/p/go/src/pkg",
		BasePkgDir:         "src/pkg",
	},
}

var defaultGoVersion = goVersions["1.2.1"]

func (v *goVersion) baseDockerfile() ([]byte, error) {
	var buf bytes.Buffer
	err := template.Must(template.New("").Parse(baseDockerfile)).Execute(&buf, struct {
		GoVersion *goVersion
		GOPATH    string
	}{
		GoVersion: v,
		GOPATH:    containerGOPATH,
	})
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (v *goVersion) containerForRepo(dir string, unit unit.SourceUnit, c *config.Repository) (*container.Container, error) {
	dockerfile, err := v.baseDockerfile()
	if err != nil {
		return nil, err
	}

	goConfig := v.goConfig(c)
	mountDir := filepath.Join(containerGOPATH, "src", goConfig.BaseImportPath)
	containerDir := mountDir

	var preCmdDockerfile []byte
	var addDirs, addFiles [][2]string
	if c.URI == v.RepositoryURI {
		// Go stdlib. This is fairly hacky. We want stdlib package paths to not
		// be prefixed with "code.google.com/p/go" everywhere (just
		dockerfile = append(dockerfile, []byte(fmt.Sprintf(`
# Adjust for Go stdlib
ENV GOROOT /tmp/go
RUN apt-get update -qqy
RUN apt-get install -qqy build-essential
RUN apt-get install -qqy mercurial
	`))...)

		// Add all dirs needed for make.bash. Exclude dirs that change when
		// we build, so that we can take advantage of ADD caching and not
		// recompile the Go stdlib for each package.
		entries, err := ioutil.ReadDir(dir)
		if err != nil {
			return nil, err
		}
		for _, e := range entries {
			if n := e.Name(); n == "." || n == "test" || n == "api" || n == ".." || n == "pkg" || n == "bin" || n == buildstore.BuildDataDirName {
				continue
			}
			if !e.Mode().IsDir() {
				continue
			}
			addDirs = append(addDirs, [2]string{e.Name(), filepath.Join("/tmp/go", e.Name())})
		}

		// We need to actually build the version of Go we want to analyze.
		preCmdDockerfile = []byte(fmt.Sprintf(`
RUN cd /tmp/go/src && ./make.bash
`))

		containerDir = "/tmp/go"
	}

	return &container.Container{
		Dockerfile:       dockerfile,
		RunOptions:       []string{"-v", dir + ":" + mountDir},
		PreCmdDockerfile: preCmdDockerfile,
		Dir:              containerDir,
		AddDirs:          addDirs,
		AddFiles:         addFiles,
	}, nil
}

const containerGOPATH = "/tmp/sg/gopath"

const baseDockerfile = `FROM ubuntu:14.04
RUN apt-get update -qq
RUN apt-get install -qqy curl

# Install Go {{.GoVersion.VersionString}}.
RUN curl -o /tmp/golang.tgz https://go.googlecode.com/files/{{.GoVersion.VersionString}}.linux-amd64.tar.gz
RUN tar -xzf /tmp/golang.tgz -C /usr/local
ENV GOROOT /usr/local/go

# Add "go" to the PATH.
ENV PATH /usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

ENV GOPATH {{.GOPATH}}
`

type baseBuild struct {
	Stdlib *goVersion
	GOPATH string
}
<commit_msg>use go 1.3 in go grapher (closes #871)<commit_after>package golang

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"sync"
	"text/template"

	"github.com/sourcegraph/go-vcsurl"
	"sourcegraph.com/sourcegraph/srcgraph/buildstore"
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/container"
	"sourcegraph.com/sourcegraph/srcgraph/dep2"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	// Register the Go toolchain.
	toolchain.Register("golang", defaultGoVersion)
}

// goVersion represents a Go release: where to download it, how to create graph
// references to it, etc.
type goVersion struct {
	// VersionString is the version string for this Go version, as listed at
	// https://code.google.com/p/go/downloads/list. (E.g., "go1.2.1" or
	// "go1.2rc5".)
	VersionString string

	RepositoryCloneURL string
	RepositoryURI      repo.URI
	RepositoryVCS      vcsurl.VCS
	VCSRevision        string
	BaseImportPath     string
	BasePkgDir         string

	resolveCache   map[string]*dep2.ResolvedTarget
	resolveCacheMu sync.Mutex
}

var goVersions = map[string]*goVersion{
	"1.3": &goVersion{
		VersionString:      "go1.3",
		RepositoryCloneURL: "https://code.google.com/p/go",
		RepositoryURI:      "code.google.com/p/go",
		RepositoryVCS:      vcsurl.Mercurial,
		VCSRevision:        "go1.3",
		BaseImportPath:     "code.google.com/p/go/src/pkg",
		BasePkgDir:         "src/pkg",
	},
}

var defaultGoVersion = goVersions["1.3"]

func (v *goVersion) baseDockerfile() ([]byte, error) {
	var buf bytes.Buffer
	err := template.Must(template.New("").Parse(baseDockerfile)).Execute(&buf, struct {
		GoVersion *goVersion
		GOPATH    string
	}{
		GoVersion: v,
		GOPATH:    containerGOPATH,
	})
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

func (v *goVersion) containerForRepo(dir string, unit unit.SourceUnit, c *config.Repository) (*container.Container, error) {
	dockerfile, err := v.baseDockerfile()
	if err != nil {
		return nil, err
	}

	goConfig := v.goConfig(c)
	mountDir := filepath.Join(containerGOPATH, "src", goConfig.BaseImportPath)
	containerDir := mountDir

	var preCmdDockerfile []byte
	var addDirs, addFiles [][2]string
	if c.URI == v.RepositoryURI {
		// Go stdlib. This is fairly hacky. We want stdlib package paths to not
		// be prefixed with "code.google.com/p/go" everywhere (just
		dockerfile = append(dockerfile, []byte(fmt.Sprintf(`
# Adjust for Go stdlib
ENV GOROOT /tmp/go
RUN apt-get update -qqy
RUN apt-get install -qqy build-essential
RUN apt-get install -qqy mercurial
	`))...)

		// Add all dirs needed for make.bash. Exclude dirs that change when
		// we build, so that we can take advantage of ADD caching and not
		// recompile the Go stdlib for each package.
		entries, err := ioutil.ReadDir(dir)
		if err != nil {
			return nil, err
		}
		for _, e := range entries {
			if n := e.Name(); n == "." || n == "test" || n == "api" || n == ".." || n == "pkg" || n == "bin" || n == buildstore.BuildDataDirName {
				continue
			}
			if !e.Mode().IsDir() {
				continue
			}
			addDirs = append(addDirs, [2]string{e.Name(), filepath.Join("/tmp/go", e.Name())})
		}

		// We need to actually build the version of Go we want to analyze.
		preCmdDockerfile = []byte(fmt.Sprintf(`
RUN cd /tmp/go/src && ./make.bash
`))

		containerDir = "/tmp/go"
	}

	return &container.Container{
		Dockerfile:       dockerfile,
		RunOptions:       []string{"-v", dir + ":" + mountDir},
		PreCmdDockerfile: preCmdDockerfile,
		Dir:              containerDir,
		AddDirs:          addDirs,
		AddFiles:         addFiles,
	}, nil
}

const containerGOPATH = "/tmp/sg/gopath"

const baseDockerfile = `FROM ubuntu:14.04
RUN apt-get update -qq
RUN apt-get install -qqy curl

# Install Go {{.GoVersion.VersionString}}.
RUN curl -Lo /tmp/golang.tgz http://golang.org/dl/{{.GoVersion.VersionString}}.linux-amd64.tar.gz
RUN tar -xzf /tmp/golang.tgz -C /usr/local
ENV GOROOT /usr/local/go

# Add "go" to the PATH.
ENV PATH /usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

ENV GOPATH {{.GOPATH}}
`

type baseBuild struct {
	Stdlib *goVersion
	GOPATH string
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package local

import (
	"github.com/globocom/config"
	"github.com/globocom/tsuru/fs"
	"github.com/globocom/tsuru/log"
	"io/ioutil"
	"os/exec"
	"strings"
	"time"
)

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		fsystem = fs.OsFs{}
	}
	return fsystem
}

// container represents an lxc container with the given name.
type container struct {
	name string
}

// runCmd executes commands and log the given stdout and stderror.
func runCmd(cmd string, args ...string) error {
	command := exec.Command(cmd, args...)
	out, err := command.CombinedOutput()
	log.Printf("running the cmd: %s with the args: %s", cmd, args)
	log.Print(string(out))
	return err
}

// ip returns the ip for the container.
func (c *container) ip() string {
	timeout, err := config.GetInt("local:ip-timeout")
	if err != nil {
		timeout = 60
	}
	quit := time.After(time.Duration(timeout) * time.Second)
	tick := time.Tick(2 * time.Second)
	for {
		select {
		case <-tick:
			file, _ := filesystem().Open("/var/lib/misc/dnsmasq.leases")
			data, _ := ioutil.ReadAll(file)
			log.Print("dnsmasq.leases")
			log.Print(string(data))
			for _, line := range strings.Split(string(data), "\n") {
				if strings.Index(line, c.name) != -1 {
					log.Printf("ip in %s", line)
					return strings.Split(line, " ")[2]
				}
			}
		case <-quit:
			return ""
		default:
			time.Sleep(1 * time.Second)
		}
	}
}

// create creates a lxc container with ubuntu template by default.
func (c *container) create() error {
	keyPath, err := config.GetString("local:authorized-key-path")
	if err != nil {
		return err
	}
	return runCmd("sudo", "lxc-create", "-t", "ubuntu", "-n", c.name, "--", "-S", keyPath)
}

// start starts a lxc container.
func (c *container) start() error {
	return runCmd("sudo", "lxc-start", "--daemon", "-n", c.name)
}

// stop stops a lxc container.
func (c *container) stop() error {
	return runCmd("sudo", "lxc-stop", "-n", c.name)
}

// destroy destory a lxc container.
func (c *container) destroy() error {
	return runCmd("sudo", "lxc-destroy", "-n", c.name)
}
<commit_msg>provision/local: fix code<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package local

import (
	"github.com/globocom/config"
	"github.com/globocom/tsuru/fs"
	"github.com/globocom/tsuru/log"
	"io/ioutil"
	"os/exec"
	"strings"
	"time"
)

var fsystem fs.Fs

func filesystem() fs.Fs {
	if fsystem == nil {
		fsystem = fs.OsFs{}
	}
	return fsystem
}

// container represents an lxc container with the given name.
type container struct {
	name string
}

// runCmd executes commands and log the given stdout and stderror.
func runCmd(cmd string, args ...string) error {
	command := exec.Command(cmd, args...)
	out, err := command.CombinedOutput()
	log.Printf("running the cmd: %s with the args: %s", cmd, args)
	log.Print(string(out))
	return err
}

// ip returns the ip for the container.
func (c *container) ip() string {
	timeout, err := config.GetInt("local:ip-timeout")
	if err != nil {
		timeout = 60
	}
	quit := time.After(time.Duration(timeout) * time.Second)
	tick := time.Tick(2 * time.Second)
	for {
		select {
		case <-tick:
			file, _ := filesystem().Open("/var/lib/misc/dnsmasq.leases")
			data, _ := ioutil.ReadAll(file)
			log.Print("dnsmasq.leases")
			log.Print(string(data))
			for _, line := range strings.Split(string(data), "\n") {
				if strings.Index(line, c.name) != -1 {
					log.Printf("ip in %s", line)
					return strings.Split(line, " ")[2]
				}
			}
		case <-quit:
			return ""
		default:
			time.Sleep(1 * time.Second)
		}
	}
	return ""
}

// create creates a lxc container with ubuntu template by default.
func (c *container) create() error {
	keyPath, err := config.GetString("local:authorized-key-path")
	if err != nil {
		return err
	}
	return runCmd("sudo", "lxc-create", "-t", "ubuntu", "-n", c.name, "--", "-S", keyPath)
}

// start starts a lxc container.
func (c *container) start() error {
	return runCmd("sudo", "lxc-start", "--daemon", "-n", c.name)
}

// stop stops a lxc container.
func (c *container) stop() error {
	return runCmd("sudo", "lxc-stop", "-n", c.name)
}

// destroy destory a lxc container.
func (c *container) destroy() error {
	return runCmd("sudo", "lxc-destroy", "-n", c.name)
}
<|endoftext|>


<commit_before>package cellnet

import (
	"runtime/debug"
)

type EventQueue interface {
	StartLoop()

	StopLoop(result int)

	// 等待退出
	Wait() int

	// 投递事件, 通过队列到达消费者端
	Post(callback func())

	// 是否捕获异常
	EnableCapturePanic(v bool)
}

type eventQueue struct {
	queue chan func()

	exitSignal chan int

	capturePanic bool
}

// 启动崩溃捕获
func (q *eventQueue) EnableCapturePanic(v bool) {
	q.capturePanic = v
}

// 派发事件处理回调到队列中
func (q *eventQueue) Post(callback func()) {

	if callback == nil {
		return
	}

	q.queue <- callback
}

// 保护调用用户函数
func (q *eventQueue) protectedCall(callback func()) {

	if callback == nil {
		return
	}

	if q.capturePanic {
		defer func() {

			if err := recover(); err != nil {

				debug.PrintStack()
			}

		}()
	}

	callback()
}

// 开启事件循环
func (q *eventQueue) StartLoop() {

	go func() {
		for callback := range q.queue {
			q.protectedCall(callback)
		}
	}()
}

// 停止事件循环
func (q *eventQueue) StopLoop(result int) {
	q.exitSignal <- result
}

// 等待退出消息
func (q *eventQueue) Wait() int {
	return <-q.exitSignal
}

const DefaultQueueSize = 100

// 创建默认长度的队列
func NewEventQueue() EventQueue {

	return NewEventQueueByLen(DefaultQueueSize)
}

// 创建指定长度的队列
func NewEventQueueByLen(l int) EventQueue {
	self := &eventQueue{
		queue:      make(chan func(), l),
		exitSignal: make(chan int),
	}

	return self
}

func QueuedCall(ses Session, callback func()) {
	if ses == nil {
		return
	}

	q := ses.Peer().EventQueue()

	// Peer有队列时，在队列线程调用用户处理函数
	if q != nil {
		q.Post(callback)

	} else {

		// 在I/O线程调用用户处理函数
		callback()
	}
}
<commit_msg>修改: 队列会在处理完所有数据后再退出<commit_after>package cellnet

import (
	"runtime/debug"
	"sync"
)

type EventQueue interface {
	StartLoop()

	StopLoop()

	// 等待退出
	Wait()

	// 投递事件, 通过队列到达消费者端
	Post(callback func())

	// 是否捕获异常
	EnableCapturePanic(v bool)
}

type eventQueue struct {
	queue chan func()

	endSignal sync.WaitGroup

	capturePanic bool
}

// 启动崩溃捕获
func (self *eventQueue) EnableCapturePanic(v bool) {
	self.capturePanic = v
}

// 派发事件处理回调到队列中
func (self *eventQueue) Post(callback func()) {

	if callback == nil {
		return
	}

	self.queue <- callback
}

// 保护调用用户函数
func (self *eventQueue) protectedCall(callback func()) {

	if self.capturePanic {
		defer func() {

			if err := recover(); err != nil {

				debug.PrintStack()
			}

		}()
	}

	callback()
}

// 开启事件循环
func (self *eventQueue) StartLoop() {

	go func() {

		for callback := range self.queue {

			if callback == nil {
				break
			}

			self.protectedCall(callback)
		}

		self.endSignal.Done()
	}()
}

// 停止事件循环
func (self *eventQueue) StopLoop() {
	self.queue <- nil
}

// 等待退出消息
func (self *eventQueue) Wait() {
	self.endSignal.Wait()
}

const DefaultQueueSize = 100

// 创建默认长度的队列
func NewEventQueue() EventQueue {

	return &eventQueue{
		queue: make(chan func(), DefaultQueueSize),
	}
}

func QueuedCall(ses Session, callback func()) {
	if ses == nil {
		return
	}

	q := ses.Peer().EventQueue()

	// Peer有队列时，在队列线程调用用户处理函数
	if q != nil {
		q.Post(callback)

	} else {

		// 在I/O线程调用用户处理函数
		callback()
	}
}
<|endoftext|>


<commit_before>//
// Copyright 2017 Pedro Salgado
//
// 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 resque

import (
	"encoding/json"
	"fmt"

	"gopkg.in/redis.v5"
)

// Queue a job queue.
type Queue struct {
	redis        *redis.Client
	jobClassName string
	Name         string
}

// newQueue links a job queue to a redis instance.
func newQueue(jcn string, c *redis.Client) *Queue {
	return &Queue{
		redis:        c,
		jobClassName: jcn,
		Name:         fmt.Sprintf("resque:queue:%s", jcn),
	}
}

// Receive gets a job from the queue.
func (q Queue) Receive() (*Job, error) {
	cmd := q.redis.LPop(q.Name)
	jsonStr, err := cmd.Bytes()
	if err != nil {
		return nil, err
	}

	job := &Job{}
	err = json.Unmarshal(jsonStr, job)
	if err != nil {
		return nil, err
	}

	return job, err
}

// Send places a job on the queue.
func (q Queue) Send(args []JobArgument) error {
	jsonStr, err := json.Marshal(Job{Class: q.jobClassName, Args: args})
	if err != nil {
		return err
	}

	return q.redis.RPush(q.Name, jsonStr).Err()
}
<commit_msg>queue.go: Receive() returned error when list was empty.<commit_after>//
// Copyright 2017 Pedro Salgado
//
// 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 resque

import (
	"encoding/json"
	"fmt"

	"gopkg.in/redis.v5"
)

// Queue a job queue.
type Queue struct {
	redis        *redis.Client
	jobClassName string
	Name         string
}

// newQueue links a job queue to a redis instance.
func newQueue(jcn string, c *redis.Client) *Queue {
	return &Queue{
		redis:        c,
		jobClassName: jcn,
		Name:         fmt.Sprintf("resque:queue:%s", jcn),
	}
}

// Receive gets a job from the queue.
func (q Queue) Receive() (*Job, error) {
	cmd := q.redis.LPop(q.Name)
	if cmd.Err() != nil {
		if cmd.Err().Error() == "redis: nil" {
			return nil, nil
		}
		return nil, cmd.Err()
	}

	jsonStr, err := cmd.Bytes()
	if err != nil {
		return nil, err
	}

	job := &Job{}
	err = json.Unmarshal(jsonStr, job)
	if err != nil {
		return nil, err
	}

	return job, err
}

// Send places a job on the queue.
func (q Queue) Send(args []JobArgument) error {
	jsonStr, err := json.Marshal(Job{Class: q.jobClassName, Args: args})
	if err != nil {
		return err
	}

	return q.redis.RPush(q.Name, jsonStr).Err()
}
<|endoftext|>


<commit_before>package pq

import (
	"container/heap"
	"fmt"
	"runtime"
	"sync"
	"sync/atomic"
)

var ErrQueueNotStarted = fmt.Errorf("Queue not started or closed")
var ErrQueueAlreadyStarted = fmt.Errorf("Queue already started")

type Queue struct {
	numWorkers  int
	pq          priorityQueue
	work        chan *item
	cond        *sync.Cond
	wg          sync.WaitGroup
	working     bool
	taskRunning int32
}

// Starts work. You can add tasks only after starting queue
func (q *Queue) Start(numWorkers int) (err error) {
	if q.cond == nil {
		q.cond = sync.NewCond(&sync.Mutex{})
	}
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	if q.working {
		return ErrQueueAlreadyStarted
	}
	q.numWorkers = numWorkers
	q.pq = make(priorityQueue, 0)
	q.work = make(chan *item)
	if q.numWorkers <= 0 {
		q.numWorkers = runtime.NumCPU()
	}
	q.runWorkers()
	go q.dispatcher()
	return
}

// Add func() to queue
func (q *Queue) AddFunc(f func() error, priority int) (err error) {
	task := &funcTask{
		f: f,
		p: priority,
	}
	return q.AddTask(task)
}

// Add func() to queue and wait while tasks will be done
func (q *Queue) WaitFunc(f func() error, priority int) (err error) {
	task := &funcTask{
		f: f,
		p: priority,
	}
	return q.WaitTask(task)
}

// Just add group of tasks
func (q *Queue) AddGroup(tasks []Task) (err error) {
	for _, t := range tasks {
		if err = q.AddTask(t); err != nil {
			return
		}
	}
	return
}

// Add group of tasks and waits while all tasks will be done
func (q *Queue) WaitGroup(tasks []Task) (err error) {
	if len(tasks) == 0 {
		return
	}

	ctrl := &itemCtrl{count: int32(len(tasks)), m: new(sync.Mutex), done: make(chan error)}

	for _, t := range tasks {
		it := &item{task: t, ctrl: ctrl}
		if err = q.addItem(it); err != nil {
			return
		}
	}

	err = <-ctrl.done
	return
}

// Add single task to queue
func (q *Queue) AddTask(task Task) (err error) {
	it := &item{task: task}
	return q.addItem(it)
}

// Add single task to queue and waits while task will be done
func (q *Queue) WaitTask(task Task) (err error) {
	return q.WaitGroup([]Task{task})
}

// Size of queue
func (q *Queue) Len() int {
	return len(q.pq)
}

// How much workers do work at this moment
func (q *Queue) TaskRunning() int {
	return int(atomic.LoadInt32(&q.taskRunning))
}

func (q *Queue) addItem(it *item) (err error) {
	q.cond.L.Lock()
	if !q.working {
		return ErrQueueNotStarted
	}
	heap.Push(&q.pq, it)
	q.cond.L.Unlock()
	q.cond.Signal()
	return
}

func (q *Queue) runWorkers() {
	for i := 0; i < q.numWorkers; i++ {
		go q.worker()
	}
	q.working = true
}

func (q *Queue) dispatcher() {
	for {
		q.cond.L.Lock()
		for q.pq.Len() == 0 {
			q.cond.Wait()
		}
		if !q.working {
			break
		}
		it := heap.Pop(&q.pq)
		q.work <- it.(*item)
		q.cond.L.Unlock()
	}
}

func (q *Queue) worker() {
	q.wg.Add(1)
	for it := range q.work {
		q.runTask(it)
	}
	q.wg.Done()
}

func (q *Queue) runTask(it *item) {
	var err error
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("PQ. Panic while executing task: %v", r)
		}
		it.done(err)
	}()

	atomic.AddInt32(&q.taskRunning, 1)
	defer atomic.AddInt32(&q.taskRunning, -1)
	if it.can() {
		err = it.task.Run()
	}
	return
}

// Stopping queue. Wait while all workers finish current tasks
func (q *Queue) Stop() {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	close(q.work)
	q.working = false
	q.wg.Wait()
}
<commit_msg>fixes<commit_after>package pq

import (
	"container/heap"
	"fmt"
	"runtime"
	"sync"
	"sync/atomic"
)

var ErrQueueNotStarted = fmt.Errorf("Queue not started or closed")
var ErrQueueAlreadyStarted = fmt.Errorf("Queue already started")

type Queue struct {
	numWorkers  int
	pq          priorityQueue
	work        chan *item
	cond        *sync.Cond
	wg          sync.WaitGroup
	working     bool
	taskRunning int32
}

// Starts work. You can add tasks only after starting queue
func (q *Queue) Start(numWorkers int) (err error) {
	if q.cond == nil {
		q.cond = sync.NewCond(&sync.Mutex{})
	}
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	if q.working {
		return ErrQueueAlreadyStarted
	}
	q.numWorkers = numWorkers
	q.pq = make(priorityQueue, 0)
	q.work = make(chan *item)
	if q.numWorkers <= 0 {
		q.numWorkers = runtime.NumCPU()
	}
	q.runWorkers()
	go q.dispatcher()
	return
}

// Add func() to queue
func (q *Queue) AddFunc(f func() error, priority int) (err error) {
	task := &funcTask{
		f: f,
		p: priority,
	}
	return q.AddTask(task)
}

// Add func() to queue and wait while tasks will be done
func (q *Queue) WaitFunc(f func() error, priority int) (err error) {
	task := &funcTask{
		f: f,
		p: priority,
	}
	return q.WaitTask(task)
}

// Just add group of tasks
func (q *Queue) AddGroup(tasks []Task) (err error) {
	for _, t := range tasks {
		if err = q.AddTask(t); err != nil {
			return
		}
	}
	return
}

// Add group of tasks and waits while all tasks will be done
func (q *Queue) WaitGroup(tasks []Task) (err error) {
	if len(tasks) == 0 {
		return
	}

	ctrl := &itemCtrl{count: int32(len(tasks)), m: new(sync.Mutex), done: make(chan error)}

	for _, t := range tasks {
		it := &item{task: t, ctrl: ctrl}
		if err = q.addItem(it); err != nil {
			return
		}
	}

	err = <-ctrl.done
	return
}

// Add single task to queue
func (q *Queue) AddTask(task Task) (err error) {
	it := &item{task: task}
	return q.addItem(it)
}

// Add single task to queue and waits while task will be done
func (q *Queue) WaitTask(task Task) (err error) {
	return q.WaitGroup([]Task{task})
}

// Size of queue
func (q *Queue) Len() int {
	return len(q.pq)
}

// How much workers do work at this moment
func (q *Queue) TaskRunning() int {
	return int(atomic.LoadInt32(&q.taskRunning))
}

func (q *Queue) addItem(it *item) (err error) {
	q.cond.L.Lock()
	if !q.working {
		return ErrQueueNotStarted
		q.cond.L.Unlock()
	}
	heap.Push(&q.pq, it)
	q.cond.L.Unlock()
	q.cond.Signal()
	return
}

func (q *Queue) runWorkers() {
	for i := 0; i < q.numWorkers; i++ {
		go q.worker()
	}
	q.working = true
}

func (q *Queue) dispatcher() {
	for {
		q.cond.L.Lock()
		for q.pq.Len() == 0 {
			q.cond.Wait()
		}
		if !q.working {
			q.cond.L.Unlock()
			break
		}
		it := heap.Pop(&q.pq)
		q.work <- it.(*item)
		q.cond.L.Unlock()
	}
}

func (q *Queue) worker() {
	q.wg.Add(1)
	for it := range q.work {
		q.runTask(it)
	}
	q.wg.Done()
}

func (q *Queue) runTask(it *item) {
	var err error
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("PQ. Panic while executing task: %v", r)
		}
		it.done(err)
	}()

	atomic.AddInt32(&q.taskRunning, 1)
	defer atomic.AddInt32(&q.taskRunning, -1)
	if it.can() {
		err = it.task.Run()
	}
	return
}

// Stopping queue. Wait while all workers finish current tasks
func (q *Queue) Stop() {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	close(q.work)
	q.working = false
	q.wg.Wait()
}
<|endoftext|>


<commit_before>package term

import (
	"io"
	"os"

	"github.com/docker/docker/pkg/term"
)

type TTY struct {
	In  io.Reader
	Out io.Writer
}

func (t *TTY) Run(remoteIn io.Reader, remoteOut io.WriteCloser, resize func(h, w uint16) error) error {
	inFd, inIsTerm := term.GetFdInfo(t.In)
	outFd, outIsTerm := term.GetFdInfo(t.Out)

	if inIsTerm {
		size := winsize(outFd)
		if err := resize(size.Height, size.Width); err != nil {
			return err
		}

		var state *term.State
		state, err := term.SetRawTerminal(inFd)
		if err == nil {
			defer term.RestoreTerminal(inFd, state)
		}
	}

	go func() {
		defer remoteOut.Close()
		io.Copy(remoteOut, t.In)
	}()

	if outIsTerm {
		r, done := resized()
		defer done()
		go t.resize(r, resize, outFd)
	}

	io.Copy(t.Out, remoteIn)
	return nil
}

func (t *TTY) resize(resized <-chan os.Signal, resize func(h, w uint16) error, fd uintptr) {
	var h, w uint16
	for range resized {
		size := winsize(fd)
		if size.Height == h && size.Width == w {
			continue
		}

		resize(size.Height, size.Width)
		h, w = size.Height, size.Width
	}
}

func winsize(fd uintptr) *term.Winsize {
	size, err := term.GetWinsize(fd)
	if err != nil {
		size = &term.Winsize{
			Height: 43,
			Width:  80,
		}
	}
	return size
}
<commit_msg>Address edge cases for run -t option<commit_after>package term

import (
	"errors"
	"io"
	"os"
	"time"

	"github.com/docker/docker/pkg/term"
)

type TTY struct {
	In  io.Reader
	Out io.Writer
}

func (t *TTY) Run(remoteIn io.Reader, remoteOut io.WriteCloser, resize func(h, w uint16) error) error {
	inFd, inIsTerm := term.GetFdInfo(t.In)
	outFd, outIsTerm := term.GetFdInfo(t.Out)

	if !inIsTerm {
		return errors.New("stdin must be an interactive terminal")
	}

	size := winsize(outFd)
	if err := resize(size.Height, size.Width); err != nil {
		time.Sleep(time.Second)
		size = winsize(outFd)
		if err := resize(size.Height, size.Width); err != nil {
			return err
		}
	}
	if state, err := term.SetRawTerminal(inFd); err == nil {
		defer term.RestoreTerminal(inFd, state)
	}

	go func() {
		defer remoteOut.Close()
		io.Copy(remoteOut, t.In)
	}()

	if outIsTerm {
		r, done := resized()
		defer done()
		go t.resize(r, resize, outFd)
	}

	io.Copy(t.Out, remoteIn)
	return nil
}

func (t *TTY) resize(resized <-chan os.Signal, resize func(h, w uint16) error, fd uintptr) {
	var h, w uint16
	for range resized {
		size := winsize(fd)
		if size.Height == h && size.Width == w {
			continue
		}

		resize(size.Height, size.Width)
		h, w = size.Height, size.Width
	}
}

func winsize(fd uintptr) *term.Winsize {
	size, err := term.GetWinsize(fd)
	if err != nil {
		size = &term.Winsize{
			Height: 43,
			Width:  80,
		}
	}
	return size
}
<|endoftext|>


<commit_before>package pgbroadcast

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/lib/pq"
)

type pgnotification struct {
	Table  string                 `json:"table"`
	Action string                 `json:"action"`
	Data   map[string]interface{} `json:"data"`
}

func Run(pgconninfo string, pglistenchannel string) error {
	go h.run()
	err := startPgListener(pgconninfo, pglistenchannel, h.broadcast)
	return err
}

func startPgListener(pgconninfo string, pglistenchannel string, broadcastingchannel chan pgnotification) error {
	// callback func
	pgEventCallback := func(ev pq.ListenerEventType, err error) {
		if err != nil {
			fmt.Println("pgbroadcast: ", err.Error())
		}
	}

	// create listener and start listening
	l := pq.NewListener(pgconninfo, 10*time.Second, time.Minute, pgEventCallback)

	err := l.Listen(pglistenchannel)
	if err != nil {
		return err
	}
	// Wait for notifications in goroutine, pass them to the broadcastingchannel.
	go waitForNotification(l)
	fmt.Println("pgbroadcast: listening for notifications")
	return nil
}

func waitForNotification(l *pq.Listener) {
	for {
		select {
		case n := <-l.Notify:
			//
			if n == nil {
				continue
			}
			// Unmarshal JSON in pgnotification struct
			var pgn pgnotification
			err := json.Unmarshal([]byte(n.Extra), &pgn)
			if err != nil {
				fmt.Println("pgbroadcast: error processing JSON: ", err)
			} else {
				h.broadcast <- pgn
			}
		case <-time.After(60 * time.Second):
			// received no events for 60 seconds, ping connection")
			go func() {
				l.Ping()
			}()
		}
	}
}
<commit_msg>small comment fix<commit_after>package pgbroadcast

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/lib/pq"
)

type pgnotification struct {
	Table  string                 `json:"table"`
	Action string                 `json:"action"`
	Data   map[string]interface{} `json:"data"`
}

func Run(pgconninfo string, pglistenchannel string) error {
	go h.run()
	err := startPgListener(pgconninfo, pglistenchannel, h.broadcast)
	return err
}

func startPgListener(pgconninfo string, pglistenchannel string, broadcastingchannel chan pgnotification) error {
	// callback func
	pgEventCallback := func(ev pq.ListenerEventType, err error) {
		if err != nil {
			fmt.Println("pgbroadcast: ", err.Error())
		}
	}

	// create listener and start listening
	l := pq.NewListener(pgconninfo, 10*time.Second, time.Minute, pgEventCallback)

	err := l.Listen(pglistenchannel)
	if err != nil {
		return err
	}
	// Wait for notifications in goroutine, pass them to the broadcastingchannel.
	go waitForNotification(l)
	fmt.Println("pgbroadcast: listening for notifications")
	return nil
}

func waitForNotification(l *pq.Listener) {
	for {
		select {
		case n := <-l.Notify:
			// For some reason after connection loss with the postgres database,
			// the first notifications is a nil notification. Ignore it.
			if n == nil {
				continue
			}
			// Unmarshal JSON in pgnotification struct
			var pgn pgnotification
			err := json.Unmarshal([]byte(n.Extra), &pgn)
			if err != nil {
				fmt.Println("pgbroadcast: error processing JSON: ", err)
			} else {
				h.broadcast <- pgn
			}
		case <-time.After(60 * time.Second):
			// received no events for 60 seconds, ping connection")
			go func() {
				l.Ping()
			}()
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const PresentationJs = `
$(function() {
	var presentationSelector = 'body > article.presentation > .content';

	if ($(presentationSelector).length == 0) {
		// this document is not a presentation
		return;
	}

	/**
	 * Toggle the page header elements
	 */
	var togglePresentationMode = function() {
		$("body>nav.toplevel").toggle();
		$("body>nav.breadcrumb").toggle();
		$(".presentation>header").toggle();
		$(".presentation>.description").toggle();
	};

	// render the presentation
	$.deck('.slide', {
		selectors: {
			container: presentationSelector
		},

		keys: {
			goto: 71 // 'g'
		}
	});

	// handle keyboard shortcuts
	$(document).keydown(function(e) {

		/* <ctrl> + <shift> */
		if (e.ctrlKey && (e.which === 16) ) {
			console.log( "You pressed Ctrl + Shift" );
			togglePresentationMode();
		}

	});

});`<commit_msg>Default Theme Presentations Bug Fix: Toggle the footer when in presentation mode<commit_after>// Copyright 2013 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package themefiles

const PresentationJs = `
$(function() {
	var presentationSelector = 'body > article.presentation > .content';

	if ($(presentationSelector).length == 0) {
		// this document is not a presentation
		return;
	}

	/**
	 * Toggle the page header elements
	 */
	var togglePresentationMode = function() {
		$("body>nav.toplevel").toggle();
		$("body>nav.breadcrumb").toggle();
		$(".presentation>header").toggle();
		$(".presentation>.description").toggle();
		$("body>footer").toggle();
	};

	// render the presentation
	$.deck('.slide', {
		selectors: {
			container: presentationSelector
		},

		keys: {
			goto: 71 // 'g'
		}
	});

	// handle keyboard shortcuts
	$(document).keydown(function(e) {

		/* <ctrl> + <shift> */
		if (e.ctrlKey && (e.which === 16) ) {
			console.log( "You pressed Ctrl + Shift" );
			togglePresentationMode();
		}

	});

});`
<|endoftext|>