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

package plan

import (
	"bytes"
	"fmt"

	"github.com/pingcap/tidb/expression"
	"github.com/pingcap/tidb/expression/aggregation"
)

func setParents4FinalPlan(plan PhysicalPlan) {
	allPlans := []PhysicalPlan{plan}
	planMark := map[int]bool{}
	planMark[plan.ID()] = true
	for pID := 0; pID < len(allPlans); pID++ {
		allPlans[pID].SetParents()
		switch copPlan := allPlans[pID].(type) {
		case *PhysicalTableReader:
			setParents4FinalPlan(copPlan.tablePlan)
		case *PhysicalIndexReader:
			setParents4FinalPlan(copPlan.indexPlan)
		case *PhysicalIndexLookUpReader:
			setParents4FinalPlan(copPlan.indexPlan)
			setParents4FinalPlan(copPlan.tablePlan)
		}
		for _, p := range allPlans[pID].Children() {
			if !planMark[p.ID()] {
				allPlans = append(allPlans, p.(PhysicalPlan))
				planMark[p.ID()] = true
			}
		}
	}

	allPlans = allPlans[0:1]
	planMark[plan.ID()] = false
	for pID := 0; pID < len(allPlans); pID++ {
		for _, p := range allPlans[pID].Children() {
			p.SetParents(allPlans[pID])
			if planMark[p.ID()] {
				planMark[p.ID()] = false
				allPlans = append(allPlans, p.(PhysicalPlan))
			}
		}
	}
}

// ExplainInfo implements PhysicalPlan interface.
func (p *SelectLock) ExplainInfo() string {
	return p.Lock.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexScan) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	tblName := p.Table.Name.O
	if p.TableAsName != nil && p.TableAsName.O != "" {
		tblName = p.TableAsName.O
	}
	buffer.WriteString(fmt.Sprintf("table:%s", tblName))
	if len(p.Index.Columns) > 0 {
		buffer.WriteString(", index:")
		for i, idxCol := range p.Index.Columns {
			buffer.WriteString(idxCol.Name.O)
			if i+1 < len(p.Index.Columns) {
				buffer.WriteString(", ")
			}
		}
	}
	if len(p.Ranges) > 0 {
		buffer.WriteString(", range:")
		for i, idxRange := range p.Ranges {
			buffer.WriteString(idxRange.String())
			if i+1 < len(p.Ranges) {
				buffer.WriteString(", ")
			}
		}
	}
	buffer.WriteString(fmt.Sprintf(", out of order:%v", p.OutOfOrder))
	if p.Desc {
		buffer.WriteString(", desc")
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalTableScan) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	tblName := p.Table.Name.O
	if p.TableAsName != nil && p.TableAsName.O != "" {
		tblName = p.TableAsName.O
	}
	buffer.WriteString(fmt.Sprintf("table:%s", tblName))
	if p.pkCol != nil {
		buffer.WriteString(fmt.Sprintf(", pk col:%s", p.pkCol.ExplainInfo()))
	}
	if len(p.Ranges) > 0 {
		buffer.WriteString(", range:")
		for i, idxRange := range p.Ranges {
			buffer.WriteString(idxRange.String())
			if i+1 < len(p.Ranges) {
				buffer.WriteString(", ")
			}
		}
	}
	buffer.WriteString(fmt.Sprintf(", keep order:%v", p.KeepOrder))
	if p.Desc {
		buffer.WriteString(", desc")
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalTableReader) ExplainInfo() string {
	return fmt.Sprintf("data:%s", p.tablePlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexReader) ExplainInfo() string {
	return fmt.Sprintf("index:%s", p.indexPlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexLookUpReader) ExplainInfo() string {
	return fmt.Sprintf("index:%s, table:%s", p.indexPlan.ExplainID(), p.tablePlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalUnionScan) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Conditions))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalSelection) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Conditions))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Projection) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Exprs))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *TableDual) ExplainInfo() string {
	return fmt.Sprintf("rows:%v", p.RowCount)
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Sort) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	for i, item := range p.ByItems {
		order := "asc"
		if item.Desc {
			order = "desc"
		}
		buffer.WriteString(fmt.Sprintf("%s:%s", item.Expr.ExplainInfo(), order))
		if i+1 < len(p.ByItems) {
			buffer.WriteString(", ")
		}
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Limit) ExplainInfo() string {
	return fmt.Sprintf("offset:%v, count:%v", p.Offset, p.Count)
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalAggregation) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("type:%s", p.AggType))
	if len(p.GroupByItems) > 0 {
		buffer.WriteString(fmt.Sprintf(", group by:%s",
			expression.ExplainExpressionList(p.GroupByItems)))
	}
	buffer.WriteString(", funcs:")
	for i, agg := range p.AggFuncs {
		buffer.WriteString(aggregation.ExplainAggFunc(agg))
		if i+1 < len(p.AggFuncs) {
			buffer.WriteString(", ")
		}
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalApply) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.PhysicalJoin.ExplainInfo())
	buffer.WriteString(fmt.Sprintf(", right:%s", p.Children()[1].ExplainID()))
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("outer:%s",
		p.Children()[p.OuterIndex].ExplainID()))
	buffer.WriteString(fmt.Sprintf(", %s", p.JoinType))
	if len(p.OuterJoinKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", outer key:%s",
			expression.ExplainColumnList(p.OuterJoinKeys)))
	}
	if len(p.InnerJoinKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", inner key:%s",
			expression.ExplainColumnList(p.InnerJoinKeys)))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s",
			expression.ExplainExpressionList(p.LeftConditions)))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalHashJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.JoinType.String())
	buffer.WriteString(fmt.Sprintf(", small:%s", p.Children()[p.SmallChildIdx].ExplainID()))
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalHashSemiJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("right:%s", p.Children()[1].ExplainID()))
	if p.WithAux {
		buffer.WriteString(", aux")
	}
	if p.Anti {
		buffer.WriteString(", anti")
	}
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalMergeJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.JoinType.String())
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	if len(p.leftKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", left key:%s",
			expression.ExplainColumnList(p.leftKeys)))
	}
	if len(p.rightKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", right key:%s",
			expression.ExplainColumnList(p.rightKeys)))
	}
	return buffer.String()
}
<commit_msg>plan/explain: add explain info for topn. (#5287)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package plan

import (
	"bytes"
	"fmt"

	"github.com/pingcap/tidb/expression"
	"github.com/pingcap/tidb/expression/aggregation"
)

func setParents4FinalPlan(plan PhysicalPlan) {
	allPlans := []PhysicalPlan{plan}
	planMark := map[int]bool{}
	planMark[plan.ID()] = true
	for pID := 0; pID < len(allPlans); pID++ {
		allPlans[pID].SetParents()
		switch copPlan := allPlans[pID].(type) {
		case *PhysicalTableReader:
			setParents4FinalPlan(copPlan.tablePlan)
		case *PhysicalIndexReader:
			setParents4FinalPlan(copPlan.indexPlan)
		case *PhysicalIndexLookUpReader:
			setParents4FinalPlan(copPlan.indexPlan)
			setParents4FinalPlan(copPlan.tablePlan)
		}
		for _, p := range allPlans[pID].Children() {
			if !planMark[p.ID()] {
				allPlans = append(allPlans, p.(PhysicalPlan))
				planMark[p.ID()] = true
			}
		}
	}

	allPlans = allPlans[0:1]
	planMark[plan.ID()] = false
	for pID := 0; pID < len(allPlans); pID++ {
		for _, p := range allPlans[pID].Children() {
			p.SetParents(allPlans[pID])
			if planMark[p.ID()] {
				planMark[p.ID()] = false
				allPlans = append(allPlans, p.(PhysicalPlan))
			}
		}
	}
}

// ExplainInfo implements PhysicalPlan interface.
func (p *SelectLock) ExplainInfo() string {
	return p.Lock.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexScan) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	tblName := p.Table.Name.O
	if p.TableAsName != nil && p.TableAsName.O != "" {
		tblName = p.TableAsName.O
	}
	buffer.WriteString(fmt.Sprintf("table:%s", tblName))
	if len(p.Index.Columns) > 0 {
		buffer.WriteString(", index:")
		for i, idxCol := range p.Index.Columns {
			buffer.WriteString(idxCol.Name.O)
			if i+1 < len(p.Index.Columns) {
				buffer.WriteString(", ")
			}
		}
	}
	if len(p.Ranges) > 0 {
		buffer.WriteString(", range:")
		for i, idxRange := range p.Ranges {
			buffer.WriteString(idxRange.String())
			if i+1 < len(p.Ranges) {
				buffer.WriteString(", ")
			}
		}
	}
	buffer.WriteString(fmt.Sprintf(", out of order:%v", p.OutOfOrder))
	if p.Desc {
		buffer.WriteString(", desc")
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalTableScan) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	tblName := p.Table.Name.O
	if p.TableAsName != nil && p.TableAsName.O != "" {
		tblName = p.TableAsName.O
	}
	buffer.WriteString(fmt.Sprintf("table:%s", tblName))
	if p.pkCol != nil {
		buffer.WriteString(fmt.Sprintf(", pk col:%s", p.pkCol.ExplainInfo()))
	}
	if len(p.Ranges) > 0 {
		buffer.WriteString(", range:")
		for i, idxRange := range p.Ranges {
			buffer.WriteString(idxRange.String())
			if i+1 < len(p.Ranges) {
				buffer.WriteString(", ")
			}
		}
	}
	buffer.WriteString(fmt.Sprintf(", keep order:%v", p.KeepOrder))
	if p.Desc {
		buffer.WriteString(", desc")
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalTableReader) ExplainInfo() string {
	return fmt.Sprintf("data:%s", p.tablePlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexReader) ExplainInfo() string {
	return fmt.Sprintf("index:%s", p.indexPlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexLookUpReader) ExplainInfo() string {
	return fmt.Sprintf("index:%s, table:%s", p.indexPlan.ExplainID(), p.tablePlan.ExplainID())
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalUnionScan) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Conditions))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalSelection) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Conditions))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Projection) ExplainInfo() string {
	return string(expression.ExplainExpressionList(p.Exprs))
}

