<commit_before>// Copyright 2012 The GoForms 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 goforms/forms enables form data validation, cleaning and error collection, similar to Django forms. From forms_test.go:

	formFields := FormFields{
		"name": fields.NewCharField(fields.Defaults{
			"Required": true,
		}),
		"age": fields.NewIntegerField(fields.Defaults{
			"Required": false,
		}),
		"about": fields.NewCharField(fields.Defaults{
			"Max": 10,
		}),
	}
	personForm := Form{Fields: formFields}

	personForm.Data = urls.Values{
		"name": {"Michael Nelson"},
		"age":  {"37"},
	}

	if personForm.IsValid() {
		doStuffWithCleanedData()
		// personForm.CleanedData contains cleaned data
		// (ie. an int for age in this case):
		// {"name": "Michael Nelson", "age": 37}
		// so that for required fields you can safely do:
		// var age int = personForm.CleanedData["age"].(int)
	} else {
		doStuffWithErrors()
		// If personForm.Data = urls.Values{"age": {"Not a number"}},
		// then personForm.Errors would be {
		//	 "name": "This field is required.",
		//	 "age":  "The value ust be a valid integer."
		// }
	}

You can see more examples in goforms/forms/forms_test.go.

For another form-data processing library, see github.com/gorilla/schema, which fills structs with form data using struct tags.

*/
package forms

import (
	"github.com/absoludity/goforms/fields"
	"net/url"
)

// A collection of fields used on a Form.
type FormFields map[string]fields.Field

// A form brings together a collection of fields, the form data
// to be validated against those fields, as well as the
// generated cleaned data or the collection of errors.
type Form struct {
	Fields      FormFields
	Data        url.Values
	CleanedData map[string]interface{}
	Errors      map[string]string
}

// Contains the cleaned data after a call to IsValid().
type CleanedData map[string]interface{}

// Returns whether the given data validates against the form's
// fields. If successful, CleanedData will be populated,
// otherwise Errors will be populated.
func (f *Form) IsValid() bool {
	isValid := true
	cleanedData := CleanedData{}
	errors := map[string]string{}

	for fieldName, field := range f.Fields {
		dataValues, fieldHasData := f.Data[fieldName]
		dataValue := ""
		switch fieldHasData {
		case true:
			if len(dataValues) == 0 {
				continue
			} else {
				dataValue = dataValues[0]
			}
		case false:
			if field.IsRequired() {
				errors[fieldName] = "This field is required."
				isValid = false
			}
			continue
		}
		cleanedValue, err := field.Clean(dataValue)
		if err == nil {
			cleanedData[fieldName] = cleanedValue
		} else {
			errors[fieldName] = err.Error()
			isValid = false
		}
	}

	if isValid {
		f.CleanedData = cleanedData
	} else {
		f.Errors = errors
	}
	return isValid
}
<commit_msg>Update forms.go<commit_after>// Copyright 2012 The GoForms 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 goforms/forms enables form data validation, cleaning and error collection, similar to Django forms. From forms_test.go:

	formFields := FormFields{
		"name": fields.NewCharField(fields.Defaults{
			"Required": true,
		}),
		"age": fields.NewIntegerField(fields.Defaults{
			"Required": false,
		}),
		"about": fields.NewCharField(fields.Defaults{
			"Max": 10,
		}),
	}
	personForm := Form{Fields: formFields}

	personForm.Data = urls.Values{
		"name": {"Michael Nelson"},
		"age":  {"37"},
	}

	if personForm.IsValid() {
		doStuffWithCleanedData()
		// personForm.CleanedData contains cleaned data
		// (ie. an int for age in this case):
		// {"name": "Michael Nelson", "age": 37}
		// so that for required fields you can safely do:
		// var age int = personForm.CleanedData["age"].(int)
	} else {
		doStuffWithErrors()
		// If personForm.Data = urls.Values{"age": {"Not a number"}},
		// then personForm.Errors would be {
		//	 "name": "This field is required.",
		//	 "age":  "The value ust be a valid integer."
		// }
	}

You can see more examples in goforms/forms/forms_test.go.

For another form-data processing library, see github.com/gorilla/schema, which fills structs with form data using struct tags.

*/
package forms

import (
	"github.com/absoludity/goforms/fields"
	"net/url"
)

// A collection of fields used on a Form.
type FormFields map[string]fields.Field

// A form brings together a collection of fields, the form data
// to be validated against those fields, as well as the
// generated cleaned data or the collection of errors.
type Form struct {
	Fields      FormFields
	Data        url.Values
	CleanedData map[string]interface{}
	Errors      map[string]string
}

// Contains the cleaned data after a call to IsValid().
type CleanedData map[string]interface{}

// Returns whether the given data validates against the form's
// fields. If successful, CleanedData will be populated,
// otherwise Errors will be populated.
func (f *Form) IsValid() bool {
	isValid := true
	cleanedData := CleanedData{}
	errors := map[string]string{}

	for fieldName, field := range f.Fields {
		dataValues, fieldHasData := f.Data[fieldName]
		dataValue := ""
		switch fieldHasData {
		case true:
			if len(dataValues) == 0 {
				fallthrough
			} else {
				dataValue = dataValues[0]
			}
		case false:
			if field.IsRequired() {
				errors[fieldName] = "This field is required."
				isValid = false
			}
			continue
		}
		cleanedValue, err := field.Clean(dataValue)
		if err == nil {
			cleanedData[fieldName] = cleanedValue
		} else {
			errors[fieldName] = err.Error()
			isValid = false
		}
	}

	if isValid {
		f.CleanedData = cleanedData
	} else {
		f.Errors = errors
	}
	return isValid
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes 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 priorities

import (
	"sync"

	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/labels"
	utilnode "k8s.io/kubernetes/pkg/util/node"
	utilruntime "k8s.io/kubernetes/pkg/util/runtime"
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// The maximum priority value to give to a node
// Prioritiy values range from 0-maxPriority
const maxPriority = 10

// When zone information is present, give 2/3 of the weighting to zone spreading, 1/3 to node spreading
// TODO: Any way to justify this weighting?
const zoneWeighting = 2.0 / 3.0

type SelectorSpread struct {
	podLister        algorithm.PodLister
	serviceLister    algorithm.ServiceLister
	controllerLister algorithm.ControllerLister
	replicaSetLister algorithm.ReplicaSetLister
}

func NewSelectorSpreadPriority(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, controllerLister algorithm.ControllerLister, replicaSetLister algorithm.ReplicaSetLister) algorithm.PriorityFunction {
	selectorSpread := &SelectorSpread{
		podLister:        podLister,
		serviceLister:    serviceLister,
		controllerLister: controllerLister,
		replicaSetLister: replicaSetLister,
	}
	return selectorSpread.CalculateSpreadPriority
}

// CalculateSpreadPriority spreads pods across hosts and zones, considering pods belonging to the same service or replication controller.
// When a pod is scheduled, it looks for services or RCs that match the pod, then finds existing pods that match those selectors.
// It favors nodes that have fewer existing matching pods.
// i.e. it pushes the scheduler towards a node where there's the smallest number of
// pods which match the same service selectors or RC selectors as the pod being scheduled.
// Where zone information is included on the nodes, it favors nodes in zones with fewer existing matching pods.
func (s *SelectorSpread) CalculateSpreadPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodeLister algorithm.NodeLister) (schedulerapi.HostPriorityList, error) {
	selectors := make([]labels.Selector, 0)
	services, err := s.serviceLister.GetPodServices(pod)
	if err == nil {
		for _, service := range services {
			selectors = append(selectors, labels.SelectorFromSet(service.Spec.Selector))
		}
	}
	rcs, err := s.controllerLister.GetPodControllers(pod)
	if err == nil {
		for _, rc := range rcs {
			selectors = append(selectors, labels.SelectorFromSet(rc.Spec.Selector))
		}
	}
	rss, err := s.replicaSetLister.GetPodReplicaSets(pod)
	if err == nil {
		for _, rs := range rss {
			if selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector); err == nil {
				selectors = append(selectors, selector)
			}
		}
	}

	nodes, err := nodeLister.List()
	if err != nil {
		return nil, err
	}

	// Count similar pods by node
	countsByNodeName := map[string]int{}
	countsByNodeNameLock := sync.Mutex{}

	if len(selectors) > 0 {
		// Create a number of go-routines that will be computing number
		// of "similar" pods for given nodes.
		workers := 16
		toProcess := make(chan string, len(nodes))
		for i := range nodes {
			toProcess <- nodes[i].Name
		}
		close(toProcess)

		// TODO: Use Parallelize.
		wg := sync.WaitGroup{}
		wg.Add(workers)
		for i := 0; i < workers; i++ {
			go func() {
				defer utilruntime.HandleCrash()
				defer wg.Done()
				for {
					nodeName, ok := <-toProcess
					if !ok {
						return
					}
					count := 0
					for _, nodePod := range nodeNameToInfo[nodeName].Pods() {
						if pod.Namespace != nodePod.Namespace {
							continue
						}
						// When we are replacing a failed pod, we often see the previous
						// deleted version while scheduling the replacement.
						// Ignore the previous deleted version for spreading purposes
						// (it can still be considered for resource restrictions etc.)
						if nodePod.DeletionTimestamp != nil {
							glog.V(4).Infof("skipping pending-deleted pod: %s/%s", nodePod.Namespace, nodePod.Name)
							continue
						}
						matches := false
						for _, selector := range selectors {
							if selector.Matches(labels.Set(nodePod.ObjectMeta.Labels)) {
								matches = true
								break
							}
						}
						if matches {
							count++
						}
					}

					func() {
						countsByNodeNameLock.Lock()
						defer countsByNodeNameLock.Unlock()
						countsByNodeName[nodeName] = count
					}()
				}
			}()
		}
		wg.Wait()
	}

	// Aggregate by-node information
	// Compute the maximum number of pods hosted on any node
	maxCountByNodeName := 0
	for _, count := range countsByNodeName {
		if count > maxCountByNodeName {
			maxCountByNodeName = count
		}
	}

	// Count similar pods by zone, if zone information is present
	countsByZone := map[string]int{}
	for _, node := range nodes {
		count, found := countsByNodeName[node.Name]
		if !found {
			continue
		}

		zoneId := utilnode.GetZoneKey(node)
		if zoneId == "" {
			continue
		}

		countsByZone[zoneId] += count
	}

	// Aggregate by-zone information
	// Compute the maximum number of pods hosted in any zone
	haveZones := len(countsByZone) != 0
	maxCountByZone := 0
	for _, count := range countsByZone {
		if count > maxCountByZone {
			maxCountByZone = count
		}
	}

	result := make(schedulerapi.HostPriorityList, 0, len(nodes))
	//score int - scale of 0-maxPriority
	// 0 being the lowest priority and maxPriority being the highest
	for _, node := range nodes {
		// initializing to the default/max node score of maxPriority
		fScore := float32(maxPriority)
		if maxCountByNodeName > 0 {
			fScore = maxPriority * (float32(maxCountByNodeName-countsByNodeName[node.Name]) / float32(maxCountByNodeName))
		}

		// If there is zone information present, incorporate it
		if haveZones {
			zoneId := utilnode.GetZoneKey(node)
			if zoneId != "" {
				zoneScore := maxPriority * (float32(maxCountByZone-countsByZone[zoneId]) / float32(maxCountByZone))
				fScore = (fScore * (1.0 - zoneWeighting)) + (zoneWeighting * zoneScore)
			}
		}

		result = append(result, schedulerapi.HostPriority{Host: node.Name, Score: int(fScore)})
		glog.V(10).Infof(
			"%v -> %v: SelectorSpreadPriority, Score: (%d)", pod.Name, node.Name, int(fScore),
		)
	}
	return result, nil
}