// ExplainInfo implements PhysicalPlan interface.
func (p *TableDual) ExplainInfo() string {
	return fmt.Sprintf("rows:%v", p.RowCount)
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Sort) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	for i, item := range p.ByItems {
		order := "asc"
		if item.Desc {
			order = "desc"
		}
		buffer.WriteString(fmt.Sprintf("%s:%s", item.Expr.ExplainInfo(), order))
		if i+1 < len(p.ByItems) {
			buffer.WriteString(", ")
		}
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *Limit) ExplainInfo() string {
	return fmt.Sprintf("offset:%v, count:%v", p.Offset, p.Count)
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalAggregation) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("type:%s", p.AggType))
	if len(p.GroupByItems) > 0 {
		buffer.WriteString(fmt.Sprintf(", group by:%s",
			expression.ExplainExpressionList(p.GroupByItems)))
	}
	buffer.WriteString(", funcs:")
	for i, agg := range p.AggFuncs {
		buffer.WriteString(aggregation.ExplainAggFunc(agg))
		if i+1 < len(p.AggFuncs) {
			buffer.WriteString(", ")
		}
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalApply) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.PhysicalJoin.ExplainInfo())
	buffer.WriteString(fmt.Sprintf(", right:%s", p.Children()[1].ExplainID()))
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalIndexJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("outer:%s",
		p.Children()[p.OuterIndex].ExplainID()))
	buffer.WriteString(fmt.Sprintf(", %s", p.JoinType))
	if len(p.OuterJoinKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", outer key:%s",
			expression.ExplainColumnList(p.OuterJoinKeys)))
	}
	if len(p.InnerJoinKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", inner key:%s",
			expression.ExplainColumnList(p.InnerJoinKeys)))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s",
			expression.ExplainExpressionList(p.LeftConditions)))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalHashJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.JoinType.String())
	buffer.WriteString(fmt.Sprintf(", small:%s", p.Children()[p.SmallChildIdx].ExplainID()))
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalHashSemiJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(fmt.Sprintf("right:%s", p.Children()[1].ExplainID()))
	if p.WithAux {
		buffer.WriteString(", aux")
	}
	if p.Anti {
		buffer.WriteString(", anti")
	}
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalMergeJoin) ExplainInfo() string {
	buffer := bytes.NewBufferString(p.JoinType.String())
	if len(p.EqualConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", equal:%s", p.EqualConditions))
	}
	if len(p.LeftConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", left cond:%s", p.LeftConditions))
	}
	if len(p.RightConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", right cond:%s",
			expression.ExplainExpressionList(p.RightConditions)))
	}
	if len(p.OtherConditions) > 0 {
		buffer.WriteString(fmt.Sprintf(", other cond:%s",
			expression.ExplainExpressionList(p.OtherConditions)))
	}
	if len(p.leftKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", left key:%s",
			expression.ExplainColumnList(p.leftKeys)))
	}
	if len(p.rightKeys) > 0 {
		buffer.WriteString(fmt.Sprintf(", right key:%s",
			expression.ExplainColumnList(p.rightKeys)))
	}
	return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *TopN) ExplainInfo() string {
	buffer := bytes.NewBufferString("")
	for i, item := range p.ByItems {
		order := "asc"
		if item.Desc {
			order = "desc"
		}
		buffer.WriteString(fmt.Sprintf("%s:%s", item.Expr.ExplainInfo(), order))
		if i+1 < len(p.ByItems) {
			buffer.WriteString(", ")
		}
	}
	buffer.WriteString(fmt.Sprintf(", offset:%v, count:%v", p.Offset, p.Count))
	return buffer.String()
}
<|endoftext|>


<commit_before>// Copyright 2014 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 main

import (
	"errors"
	"fmt"
	"github.com/tsuru/tsuru/cmd"
	"launchpad.net/gnuflag"
	"net/http"
	"strings"
)

type platformAdd struct {
	name       string
	dockerfile string
	fs         *gnuflag.FlagSet
}

func (p *platformAdd) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "platform-add",
		Usage:   "platform-add <platform name> [--dockerfile/-d Dockerfile]",
		Desc:    "Add new platform to tsuru.",
		MinArgs: 1,
	}
}

func (p *platformAdd) Run(context *cmd.Context, client *cmd.Client) error {
	name := context.Args[0]
	if name == "" {
		return errors.New("The platform's name required.")
	}

	if p.dockerfile == "" {
		return errors.New("The Dockerfile doens't exists.")
	}

	body := fmt.Sprintf("name=%s&dockerfile=%s", name, p.dockerfile)
	url, err := cmd.GetURL("/platforms/add")
	request, err := http.NewRequest("PUT", url, strings.NewReader(body))
	if err != nil {
		return err
	}
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	_, err = client.Do(request)
	if err != nil {
		return err
	}

	fmt.Fprintf(context.Stdout, "Platform successfully added!\n")
	return nil
}

func (p *platformAdd) Flags() *gnuflag.FlagSet {
	message := "The dockerfile url to create a platform"
	if p.fs == nil {
		p.fs = gnuflag.NewFlagSet("platform-add", gnuflag.ExitOnError)
		p.fs.StringVar(&p.dockerfile, "dockerfile", "", message)
		p.fs.StringVar(&p.dockerfile, "d", "", message)
	}

	return p.fs
}
<commit_msg>change data validation to app package<commit_after>// Copyright 2014 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 main

import (
	"fmt"
	"github.com/tsuru/tsuru/cmd"
	"launchpad.net/gnuflag"
	"net/http"
	"strings"
)

type platformAdd struct {
	name       string
	dockerfile string
	fs         *gnuflag.FlagSet
}

func (p *platformAdd) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "platform-add",
		Usage:   "platform-add <platform name> [--dockerfile/-d Dockerfile]",
		Desc:    "Add new platform to tsuru.",
		MinArgs: 1,
	}
}

func (p *platformAdd) Run(context *cmd.Context, client *cmd.Client) error {
	name := context.Args[0]
    body := fmt.Sprintf("name=%s&dockerfile=%s", name, p.dockerfile)
	url, err := cmd.GetURL("/platforms/add")
	request, err := http.NewRequest("PUT", url, strings.NewReader(body))
	if err != nil {
		return err
	}
	request.Header.Add("Content-Type", "application/x-www-form-urlencoded")

	_, err = client.Do(request)
	if err != nil {
		return err
	}

	fmt.Fprintf(context.Stdout, "Platform successfully added!\n")
	return nil
}

func (p *platformAdd) Flags() *gnuflag.FlagSet {
	message := "The dockerfile url to create a platform"
	if p.fs == nil {
		p.fs = gnuflag.NewFlagSet("platform-add", gnuflag.ExitOnError)
		p.fs.StringVar(&p.dockerfile, "dockerfile", "", message)
		p.fs.StringVar(&p.dockerfile, "d", "", message)
	}

	return p.fs
}
<|endoftext|>


<commit_before>package pretty_test

import (
	"fmt"
	"github.com/kylelemons/godebug/pretty"
)

func ExampleReflect() {
	type Pair [2]int
	type Map struct {
		Name      string
		Players   map[string]Pair
		Obstacles map[Pair]string
	}

	m := Map{
		Name: "Rock Creek",
		Players: map[string]Pair{
			"player1": {1, 3},
			"player2": {0, -1},
		},
		Obstacles: map[Pair]string{
			Pair{0, 0}: "rock",
			Pair{2, 1}: "pond",
			Pair{1, 1}: "stream",
			Pair{0, 1}: "stream",
		},
	}

	// Print out a summary
	players := pretty.Reflect(m.Players, &pretty.Options{Compact: true})
	fmt.Printf("Players: %s\n", players)

	// Print diffable output
	state := pretty.Reflect(m, &pretty.Options{Diffable: true})
	fmt.Printf("Map State:\n%s", state)

	// Output:
	// Players: {player1:[1,3],player2:[0,-1]}
	// Map State:
	// {
	//  Name:      "Rock Creek",
	//  Players:   {
	//              player1: [
	//                        1,
	//                        3,
	//                       ],
	//              player2: [
	//                        0,
	//                        -1,
	//                       ],
	//             },
	//  Obstacles: {
	//              [0,0]: "rock",
	//              [0,1]: "stream",
	//              [1,1]: "stream",
	//              [2,1]: "pond",
	//             },
	// }
}

func ExamplePrint() {
	type ShipManifest struct {
		Name     string
		Crew     map[string]string
		Androids int
		Stolen   bool
	}

	manifest := &ShipManifest{
		Name: "Spaceship Heart of Gold",
		Crew: map[string]string{
			"Zaphod Beeblebrox": "Galactic President",
			"Trillian":          "Human",
			"Ford Prefect":      "A Hoopy Frood",
			"Arthur Dent":       "Along for the Ride",
		},
		Androids: 1,
		Stolen:   true,
	}

	pretty.Print(manifest)

	// Output:
	// {Name:     "Spaceship Heart of Gold",
	//  Crew:     {Arthur Dent:       "Along for the Ride",
	//             Ford Prefect:      "A Hoopy Frood",
	//             Trillian:          "Human",
	//             Zaphod Beeblebrox: "Galactic President"},
	//  Androids: 1,
	//  Stolen:   true}
}
<commit_msg>Add Compare example<commit_after>package pretty_test

import (
	"fmt"
	"github.com/kylelemons/godebug/pretty"
)

func ExampleReflect() {
	type Pair [2]int
	type Map struct {
		Name      string
		Players   map[string]Pair
		Obstacles map[Pair]string
	}

	m := Map{
		Name: "Rock Creek",
		Players: map[string]Pair{
			"player1": {1, 3},
			"player2": {0, -1},
		},
		Obstacles: map[Pair]string{
			Pair{0, 0}: "rock",
			Pair{2, 1}: "pond",
			Pair{1, 1}: "stream",
			Pair{0, 1}: "stream",
		},
	}

	// Print out a summary
	players := pretty.Reflect(m.Players, &pretty.Options{Compact: true})
	fmt.Printf("Players: %s\n", players)

	// Print diffable output
	state := pretty.Reflect(m, &pretty.Options{Diffable: true})
	fmt.Printf("Map State:\n%s", state)

	// Output:
	// Players: {player1:[1,3],player2:[0,-1]}
	// Map State:
	// {
	//  Name:      "Rock Creek",
	//  Players:   {
	//              player1: [
	//                        1,
	//                        3,
	//                       ],
	//              player2: [
	//                        0,
	//                        -1,
	//                       ],
	//             },
	//  Obstacles: {
	//              [0,0]: "rock",
	//              [0,1]: "stream",
	//              [1,1]: "stream",
	//              [2,1]: "pond",
	//             },
	// }
}

func ExamplePrint() {
	type ShipManifest struct {
		Name     string
		Crew     map[string]string
		Androids int
		Stolen   bool
	}

	manifest := &ShipManifest{
		Name: "Spaceship Heart of Gold",
		Crew: map[string]string{
			"Zaphod Beeblebrox": "Galactic President",
			"Trillian":          "Human",
			"Ford Prefect":      "A Hoopy Frood",
			"Arthur Dent":       "Along for the Ride",
		},
		Androids: 1,
		Stolen:   true,
	}

	pretty.Print(manifest)

	// Output:
	// {Name:     "Spaceship Heart of Gold",
	//  Crew:     {Arthur Dent:       "Along for the Ride",
	//             Ford Prefect:      "A Hoopy Frood",
	//             Trillian:          "Human",
	//             Zaphod Beeblebrox: "Galactic President"},
	//  Androids: 1,
	//  Stolen:   true}
}

func ExampleCompare() {
	type ShipManifest struct {
		Name     string
		Crew     map[string]string
		Androids int
		Stolen   bool
	}

	reported := &ShipManifest{
		Name: "Spaceship Heart of Gold",
		Crew: map[string]string{
			"Zaphod Beeblebrox": "Galactic President",
			"Trillian":          "Human",
			"Ford Prefect":      "A Hoopy Frood",
			"Arthur Dent":       "Along for the Ride",
		},
		Androids: 1,
		Stolen:   true,
	}

	expected := &ShipManifest{
		Name: "Spaceship Heart of Gold",
		Crew: map[string]string{
			"Rowan Artosok": "Captain",
		},
		Androids: 1,
		Stolen:   false,
	}

	fmt.Println(pretty.Compare(reported, expected))
	// Output:
	//  {
	//   Name:     "Spaceship Heart of Gold",
	//   Crew:     {
	// -            Arthur Dent:       "Along for the Ride",
	// -            Ford Prefect:      "A Hoopy Frood",
	// -            Trillian:          "Human",
	// -            Zaphod Beeblebrox: "Galactic President",
	// +            Rowan Artosok: "Captain",
	//             },
	//   Androids: 1,
	// - Stolen:   true,
	// + Stolen:   false,
	//  }
}
<|endoftext|>


<commit_before>package markdown

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/mholt/caddy/middleware"
	"github.com/russross/blackfriday"
)

func TestMarkdown(t *testing.T) {
	templates := make(map[string]string)
	templates[DefaultTemplate] = "testdata/markdown_tpl.html"
	md := Markdown{
		Root:    "./testdata",
		FileSys: http.Dir("./testdata"),
		Configs: []Config{
			Config{
				Renderer:   blackfriday.HtmlRenderer(0, "", ""),
				PathScope:  "/blog",
				Extensions: []string{".md"},
				Styles:     []string{},
				Scripts:    []string{},
				Templates:  templates,
			},
			Config{
				Renderer:   blackfriday.HtmlRenderer(0, "", ""),
				PathScope:  "/log",
				Extensions: []string{".md"},
				Styles:     []string{"/resources/css/log.css", "/resources/css/default.css"},
				Scripts:    []string{"/resources/js/log.js", "/resources/js/default.js"},
				Templates:  make(map[string]string),
			},
			Config{
				Renderer:    blackfriday.HtmlRenderer(0, "", ""),
				PathScope:   "/og",
				Extensions:  []string{".md"},
				Styles:      []string{},
				Scripts:     []string{},
				Templates:   templates,
				StaticDir:   "/og_static",
				StaticFiles: map[string]string{"/og/first.md": "testdata/og_static/og/first.md/index.html"},
			},
		},
		IndexFiles: []string{"index.html"},
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
	}

	req, err := http.NewRequest("GET", "/blog/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html>

<title>Markdown test</title>

Header

Welcome to A Caddy website!

Welcome on the blog

Body

go
func getTrue() bool {
    return true
}

`
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/log/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>

		<title>Markdown test</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="/resources/css/log.css">
<link rel="stylesheet" href="/resources/css/default.css">

Welcome on the blog

Body

go
func getTrue() bool {
    return true
}

`

	replacer := strings.NewReplacer("\r", "", "\n", "")
	respBody = replacer.Replace(respBody)
	expectedBody = replacer.Replace(expectedBody)
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/og/first.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>

<title>first_post</title>

Header title

Test h1

`
	respBody = replacer.Replace(respBody)
	expectedBody = replacer.Replace(expectedBody)
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}
}
<commit_msg>Fixed path issue: was absolute path but should be relative path<commit_after>package markdown

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/mholt/caddy/middleware"
	"github.com/russross/blackfriday"
)

func TestMarkdown(t *testing.T) {
	templates := make(map[string]string)
	templates[DefaultTemplate] = "testdata/markdown_tpl.html"
	md := Markdown{
		Root:    "./testdata",
		FileSys: http.Dir("./testdata"),
		Configs: []Config{
			Config{
				Renderer:   blackfriday.HtmlRenderer(0, "", ""),
				PathScope:  "/blog",
				Extensions: []string{".md"},
				Styles:     []string{},
				Scripts:    []string{},
				Templates:  templates,
			},
			Config{
				Renderer:   blackfriday.HtmlRenderer(0, "", ""),
				PathScope:  "/log",
				Extensions: []string{".md"},
				Styles:     []string{"/resources/css/log.css", "/resources/css/default.css"},
				Scripts:    []string{"/resources/js/log.js", "/resources/js/default.js"},
				Templates:  make(map[string]string),
			},
			Config{
				Renderer:    blackfriday.HtmlRenderer(0, "", ""),
				PathScope:   "/og",
				Extensions:  []string{".md"},
				Styles:      []string{},
				Scripts:     []string{},
				Templates:   templates,
				StaticDir:   "testdata/og_static",
				StaticFiles: map[string]string{"/og/first.md": "testdata/og_static/og/first.md/index.html"},
			},
		},
		IndexFiles: []string{"index.html"},
		Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
			t.Fatalf("Next shouldn't be called")
			return 0, nil
		}),
	}

	req, err := http.NewRequest("GET", "/blog/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}

	rec := httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}

	respBody := rec.Body.String()
	expectedBody := `<!DOCTYPE html>

<title>Markdown test</title>

Header

Welcome to A Caddy website!

Welcome on the blog

Body

go
func getTrue() bool {
    return true
}

`
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/log/test.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>

		<title>Markdown test</title>
		<meta charset="utf-8">
		<link rel="stylesheet" href="/resources/css/log.css">
<link rel="stylesheet" href="/resources/css/default.css">

Welcome on the blog

Body

go
func getTrue() bool {
    return true
}

`

	replacer := strings.NewReplacer("\r", "", "\n", "")
	respBody = replacer.Replace(respBody)
	expectedBody = replacer.Replace(expectedBody)
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}

	req, err = http.NewRequest("GET", "/og/first.md", nil)
	if err != nil {
		t.Fatalf("Could not create HTTP request: %v", err)
	}
	rec = httptest.NewRecorder()

	md.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("Wrong status, expected: %d and got %d", http.StatusOK, rec.Code)
	}
	respBody = rec.Body.String()
	expectedBody = `<!DOCTYPE html>

<title>first_post</title>

Header title

Test h1

`
	respBody = replacer.Replace(respBody)
	expectedBody = replacer.Replace(expectedBody)
	if respBody != expectedBody {
		t.Fatalf("Expected body: %v got: %v", expectedBody, respBody)
	}
}
<|endoftext|>