type ServiceAntiAffinity struct {
	podLister     algorithm.PodLister
	serviceLister algorithm.ServiceLister
	label         string
}

func NewServiceAntiAffinityPriority(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, label string) algorithm.PriorityFunction {
	antiAffinity := &ServiceAntiAffinity{
		podLister:     podLister,
		serviceLister: serviceLister,
		label:         label,
	}
	return antiAffinity.CalculateAntiAffinityPriority
}

// CalculateAntiAffinityPriority spreads pods by minimizing the number of pods belonging to the same service
// on machines with the same value for a particular label.
// The label to be considered is provided to the struct (ServiceAntiAffinity).
func (s *ServiceAntiAffinity) CalculateAntiAffinityPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodeLister algorithm.NodeLister) (schedulerapi.HostPriorityList, error) {
	var nsServicePods []*api.Pod

	services, err := s.serviceLister.GetPodServices(pod)
	if err == nil {
		// just use the first service and get the other pods within the service
		// TODO: a separate predicate can be created that tries to handle all services for the pod
		selector := labels.SelectorFromSet(services[0].Spec.Selector)
		pods, err := s.podLister.List(selector)
		if err != nil {
			return nil, err
		}
		// consider only the pods that belong to the same namespace
		for _, nsPod := range pods {
			if nsPod.Namespace == pod.Namespace {
				nsServicePods = append(nsServicePods, nsPod)
			}
		}
	}

	nodes, err := nodeLister.List()
	if err != nil {
		return nil, err
	}

	// separate out the nodes that have the label from the ones that don't
	otherNodes := []string{}
	labeledNodes := map[string]string{}
	for _, node := range nodes {
		if labels.Set(node.Labels).Has(s.label) {
			label := labels.Set(node.Labels).Get(s.label)
			labeledNodes[node.Name] = label
		} else {
			otherNodes = append(otherNodes, node.Name)
		}
	}

	podCounts := map[string]int{}
	for _, pod := range nsServicePods {
		label, exists := labeledNodes[pod.Spec.NodeName]
		if !exists {
			continue
		}
		podCounts[label]++
	}

	numServicePods := len(nsServicePods)
	result := []schedulerapi.HostPriority{}
	//score int - scale of 0-maxPriority
	// 0 being the lowest priority and maxPriority being the highest
	for node := range labeledNodes {
		// initializing to the default/max node score of maxPriority
		fScore := float32(maxPriority)
		if numServicePods > 0 {
			fScore = maxPriority * (float32(numServicePods-podCounts[labeledNodes[node]]) / float32(numServicePods))
		}
		result = append(result, schedulerapi.HostPriority{Host: node, Score: int(fScore)})
	}
	// add the open nodes with a score of 0
	for _, node := range otherNodes {
		result = append(result, schedulerapi.HostPriority{Host: node, Score: 0})
	}

	return result, nil
}
<commit_msg>Optimize selector spreading<commit_after>/*
Copyright 2014 The Kubernetes 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 priorities

import (
	"sync"

	"github.com/golang/glog"
	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/unversioned"
	"k8s.io/kubernetes/pkg/labels"
	utilnode "k8s.io/kubernetes/pkg/util/node"
	"k8s.io/kubernetes/pkg/util/workqueue"
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
)

// The maximum priority value to give to a node
// Prioritiy values range from 0-maxPriority
const maxPriority float32 = 10

// When zone information is present, give 2/3 of the weighting to zone spreading, 1/3 to node spreading
// TODO: Any way to justify this weighting?
const zoneWeighting = 2.0 / 3.0

type SelectorSpread struct {
	podLister        algorithm.PodLister
	serviceLister    algorithm.ServiceLister
	controllerLister algorithm.ControllerLister
	replicaSetLister algorithm.ReplicaSetLister
}

func NewSelectorSpreadPriority(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, controllerLister algorithm.ControllerLister, replicaSetLister algorithm.ReplicaSetLister) algorithm.PriorityFunction {
	selectorSpread := &SelectorSpread{
		podLister:        podLister,
		serviceLister:    serviceLister,
		controllerLister: controllerLister,
		replicaSetLister: replicaSetLister,
	}
	return selectorSpread.CalculateSpreadPriority
}

// CalculateSpreadPriority spreads pods across hosts and zones, considering pods belonging to the same service or replication controller.
// When a pod is scheduled, it looks for services or RCs that match the pod, then finds existing pods that match those selectors.
// It favors nodes that have fewer existing matching pods.
// i.e. it pushes the scheduler towards a node where there's the smallest number of
// pods which match the same service selectors or RC selectors as the pod being scheduled.
// Where zone information is included on the nodes, it favors nodes in zones with fewer existing matching pods.
func (s *SelectorSpread) CalculateSpreadPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodeLister algorithm.NodeLister) (schedulerapi.HostPriorityList, error) {
	selectors := make([]labels.Selector, 0, 3)
	if services, err := s.serviceLister.GetPodServices(pod); err == nil {
		for _, service := range services {
			selectors = append(selectors, labels.SelectorFromSet(service.Spec.Selector))
		}
	}
	if rcs, err := s.controllerLister.GetPodControllers(pod); err == nil {
		for _, rc := range rcs {
			selectors = append(selectors, labels.SelectorFromSet(rc.Spec.Selector))
		}
	}
	if rss, err := s.replicaSetLister.GetPodReplicaSets(pod); err == nil {
		for _, rs := range rss {
			if selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector); err == nil {
				selectors = append(selectors, selector)
			}
		}
	}

	nodes, err := nodeLister.List()
	if err != nil {
		return nil, err
	}

	// Count similar pods by node
	countsByNodeName := make(map[string]float32, len(nodes))
	countsByZone := make(map[string]float32, 10)
	maxCountByNodeName := float32(0)
	countsByNodeNameLock := sync.Mutex{}

	if len(selectors) > 0 {
		processNodeFunc := func(i int) {
			nodeName := nodes[i].Name
			count := float32(0)
			for _, nodePod := range nodeNameToInfo[nodeName].Pods() {
				if pod.Namespace != nodePod.Namespace {
					continue
				}
				// When we are replacing a failed pod, we often see the previous
				// deleted version while scheduling the replacement.
				// Ignore the previous deleted version for spreading purposes
				// (it can still be considered for resource restrictions etc.)
				if nodePod.DeletionTimestamp != nil {
					glog.V(4).Infof("skipping pending-deleted pod: %s/%s", nodePod.Namespace, nodePod.Name)
					continue
				}
				matches := false
				for _, selector := range selectors {
					if selector.Matches(labels.Set(nodePod.ObjectMeta.Labels)) {
						matches = true
						break
					}
				}
				if matches {
					count++
				}
			}
			zoneId := utilnode.GetZoneKey(nodes[i])

			countsByNodeNameLock.Lock()
			defer countsByNodeNameLock.Unlock()
			countsByNodeName[nodeName] = count
			if count > maxCountByNodeName {
				maxCountByNodeName = count
			}
			if zoneId != "" {
				countsByZone[zoneId] += count
			}
		}
		workqueue.Parallelize(16, len(nodes), processNodeFunc)
	}

	// Aggregate by-zone information
	// Compute the maximum number of pods hosted in any zone
	haveZones := len(countsByZone) != 0
	maxCountByZone := float32(0)
	for _, count := range countsByZone {
		if count > maxCountByZone {
			maxCountByZone = count
		}
	}

	result := make(schedulerapi.HostPriorityList, 0, len(nodes))
	//score int - scale of 0-maxPriority
	// 0 being the lowest priority and maxPriority being the highest
	for _, node := range nodes {
		// initializing to the default/max node score of maxPriority
		fScore := maxPriority
		if maxCountByNodeName > 0 {
			fScore = maxPriority * ((maxCountByNodeName - countsByNodeName[node.Name]) / maxCountByNodeName)
		}

		// If there is zone information present, incorporate it
		if haveZones {
			zoneId := utilnode.GetZoneKey(node)
			if zoneId != "" {
				zoneScore := maxPriority * ((maxCountByZone - countsByZone[zoneId]) / maxCountByZone)
				fScore = (fScore * (1.0 - zoneWeighting)) + (zoneWeighting * zoneScore)
			}
		}

		result = append(result, schedulerapi.HostPriority{Host: node.Name, Score: int(fScore)})
		if glog.V(10) {
			// We explicitly don't do glog.V(10).Infof() to avoid computing all the parameters if this is
			// not logged. There is visible performance gain from it.
			glog.V(10).Infof(
				"%v -> %v: SelectorSpreadPriority, Score: (%d)", pod.Name, node.Name, int(fScore),
			)
		}
	}
	return result, nil
}

type ServiceAntiAffinity struct {
	podLister     algorithm.PodLister
	serviceLister algorithm.ServiceLister
	label         string
}

func NewServiceAntiAffinityPriority(podLister algorithm.PodLister, serviceLister algorithm.ServiceLister, label string) algorithm.PriorityFunction {
	antiAffinity := &ServiceAntiAffinity{
		podLister:     podLister,
		serviceLister: serviceLister,
		label:         label,
	}
	return antiAffinity.CalculateAntiAffinityPriority
}

// CalculateAntiAffinityPriority spreads pods by minimizing the number of pods belonging to the same service
// on machines with the same value for a particular label.
// The label to be considered is provided to the struct (ServiceAntiAffinity).
func (s *ServiceAntiAffinity) CalculateAntiAffinityPriority(pod *api.Pod, nodeNameToInfo map[string]*schedulercache.NodeInfo, nodeLister algorithm.NodeLister) (schedulerapi.HostPriorityList, error) {
	var nsServicePods []*api.Pod

	if services, err := s.serviceLister.GetPodServices(pod); err == nil {
		// just use the first service and get the other pods within the service
		// TODO: a separate predicate can be created that tries to handle all services for the pod
		selector := labels.SelectorFromSet(services[0].Spec.Selector)
		pods, err := s.podLister.List(selector)
		if err != nil {
			return nil, err
		}
		// consider only the pods that belong to the same namespace
		for _, nsPod := range pods {
			if nsPod.Namespace == pod.Namespace {
				nsServicePods = append(nsServicePods, nsPod)
			}
		}
	}

	nodes, err := nodeLister.List()
	if err != nil {
		return nil, err
	}

	// separate out the nodes that have the label from the ones that don't
	otherNodes := []string{}
	labeledNodes := map[string]string{}
	for _, node := range nodes {
		if labels.Set(node.Labels).Has(s.label) {
			label := labels.Set(node.Labels).Get(s.label)
			labeledNodes[node.Name] = label
		} else {
			otherNodes = append(otherNodes, node.Name)
		}
	}

	podCounts := map[string]int{}
	for _, pod := range nsServicePods {
		label, exists := labeledNodes[pod.Spec.NodeName]
		if !exists {
			continue
		}
		podCounts[label]++
	}

	numServicePods := len(nsServicePods)
	result := []schedulerapi.HostPriority{}
	//score int - scale of 0-maxPriority
	// 0 being the lowest priority and maxPriority being the highest
	for node := range labeledNodes {
		// initializing to the default/max node score of maxPriority
		fScore := float32(maxPriority)
		if numServicePods > 0 {
			fScore = maxPriority * (float32(numServicePods-podCounts[labeledNodes[node]]) / float32(numServicePods))
		}
		result = append(result, schedulerapi.HostPriority{Host: node, Score: int(fScore)})
	}
	// add the open nodes with a score of 0
	for _, node := range otherNodes {
		result = append(result, schedulerapi.HostPriority{Host: node, Score: 0})
	}

	return result, nil
}
<|endoftext|>


<commit_before>package filters

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	gh "github.com/crosbymichael/octokat"
	"github.com/docker/gordon"
)

func FilterPullRequests(c *cli.Context, prs []*gh.PullRequest) ([]*gh.PullRequest, error) {
	var (
		yesterday  = time.Now().Add(-24 * time.Hour)
		out        = []*gh.PullRequest{}
		email, err = gordon.GetMaintainerManagerEmail()
	)
	if err != nil {
		return nil, err
	}

	for _, pr := range prs {
		fmt.Printf(".")

		if c.Bool("new") && !pr.CreatedAt.After(yesterday) {
			continue
		}

		if user := c.String("user"); user != "" {
			if pr.User.Login != user {
				continue
			}
		}

		if c.Bool("cleanup") {
			if !strings.HasPrefix(strings.ToLower(pr.Title), "cleanup") {
				continue
			}
		}

		maintainer := c.String("maintainer")
		dir := c.String("dir")
		extension := c.String("extension")

		var diff []byte

		if maintainer != "" || dir != "" || extension != "" {
			diffResp, err := http.Get(pr.DiffURL)
			if err != nil {
				continue
			}

			diff, err = ioutil.ReadAll(diffResp.Body)
			if err != nil {
				continue
			}

			diffResp.Body.Close()
		}

		if dir != "" {
			dirs, err := gordon.GetDirsForPR(diff, dir)
			if err != nil {
				continue
			}

			if len(dirs) == 0 {
				continue
			}
		}

		if extension != "" {
			files, err := gordon.GetFileExtensionsForPR(diff, extension)
			if err != nil {
				continue
			}

			if len(files) == 0 {
				continue
			}
		}

		if maintainer != "" || c.Bool("mine") {
			if maintainer == "" {
				maintainer = email
			}

			var found bool
			reviewers, err := gordon.GetReviewersForPR(diff, true)
			if err != nil {
				continue
			}
			for file := range reviewers {
				for _, reviewer := range reviewers[file] {
					if reviewer == maintainer {
						found = true
					}
				}
			}
			if !found {
				continue
			}

		}

		if c.Bool("unassigned") && pr.Assignee != nil {
			continue
		} else if assigned := c.String("assigned"); assigned != "" && (pr.Assignee == nil || pr.Assignee.Login != assigned) {
			continue
		}

		if c.Bool("lgtm") {
			pr.ReviewComments = 0
			maintainersOccurrence := map[string]bool{}
			for _, comment := range pr.CommentsBody {
				// We should check it this LGTM is by a user in
				// the maintainers file
				userName := comment.User.Login
				if strings.Contains(comment.Body, "LGTM") && !maintainersOccurrence[userName] {
					maintainersOccurrence[userName] = true
					pr.ReviewComments += 1
				}
			}
		}

		if c.Bool("no-merge") && pr.Mergeable {
			continue
		}

		out = append(out, pr)
	}
	return out, nil

}

func FilterIssues(c *cli.Context, issues []*gh.Issue) ([]*gh.Issue, error) {
	var (
		yesterday      = time.Now().Add(-24 * time.Hour)
		out            = []*gh.Issue{}
		client         = gh.NewClient()
		org, name, err = gordon.GetRemoteUrl(c.String("remote"))
	)
	if err != nil {
		return nil, err
	}
	t, err := gordon.NewMaintainerManager(client, org, name)
	if err != nil {
		return nil, err
	}

	for _, issue := range issues {
		fmt.Printf(".")

		if c.Bool("new") && !issue.CreatedAt.After(yesterday) {
			continue
		}

		if milestone := c.String("milestone"); milestone != "" && issue.Milestone.Title != milestone {
			continue
		}

		if numVotes := c.Int("votes"); numVotes > 0 {
			comments, err := t.GetComments(strconv.Itoa(issue.Number))
			if err != nil {
				return nil, err
			}
			issue.Comments = 0
			for _, comment := range comments {
				if strings.Contains(comment.Body, "+1") {
					issue.Comments += 1
				}
			}
			if issue.Comments < numVotes {
				continue
			}
		}

		if c.Bool("proposals") && !strings.HasPrefix(issue.Title, "Proposal") {
			continue
		}

		out = append(out, issue)
	}
	return out, nil

}
<commit_msg>Fix `pulls --mine`<commit_after>package filters

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	gh "github.com/crosbymichael/octokat"
	"github.com/docker/gordon"
)

func FilterPullRequests(c *cli.Context, prs []*gh.PullRequest) ([]*gh.PullRequest, error) {
	var (
		yesterday  = time.Now().Add(-24 * time.Hour)
		out        = []*gh.PullRequest{}
		email, err = gordon.GetMaintainerManagerEmail()
	)
	if err != nil {
		return nil, err
	}

	for _, pr := range prs {
		fmt.Printf(".")

		if c.Bool("new") && !pr.CreatedAt.After(yesterday) {
			continue
		}

		if user := c.String("user"); user != "" {
			if pr.User.Login != user {
				continue
			}
		}

		if c.Bool("cleanup") {
			if !strings.HasPrefix(strings.ToLower(pr.Title), "cleanup") {
				continue
			}
		}

		maintainer := c.String("maintainer")
		dir := c.String("dir")
		extension := c.String("extension")

		var diff []byte

		if maintainer != "" || dir != "" || extension != "" || c.Bool("mine") {
			diffResp, err := http.Get(pr.DiffURL)
			if err != nil {
				continue
			}

			diff, err = ioutil.ReadAll(diffResp.Body)
			if err != nil {
				continue
			}

			diffResp.Body.Close()
		}

		if dir != "" {
			dirs, err := gordon.GetDirsForPR(diff, dir)
			if err != nil {
				continue
			}

			if len(dirs) == 0 {
				continue
			}
		}

		if extension != "" {
			files, err := gordon.GetFileExtensionsForPR(diff, extension)
			if err != nil {
				continue
			}

			if len(files) == 0 {
				continue
			}
		}

		if maintainer != "" || c.Bool("mine") {
			if maintainer == "" {
				maintainer = email
			}

			var found bool
			reviewers, err := gordon.GetReviewersForPR(diff, true)
			if err != nil {
				continue
			}
			for file := range reviewers {
				for _, reviewer := range reviewers[file] {
					if reviewer == maintainer {
						found = true
					}
				}
			}
			if !found {
				continue
			}

		}

		if c.Bool("unassigned") && pr.Assignee != nil {
			continue
		} else if assigned := c.String("assigned"); assigned != "" && (pr.Assignee == nil || pr.Assignee.Login != assigned) {
			continue
		}

		if c.Bool("lgtm") {
			pr.ReviewComments = 0
			maintainersOccurrence := map[string]bool{}
			for _, comment := range pr.CommentsBody {
				// We should check it this LGTM is by a user in
				// the maintainers file
				userName := comment.User.Login
				if strings.Contains(comment.Body, "LGTM") && !maintainersOccurrence[userName] {
					maintainersOccurrence[userName] = true
					pr.ReviewComments += 1
				}
			}
		}

		if c.Bool("no-merge") && pr.Mergeable {
			continue
		}

		out = append(out, pr)
	}
	return out, nil

}

func FilterIssues(c *cli.Context, issues []*gh.Issue) ([]*gh.Issue, error) {
	var (
		yesterday      = time.Now().Add(-24 * time.Hour)
		out            = []*gh.Issue{}
		client         = gh.NewClient()
		org, name, err = gordon.GetRemoteUrl(c.String("remote"))
	)
	if err != nil {
		return nil, err
	}
	t, err := gordon.NewMaintainerManager(client, org, name)
	if err != nil {
		return nil, err
	}

	for _, issue := range issues {
		fmt.Printf(".")

		if c.Bool("new") && !issue.CreatedAt.After(yesterday) {
			continue
		}

		if milestone := c.String("milestone"); milestone != "" && issue.Milestone.Title != milestone {
			continue
		}

		if numVotes := c.Int("votes"); numVotes > 0 {
			comments, err := t.GetComments(strconv.Itoa(issue.Number))
			if err != nil {
				return nil, err
			}
			issue.Comments = 0
			for _, comment := range comments {
				if strings.Contains(comment.Body, "+1") {
					issue.Comments += 1
				}
			}
			if issue.Comments < numVotes {
				continue
			}
		}

		if c.Bool("proposals") && !strings.HasPrefix(issue.Title, "Proposal") {
			continue
		}

		out = append(out, issue)
	}
	return out, nil

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/ast"
	"strings"

	"github.com/lukechampine/ply/types"
)

type rewriter func(*ast.CallExpr)

func rewriteFunc(name string) rewriter {
	return func(c *ast.CallExpr) {
		c.Fun.(*ast.Ident).Name = name
	}
}

func rewriteMethod(name string) rewriter {
	return func(c *ast.CallExpr) {
		fn := c.Fun.(*ast.SelectorExpr)
		fn.X = &ast.CallExpr{
			Fun:  ast.NewIdent(name),
			Args: []ast.Expr{fn.X},
		}
	}
}

func rewriteReassign(reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		c.Args = append(c.Args, reassign)
	}
}

func rewriteMethodReassign(name string, reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		rewriteMethod(name)(c)
		rewriteReassign(reassign)(c)
	}
}

func rewriteFuncReassign(name string, reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		rewriteFunc(name)(c)
		rewriteReassign(reassign)(c)
	}
}

type genFunc func(*ast.Ident, []ast.Expr, ast.Expr, map[ast.Expr]types.TypeAndValue) (string, string, rewriter)

type genMethod func(*ast.SelectorExpr, []ast.Expr, ast.Expr, map[ast.Expr]types.TypeAndValue) (string, string, rewriter)

var funcGenerators = map[string]genFunc{
	"merge": mergeGen,
}

var methodGenerators = map[string]genMethod{
	"filter": filterGen,
	"morph":  morphGen,
	"reduce": reduceGen,
}

// some types may have "unfriendly" names, e.g. "chan int". Need to sanitize
// these before concatenating them into a new ident.
func safeIdent(s string) string {
	return strings.NewReplacer(
		// slices/arrays
		"[", "",
		"]", "",
		// channels
		"chan<-", "chan_in",
		"<-chan", "chan_out",
		" ", "_",
		// structs
		"{", "",
		"}", "",
		";", "",
		// imports
		".", "",
	).Replace(s)
}

const mergeTempl = `
func %[1]s(m1, m2 map[%[2]s]%[3]s) map[%[2]s]%[3]s {
	m3 := make(map[%[2]s]%[3]s)
	for k, v := range m1 {
		m3[k] = v
	}
	for k, v := range m2 {
		m3[k] = v
	}
	return m3
}
`

func mergeGen(fn *ast.Ident, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	mt := exprTypes[args[0]].Type.(*types.Map)
	key, elem := mt.Key().String(), mt.Elem().String()
	name = safeIdent("merge" + key + elem)
	code = fmt.Sprintf(mergeTempl, name, key, elem)
	r = rewriteFunc(name)
	return
}

const filterTempl = `
type %[1]s []%[2]s

func (xs %[1]s) filter(pred func(%[2]s) bool) []%[2]s {
	var filtered []%[2]s
	for _, x := range xs {
		if pred(x) {
			filtered = append(filtered, x)
		}
	}
	return filtered
}
`

const filterReassignTempl = `
type %[1]s []%[2]s

func (xs %[1]s) filter(pred func(%[2]s) bool, reassign []%[2]s) []%[2]s {
	filtered := reassign[:0]
	for _, x := range xs {
		if pred(x) {
			filtered = append(filtered, x)
		}
	}
	return filtered
}
`

func filterGen(fn *ast.SelectorExpr, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	T := exprTypes[fn.X].Type.Underlying().(*types.Slice).Elem().String()
	name = safeIdent("filter" + T + "slice")
	if reassign != nil {
		name += "reassign"
		code = fmt.Sprintf(filterReassignTempl, name, T)
		r = rewriteMethodReassign(name, reassign)
	} else {
		code = fmt.Sprintf(filterTempl, name, T)
		r = rewriteMethod(name)
	}
	return
}

const morphTempl = `
type %[1]s []%[2]s

func (xs %[1]s) morph(fn func(%[2]s) %[3]s) []%[3]s {
	morphed := make([]%[3]s, len(xs))
	for i := range xs {
		morphed[i] = fn(xs[i])
	}
	return morphed
}
`

const morphReassignTempl = `
type %[1]s []%[2]s

func (xs %[1]s) morph(fn func(%[2]s) %[3]s, reassign []%[3]s) []%[3]s {
	var morphed []%[3]s
	if len(reassign) >= len(xs) {
		morphed = reassign[:len(xs)]
	} else {
		morphed = make([]%[3]s, len(xs))
	}
	for i := range xs {
		morphed[i] = fn(xs[i])
	}
	return morphed
}
`

func morphGen(fn *ast.SelectorExpr, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	// determine arg types
	morphFn := exprTypes[args[0]].Type.Underlying().(*types.Signature)
	T := morphFn.Params().At(0).Type().String()
	U := morphFn.Results().At(0).Type().String()
	name = safeIdent("morph" + T + U + "slice")
	if reassign != nil {
		name += "reassign"
		code = fmt.Sprintf(morphReassignTempl, name, T, U)
		r = rewriteMethodReassign(name, reassign)
	} else {
		code = fmt.Sprintf(morphTempl, name, T, U)
		r = rewriteMethod(name)
	}
	return
}

const reduceTempl = `
type %[1]s []%[2]s

func (xs %[1]s) reduce(fn func(%[3]s, %[2]s) %[3]s, acc %[3]s) %[3]s {
	for _, x := range xs {
		acc = fn(acc, x)
	}
	return acc
}
`

const reduce1Templ = `
type %[1]s []%[2]s

func (xs %[1]s) reduce(fn func(%[3]s, %[2]s) %[3]s) %[3]s {
	if len(xs) == 0 {
		panic("reduce of empty slice")
	}
	acc := xs[0]
	for _, x := range xs {
		acc = fn(acc, x)
	}
	return acc
}
`

func reduceGen(fn *ast.SelectorExpr, args []ast.Expr, _ ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	// determine arg types
	T := exprTypes[fn.X].Type.Underlying().(*types.Slice).Elem().String()
	U := exprTypes[args[0]].Type.(*types.Signature).Params().At(0).Type().String()
	if len(args) == 1 {
		name = safeIdent("reduce1" + T + U + "slice")
		code = fmt.Sprintf(reduce1Templ, name, T, U)
	} else if len(args) == 2 {
		name = safeIdent("reduce" + T + U + "slice")
		code = fmt.Sprintf(reduceTempl, name, T, U)
	}
	r = rewriteMethod(name)
	return
}
<commit_msg>use cap for morph reassign check<commit_after>package main

import (
	"fmt"
	"go/ast"
	"strings"

	"github.com/lukechampine/ply/types"
)

type rewriter func(*ast.CallExpr)

func rewriteFunc(name string) rewriter {
	return func(c *ast.CallExpr) {
		c.Fun.(*ast.Ident).Name = name
	}
}

func rewriteMethod(name string) rewriter {
	return func(c *ast.CallExpr) {
		fn := c.Fun.(*ast.SelectorExpr)
		fn.X = &ast.CallExpr{
			Fun:  ast.NewIdent(name),
			Args: []ast.Expr{fn.X},
		}
	}
}

func rewriteReassign(reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		c.Args = append(c.Args, reassign)
	}
}

func rewriteMethodReassign(name string, reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		rewriteMethod(name)(c)
		rewriteReassign(reassign)(c)
	}
}

func rewriteFuncReassign(name string, reassign ast.Expr) rewriter {
	return func(c *ast.CallExpr) {
		rewriteFunc(name)(c)
		rewriteReassign(reassign)(c)
	}
}

type genFunc func(*ast.Ident, []ast.Expr, ast.Expr, map[ast.Expr]types.TypeAndValue) (string, string, rewriter)

type genMethod func(*ast.SelectorExpr, []ast.Expr, ast.Expr, map[ast.Expr]types.TypeAndValue) (string, string, rewriter)

var funcGenerators = map[string]genFunc{
	"merge": mergeGen,
}

var methodGenerators = map[string]genMethod{
	"filter": filterGen,
	"morph":  morphGen,
	"reduce": reduceGen,
}

// some types may have "unfriendly" names, e.g. "chan int". Need to sanitize
// these before concatenating them into a new ident.
func safeIdent(s string) string {
	return strings.NewReplacer(
		// slices/arrays
		"[", "",
		"]", "",
		// channels
		"chan<-", "chan_in",
		"<-chan", "chan_out",
		" ", "_",
		// structs
		"{", "",
		"}", "",
		";", "",
		// imports
		".", "",
	).Replace(s)
}

const mergeTempl = `
func %[1]s(m1, m2 map[%[2]s]%[3]s) map[%[2]s]%[3]s {
	m3 := make(map[%[2]s]%[3]s)
	for k, v := range m1 {
		m3[k] = v
	}
	for k, v := range m2 {
		m3[k] = v
	}
	return m3
}
`

func mergeGen(fn *ast.Ident, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	mt := exprTypes[args[0]].Type.(*types.Map)
	key, elem := mt.Key().String(), mt.Elem().String()
	name = safeIdent("merge" + key + elem)
	code = fmt.Sprintf(mergeTempl, name, key, elem)
	r = rewriteFunc(name)
	return
}

const filterTempl = `
type %[1]s []%[2]s

func (xs %[1]s) filter(pred func(%[2]s) bool) []%[2]s {
	var filtered []%[2]s
	for _, x := range xs {
		if pred(x) {
			filtered = append(filtered, x)
		}
	}
	return filtered
}
`

const filterReassignTempl = `
type %[1]s []%[2]s

func (xs %[1]s) filter(pred func(%[2]s) bool, reassign []%[2]s) []%[2]s {
	filtered := reassign[:0]
	for _, x := range xs {
		if pred(x) {
			filtered = append(filtered, x)
		}
	}
	return filtered
}
`

func filterGen(fn *ast.SelectorExpr, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	T := exprTypes[fn.X].Type.Underlying().(*types.Slice).Elem().String()
	name = safeIdent("filter" + T + "slice")
	if reassign != nil {
		name += "reassign"
		code = fmt.Sprintf(filterReassignTempl, name, T)
		r = rewriteMethodReassign(name, reassign)
	} else {
		code = fmt.Sprintf(filterTempl, name, T)
		r = rewriteMethod(name)
	}
	return
}

const morphTempl = `
type %[1]s []%[2]s

func (xs %[1]s) morph(fn func(%[2]s) %[3]s) []%[3]s {
	morphed := make([]%[3]s, len(xs))
	for i := range xs {
		morphed[i] = fn(xs[i])
	}
	return morphed
}
`

const morphReassignTempl = `
type %[1]s []%[2]s

func (xs %[1]s) morph(fn func(%[2]s) %[3]s, reassign []%[3]s) []%[3]s {
	var morphed []%[3]s
	if cap(reassign) >= len(xs) {
		morphed = reassign[:len(xs)]
	} else {
		morphed = make([]%[3]s, len(xs))
	}
	for i := range xs {
		morphed[i] = fn(xs[i])
	}
	return morphed
}
`

func morphGen(fn *ast.SelectorExpr, args []ast.Expr, reassign ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	// determine arg types
	morphFn := exprTypes[args[0]].Type.Underlying().(*types.Signature)
	T := morphFn.Params().At(0).Type().String()
	U := morphFn.Results().At(0).Type().String()
	name = safeIdent("morph" + T + U + "slice")
	if reassign != nil {
		name += "reassign"
		code = fmt.Sprintf(morphReassignTempl, name, T, U)
		r = rewriteMethodReassign(name, reassign)
	} else {
		code = fmt.Sprintf(morphTempl, name, T, U)
		r = rewriteMethod(name)
	}
	return
}

const reduceTempl = `
type %[1]s []%[2]s

func (xs %[1]s) reduce(fn func(%[3]s, %[2]s) %[3]s, acc %[3]s) %[3]s {
	for _, x := range xs {
		acc = fn(acc, x)
	}
	return acc
}
`

const reduce1Templ = `
type %[1]s []%[2]s

func (xs %[1]s) reduce(fn func(%[3]s, %[2]s) %[3]s) %[3]s {
	if len(xs) == 0 {
		panic("reduce of empty slice")
	}
	acc := xs[0]
	for _, x := range xs {
		acc = fn(acc, x)
	}
	return acc
}
`

func reduceGen(fn *ast.SelectorExpr, args []ast.Expr, _ ast.Expr, exprTypes map[ast.Expr]types.TypeAndValue) (name, code string, r rewriter) {
	// determine arg types
	T := exprTypes[fn.X].Type.Underlying().(*types.Slice).Elem().String()
	U := exprTypes[args[0]].Type.(*types.Signature).Params().At(0).Type().String()
	if len(args) == 1 {
		name = safeIdent("reduce1" + T + U + "slice")
		code = fmt.Sprintf(reduce1Templ, name, T, U)
	} else if len(args) == 2 {
		name = safeIdent("reduce" + T + U + "slice")
		code = fmt.Sprintf(reduceTempl, name, T, U)
	}
	r = rewriteMethod(name)
	return
}
<|endoftext|>


<commit_before>package main

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

func execCommand(command []string) string {
	cmd := exec.Command(command[0], command[1:]...)
	out, err := cmd.CombinedOutput()

	if err != nil {
		log.Fatal(fmt.Sprint(err) + ": " + string(out))
	}
	output := strings.TrimSpace(string(out))

	return output
}

func GetCurrentBranch() string {
	return execCommand([]string{
		"git",
		"symbolic-ref",
		"--short",
		"HEAD",
	})
}

func GetConfigValue(name string) string {
	val := execCommand([]string{
		"git",
		"config",
		name,
	})
	return val
}

func SetConfigValue(name, value string) {
	execCommand([]string{
		"git",
		"config",
		"set",
		name,
		value,
	})
}
<commit_msg>Fixing SetConfigValue.<commit_after>package main

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

func execCommand(command []string) string {
	cmd := exec.Command(command[0], command[1:]...)
	out, err := cmd.CombinedOutput()

	if err != nil {
		log.Fatal(fmt.Sprint(err) + ": " + string(out))
	}
	output := strings.TrimSpace(string(out))

	return output
}

func GetCurrentBranch() string {
	return execCommand([]string{
		"git",
		"symbolic-ref",
		"--short",
		"HEAD",
	})
}

func GetConfigValue(name string) string {
	val := execCommand([]string{
		"git",
		"config",
		name,
	})
	return val
}

func SetConfigValue(name, value string) {
	execCommand([]string{
		"git",
		"config",
		"--add",
		name,
		value,
	})
}
<|endoftext|>


<commit_before>package main

import (
	"net/url"
	"os"
	"strings"

	"github.com/libgit2/git2go"
	. "github.com/reujab/bronze/types"
)

// the git segment provides useful information about a git repository such as the domain of the "origin" remote (with an icon), the current branch, and whether the HEAD is dirty
func gitSegment(segment *Segment) {
	dir, err := os.Getwd()
	die(err)
	repo, err := git.OpenRepositoryExtended(dir, 0, "/")
	if err != nil {
		return
	}
	defer repo.Free()

	var domainName string
	remote, err := repo.Remotes.Lookup("origin")
	if err == nil {
		uri, err := url.Parse(remote.Url())
		die(err)
		// strip the tld off the hostname
		if len(uri.Hostname()) > 4 {
			domainName = uri.Hostname()[:len(uri.Hostname())-4]
		}
		remote.Free()
	}

	var stashes int
	repo.Stashes.Foreach(func(int, string, *git.Oid) error {
		stashes++
		return nil
	})

	var ahead, behind int
	var branch string
	head, err := repo.Head()
	if err == nil {
		upstream, err := head.Branch().Upstream()
		if err == nil {
			ahead, behind, err = repo.AheadBehind(head.Branch().Target(), upstream.Target())
			die(err)
		}

		branch, err = head.Branch().Name()
		if err != nil {
			// head is detached
			branch = head.Branch().Target().String()[:7]
		}
		head.Free()
	}

	var dirty, modified, staged bool
	status, err := repo.StatusList(&git.StatusOptions{
		Flags: git.StatusOptIncludeUntracked,
	})
	die(err)
	count, err := status.EntryCount()
	die(err)
	if count != 0 {
		dirty = true
	}
	for i := 0; i < count; i++ {
		entry, err := status.ByIndex(i)
		die(err)
		if entry.Status&git.StatusWtNew != 0 || entry.Status&git.StatusWtModified != 0 || entry.Status&git.StatusWtDeleted != 0 || entry.Status&git.StatusWtTypeChange != 0 || entry.Status&git.StatusWtRenamed != 0 {
			modified = true
		}
		if entry.Status&git.StatusIndexNew != 0 || entry.Status&git.StatusIndexModified != 0 || entry.Status&git.StatusIndexDeleted != 0 || entry.Status&git.StatusIndexRenamed != 0 || entry.Status&git.StatusIndexTypeChange != 0 {
			staged = true
		}
	}
	status.Free()

	var segments []string
	domainIcon := icons[domainName]
	if domainIcon == "" {
		domainIcon = icons["git"]
	}
	if domainIcon != "" {
		segments = append(segments, domainIcon)
	}
	if stashes != 0 || ahead != 0 || behind != 0 {
		section := strings.Repeat(icons["stash"], stashes) + strings.Repeat(icons["ahead"], ahead) + strings.Repeat(icons["behind"], behind)
		if section != "" {
			segments = append(segments, section)
		}
	}
	if branch != "" {
		segments = append(segments, branch)
	}
	if dirty {
		segment.Background = "yellow"

		var section string
		if modified {
			section += icons["modified"]
		}
		if staged {
			section += icons["staged"]
		}
		if section != "" {
			segments = append(segments, section)
		}
	}
	segment.Value = strings.Join(segments, " ")
}
<commit_msg>fixed panic on bare repositories<commit_after>package main

import (
	"net/url"
	"os"
	"strings"

	"github.com/libgit2/git2go"
	. "github.com/reujab/bronze/types"
)

// the git segment provides useful information about a git repository such as the domain of the "origin" remote (with an icon), the current branch, and whether the HEAD is dirty
func gitSegment(segment *Segment) {
	dir, err := os.Getwd()
	die(err)
	repo, err := git.OpenRepositoryExtended(dir, 0, "/")
	if err != nil {
		return
	}
	defer repo.Free()

	var domainName string
	remote, err := repo.Remotes.Lookup("origin")
	if err == nil {
		uri, err := url.Parse(remote.Url())
		die(err)
		// strip the tld off the hostname
		if len(uri.Hostname()) > 4 {
			domainName = uri.Hostname()[:len(uri.Hostname())-4]
		}
		remote.Free()
	}

	var stashes int
	repo.Stashes.Foreach(func(int, string, *git.Oid) error {
		stashes++
		return nil
	})

	var ahead, behind int
	var branch string
	head, err := repo.Head()
	if err == nil {
		upstream, err := head.Branch().Upstream()
		if err == nil {
			ahead, behind, err = repo.AheadBehind(head.Branch().Target(), upstream.Target())
			die(err)
		}

		branch, err = head.Branch().Name()
		if err != nil {
			// head is detached
			branch = head.Branch().Target().String()[:7]
		}
		head.Free()
	}

	var dirty, modified, staged bool
	status, err := repo.StatusList(&git.StatusOptions{
		Flags: git.StatusOptIncludeUntracked,
	})
	if err != nil {
		// bare repository
		return
	}
	count, err := status.EntryCount()
	die(err)
	if count != 0 {
		dirty = true
	}
	for i := 0; i < count; i++ {
		entry, err := status.ByIndex(i)
		die(err)
		if entry.Status&git.StatusWtNew != 0 || entry.Status&git.StatusWtModified != 0 || entry.Status&git.StatusWtDeleted != 0 || entry.Status&git.StatusWtTypeChange != 0 || entry.Status&git.StatusWtRenamed != 0 {
			modified = true
		}
		if entry.Status&git.StatusIndexNew != 0 || entry.Status&git.StatusIndexModified != 0 || entry.Status&git.StatusIndexDeleted != 0 || entry.Status&git.StatusIndexRenamed != 0 || entry.Status&git.StatusIndexTypeChange != 0 {
			staged = true
		}
	}
	status.Free()

	var segments []string
	domainIcon := icons[domainName]
	if domainIcon == "" {
		domainIcon = icons["git"]
	}
	if domainIcon != "" {
		segments = append(segments, domainIcon)
	}
	if stashes != 0 || ahead != 0 || behind != 0 {
		section := strings.Repeat(icons["stash"], stashes) + strings.Repeat(icons["ahead"], ahead) + strings.Repeat(icons["behind"], behind)
		if section != "" {
			segments = append(segments, section)
		}
	}
	if branch != "" {
		segments = append(segments, branch)
	}
	if dirty {
		segment.Background = "yellow"

		var section string
		if modified {
			section += icons["modified"]
		}
		if staged {
			section += icons["staged"]
		}
		if section != "" {
			segments = append(segments, section)
		}
	}
	segment.Value = strings.Join(segments, " ")
}
<|endoftext|>


<commit_before>package params

import (
	"fmt"
)

const (
	VersionMajor = 0          // Major version component of the current release
	VersionMinor = 9          // Minor version component of the current release
	VersionPatch = 6          // Patch version component of the current release
	VersionMeta  = "unstable" // Version metadata to append to the version string
)

// Version exposes string representation of program version.
var Version = fmt.Sprintf("%d.%d.%d-%s", VersionMajor, VersionMinor, VersionPatch, VersionMeta)
<commit_msg>version: 0.9.6 released<commit_after>package params

import (
	"fmt"
)

const (
	VersionMajor = 0        // Major version component of the current release
	VersionMinor = 9        // Minor version component of the current release
	VersionPatch = 6        // Patch version component of the current release
	VersionMeta  = "stable" // Version metadata to append to the version string
)

// Version exposes string representation of program version.
var Version = fmt.Sprintf("%d.%d.%d-%s", VersionMajor, VersionMinor, VersionPatch, VersionMeta)
<|endoftext|>


<commit_before>package fsutil

import (
	"io/ioutil"
	"os"
	"testing"
)

func TestCheckIfCompressed(t *testing.T) {
	var compressedZipFile = "./TestFiles/ZipFiles/test.zip"
	var uncompressedZipFile = "./TestFiles/OtherFiles/othertestfile.txt"

	var tests = []struct {
		source       string
		shouldAssert bool
	}{
		{compressedZipFile, true},
		{uncompressedZipFile, false},
	}

	for _, test := range tests {
		// I'm ignoring error checking because I'm assuming os.Open is tested and working
		// is this bad practice?
		f, _ := os.Open(test.source)
		r := CheckIfCompressed(f)
		if r != test.shouldAssert {
			t.Errorf("Test should of returned %v but returned %v instead", test.shouldAssert, r)
		}
	}

}

func TestCopyFile(t *testing.T) {
	var badSourceFile = "./TestFiles/FGFailedSourceFileLocation.fg"
	var badDestinationFile = "./TestFiles/NonexistantDirectory/FGFailedDestFileLocation.fg"
	var goodSourceFile = "./TestFiles/OtherFiles/othertestfile.txt"
	var goodDestinationFile = "./TestFiles/OtherFiles/othertestfile_copy.txt"
	var symlinkSourceFile = "./TestFiles/OtherFiles/TestSubdirectory/TextFiles"
	var symlinkDestinationFile = "./TestFiles/OtherFiles/TestSubdirectory/TextFilesCopy"

	var tests = []struct {
		source       string
		destination  string
		shouldAssert bool
	}{
		{"", goodDestinationFile, false},
		{goodSourceFile, "", false},
		{badSourceFile, goodDestinationFile, false},
		{goodSourceFile, badDestinationFile, false},
		{goodSourceFile, goodDestinationFile, true},
		{symlinkSourceFile, symlinkDestinationFile, true},
	}

	for index, test := range tests {
		err := CopyFile(test.source, test.destination)
		if err != nil && test.shouldAssert == true {
			t.Errorf("Test %d failed but should have passed. "+err.Error(), index)
		} else if err == nil && test.shouldAssert == false {
			t.Errorf("Test %d passed but should have failed.", index)
		} else if err == nil && test.shouldAssert == true {
			if _, err := os.Stat(test.source); err != nil {
				t.Error("CopyFile did not throw an error, but the test file was not created.")
			}

			if err := os.Remove(test.destination); err != nil {
				t.Error("Unable to clean up after running CopyFile tests. " + err.Error())
			}
		}
	}
}

func TestCopyDirectory(t *testing.T) {
	var badSourceDirectory = "./TestFiles/BadSourceFolder"
	var goodSourceDirectory = "./TestFiles/OtherFiles"
	var goodDestinationDirectory = "./TestFiles/TextFilesCopy"

	var tests = []struct {
		source       string
		destination  string
		shouldAssert bool
	}{
		{"", goodDestinationDirectory, false},
		{goodSourceDirectory, "", false},
		{badSourceDirectory, goodDestinationDirectory, false},
		{goodSourceDirectory, goodDestinationDirectory, true},
	}

	var testsPassed = true
	for index, test := range tests {
		err := CopyDirectory(test.source, test.destination, true)
		if err != nil && test.shouldAssert == true {
			t.Errorf("Test %d failed but should have passed.", index)
			testsPassed = false
		} else if err == nil && test.shouldAssert == false {
			t.Errorf("Test %d passed but should have failed.", index)
			testsPassed = false
		}
	}

	if testsPassed {
		if _, err := os.Stat(goodDestinationDirectory); err != nil {
			t.Error("CopyDirectory test directory was not created.")
		}
	}

	if err := os.RemoveAll(goodDestinationDirectory); err != nil {
		t.Error("Unable to clean up after running CopyDirectory tests. " + err.Error())
	}
}

func TestIsEmpty(t *testing.T) {
	// I'm ignoring error checking because I'm assuming ioutil.TempDir is tested and working
	// is this bad practice?
	dir, _ := ioutil.TempDir("", "test")

	tests := []struct {
		dir      string
		expected bool
		pass     bool
	}{
		{"", false, false},
		{dir, true, true},
		{"TestFiles", false, true},
	}

	for _, test := range tests {
		result, err := IsEmpty(test.dir)
		if err != nil && test.pass {
			t.Error("IsEmpty errored", err)
		} else if err == nil && !test.pass {
			t.Error("IsEmpty should have erroed")
		}

		if result != test.expected {
			t.Errorf("Expected %t, Result was: %t", test.expected, result)
		}
	}
}

func TestRemoveDirContents(t *testing.T) {
	tests := []struct {
		testDir string
		tempDir string
		pass    bool
	}{
		{"./TestFiles/TextFiles", "./TestFiles/TextFilesCopy", true},
		{"", "", false},
	}

	for _, test := range tests {
		// Make a copy of the directory for testing
		if test.pass {
			err := CopyDirectory(test.testDir, test.tempDir, true)
			if err != nil {
				t.Error("Unabled to copy directory", err)
			}
		}

		// Remove all contents in TextFilesCopy
		err := RemoveDirContent(test.tempDir)
		if err != nil && test.pass {
			t.Error("Error Removing Directory Contents", err)
		} else if err == nil && !test.pass {
			t.Error("RemoveDirContents should have errored")
		}

		// Test if directory is empty
		empty, err := IsEmpty(test.tempDir)
		if err != nil && test.pass {
			t.Error("IsEmpty errored")
		} else if err == nil && !test.pass {
			t.Error("IsEmpty should have errored")
		}

		if !empty && test.pass {
			t.Error("RemoveDirContents Failed. Directory should be empty")
		}

		// Delete TextFilesCopy
		os.RemoveAll(test.tempDir)
	}

}
<commit_msg>add error handling to test<commit_after>package fsutil

import (
	"io/ioutil"
	"os"
	"testing"
)

func TestCheckIfCompressed(t *testing.T) {
	var compressedZipFile = "./TestFiles/ZipFiles/test.zip"
	var uncompressedZipFile = "./TestFiles/OtherFiles/othertestfile.txt"

	var tests = []struct {
		source       string
		shouldAssert bool
	}{
		{compressedZipFile, true},
		{uncompressedZipFile, false},
	}

	for _, test := range tests {
		f, err := os.Open(test.source)
		if err != nil {
			t.Error("Error opening file", err)
		}
		r := CheckIfCompressed(f)
		if r != test.shouldAssert {
			t.Errorf("Test should of returned %v but returned %v instead", test.shouldAssert, r)
		}
	}

}

func TestCopyFile(t *testing.T) {
	var badSourceFile = "./TestFiles/FGFailedSourceFileLocation.fg"
	var badDestinationFile = "./TestFiles/NonexistantDirectory/FGFailedDestFileLocation.fg"
	var goodSourceFile = "./TestFiles/OtherFiles/othertestfile.txt"
	var goodDestinationFile = "./TestFiles/OtherFiles/othertestfile_copy.txt"
	var symlinkSourceFile = "./TestFiles/OtherFiles/TestSubdirectory/TextFiles"
	var symlinkDestinationFile = "./TestFiles/OtherFiles/TestSubdirectory/TextFilesCopy"

	var tests = []struct {
		source       string
		destination  string
		shouldAssert bool
	}{
		{"", goodDestinationFile, false},
		{goodSourceFile, "", false},
		{badSourceFile, goodDestinationFile, false},
		{goodSourceFile, badDestinationFile, false},
		{goodSourceFile, goodDestinationFile, true},
		{symlinkSourceFile, symlinkDestinationFile, true},
	}

	for index, test := range tests {
		err := CopyFile(test.source, test.destination)
		if err != nil && test.shouldAssert == true {
			t.Errorf("Test %d failed but should have passed. "+err.Error(), index)
		} else if err == nil && test.shouldAssert == false {
			t.Errorf("Test %d passed but should have failed.", index)
		} else if err == nil && test.shouldAssert == true {
			if _, err := os.Stat(test.source); err != nil {
				t.Error("CopyFile did not throw an error, but the test file was not created.")
			}

			if err := os.Remove(test.destination); err != nil {
				t.Error("Unable to clean up after running CopyFile tests. " + err.Error())
			}
		}
	}
}

func TestCopyDirectory(t *testing.T) {
	var badSourceDirectory = "./TestFiles/BadSourceFolder"
	var goodSourceDirectory = "./TestFiles/OtherFiles"
	var goodDestinationDirectory = "./TestFiles/TextFilesCopy"

	var tests = []struct {
		source       string
		destination  string
		shouldAssert bool
	}{
		{"", goodDestinationDirectory, false},
		{goodSourceDirectory, "", false},
		{badSourceDirectory, goodDestinationDirectory, false},
		{goodSourceDirectory, goodDestinationDirectory, true},
	}

	var testsPassed = true
	for index, test := range tests {
		err := CopyDirectory(test.source, test.destination, true)
		if err != nil && test.shouldAssert == true {
			t.Errorf("Test %d failed but should have passed.", index)
			testsPassed = false
		} else if err == nil && test.shouldAssert == false {
			t.Errorf("Test %d passed but should have failed.", index)
			testsPassed = false
		}
	}

	if testsPassed {
		if _, err := os.Stat(goodDestinationDirectory); err != nil {
			t.Error("CopyDirectory test directory was not created.")
		}
	}

	if err := os.RemoveAll(goodDestinationDirectory); err != nil {
		t.Error("Unable to clean up after running CopyDirectory tests. " + err.Error())
	}
}

func TestIsEmpty(t *testing.T) {
	dir, err := ioutil.TempDir("", "test")
	if err != nil {
		t.Error("Error creating temp file", err)
	}

	tests := []struct {
		dir      string
		expected bool
		pass     bool
	}{
		{"", false, false},
		{dir, true, true},
		{"TestFiles", false, true},
	}

	for _, test := range tests {
		result, err := IsEmpty(test.dir)
		if err != nil && test.pass {
			t.Error("IsEmpty errored", err)
		} else if err == nil && !test.pass {
			t.Error("IsEmpty should have erroed")
		}

		if result != test.expected {
			t.Errorf("Expected %t, Result was: %t", test.expected, result)
		}
	}
}

func TestRemoveDirContents(t *testing.T) {
	tests := []struct {
		testDir string
		tempDir string
		pass    bool
	}{
		{"./TestFiles/TextFiles", "./TestFiles/TextFilesCopy", true},
		{"", "", false},
	}

	for _, test := range tests {
		// Make a copy of the directory for testing
		if test.pass {
			err := CopyDirectory(test.testDir, test.tempDir, true)
			if err != nil {
				t.Error("Unabled to copy directory", err)
			}
		}

		// Remove all contents in TextFilesCopy
		err := RemoveDirContent(test.tempDir)
		if err != nil && test.pass {
			t.Error("Error Removing Directory Contents", err)
		} else if err == nil && !test.pass {
			t.Error("RemoveDirContents should have errored")
		}

		// Test if directory is empty
		empty, err := IsEmpty(test.tempDir)
		if err != nil && test.pass {
			t.Error("IsEmpty errored")
		} else if err == nil && !test.pass {
			t.Error("IsEmpty should have errored")
		}

		if !empty && test.pass {
			t.Error("RemoveDirContents Failed. Directory should be empty")
		}

		// Delete TextFilesCopy
		os.RemoveAll(test.tempDir)
	}

}
<|endoftext|>


<commit_before>package main // import "github.com/mvanholsteijn/paas-monitor"

import (
    "os"
    "fmt"
    "strings"
    "net/http"
    "encoding/json"
)

func environmentHandler(w http.ResponseWriter, r *http.Request) {
    var variables map[string]string
    variables = make(map[string]string)

    for _, e := range os.Environ() {
        pair := strings.Split(e, "=")
	variables[pair[0]] = pair[1]
    }

    js, err := json.Marshal(variables)
    if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
    }

    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

var (
    count = 0
)

func statusHandler(w http.ResponseWriter, r *http.Request) {
    var variables map[string]string

    hostName, _ := os.Hostname()
    port := os.Getenv("PORT")
    release := os.Getenv("RELEASE")
    message := os.Getenv("MESSAGE")
    if message == "" {
       message = "Hello World"
    }

    count = count + 1

    variables = make(map[string]string)
    variables["key"] = fmt.Sprintf("%s:%s", hostName, port)
    variables["release"] = release
    variables["servercount"] = fmt.Sprintf("%d", count)
    variables["message"] = fmt.Sprintf("%s from release %s; server call count is %d", message, release, count)

    js, err := json.Marshal(variables)
    if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
    }
    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

func main() {
    var dir string

    dir = os.Getenv("APPDIR")
    if dir == "" {
	dir = "."
    }
    fs := http.FileServer(http.Dir( dir + "/public"))

    http.Handle("/", fs)
    http.HandleFunc("/environment", environmentHandler)
    http.HandleFunc("/status", statusHandler)

    if os.Getenv("MESOS_TASK_ID") != "" {
        // Mesos sets PORT to the external Port :-) Grrrrr
	os.Setenv("PORT", "1337")
    }

    var addr string
    port := os.Getenv("PORT")
    if port != "" {
	addr = ":" + port
    } else {
	addr = ":1337"
	os.Setenv("PORT", "1337")
    }

    http.ListenAndServe(addr, nil)
}
<commit_msg>header requests<commit_after>package main // import "github.com/mvanholsteijn/paas-monitor"

import (
    "os"
    "fmt"
    "strings"
    "net/http"
    "encoding/json"
)

func environmentHandler(w http.ResponseWriter, r *http.Request) {
    var variables map[string]string
    variables = make(map[string]string)

    for _, e := range os.Environ() {
        pair := strings.Split(e, "=")
	variables[pair[0]] = pair[1]
    }

    js, err := json.Marshal(variables)
    if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
    }

    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

func headerHandler(w http.ResponseWriter, r *http.Request) {

    js, err := json.Marshal(r.Header)
    if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
    }

    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}
var (
    count = 0
)

func statusHandler(w http.ResponseWriter, r *http.Request) {
    var variables map[string]string

    hostName, _ := os.Hostname()
    port := os.Getenv("PORT")
    release := os.Getenv("RELEASE")
    message := os.Getenv("MESSAGE")
    if message == "" {
       message = "Hello World"
    }

    count = count + 1

    variables = make(map[string]string)
    variables["key"] = fmt.Sprintf("%s:%s", hostName, port)
    variables["release"] = release
    variables["servercount"] = fmt.Sprintf("%d", count)
    variables["message"] = fmt.Sprintf("%s from release %s; server call count is %d", message, release, count)

    js, err := json.Marshal(variables)
    if err != nil {
	http.Error(w, err.Error(), http.StatusInternalServerError)
	return
    }
    w.Header().Set("Content-Type", "application/json")
    w.Write(js)
}

func main() {
    var dir string

    dir = os.Getenv("APPDIR")
    if dir == "" {
	dir = "."
    }
    fs := http.FileServer(http.Dir( dir + "/public"))

    http.Handle("/", fs)
    http.HandleFunc("/environment", environmentHandler)
    http.HandleFunc("/status", statusHandler)
    http.HandleFunc("/header", headerHandler)

    if os.Getenv("MESOS_TASK_ID") != "" {
        // Mesos sets PORT to the external Port :-) Grrrrr
	os.Setenv("PORT", "1337")
    }

    var addr string
    port := os.Getenv("PORT")
    if port != "" {
	addr = ":" + port
    } else {
	addr = ":1337"
	os.Setenv("PORT", "1337")
    }

    http.ListenAndServe(addr, nil)
}
<|endoftext|>


<commit_before>package service

import (
	"net/http"
	"path/filepath"

	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/db/schema"
	"github.com/materials-commons/mcstore/pkg/domain"
	"github.com/materials-commons/mcstore/pkg/ws"
)

// dataHandler implements the http.Handler interface. It provides an interface
// to serving up data stored in materials commons.
type dataHandler struct {
	access domain.Access
}

// NewDataHandler creates a new instance of a dataHandler.
func NewDataHandler(access domain.Access) http.Handler {
	return &dataHandler{
		access: access,
	}
}

// ServeHTTP serves data stored in materials commons.
func (h *dataHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	path, mediaType, err := h.serveData(writer, req)
	switch {
	case err != nil:
		ws.WriteError(err, writer)
	default:
		serveFile(writer, req, path, mediaType)
	}
}

// serveFile serves up the actual file contents. It sets the content-type header to
// the mediatype specified. If the file doesn't exist, or the server doesn't have
// permissions to access the file then a 404 (not found) will be returned by the
// http.ServeFile method.
func serveFile(writer http.ResponseWriter, req *http.Request, path, mediatype string) {
	writer.Header().Set("Content-Type", mediatype)
	app.Log.Debug(app.Logf("Set Content-Type to %s", mediatype))
	http.ServeFile(writer, req, path)
}

// serveData does the actual work of serving the data. It checks the access on each
// request. It will also serve up converted images unless the original flag has been
// specified. The assumption is that without the original flag we are actually trying
// to render an image in a browser. Since browsers do not render all image types we
// convert some types to jpg files. This routine will serve up these jpg conversions
// rather than the original file unless the original flag is specified.
func (h *dataHandler) serveData(writer http.ResponseWriter, req *http.Request) (path string, mediatype string, err error) {
	// All requests require an apikey.
	apikey := req.FormValue("apikey")
	if apikey == "" {
		return path, mediatype, app.ErrNoAccess
	}
	app.Log.Debug(app.Logf("serveData - Request for apikey %s", apikey))

	// Is the original data requested, or can we serve the converted
	// image data (if it exists)?
	original := getOriginalFormValue(req)
	app.Log.Debug(app.Logf("serveData - Original flag %s", original))

	fileID := filepath.Base(req.URL.Path)
	app.Log.Debug(app.Logf("serveData - fileID %s, URL %s", fileID, req.URL.Path))

	// Get the file checking its access.
	file, err := h.access.GetFile(apikey, fileID)
	if err != nil {
		return path, mediatype, err
	}

	path = filePath(file, original)
	app.Log.Debug(app.Logf("serveData - Serving path: %s\n", path))

	mediatype = file.MediaType.Mime

	// The content type is dependent on whether we are
	// serving the original or the converted file.
	if !original {
		mediatype = "image/jpeg"
	}

	return path, mediatype, nil
}

// getOriginalFormValue looks for the original argument on the URL. If it exists
// (has a value specified) then return true. The original flag specifies whether
// the user wants the original rather than the converted data.
func getOriginalFormValue(req *http.Request) bool {
	if req.FormValue("original") == "" {
		return false
	}
	return true
}

// filePath determines which file to serve. If there is a converted image we
// will serve that one up unless the original flag is set to true.
func filePath(file *schema.File, original bool) string {
	switch {
	case isConvertedImage(file.MediaType.Mime) && !original:
		return app.MCDir.FilePathImageConversion(file.FileID())
	default:
		return app.MCDir.FilePath(file.FileID())
	}
}

// isConvertedImage checks a name to see if it is an image type we have converted.
func isConvertedImage(mime string) bool {
	switch mime {
	case "image/tiff":
		return true
	case "image/x-ms-bmp":
		return true
	default:
		return false
	}
}
<commit_msg>Correct the logic for which content type is being served. Fix format statement in log entry.<commit_after>package service

import (
	"net/http"
	"path/filepath"

	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/db/schema"
	"github.com/materials-commons/mcstore/pkg/domain"
	"github.com/materials-commons/mcstore/pkg/ws"
)

// dataHandler implements the http.Handler interface. It provides an interface
// to serving up data stored in materials commons.
type dataHandler struct {
	access domain.Access
}

// NewDataHandler creates a new instance of a dataHandler.
func NewDataHandler(access domain.Access) http.Handler {
	return &dataHandler{
		access: access,
	}
}

// ServeHTTP serves data stored in materials commons.
func (h *dataHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
	path, mediaType, err := h.serveData(writer, req)
	switch {
	case err != nil:
		ws.WriteError(err, writer)
	default:
		serveFile(writer, req, path, mediaType)
	}
}

// serveFile serves up the actual file contents. It sets the content-type header to
// the mediatype specified. If the file doesn't exist, or the server doesn't have
// permissions to access the file then a 404 (not found) will be returned by the
// http.ServeFile method.
func serveFile(writer http.ResponseWriter, req *http.Request, path, mediatype string) {
	writer.Header().Set("Content-Type", mediatype)
	app.Log.Debug(app.Logf("Set Content-Type to %s", mediatype))
	http.ServeFile(writer, req, path)
}

// serveData does the actual work of serving the data. It checks the access on each
// request. It will also serve up converted images unless the original flag has been
// specified. The assumption is that without the original flag we are actually trying
// to render an image in a browser. Since browsers do not render all image types we
// convert some types to jpg files. This routine will serve up these jpg conversions
// rather than the original file unless the original flag is specified.
func (h *dataHandler) serveData(writer http.ResponseWriter, req *http.Request) (path string, mediatype string, err error) {
	// All requests require an apikey.
	apikey := req.FormValue("apikey")
	if apikey == "" {
		return path, mediatype, app.ErrNoAccess
	}
	app.Log.Debug(app.Logf("serveData - Request for apikey %s", apikey))

	// Is the original data requested, or can we serve the converted
	// image data (if it exists)?
	original := getOriginalFormValue(req)
	app.Log.Debug(app.Logf("serveData - Original flag %t", original))

	fileID := filepath.Base(req.URL.Path)
	app.Log.Debug(app.Logf("serveData - fileID %s, URL %s", fileID, req.URL.Path))

	// Get the file checking its access.
	file, err := h.access.GetFile(apikey, fileID)
	if err != nil {
		return path, mediatype, err
	}

	path = filePath(file, original)
	app.Log.Debug(app.Logf("serveData - Serving path: %s\n", path))

	mediatype = file.MediaType.Mime

	// The content type is dependent on whether we are
	// serving the original or the converted file.
	if !original && isConvertedImage(file.MediaType.Mime) {
		mediatype = "image/jpeg"
	}

	return path, mediatype, nil
}

// getOriginalFormValue looks for the original argument on the URL. If it exists
// (has a value specified) then return true. The original flag specifies whether
// the user wants the original rather than the converted data.
func getOriginalFormValue(req *http.Request) bool {
	if req.FormValue("original") == "" {
		return false
	}
	return true
}

// filePath determines which file to serve. If there is a converted image we
// will serve that one up unless the original flag is set to true.
func filePath(file *schema.File, original bool) string {
	switch {
	case isConvertedImage(file.MediaType.Mime) && !original:
		return app.MCDir.FilePathImageConversion(file.FileID())
	default:
		return app.MCDir.FilePath(file.FileID())
	}
}

// isConvertedImage checks a name to see if it is an image type we have converted.
func isConvertedImage(mime string) bool {
	switch mime {
	case "image/tiff":
		return true
	case "image/x-ms-bmp":
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package docker

import (
	"fmt"
	"log"
	"os"
	"testing"

	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/koding/kite"
)

var (
	d      *kite.Kite
	remote *kite.Client
)

func init() {
	d = kite.New("docker", "0.0.1")
	d.Config.DisableAuthentication = true
	d.Config.Port = 3636

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "tcp://192.168.59.103:2376" // darwin, boot2docker
	}

	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
	if dockerCertPath == "" {
		panic("please set DOCKER_CERT_PATH")
	}

	certFile := dockerCertPath + "/cert.pem"
	keyFile := dockerCertPath + "/key.pem"
	caFile := dockerCertPath + "/ca.pem"

	client, _ := dockerclient.NewTLSClient(dockerHost, certFile, keyFile, caFile)
	dock := &Docker{
		client: client,
	}

	d.HandleFunc("list", dock.List)

	go d.Run()
	<-d.ServerReadyNotify()

	remote = d.NewClient("http://127.0.0.1:3636/kite")
	err := remote.Dial()
	if err != nil {
		log.Fatal("err")
	}
}

func TestList(t *testing.T) {
	resp, err := remote.Tell("list")
	if err != nil {
		t.Fatal(err)
	}

	var containers []dockerclient.APIContainers

	err = resp.Unmarshal(&containers)
	if err != nil {
		t.Error(err)
	}

	fmt.Printf("len(containers) %+v\n", len(containers))
	fmt.Printf("containers %+v\n", containers)
}
<commit_msg>docker: print the names<commit_after>package docker

import (
	"fmt"
	"log"
	"os"
	"testing"

	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/koding/kite"
)

var (
	d      *kite.Kite
	remote *kite.Client
)

func init() {
	d = kite.New("docker", "0.0.1")
	d.Config.DisableAuthentication = true
	d.Config.Port = 3636

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "tcp://192.168.59.103:2376" // darwin, boot2docker
	}

	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
	if dockerCertPath == "" {
		panic("please set DOCKER_CERT_PATH")
	}

	certFile := dockerCertPath + "/cert.pem"
	keyFile := dockerCertPath + "/key.pem"
	caFile := dockerCertPath + "/ca.pem"

	client, _ := dockerclient.NewTLSClient(dockerHost, certFile, keyFile, caFile)
	dock := &Docker{
		client: client,
	}

	d.HandleFunc("list", dock.List)

	go d.Run()
	<-d.ServerReadyNotify()

	remote = d.NewClient("http://127.0.0.1:3636/kite")
	err := remote.Dial()
	if err != nil {
		log.Fatal("err")
	}
}

func TestList(t *testing.T) {
	resp, err := remote.Tell("list")
	if err != nil {
		t.Fatal(err)
	}

	var containers []dockerclient.APIContainers

	err = resp.Unmarshal(&containers)
	if err != nil {
		t.Error(err)
	}

	fmt.Printf("len(containers) %+v\n", len(containers))
	for _, container := range containers {
		image := container.Image
		fmt.Printf("image %+v\n", image)
	}
}
<|endoftext|>


<commit_before>package octorrent

import (
	"bytes"
	"testing"
)

func TestReadInt(t testing.T) {
	const in, out = "412e51", 412
	buf := bytes.NewBufferString(in)
	dec := decoder{
		*buf,
	}

	out, err := dec.readInt()
	if err != nil {
		t.Errorf("readInt returned error: %s", err)
	}

	if out != in {
		t.Errorf("readInt should return %i, but did return %i", in, out)
	}
}
<commit_msg>Add TestReadString, getDecoder()<commit_after>package octorrent

import (
	"bytes"
	"testing"
)

func getDecoder(d []byte) decoder {
	buf := bytes.NewBuffer(d)

	return decoder{
		*buf,
	}
}

func TestReadInt(t *testing.T) {
	const i, o = "412e51", 412
	dec := getDecoder([]byte(i))

	num, err := dec.readInt()
	if err != nil {
		t.Errorf("readInt returned error: %s", err)
	}

	if num != o {
		t.Errorf("readInt did return %i, but should return %i", num, out)
	}
}

func TestReadString(t *testing.T) {
	const i, o = "4:testfoobar", "test"
	dec := getDecoder([]byte(i))

	str, err := dec.readString()
	if err != nil {
		t.Errorf("readString returned error: %s", err)
	}

	if str != o {
		t.Errorf("readString returned %s, but should return %s", str, o)
	}
}
<|endoftext|>


<commit_before>package gomposer

import (
	"fmt"

	"net/http"
	"net/http/httptest"
	// "reflect"
	"testing"
)

func getMuxAndServer() (*http.ServeMux, *httptest.Server) {

	mux := http.NewServeMux()
	server := httptest.NewServer(mux)

	return mux, server
}

func TestPackageRepository_Find(t *testing.T) {

	mux, server := getMuxAndServer()
	apiHit := false
	mux.HandleFunc("/phpunit.json", func(w http.ResponseWriter, r *http.Request) {
		if m := "GET"; m != r.Method {
			t.Errorf("Request method = %v, expected %v", r.Method, m)
		}
		fmt.Fprint(w, `{"name":"phpunit/phpunit"}`)
		apiHit = true
	})

	hc := getHttpClient(server)
	packageRepo := PackageRepository{client: hc}
	pkg, err := packageRepo.Find("phpunit")

	if err != nil {
		t.Errorf("Didn't expect an error but got '%s'", err)
	}

	if apiHit == false {
		t.Errorf("Didn't hit api")
	}
	expectedName := "phpunit/phpunit"
	if pkg.Name != expectedName {
		t.Errorf("Expected '%s' but got '%s'", expectedName, pkg.Name)
	}

	server.Close()
}
<commit_msg>Refactor package test<commit_after>package gomposer

import (
	"fmt"

	"net/http"
	"net/http/httptest"
	// "reflect"
	"testing"
)

func getMuxAndServer() (*http.ServeMux, *httptest.Server) {

	mux := http.NewServeMux()
	server := httptest.NewServer(mux)

	return mux, server
}

func TestPackageRepository_Find(t *testing.T) {

	mux, server := getMuxAndServer()
	apiHit := false
	mux.HandleFunc("/phpunit/phpunit.json", func(w http.ResponseWriter, r *http.Request) {
		if m := "GET"; m != r.Method {
			t.Errorf("Request method = %v, expected %v", r.Method, m)
		}
		fmt.Fprint(w, `{"name":"phpunit/phpunit"}`)
		apiHit = true
	})

	hc := getHttpClient(server)
	packageRepo := PackageRepository{client: hc}
	pkg, err := packageRepo.Find("phpunit/phpunit")

	if err != nil {
		t.Errorf("Didn't expect an error but got '%s'", err)
	}

	if apiHit == false {
		t.Errorf("Didn't hit api")
	}
	expectedName := "phpunit/phpunit"
	if pkg.Name != expectedName {
		t.Errorf("Expected '%s' but got '%s'", expectedName, pkg.Name)
	}

	server.Close()
}
<|endoftext|>


<commit_before>package typhon

import (
	"bufio"
	"context"
	"net"
	"net/http"
	"net/textproto"
	"sync"

	"github.com/monzo/terrors"
	"golang.org/x/net/http/httpguts"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
)

// H2cFilter adds HTTP/2 h2c upgrade support to the wrapped Service (as defined in RFC 7540 §3.2, §3.4).
func H2cFilter(req Request, svc Service) Response {
	h := req.Header
	// h2c with prior knowledge (RFC 7540 Section 3.4)
	isPrior := (req.Method == "PRI" && len(h) == 0 && req.URL.Path == "*" && req.Proto == "HTTP/2.0")
	// h2c upgrade (RFC 7540 Section 3.2)
	isUpgrade := httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
		httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
	if isPrior || isUpgrade {
		rsp := NewResponse(req)
		rw, h2s, err := setupH2cHijacker(req, rsp.Writer())
		if err != nil {
			return Response{Error: err}
		}
		h2c.NewHandler(HttpHandler(svc), h2s).ServeHTTP(rw, &req.Request)
		return rsp
	}
	return svc(req)
}

// Dear reader: I'm sorry, the code below isn't fun. This is because Go's h2c implementation doesn't have support for
// connection draining, and all the hooks that make would make this easy are unexported.
//
// If this ticket gets resolved this code can be dramatically simplified, but it is not a priority for the Go team:
// https://github.com/golang/go/issues/26682
//
// 🤢

var h2cConns sync.Map // map[*Server]*h2cInfo

// h2cInfo stores information about connections that have been upgraded by a single Typhon server
type h2cInfo struct {
	sync.Mutex
	conns []*hijackedConn
	h2s   *http2.Server
}

// hijackedConn represents a network connection that has been hijacked for a h2c upgrade. This is necessary because we
// need to know when the connection has been closed, to know if/when graceful shutdown completes.
type hijackedConn struct {
	net.Conn
	closed    chan struct{}
	closeOnce sync.Once
}

func (c *hijackedConn) Close() error {
	defer c.closeOnce.Do(func() { close(c.closed) })
	return c.Conn.Close()
}

type h2cHijacker struct {
	http.ResponseWriter
	http.Hijacker
	hijacked func(*hijackedConn)
}

func (h h2cHijacker) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	c, r, err := h.Hijacker.Hijack()
	conn := &hijackedConn{
		Conn:   c,
		closed: make(chan struct{})}
	h.hijacked(conn)
	return conn, r, err
}

func shutdownH2c(ctx context.Context, srv *Server) {
	_h2c, ok := h2cConns.Load(srv)
	if !ok {
		return
	}
	h2c := _h2c.(*h2cInfo)
	h2c.Lock()
	defer h2c.Unlock()

gracefulCloseLoop:
	for _, c := range h2c.conns {
		select {
		case <-ctx.Done():
			break gracefulCloseLoop
		case <-c.closed:
			h2c.conns = h2c.conns[1:]
		}
	}
	// If any connections remain after gracefulCloseLoop, we need to forcefully close them
	for _, c := range h2c.conns {
		c.Close()
		h2c.conns = h2c.conns[1:]
	}
	h2cConns.Delete(srv)
}

func setupH2cHijacker(req Request, rw http.ResponseWriter) (http.ResponseWriter, *http2.Server, error) {
	hijacker, ok := rw.(http.Hijacker)
	if !ok {
		err := terrors.InternalService("hijack_impossible", "Cannot hijack response; h2c upgrade impossible", nil)
		return nil, nil, err
	}
	srv := req.server
	if srv == nil {
		return rw, &http2.Server{}, nil
	}

	h2c := &h2cInfo{
		h2s: &http2.Server{}}
	_h2c, loaded := h2cConns.LoadOrStore(srv, h2c)
	h2c = _h2c.(*h2cInfo)
	if !loaded {
		// http2.ConfigureServer wires up an unexported method within the http2 library so it gracefully drains h2c
		// connections when the http1 server is stopped. However, this happens asynchronously: the http1 server will
		// think it has shut down before the h2c connections have finished draining. To work around this, we add
		// a shutdown function of our own in the Typhon server which waits for connections to be drained, or if things
		// timeout before then to terminate them forcefully.
		http2.ConfigureServer(srv.srv, h2c.h2s)
		srv.addShutdownFunc(func(ctx context.Context) {
			shutdownH2c(ctx, srv)
		})
	}

	h := h2cHijacker{
		ResponseWriter: rw,
		Hijacker:       hijacker,
		hijacked: func(c *hijackedConn) {
			h2c.Lock()
			defer h2c.Unlock()
			h2c.conns = append(h2c.conns, c)
		}}
	return h, h2c.h2s, nil
}
<commit_msg>Remove connections from h2cInfo when they are closed 💨<commit_after>package typhon

import (
	"bufio"
	"context"
	"net"
	"net/http"
	"net/textproto"
	"sync"

	"github.com/deckarep/golang-set"
	"github.com/monzo/terrors"
	"golang.org/x/net/http/httpguts"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
)

// H2cFilter adds HTTP/2 h2c upgrade support to the wrapped Service (as defined in RFC 7540 §3.2, §3.4).
func H2cFilter(req Request, svc Service) Response {
	h := req.Header
	// h2c with prior knowledge (RFC 7540 Section 3.4)
	isPrior := (req.Method == "PRI" && len(h) == 0 && req.URL.Path == "*" && req.Proto == "HTTP/2.0")
	// h2c upgrade (RFC 7540 Section 3.2)
	isUpgrade := httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Upgrade")], "h2c") &&
		httpguts.HeaderValuesContainsToken(h[textproto.CanonicalMIMEHeaderKey("Connection")], "HTTP2-Settings")
	if isPrior || isUpgrade {
		rsp := NewResponse(req)
		rw, h2s, err := setupH2cHijacker(req, rsp.Writer())
		if err != nil {
			return Response{Error: err}
		}
		h2c.NewHandler(HttpHandler(svc), h2s).ServeHTTP(rw, &req.Request)
		return rsp
	}
	return svc(req)
}

// Dear reader: I'm sorry, the code below isn't fun. This is because Go's h2c implementation doesn't have support for
// connection draining, and all the hooks that make would make this easy are unexported.
//
// If this ticket gets resolved this code can be dramatically simplified, but it is not a priority for the Go team:
// https://github.com/golang/go/issues/26682
//
// 🤢

var h2cConns sync.Map // map[*Server]*h2cInfo

// h2cInfo stores information about connections that have been upgraded by a single Typhon server
type h2cInfo struct {
	conns mapset.Set
	h2s   *http2.Server
}

// hijackedConn represents a network connection that has been hijacked for a h2c upgrade. This is necessary because we
// need to know when the connection has been closed, to know if/when graceful shutdown completes.
type hijackedConn struct {
	net.Conn
	onClose   func(*hijackedConn)
	closed    chan struct{}
	closeOnce sync.Once
}

func (c *hijackedConn) Close() error {
	defer c.closeOnce.Do(func() {
		close(c.closed)
		c.onClose(c)
	})
	return c.Conn.Close()
}

type h2cHijacker struct {
	http.ResponseWriter
	http.Hijacker
	onHijack func(*hijackedConn)
}

func (h h2cHijacker) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	c, r, err := h.Hijacker.Hijack()
	conn := &hijackedConn{
		Conn:   c,
		closed: make(chan struct{})}
	h.onHijack(conn)
	return conn, r, err
}

func shutdownH2c(ctx context.Context, srv *Server, h2c *h2cInfo) {
gracefulCloseLoop:
	for _, _c := range h2c.conns.ToSlice() {
		c := _c.(*hijackedConn)
		select {
		case <-ctx.Done():
			break gracefulCloseLoop
		case <-c.closed:
			h2c.conns.Remove(c)
		}
	}
	// If any connections remain after gracefulCloseLoop, we need to forcefully close them
	for _, _c := range h2c.conns.ToSlice() {
		c := _c.(*hijackedConn)
		c.Close()
		h2c.conns.Remove(c)
	}
	h2cConns.Delete(srv)
}

func setupH2cHijacker(req Request, rw http.ResponseWriter) (http.ResponseWriter, *http2.Server, error) {
	hijacker, ok := rw.(http.Hijacker)
	if !ok {
		err := terrors.InternalService("hijack_impossible", "Cannot hijack response; h2c upgrade impossible", nil)
		return nil, nil, err
	}
	srv := req.server
	if srv == nil {
		return rw, &http2.Server{}, nil
	}

	h2c := &h2cInfo{
		conns: mapset.NewSet(),
		h2s:   &http2.Server{}}
	_h2c, loaded := h2cConns.LoadOrStore(srv, h2c)
	h2c = _h2c.(*h2cInfo)
	if !loaded {
		// http2.ConfigureServer wires up an unexported method within the http2 library so it gracefully drains h2c
		// connections when the http1 server is stopped. However, this happens asynchronously: the http1 server will
		// think it has shut down before the h2c connections have finished draining. To work around this, we add
		// a shutdown function of our own in the Typhon server which waits for connections to be drained, or if things
		// timeout before then to terminate them forcefully.
		http2.ConfigureServer(srv.srv, h2c.h2s)
		srv.addShutdownFunc(func(ctx context.Context) {
			shutdownH2c(ctx, srv, h2c)
		})
	}

	h := h2cHijacker{
		ResponseWriter: rw,
		Hijacker:       hijacker,
		onHijack: func(c *hijackedConn) {
			h2c.conns.Add(c)
			// when the connection closes, remove from h2cInfo's to prevent refs to dead connections accumulating
			c.onClose = func(c *hijackedConn) {
				h2c.conns.Remove(c)
			}
		}}
	return h, h2c.h2s, nil
}
<|endoftext|>