<commit_before>package duet

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

type scope int

const (
	Default scope = iota
	Local
	Global
)

// GitConfig provides methods for interacting with git config
// If scope is Global, interacts with user git config (~/.gitconfig)
// If scope is Local, interacts with repo config
// If scope is Default 'SetXXX' operates on repo config and 'GetXXX' looks in
// repo then global (similar to `git config`)
// Namespace determines the section under which configuration will be stored
type GitConfig struct {
	Namespace string
	Scope     scope
}

// GetAuthorConfig returns the config source for git author information.
func GetAuthorConfig(namespace string) (config *GitConfig, err error) {
	configs := []*GitConfig{
		&GitConfig{Namespace: namespace, Scope: Local},
		&GitConfig{Namespace: namespace, Scope: Global},
	}

	for _, config := range configs {
		author, err := config.GetAuthor()
		if err != nil {
			return nil, err
		}
		if author != nil {
			return config, nil
		}
	}

	return nil, errors.New("git-author not set")
}

// ClearCommitter removes committer name/email from config
func (gc *GitConfig) ClearCommitter() (err error) {
	if err = gc.unsetKey("git-committer-name"); err != nil {
		return err
	}
	if err = gc.unsetKey("git-committer-email"); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

// SetAuthor sets the configuration for author name and email
func (gc *GitConfig) SetAuthor(author *Pair) (err error) {
	if err = gc.setAuthor(author); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

// SetCommitter sets the configuration for committer name and email
func (gc *GitConfig) SetCommitter(committer *Pair) (err error) {
	if err = gc.setCommitter(committer); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) RotateAuthor() (err error) {
	var author, committer *Pair
	if author, err = gc.GetAuthor(); err != nil {
		return err
	}
	if committer, err = gc.GetCommitter(); err != nil {
		return err
	}

	if committer != nil {
		if err = gc.setAuthor(committer); err != nil {
			return err
		}
		if err = gc.setCommitter(author); err != nil {
			return err
		}
	}

	return nil
}

func (gc *GitConfig) setAuthor(author *Pair) (err error) {
	if err = gc.setKey("git-author-name", author.Name); err != nil {
		return err
	}
	if err = gc.setKey("git-author-email", author.Email); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) setCommitter(committer *Pair) (err error) {
	if err = gc.setKey("git-committer-name", committer.Name); err != nil {
		return err
	}
	if err = gc.setKey("git-committer-email", committer.Email); err != nil {
		return err
	}
	return nil
}

// GetAuthor returns the currently configured author (nil if none)
func (gc *GitConfig) GetAuthor() (pair *Pair, err error) {
	name, err := gc.getKey("git-author-name")
	if err != nil {
		return nil, err
	}

	email, err := gc.getKey("git-author-email")
	if err != nil {
		return nil, err
	}

	if name == "" || email == "" {
		return nil, nil
	}

	return &Pair{
		Name:  name,
		Email: email,
	}, nil
}

// GetCommitter returns the currently configured committer (nil if none)
func (gc *GitConfig) GetCommitter() (pair *Pair, err error) {
	name, err := gc.getKey("git-committer-name")
	if err != nil {
		return nil, err
	}

	email, err := gc.getKey("git-committer-email")
	if err != nil {
		return nil, err
	}

	if name == "" || email == "" {
		return nil, nil
	}

	return &Pair{
		Name:  name,
		Email: email,
	}, nil
}

// GetMtime returns the last time the author/committer was written
// Returns zero Time if key is missing
func (gc *GitConfig) GetMtime() (mtime time.Time, err error) {
	mtimeString, err := gc.getKey("mtime")
	if err != nil {
		return time.Time{}, err
	}

	if mtimeString == "" {
		return time.Time{}, nil
	}

	mtimeUnix, err := strconv.ParseInt(mtimeString, 10, 64)
	if err != nil {
		return time.Time{}, err
	}

	return time.Unix(mtimeUnix, 0), nil
}

func (gc *GitConfig) getKey(key string) (value string, err error) {
	output := new(bytes.Buffer)
	cmd := gc.configCommand(fmt.Sprintf("%s.%s", gc.Namespace, key))
	cmd.Stdout = output

	err = newIgnorableCommand(cmd, 1).Run()
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(output.String()), nil
}

func (gc *GitConfig) unsetKey(key string) (err error) {
	if err = newIgnorableCommand(
		gc.configCommand("--unset-all", fmt.Sprintf("%s.%s", gc.Namespace, key)),
		5).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) setKey(key, value string) (err error) {
	if err = gc.configCommand(fmt.Sprintf("%s.%s", gc.Namespace, key), value).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) updateMtime() (err error) {
	if err = gc.configCommand(
		fmt.Sprintf("%s.%s", gc.Namespace, "mtime"),
		strconv.FormatInt(time.Now().Unix(), 10)).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) configCommand(args ...string) *exec.Cmd {
	config := []string{"config"}
	switch gc.Scope {
	case Global:
		config = append(config, "--global")
	case Local:
		config = append(config, "--local")
	}
	config = append(config, args...)
	cmd := exec.Command("git", config...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd
}
<commit_msg>Add comments<commit_after>package duet

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

type scope int

// Default uses the default search order and writes to the local config
// Local reads and writes from the local git config
// Global reads and writes from the user git config
const (
	Default scope = iota
	Local
	Global
)

// GitConfig provides methods for interacting with git config
// If scope is Global, interacts with user git config (~/.gitconfig)
// If scope is Local, interacts with repo config
// If scope is Default 'SetXXX' operates on repo config and 'GetXXX' looks in
// repo then global (similar to `git config`)
// Namespace determines the section under which configuration will be stored
type GitConfig struct {
	Namespace string
	Scope     scope
}

// GetAuthorConfig returns the config source for git author information.
func GetAuthorConfig(namespace string) (config *GitConfig, err error) {
	configs := []*GitConfig{
		&GitConfig{Namespace: namespace, Scope: Local},
		&GitConfig{Namespace: namespace, Scope: Global},
	}

	for _, config := range configs {
		author, err := config.GetAuthor()
		if err != nil {
			return nil, err
		}
		if author != nil {
			return config, nil
		}
	}

	return nil, errors.New("git-author not set")
}

// ClearCommitter removes committer name/email from config
func (gc *GitConfig) ClearCommitter() (err error) {
	if err = gc.unsetKey("git-committer-name"); err != nil {
		return err
	}
	if err = gc.unsetKey("git-committer-email"); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

// SetAuthor sets the configuration for author name and email
func (gc *GitConfig) SetAuthor(author *Pair) (err error) {
	if err = gc.setAuthor(author); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

// SetCommitter sets the configuration for committer name and email
func (gc *GitConfig) SetCommitter(committer *Pair) (err error) {
	if err = gc.setCommitter(committer); err != nil {
		return err
	}
	if err = gc.updateMtime(); err != nil {
		return err
	}
	return nil
}

// RotateAuthor flips the committer and author if committer is set
func (gc *GitConfig) RotateAuthor() (err error) {
	var author, committer *Pair
	if author, err = gc.GetAuthor(); err != nil {
		return err
	}
	if committer, err = gc.GetCommitter(); err != nil {
		return err
	}

	if committer != nil {
		if err = gc.setAuthor(committer); err != nil {
			return err
		}
		if err = gc.setCommitter(author); err != nil {
			return err
		}
	}

	return nil
}

func (gc *GitConfig) setAuthor(author *Pair) (err error) {
	if err = gc.setKey("git-author-name", author.Name); err != nil {
		return err
	}
	if err = gc.setKey("git-author-email", author.Email); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) setCommitter(committer *Pair) (err error) {
	if err = gc.setKey("git-committer-name", committer.Name); err != nil {
		return err
	}
	if err = gc.setKey("git-committer-email", committer.Email); err != nil {
		return err
	}
	return nil
}

// GetAuthor returns the currently configured author (nil if none)
func (gc *GitConfig) GetAuthor() (pair *Pair, err error) {
	name, err := gc.getKey("git-author-name")
	if err != nil {
		return nil, err
	}

	email, err := gc.getKey("git-author-email")
	if err != nil {
		return nil, err
	}

	if name == "" || email == "" {
		return nil, nil
	}

	return &Pair{
		Name:  name,
		Email: email,
	}, nil
}

// GetCommitter returns the currently configured committer (nil if none)
func (gc *GitConfig) GetCommitter() (pair *Pair, err error) {
	name, err := gc.getKey("git-committer-name")
	if err != nil {
		return nil, err
	}

	email, err := gc.getKey("git-committer-email")
	if err != nil {
		return nil, err
	}

	if name == "" || email == "" {
		return nil, nil
	}

	return &Pair{
		Name:  name,
		Email: email,
	}, nil
}

// GetMtime returns the last time the author/committer was written
// Returns zero Time if key is missing
func (gc *GitConfig) GetMtime() (mtime time.Time, err error) {
	mtimeString, err := gc.getKey("mtime")
	if err != nil {
		return time.Time{}, err
	}

	if mtimeString == "" {
		return time.Time{}, nil
	}

	mtimeUnix, err := strconv.ParseInt(mtimeString, 10, 64)
	if err != nil {
		return time.Time{}, err
	}

	return time.Unix(mtimeUnix, 0), nil
}

func (gc *GitConfig) getKey(key string) (value string, err error) {
	output := new(bytes.Buffer)
	cmd := gc.configCommand(fmt.Sprintf("%s.%s", gc.Namespace, key))
	cmd.Stdout = output

	err = newIgnorableCommand(cmd, 1).Run()
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(output.String()), nil
}

func (gc *GitConfig) unsetKey(key string) (err error) {
	if err = newIgnorableCommand(
		gc.configCommand("--unset-all", fmt.Sprintf("%s.%s", gc.Namespace, key)),
		5).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) setKey(key, value string) (err error) {
	if err = gc.configCommand(fmt.Sprintf("%s.%s", gc.Namespace, key), value).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) updateMtime() (err error) {
	if err = gc.configCommand(
		fmt.Sprintf("%s.%s", gc.Namespace, "mtime"),
		strconv.FormatInt(time.Now().Unix(), 10)).Run(); err != nil {
		return err
	}
	return nil
}

func (gc *GitConfig) configCommand(args ...string) *exec.Cmd {
	config := []string{"config"}
	switch gc.Scope {
	case Global:
		config = append(config, "--global")
	case Local:
		config = append(config, "--local")
	}
	config = append(config, args...)
	cmd := exec.Command("git", config...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd
}
<|endoftext|>


<commit_before>package buffer

import (
	"crypto/rand"
	"fmt"
	"io"
	"testing"
	"unsafe"
)

func randBytes(n int) (b []byte, err error) {
	b = make([]byte, n)
	_, err = io.ReadFull(rand.Reader, b)
	return
}

func TestMemclr(t *testing.T) {
	// All sizes up to 32 bytes.
	var sizes []int
	for i := 0; i <= 32; i++ {
		sizes = append(sizes, i)
	}

	// And a few hand-chosen sizes.
	sizes = append(sizes, []int{
		39, 41, 64, 127, 128, 129,
		1<<20 - 1,
		1 << 20,
		1<<20 + 1,
	}...)

	// For each size, fill a buffer with random bytes and then zero it.
	for _, size := range sizes {
		size := size
		t.Run(fmt.Sprintf("size=%d", size), func(t *testing.T) {
			// Generate
			b, err := randBytes(size)
			if err != nil {
				t.Fatalf("randBytes: %v", err)
			}

			// Clear
			var p unsafe.Pointer
			if len(b) != 0 {
				p = unsafe.Pointer(&b[0])
			}

			memclr(p, uintptr(len(b)))

			// Check
			for i, x := range b {
				if x != 0 {
					t.Fatalf("non-zero byte %d at offset %d", x, i)
				}
			}
		})
	}
}

func BenchmarkOutMessageReset(b *testing.B) {
	// A single buffer, which should fit in some level of CPU cache.
	b.Run("Single buffer", func(b *testing.B) {
		b.SetBytes(int64(unsafe.Sizeof(OutMessage{})))

		var om OutMessage
		for i := 0; i < b.N; i++ {
			om.Reset()
		}
	})

	// Many megabytes worth of buffers, which should defeat the CPU cache.
	b.Run("Many buffers", func(b *testing.B) {
		b.SetBytes(int64(unsafe.Sizeof(OutMessage{})))

		// The number of messages; intentionally a power of two.
		const numMessages = 128

		var oms [numMessages]OutMessage
		if s := unsafe.Sizeof(oms); s < 128<<20 {
			panic(fmt.Sprintf("Array is too small; total size: %d", s))
		}

		for i := 0; i < b.N; i++ {
			oms[i%numMessages].Reset()
		}
	})
}
<commit_msg>Fix a bug in BenchmarkOutMessageReset.<commit_after>package buffer

import (
	"crypto/rand"
	"fmt"
	"io"
	"testing"
	"unsafe"
)

func randBytes(n int) (b []byte, err error) {
	b = make([]byte, n)
	_, err = io.ReadFull(rand.Reader, b)
	return
}

func TestMemclr(t *testing.T) {
	// All sizes up to 32 bytes.
	var sizes []int
	for i := 0; i <= 32; i++ {
		sizes = append(sizes, i)
	}

	// And a few hand-chosen sizes.
	sizes = append(sizes, []int{
		39, 41, 64, 127, 128, 129,
		1<<20 - 1,
		1 << 20,
		1<<20 + 1,
	}...)

	// For each size, fill a buffer with random bytes and then zero it.
	for _, size := range sizes {
		size := size
		t.Run(fmt.Sprintf("size=%d", size), func(t *testing.T) {
			// Generate
			b, err := randBytes(size)
			if err != nil {
				t.Fatalf("randBytes: %v", err)
			}

			// Clear
			var p unsafe.Pointer
			if len(b) != 0 {
				p = unsafe.Pointer(&b[0])
			}

			memclr(p, uintptr(len(b)))

			// Check
			for i, x := range b {
				if x != 0 {
					t.Fatalf("non-zero byte %d at offset %d", x, i)
				}
			}
		})
	}
}

func BenchmarkOutMessageReset(b *testing.B) {
	// A single buffer, which should fit in some level of CPU cache.
	b.Run("Single buffer", func(b *testing.B) {
		var om OutMessage
		for i := 0; i < b.N; i++ {
			om.Reset()
		}

		b.SetBytes(int64(om.offset))
	})

	// Many megabytes worth of buffers, which should defeat the CPU cache.
	b.Run("Many buffers", func(b *testing.B) {
		// The number of messages; intentionally a power of two.
		const numMessages = 128

		var oms [numMessages]OutMessage
		if s := unsafe.Sizeof(oms); s < 128<<20 {
			panic(fmt.Sprintf("Array is too small; total size: %d", s))
		}

		for i := 0; i < b.N; i++ {
			oms[i%numMessages].Reset()
		}

		b.SetBytes(int64(oms[0].offset))
	})
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"text/template"

	"github.com/BurntSushi/toml"
)

type status struct {
	Name   string `toml:"name"`
	Type   string `toml:"type"`
	Status string
	URL    string `toml:"url"`
}

type sites struct {
	Service []status
}

type Status interface {
	Check(url string) (bool, error)
}

var check map[string]Status

func readConfig() ([]status, error) {
	var config sites

	_, err := toml.DecodeFile("sitecheck.conf", &config)
	if err != nil {
		return nil, err
	}

	return config.Service, nil
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	status, err := readConfig()
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}

	for i, s := range status {
		status[i].Status = "offline"

		ck, ok := check[s.Type]
		if ok == false {
			log.Println(s.Type, s.URL, err)
			continue
		}

		healthy, err := ck.Check(s.URL)
		if err != nil {
			log.Println(s.Type, s.URL, err)
			continue
		}

		if healthy {
			status[i].Status = "online"
		}
	}

	t, err := template.ParseFiles("status.html")
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}

	err = t.Execute(w, status)
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}
}

func init() {
	check = map[string]Status{
		"website":  new(Website),
		"etcd":     new(Etcd),
		"docker":   new(Docker),
		"registry": new(Registry),
	}
}

func main() {
	http.HandleFunc("/", statusHandler)

	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>specify http port on command line - mandatory<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"text/template"

	"github.com/BurntSushi/toml"
)

type status struct {
	Name   string `toml:"name"`
	Type   string `toml:"type"`
	Status string
	URL    string `toml:"url"`
}

type sites struct {
	Service []status
}

type Status interface {
	Check(url string) (bool, error)
}

var check map[string]Status

func readConfig() ([]status, error) {
	var config sites

	_, err := toml.DecodeFile("sitecheck.conf", &config)
	if err != nil {
		return nil, err
	}

	return config.Service, nil
}

func statusHandler(w http.ResponseWriter, r *http.Request) {
	status, err := readConfig()
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}

	for i, s := range status {
		status[i].Status = "offline"

		ck, ok := check[s.Type]
		if ok == false {
			log.Println(s.Type, s.URL, err)
			continue
		}

		healthy, err := ck.Check(s.URL)
		if err != nil {
			log.Println(s.Type, s.URL, err)
			continue
		}

		if healthy {
			status[i].Status = "online"
		}
	}

	t, err := template.ParseFiles("status.html")
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}

	err = t.Execute(w, status)
	if err != nil {
		http.Error(w, "internal error", http.StatusInternalServerError)
		log.Println(err)
		return
	}
}

func init() {
	check = map[string]Status{
		"website":  new(Website),
		"etcd":     new(Etcd),
		"docker":   new(Docker),
		"registry": new(Registry),
	}
}

func main() {
	var port = flag.String("http", "", "HTTP service address (.e.g. :8080)")

	flag.Parse()

	if *port == "" {
		flag.Usage()
		return
	}

	http.HandleFunc("/", statusHandler)

	log.Fatal(http.ListenAndServe(*port, nil))
}
<|endoftext|>


<commit_before>package mmm

import (
	"testing"
	"unsafe"
)

// -----------------------------------------------------------------------------

func TestSize_SizeOf_bool(t *testing.T) {
	var v bool
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for bool")
	}
}

func TestSize_SizeOf_int(t *testing.T) {
	var v int
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int")
	}
}

func TestSize_SizeOf_int8(t *testing.T) {
	var v int8
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int8")
	}
}

func TestSize_SizeOf_int16(t *testing.T) {
	var v int16
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int16")
	}
}

func TestSize_SizeOf_int32(t *testing.T) {
	var v int32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int32")
	}
}

func TestSize_SizeOf_int64(t *testing.T) {
	var v int64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int64")
	}
}

func TestSize_SizeOf_uint(t *testing.T) {
	var v uint
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint")
	}
}

func TestSize_SizeOf_uint8(t *testing.T) {
	var v uint8
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint8")
	}
}

func TestSize_SizeOf_uint16(t *testing.T) {
	var v uint16
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint16")
	}
}

func TestSize_SizeOf_uint32(t *testing.T) {
	var v uint32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint32")
	}
}

func TestSize_SizeOf_uint64(t *testing.T) {
	var v uint64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint64")
	}
}

func TestSize_SizeOf_uintptr(t *testing.T) {
	var v uintptr
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uintptr")
	}
}

func TestSize_SizeOf_float32(t *testing.T) {
	var v float32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for float32")
	}
}

func TestSize_SizeOf_float64(t *testing.T) {
	var v float64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for float64")
	}
}

func TestSize_SizeOf_complex64(t *testing.T) {
	var v complex64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for complex64")
	}
}

func TestSize_SizeOf_complex128(t *testing.T) {
	var v complex128
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for complex128")
	}
}

func TestSize_SizeOf_int_array(t *testing.T) {
	var v [42]int
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for [42]int")
	}
}

func TestSize_SizeOf_int_chan(t *testing.T) {
	var v chan int
	_, err := SizeOf(v)
	if err == nil {
		t.Error("should not be supported")
		if _, ok := err.(Error); !ok {
			t.Error("should have mmm.Error")
		}
	}
}

func TestSize_SizeOf_int_map(t *testing.T) {
	var v map[int]int
	_, err := SizeOf(v)
	if err == nil {
		t.Error("should not be supported")
		if _, ok := err.(Error); !ok {
			t.Error("should have mmm.Error")
		}
	}
}

//var imap map[int]int
//var iptr *int
//var islice []int
//var str string
//var srt struct{}

//var itf interface{}
<commit_msg>added TestSize_SizeOf_int_pointer<commit_after>package mmm

import (
	"testing"
	"unsafe"
)

// -----------------------------------------------------------------------------

func TestSize_SizeOf_bool(t *testing.T) {
	var v bool
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for bool")
	}
}

func TestSize_SizeOf_int(t *testing.T) {
	var v int
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int")
	}
}

func TestSize_SizeOf_int8(t *testing.T) {
	var v int8
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int8")
	}
}

func TestSize_SizeOf_int16(t *testing.T) {
	var v int16
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int16")
	}
}

func TestSize_SizeOf_int32(t *testing.T) {
	var v int32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int32")
	}
}

func TestSize_SizeOf_int64(t *testing.T) {
	var v int64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for int64")
	}
}

func TestSize_SizeOf_uint(t *testing.T) {
	var v uint
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint")
	}
}

func TestSize_SizeOf_uint8(t *testing.T) {
	var v uint8
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint8")
	}
}

func TestSize_SizeOf_uint16(t *testing.T) {
	var v uint16
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint16")
	}
}

func TestSize_SizeOf_uint32(t *testing.T) {
	var v uint32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint32")
	}
}

func TestSize_SizeOf_uint64(t *testing.T) {
	var v uint64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uint64")
	}
}

func TestSize_SizeOf_uintptr(t *testing.T) {
	var v uintptr
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for uintptr")
	}
}

func TestSize_SizeOf_float32(t *testing.T) {
	var v float32
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for float32")
	}
}

func TestSize_SizeOf_float64(t *testing.T) {
	var v float64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for float64")
	}
}

func TestSize_SizeOf_complex64(t *testing.T) {
	var v complex64
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for complex64")
	}
}

func TestSize_SizeOf_complex128(t *testing.T) {
	var v complex128
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for complex128")
	}
}

func TestSize_SizeOf_int_array(t *testing.T) {
	var v [42]int
	size, err := SizeOf(v)
	if err != nil {
		t.Error(err)
	}
	if size != unsafe.Sizeof(v) {
		t.Error("invalid size for [42]int")
	}
}

func TestSize_SizeOf_int_chan(t *testing.T) {
	var v chan int
	_, err := SizeOf(v)
	if err == nil {
		t.Error("should not be supported")
		if _, ok := err.(Error); !ok {
			t.Error("should have mmm.Error")
		}
	}
}

func TestSize_SizeOf_int_map(t *testing.T) {
	var v map[int]int
	_, err := SizeOf(v)
	if err == nil {
		t.Error("should not be supported")
		if _, ok := err.(Error); !ok {
			t.Error("should have mmm.Error")
		}
	}
}

func TestSize_SizeOf_int_pointer(t *testing.T) {
	var v *int
	_, err := SizeOf(v)
	if err == nil {
		t.Error("should not be supported")
		if _, ok := err.(Error); !ok {
			t.Error("should have mmm.Error")
		}
	}
}

//var islice []int
//var str string
//var srt struct{}

//var itf interface{}
<|endoftext|>


<commit_before>/*
 * This file is part of easyKV.
 * © 2016 The easyKV Authors
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

package file

import (
	"context"
	"io/ioutil"
	"net/http"
	"strings"

	"time"

	"github.com/HeavyHorst/easyKV"
	"github.com/fsnotify/fsnotify"
	"gopkg.in/yaml.v2"
)

// Client is a wrapper around the file client
type Client struct {
	filepath   string
	isURL      bool
	httpClient http.Client
}

// New returns a new FileClient
// The filepath can be a local path to a file or a remote http/https location.
func New(filepath string) (*Client, error) {
	c := &Client{filepath: filepath}
	if strings.HasPrefix(filepath, "http://") || strings.HasPrefix(filepath, "https://") {
		c.isURL = true
		c.httpClient = http.Client{
			Timeout: 5 * time.Second,
		}
	}
	return c, nil
}

// GetValues returns all key-value pairs from the yaml or json file where the
// keys begins with one of the prefixes specified in the keys array.
func (c *Client) GetValues(keys []string) (map[string]string, error) {
	yamlMap := make(map[interface{}]interface{})
	vars := make(map[string]string)
	kvs := make(map[string]string)

	var data []byte
	var err error
	if c.isURL {
		resp, err := c.httpClient.Get(c.filepath)
		if err != nil {
			return vars, err
		}
		defer resp.Body.Close()
		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return vars, err
		}
	} else {
		data, err = ioutil.ReadFile(c.filepath)
		if err != nil {
			return vars, err
		}
	}

	err = yaml.Unmarshal(data, &yamlMap)
	if err != nil {
		return vars, err
	}

	nodeWalk(yamlMap, "", vars)

	for _, k := range keys {
		for key, val := range vars {
			if strings.HasPrefix(key, k) {
				kvs[key] = val
			}
		}
	}

	return kvs, nil
}

// Close is only meant to fulfill the easyKV.ReadWatcher interface.
// Does nothing.
func (c *Client) Close() {
	return
}

// nodeWalk recursively descends nodes, updating vars.
func nodeWalk(node map[interface{}]interface{}, key string, vars map[string]string) error {
	for k, v := range node {
		key := key + "/" + k.(string)

		switch v.(type) {
		case map[interface{}]interface{}:
			nodeWalk(v.(map[interface{}]interface{}), key, vars)
		case []interface{}:
			for _, j := range v.([]interface{}) {
				switch j.(type) {
				case map[interface{}]interface{}:
					nodeWalk(j.(map[interface{}]interface{}), key, vars)
				case string:
					vars[key+"/"+j.(string)] = ""
				}
			}
		case string:
			vars[key] = v.(string)
		}
	}
	return nil
}

// WatchPrefix watches the file for changes with fsnotify.
// Prefix, keys and waitIndex are only here to implement the StoreClient interface.
// WatchPrefix is only supported for local files. Remote files over http/https arent supported.
// Remote filesystems like nfs are also not supported.
func (c *Client) WatchPrefix(ctx context.Context, prefix string, opts ...easyKV.WatchOption) (uint64, error) {
	if c.isURL {
		// watch is not supported for urls
		return 0, easyKV.ErrWatchNotSupported
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return 0, err
	}
	defer watcher.Close()

	err = watcher.Add(c.filepath)
	if err != nil {
		return 0, err
	}

	for {
		select {
		case event := <-watcher.Events:
			if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Remove == fsnotify.Remove {
				return 1, nil
			}
		case err := <-watcher.Errors:
			return 0, err
		case <-ctx.Done():
			return 0, easyKV.ErrWatchCanceled
		}
	}
}
<commit_msg>little cleanup<commit_after>/*
 * This file is part of easyKV.
 * © 2016 The easyKV Authors
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

package file

import (
	"context"
	"io/ioutil"
	"net/http"
	"strings"

	"time"

	"github.com/HeavyHorst/easyKV"
	"github.com/fsnotify/fsnotify"
	"gopkg.in/yaml.v2"
)

// Client is a wrapper around the file client
type Client struct {
	filepath   string
	isURL      bool
	httpClient http.Client
}

// New returns a new FileClient
// The filepath can be a local path to a file or a remote http/https location.
func New(filepath string) (*Client, error) {
	c := &Client{filepath: filepath}
	if strings.HasPrefix(filepath, "http://") || strings.HasPrefix(filepath, "https://") {
		c.isURL = true
		c.httpClient = http.Client{
			Timeout: 5 * time.Second,
		}
	}
	return c, nil
}

// GetValues returns all key-value pairs from the yaml or json file where the
// keys begins with one of the prefixes specified in the keys array.
func (c *Client) GetValues(keys []string) (map[string]string, error) {
	yamlMap := make(map[interface{}]interface{})
	vars := make(map[string]string)
	kvs := make(map[string]string)

	var data []byte
	var err error
	if c.isURL {
		resp, err := c.httpClient.Get(c.filepath)
		if err != nil {
			return vars, err
		}
		defer resp.Body.Close()
		data, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return vars, err
		}
	} else {
		data, err = ioutil.ReadFile(c.filepath)
		if err != nil {
			return vars, err
		}
	}

	err = yaml.Unmarshal(data, &yamlMap)
	if err != nil {
		return vars, err
	}

	nodeWalk(yamlMap, "", vars)

	for _, k := range keys {
		for key, val := range vars {
			if strings.HasPrefix(key, k) {
				kvs[key] = val
			}
		}
	}

	return kvs, nil
}

// Close is only meant to fulfill the easyKV.ReadWatcher interface.
// Does nothing.
func (c *Client) Close() {
	return
}

// nodeWalk recursively descends nodes, updating vars.
func nodeWalk(node map[interface{}]interface{}, key string, vars map[string]string) error {
	for k, v := range node {
		key := key + "/" + k.(string)

		switch v := v.(type) {
		case map[interface{}]interface{}:
			nodeWalk(v, key, vars)
		case []interface{}:
			for _, j := range v {
				switch j := j.(type) {
				case map[interface{}]interface{}:
					nodeWalk(j, key, vars)
				case string:
					vars[key+"/"+j] = ""
				}
			}
		case string:
			vars[key] = v
		}
	}
	return nil
}

// WatchPrefix watches the file for changes with fsnotify.
// Prefix, keys and waitIndex are only here to implement the StoreClient interface.
// WatchPrefix is only supported for local files. Remote files over http/https arent supported.
// Remote filesystems like nfs are also not supported.
func (c *Client) WatchPrefix(ctx context.Context, prefix string, opts ...easyKV.WatchOption) (uint64, error) {
	if c.isURL {
		// watch is not supported for urls
		return 0, easyKV.ErrWatchNotSupported
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return 0, err
	}
	defer watcher.Close()

	err = watcher.Add(c.filepath)
	if err != nil {
		return 0, err
	}

	for {
		select {
		case event := <-watcher.Events:
			if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Remove == fsnotify.Remove {
				return 1, nil
			}
		case err := <-watcher.Errors:
			return 0, err
		case <-ctx.Done():
			return 0, easyKV.ErrWatchCanceled
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 CNI 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 skel provides skeleton code for a CNI plugin.
// In particular, it implements argument parsing and validation.
package skel

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/containernetworking/cni/pkg/types"
)

// CmdArgs captures all the arguments passed in to the plugin
// via both env vars and stdin
type CmdArgs struct {
	ContainerID string
	Netns       string
	IfName      string
	Args        string
	Path        string
	StdinData   []byte
}

// PluginMain is the "main" for a plugin. It accepts
// two callback functions for add and del commands.
func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) {
	var cmd, contID, netns, ifName, args, path string

	vars := []struct {
		name string
		val  *string
		req  bool
	}{
		{"CNI_COMMAND", &cmd, true},
		{"CNI_CONTAINERID", &contID, false},
		{"CNI_NETNS", &netns, true},
		{"CNI_IFNAME", &ifName, true},
		{"CNI_ARGS", &args, false},
		{"CNI_PATH", &path, true},
	}

	argsMissing := false
	for _, v := range vars {
		*v.val = os.Getenv(v.name)
		if v.req && *v.val == "" {
			log.Printf("%v env variable missing", v.name)
			argsMissing = true
		}
	}

	if argsMissing {
		dieMsg("required env variables missing")
	}

	stdinData, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		dieMsg("error reading from stdin: %v", err)
	}

	cmdArgs := &CmdArgs{
		ContainerID: contID,
		Netns:       netns,
		IfName:      ifName,
		Args:        args,
		Path:        path,
		StdinData:   stdinData,
	}

	switch cmd {
	case "ADD":
		err = cmdAdd(cmdArgs)

	case "DEL":
		err = cmdDel(cmdArgs)

	default:
		dieMsg("unknown CNI_COMMAND: %v", cmd)
	}

	if err != nil {
		if e, ok := err.(*types.Error); ok {
			// don't wrap Error in Error
			dieErr(e)
		}
		dieMsg(err.Error())
	}
}

func dieMsg(f string, args ...interface{}) {
	e := &types.Error{
		Code: 100,
		Msg:  fmt.Sprintf(f, args...),
	}
	dieErr(e)
}

func dieErr(e *types.Error) {
	if err := e.Print(); err != nil {
		log.Print("Error writing error JSON to stdout: ", err)
	}
	os.Exit(1)
}
<commit_msg>pkg/skel: allow arg requriements specified by CMD<commit_after>// Copyright 2014 CNI 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 skel provides skeleton code for a CNI plugin.
// In particular, it implements argument parsing and validation.
package skel

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/containernetworking/cni/pkg/types"
)

// CmdArgs captures all the arguments passed in to the plugin
// via both env vars and stdin
type CmdArgs struct {
	ContainerID string
	Netns       string
	IfName      string
	Args        string
	Path        string
	StdinData   []byte
}

type reqForCmdEntry map[string]bool

// PluginMain is the "main" for a plugin. It accepts
// two callback functions for add and del commands.
func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) {
	var cmd, contID, netns, ifName, args, path string

	vars := []struct {
		name      string
		val       *string
		reqForCmd reqForCmdEntry
	}{
		{
			"CNI_COMMAND",
			&cmd,
			reqForCmdEntry{
				"ADD": true,
				"DEL": true,
			},
		},
		{
			"CNI_CONTAINERID",
			&contID,
			reqForCmdEntry{
				"ADD": false,
				"DEL": false,
			},
		},
		{
			"CNI_NETNS",
			&netns,
			reqForCmdEntry{
				"ADD": true,
				"DEL": true,
			},
		},
		{
			"CNI_IFNAME",
			&ifName,
			reqForCmdEntry{
				"ADD": true,
				"DEL": true,
			},
		},
		{
			"CNI_ARGS",
			&args,
			reqForCmdEntry{
				"ADD": false,
				"DEL": false,
			},
		},
		{
			"CNI_PATH",
			&path,
			reqForCmdEntry{
				"ADD": true,
				"DEL": true,
			},
		},
	}

	argsMissing := false
	for _, v := range vars {
		*v.val = os.Getenv(v.name)
		if v.reqForCmd[cmd] && *v.val == "" {
			log.Printf("%v env variable missing", v.name)
			argsMissing = true
		}
	}

	if argsMissing {
		dieMsg("required env variables missing")
	}

	stdinData, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		dieMsg("error reading from stdin: %v", err)
	}

	cmdArgs := &CmdArgs{
		ContainerID: contID,
		Netns:       netns,
		IfName:      ifName,
		Args:        args,
		Path:        path,
		StdinData:   stdinData,
	}

	switch cmd {
	case "ADD":
		err = cmdAdd(cmdArgs)

	case "DEL":
		err = cmdDel(cmdArgs)

	default:
		dieMsg("unknown CNI_COMMAND: %v", cmd)
	}

	if err != nil {
		if e, ok := err.(*types.Error); ok {
			// don't wrap Error in Error
			dieErr(e)
		}
		dieMsg(err.Error())
	}
}

func dieMsg(f string, args ...interface{}) {
	e := &types.Error{
		Code: 100,
		Msg:  fmt.Sprintf(f, args...),
	}
	dieErr(e)
}

func dieErr(e *types.Error) {
	if err := e.Print(); err != nil {
		log.Print("Error writing error JSON to stdout: ", err)
	}
	os.Exit(1)
}
<|endoftext|>


<commit_before>package openstack

import (
	"github.com/mitchellh/packer/packer"
	"testing"
)

func testConfig() map[string]interface{} {
	return map[string]interface{}{
		"username":     "foo",
		"password":     "bar",
		"provider":     "foo",
		"region":       "DFW",
		"image_name":   "foo",
		"source_image": "foo",
		"flavor":       "foo",
		"ssh_username": "root",
	}
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilder_Prepare_BadType(t *testing.T) {
	b := &Builder{}
	c := map[string]interface{}{
		"password": []string{},
	}

	warns, err := b.Prepare(c)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err == nil {
		t.Fatalf("prepare should fail")
	}
}

func TestBuilderPrepare_ImageName(t *testing.T) {
	var b Builder
	config := testConfig()

	// Test good
	config["image_name"] = "foo"
	warns, err := b.Prepare(config)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err != nil {
		t.Fatalf("should not have error: %s", err)
	}

	// Test bad
	config["image_name"] = "foo {{"
	b = Builder{}
	warns, err = b.Prepare(config)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err == nil {
		t.Fatal("should have error")
	}

	// Test bad
	delete(config, "image_name")
	b = Builder{}
	warns, err = b.Prepare(config)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}

func TestBuilderPrepare_InvalidKey(t *testing.T) {
	var b Builder
	config := testConfig()

	// Add a random key
	config["i_should_not_be_valid"] = true
	warns, err := b.Prepare(config)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err == nil {
		t.Fatal("should have error")
	}
}
<commit_msg>builder/openstack: fix unit tests<commit_after>package openstack

import (
	"github.com/mitchellh/packer/packer"
	"testing"
)

func testConfig() map[string]interface{} {
	return map[string]interface{}{
		"username":     "foo",
		"password":     "bar",
		"region":       "DFW",
		"image_name":   "foo",
		"source_image": "foo",
		"flavor":       "foo",
		"ssh_username": "root",
	}
}

func TestBuilder_ImplementsBuilder(t *testing.T) {
	var raw interface{}
	raw = &Builder{}
	if _, ok := raw.(packer.Builder); !ok {
		t.Fatalf("Builder should be a builder")
	}
}

func TestBuilder_Prepare_BadType(t *testing.T) {
	b := &Builder{}
	c := map[string]interface{}{
		"password": []string{},
	}

	warns, err := b.Prepare(c)
	if len(warns) > 0 {
		t.Fatalf("bad: %#v", warns)
	}
	if err == nil {
		t.Fatalf("prepare should fail")
	}
}
<|endoftext|>


<commit_before>// +build !windows

package buildkite

import (
	"github.com/buildkite/agent/buildkite/logger"
	"os"
	"os/signal"
	"syscall"
)

func (a *Agent) MonitorSignals() {
	// Handle signals
	signals := make(chan os.Signal, 1)

	// Monitor a heap of different signals for debugging purposes. Only
	// some of them are used. Descriptions are copied from
	// http://en.wikipedia.org/wiki/Unix_signal so when working with this
	// code, we know exactly what each signal should do (and  alwsays
	// forget the specifics)

	signal.Notify(signals, os.Interrupt,
		// The SIGHUP signal is sent to a process when its controlling
		// terminal is closed. It was originally designed to notify the
		// process of a serial line drop (a hangup). In modern systems,
		// this signal usually means that the controlling pseudo or
		// virtual terminal has been closed.[3] Many daemons will
		// reload their configuration files and reopen their logfiles
		// instead of exiting when receiving this signal.[4] nohup is a
		// command to make a command ignore the signal.
		syscall.SIGHUP,

		// The SIGTERM signal is sent to a process to request its
		// termination. Unlike the SIGKILL signal, it can be caught and
		// interpreted or ignored by the process.  This allows the
		// process to perform nice termination releasing resources and
		// saving state if appropriate. It should be noted that SIGINT
		// is nearly identical to SIGTERM.
		syscall.SIGTERM,

		// The SIGKILL signal is sent to a process to cause it to
		// terminate immediately (kill). In contrast to SIGTERM and
		// SIGINT, this signal cannot be caught or ignored, and the
		// receiving process cannot perform any clean-up upon receiving
		// this signal.
		syscall.SIGKILL,

		// The SIGINT signal is sent to a process by its controlling
		// terminal when a user wishes to interrupt the process. This
		// is typically initiated by pressing Control-C, but on some
		// systems, the "delete" character or "break" key can be
		// used.[5]
		syscall.SIGINT,

		// The SIGQUIT signal is sent to a process by its controlling
		// terminal when the user requests that the process quit and
		// perform a core dump.
		syscall.SIGQUIT,

		// The SIGUSR1 and SIGUSR2 signals are sent to a process to
		// indicate user-defined conditions. In this case SIGUSR1 will
		// show debug information about the agnent, and SIGUSR2 will
		// restart the agent.
		syscall.SIGUSR1,
		syscall.SIGUSR2)

	go func() {
		// This will block until a signal is sent
		sig := <-signals

		logger.Debug("Received signal `%s`", sig.String())

		// Ignore SIGHUP, some terminals seem to send it when they get resized,
		// killing the process here would just be silly.
		if sig == syscall.SIGHUP {
			logger.Debug("Ignoring signal `%s`", sig.String())

			// Start monitoring signals again
			a.MonitorSignals()

			return
		}

		// If we've received a SIGKILL, die immediately.
		if sig == syscall.SIGKILL {
			logger.Debug("Exiting immediately", sig.String())

			os.Exit(1)
		}

		// Show debug information with SIGUSR1
		if sig == syscall.SIGUSR1 {
			logger.Debug("======DEBUG===== %s", a)
			if a.Job != nil {
				logger.Debug("======DEBUG===== %s", a.Job)
			}

			// Start monitoring signals again
			a.MonitorSignals()

			return
		}

		// If theres no job, then we can just shut down right away.
		if a.Job == nil {
			a.Stop()
		} else {
			// The user is trying to forcefully kill the agent, so we need
			// to kill any active job.
			if a.stopping {
				a.Job.Kill()
			} else {
				// We should warn the user before they try and shut down the
				// agent while it's performing a job
				logger.Warn("Waiting for job to finish before stopping. Send the signal again to exit immediately.")

				a.stopping = true
			}
		}

		// Start monitoring signals again
		a.MonitorSignals()
	}()
}
<commit_msg>Refactored signal handling - don't restart with USR2<commit_after>// +build !windows

package buildkite

import (
	"github.com/buildkite/agent/buildkite/logger"
	"os"
	"os/signal"
	"syscall"
)

func (a *Agent) MonitorSignals() {
	// Handle signals
	signals := make(chan os.Signal, 1)

	// Monitor a heap of different signals for debugging purposes. Only
	// some of them are used. Descriptions are copied from
	// http://en.wikipedia.org/wiki/Unix_signal so when working with this
	// code, we know exactly what each signal should do (and  alwsays
	// forget the specifics)

	signal.Notify(signals, os.Interrupt,
		// The SIGHUP signal is sent to a process when its controlling
		// terminal is closed. It was originally designed to notify the
		// process of a serial line drop (a hangup). In modern systems,
		// this signal usually means that the controlling pseudo or
		// virtual terminal has been closed.[3] Many daemons will
		// reload their configuration files and reopen their logfiles
		// instead of exiting when receiving this signal.[4] nohup is a
		// command to make a command ignore the signal.
		syscall.SIGHUP,

		// The SIGTERM signal is sent to a process to request its
		// termination. Unlike the SIGKILL signal, it can be caught and
		// interpreted or ignored by the process.  This allows the
		// process to perform nice termination releasing resources and
		// saving state if appropriate. It should be noted that SIGINT
		// is nearly identical to SIGTERM.
		syscall.SIGTERM,

		// The SIGKILL signal is sent to a process to cause it to
		// terminate immediately (kill). In contrast to SIGTERM and
		// SIGINT, this signal cannot be caught or ignored, and the
		// receiving process cannot perform any clean-up upon receiving
		// this signal.
		syscall.SIGKILL,

		// The SIGINT signal is sent to a process by its controlling
		// terminal when a user wishes to interrupt the process. This
		// is typically initiated by pressing Control-C, but on some
		// systems, the "delete" character or "break" key can be
		// used.[5]
		syscall.SIGINT,

		// The SIGQUIT signal is sent to a process by its controlling
		// terminal when the user requests that the process quit and
		// perform a core dump.
		syscall.SIGQUIT,

		// The SIGUSR1 and SIGUSR2 signals are sent to a process to
		// indicate user-defined conditions. In this case SIGUSR1 will
		// show debug information and SIGUSR2 is ignored for now, but
		// in the future it may reload logs.
		syscall.SIGUSR1,
		syscall.SIGUSR2)

	go func() {
		// This will block until a signal is sent
		sig := <-signals

		logger.Debug("Received signal `%s`", sig.String())

		// If we've received a SIGKILL, die immediately.
		if sig == syscall.SIGKILL {
			logger.Debug("Exiting immediately", sig.String())

			os.Exit(1)
		}

		// Show debug information with SIGUSR1
		if sig == syscall.SIGUSR1 {
			logger.Debug("======DEBUG===== %s", a)
			if a.Job != nil {
				logger.Debug("======DEBUG===== %s", a.Job)
			}

			// Start monitoring signals again
			a.MonitorSignals()

			return
		}

		// Exit the agent when it's not doing any work.
		if sig == syscall.SIGTERM || sig == syscall.SIGINT || sig == syscall.SIGQUIT {
			// If theres no job, then we can just shut down right away.
			if a.Job == nil {
				a.Stop()
			} else {
				// The user is trying to forcefully kill the agent, so we need
				// to kill any active job.
				if a.stopping {
					a.Job.Kill()
				} else {
					// We should warn the user before they try and shut down the
					// agent while it's performing a job
					logger.Warn("Waiting for job to finish before stopping. Send the signal again to exit immediately.")

					a.stopping = true
				}
			}

			// Start monitoring signals again
			a.MonitorSignals()

			return
		}

		logger.Debug("Ignoring signal `%s`", sig.String())

		// Start monitoring signals again
		a.MonitorSignals()

		return
	}()
}
<|endoftext|>