<commit_before>package markdown

import "time"

const (
	DefaultInterval = time.Second * 60
	DevInterval     = time.Second * 1
)

// Watch monitors the configured markdown directory for changes. It calls GenerateLinks
// when there are changes.
func Watch(md Markdown, c *Config, interval time.Duration) (stopChan chan struct{}) {
	return TickerFunc(interval, func() {
		GenerateLinks(md, c)
	})
}

// TickerFunc runs f at interval. If interval is <= 0, it loops f. A message to the
// returned channel will stop the executing goroutine.
func TickerFunc(interval time.Duration, f func()) chan struct{} {
	stopChan := make(chan struct{})

	ticker := time.NewTicker(interval)
	go func() {
	loop:
		for {
			select {
			case <-ticker.C:
				f()
			case <-stopChan:
				ticker.Stop()
				break loop
			}
		}
	}()

	return stopChan
}
<commit_msg>Markdown: Removed unused constant.<commit_after>package markdown

import "time"

const DefaultInterval = time.Second * 60

// Watch monitors the configured markdown directory for changes. It calls GenerateLinks
// when there are changes.
func Watch(md Markdown, c *Config, interval time.Duration) (stopChan chan struct{}) {
	return TickerFunc(interval, func() {
		GenerateLinks(md, c)
	})
}

// TickerFunc runs f at interval. If interval is <= 0, it loops f. A message to the
// returned channel will stop the executing goroutine.
func TickerFunc(interval time.Duration, f func()) chan struct{} {
	stopChan := make(chan struct{})

	ticker := time.NewTicker(interval)
	go func() {
	loop:
		for {
			select {
			case <-ticker.C:
				f()
			case <-stopChan:
				ticker.Stop()
				break loop
			}
		}
	}()

	return stopChan
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"

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

func main() {
	endpoint := "unix:///var/run/docker.sock"
	client, _ := docker.NewClient(endpoint)
	var isFiltering = false
	var filteringWord = ""
	var argc = len(os.Args)
	if argc < 2 {
		os.Exit(2)
	} else if argc == 3 {
		isFiltering = true
		filteringWord = os.Args[2]
	}

	historyList, err := client.ImageHistory(os.Args[1])
	if err != nil {
		fmt.Println("Error happens at client.ImageHistory")
		os.Exit(2)
	}
	// First CreatedBy newer to older
	var createdByHistoryList = []string{}
	// layer ID -> json
	var jsonMap = map[string]string{}
	var allJsonMap = map[string]string{}
	var layerTarMap = map[string][]*tar.Header{}
	var first = false
	for _, history := range historyList {
		createdByHistoryList = append(createdByHistoryList, history.CreatedBy)
		image, err := client.InspectImage(history.ID)
		if err != nil || first {
			// continue to create CreatedBy list
			continue
		}
		if image != nil {
			var buf bytes.Buffer
			opts := docker.ExportImageOptions{Name: image.ID, OutputStream: &buf}
			err := client.ExportImage(opts)
			if err != nil {
				fmt.Println("Error happens at client.ExportImage")
				os.Exit(2)
			}
			r := bytes.NewReader(buf.Bytes())
			tr := tar.NewReader(r)
			var header *tar.Header
			for {
				header, err = tr.Next()
				if err == io.EOF {
					// end of image tar
					break
				}
				if err != nil {
					fmt.Println(err)
					fmt.Println("Error at tar extract")
					os.Exit(2)
				}

				buf2 := new(bytes.Buffer)
				if _, err = io.Copy(buf2, tr); err != nil {
					fmt.Println(err)
				}
				//
				var field = strings.Split(header.Name, "/")
				var layerID = field[0]
				// find json and layer.tar
				if strings.HasSuffix(header.Name, "/json") {
					var jsonstring = buf2.String()
					//var imagestring = ""
					allJsonMap[layerID] = jsonstring
					if strings.Index(jsonstring, "\"Image\":\"\"") != -1 || !first {
						jsonMap[layerID] = jsonstring
					}
				} else if strings.HasSuffix(header.Name, "layer.tar") {

					r2 := bytes.NewReader(buf2.Bytes())
					layerTar := tar.NewReader(r2)
					for {
						layerTarHeader, e4 := layerTar.Next()
						if e4 == io.EOF {
							// end of layer.tar
							break
						}
						layerTarMap[layerID] = append(layerTarMap[layerID], layerTarHeader)
					}
				}
			}
		}
		first = true

	}
	// fmt.Println("---- createdBy")
	// for _, createdBy := range createdByHistoryList {
	// 	fmt.Println(createdBy)
	// }
	// construct parent map
	//fmt.Println("---- jsonMap")
	var relation = map[string]string{}
	//var key string
	var value string
	var noparentid string
	for _, value = range jsonMap {
		//fmt.Println(key + " -> " + value)
		//dec := json.NewDecoder(v)
		var f interface{}
		//dec.Decode(&d)
		json.Unmarshal([]byte(value), &f)
		//fmt.Printf("%+v\n", d)
		m := f.(map[string]interface{})
		var id = m["id"]
		var parent = m["parent"]
		if parent == nil {
			noparentid = id.(string)
		} else {
			var p = parent.(string)
			_, ok := relation[p]
			if !ok {
				relation[p] = id.(string)
			}
		}
	}

	// fmt.Println("---- tarinfo")
	// fmt.Println("Start from:" + noparentid)
	var currentid = noparentid

	for {
		//fmt.Println(currentid)
		// find next
		_, ok := relation[currentid]
		if !ok {
			break
		}
		currentid = relation[currentid]
	}
	//
	var fileHistoryListMap = map[string][]string{}
	var layerHistoryList = []string{}
	// fmt.Println("---- reconstruct")
	// fmt.Println("Start from:" + noparentid)
	currentid = noparentid
	for {
		//
		for _, layerTarHeader := range layerTarMap[currentid] {
			var filename = layerTarHeader.Name
			filename = strings.Replace(filename, ".wh.", "", -1)
			fileHistoryListMap[filename] = append(fileHistoryListMap[filename], currentid)
		}
		//
		layerHistoryList = append(layerHistoryList, currentid)
		_, ok := relation[currentid]
		if !ok {
			break
		}
		// fmt.Println(currentid + "->" + relation[currentid])
		currentid = relation[currentid]

	}
	//

	//
	// fmt.Println("---- layer")
	// reverse
	// SliceTricks · golang/go Wiki
	// https://github.com/golang/go/wiki/SliceTricks
	for i := len(layerHistoryList)/2 - 1; i >= 0; i-- {
		opp := len(layerHistoryList) - 1 - i
		layerHistoryList[i], layerHistoryList[opp] = layerHistoryList[opp], layerHistoryList[i]
	}
	// for _, layer := range layerHistoryList {
	// 	fmt.Println(layer)
	// }
	// fmt.Println("---- createdBy layer")
	// for _, createdBy := range createdByHistoryList {
	// 	fmt.Println(createdBy)
	// }
	var createdByListMap = map[string][]string{}
	var currentLayerID = ""
	var currentLayerIndex = 0
	for _, createdBy := range createdByHistoryList {
		if strings.Index(createdBy, "#(nop)") != -1 && strings.Index(createdBy, "ADD") == -1 && strings.Index(createdBy, "COPY") == -1 {
			//fmt.Println(strings.Repeat("-", 12) + " " + createdBy)
		} else {
			currentLayerID = layerHistoryList[currentLayerIndex]
			currentLayerIndex++
		}
		createdByListMap[currentLayerID] = append(createdByListMap[currentLayerID], createdBy)
	}
	//
	var layerIndex = 0

	for _, createdBy := range createdByHistoryList {
		if strings.Index(createdBy, "#(nop)") != -1 && strings.Index(createdBy, "ADD") == -1 && strings.Index(createdBy, "COPY") == -1 {
			//fmt.Println(strings.Repeat("-", 12) + " " + createdBy)
		} else {
			var layerID = layerHistoryList[layerIndex]
			for _, savedCreatedBy := range createdByListMap[layerID] {
				fmt.Println(layerID[:12] + "  " + savedCreatedBy)
			}
			//fmt.Println(allJsonMap[layerID])

			for _, layerTarHeader := range layerTarMap[layerID] {
				var filename = layerTarHeader.Name
				var deleteflag = false
				if strings.Index(filename, ".wh.") != -1 {
					deleteflag = true
					filename = strings.Replace(filename, ".wh.", "", -1)
				}
				//
				var status = "A"

				// check add or changes
				var fileHistoryList = fileHistoryListMap[filename]
				var fileHistoryIndex = 0
				var fileSize int64
				fileSize = 0
				for _, fileHistoryID := range fileHistoryList {
					var lTH2Size int64
					lTH2Size = 0
					for _, lTH2 := range layerTarMap[fileHistoryID] {
						if lTH2.Name == layerTarHeader.Name || lTH2.Name == filename {
							lTH2Size = lTH2.Size
							break
						}
					}
					fileSize = lTH2Size - fileSize
					if fileHistoryID == layerID {
						if fileHistoryIndex == 0 {

						} else {
							status = "C"

						}
						break
					}
					fileHistoryIndex++
				}

				if deleteflag {
					status = "D"
				}
				// calc size
				//
				var isOutput = false
				if isFiltering {
					if m, _ := regexp.MatchString(filteringWord, filename); m {
						isOutput = true
					}
				} else {
					isOutput = true
				}
				if isOutput {
					fmt.Println(status + " " + filename + " " + strconv.FormatInt(fileSize, 10) + " " + strconv.Itoa(layerTarHeader.Uid) + "(" + layerTarHeader.Uname + ")" + ":" + strconv.Itoa(layerTarHeader.Gid) + "(" + layerTarHeader.Gname + ")" + " " + strconv.FormatInt(layerTarHeader.Mode, 8))
				}
			}

			layerIndex++
		}
	}

}
<commit_msg>set version 0.1.2-dev<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"

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

const version = "0.1.2-dev"

func main() {
	endpoint := "unix:///var/run/docker.sock"
	client, _ := docker.NewClient(endpoint)
	var isFiltering = false
	var filteringWord = ""
	var argc = len(os.Args)
	if argc < 2 {
		os.Exit(2)
	} else if argc == 3 {
		isFiltering = true
		filteringWord = os.Args[2]
	}

	historyList, err := client.ImageHistory(os.Args[1])
	if err != nil {
		fmt.Println("Error happens at client.ImageHistory")
		os.Exit(2)
	}
	// First CreatedBy newer to older
	var createdByHistoryList = []string{}
	// layer ID -> json
	var jsonMap = map[string]string{}
	var allJsonMap = map[string]string{}
	var layerTarMap = map[string][]*tar.Header{}
	var first = false
	for _, history := range historyList {
		createdByHistoryList = append(createdByHistoryList, history.CreatedBy)
		image, err := client.InspectImage(history.ID)
		if err != nil || first {
			// continue to create CreatedBy list
			continue
		}
		if image != nil {
			var buf bytes.Buffer
			opts := docker.ExportImageOptions{Name: image.ID, OutputStream: &buf}
			err := client.ExportImage(opts)
			if err != nil {
				fmt.Println("Error happens at client.ExportImage")
				os.Exit(2)
			}
			r := bytes.NewReader(buf.Bytes())
			tr := tar.NewReader(r)
			var header *tar.Header
			for {
				header, err = tr.Next()
				if err == io.EOF {
					// end of image tar
					break
				}
				if err != nil {
					fmt.Println(err)
					fmt.Println("Error at tar extract")
					os.Exit(2)
				}

				buf2 := new(bytes.Buffer)
				if _, err = io.Copy(buf2, tr); err != nil {
					fmt.Println(err)
				}
				//
				var field = strings.Split(header.Name, "/")
				var layerID = field[0]
				// find json and layer.tar
				if strings.HasSuffix(header.Name, "/json") {
					var jsonstring = buf2.String()
					//var imagestring = ""
					allJsonMap[layerID] = jsonstring
					if strings.Index(jsonstring, "\"Image\":\"\"") != -1 || !first {
						jsonMap[layerID] = jsonstring
					}
				} else if strings.HasSuffix(header.Name, "layer.tar") {

					r2 := bytes.NewReader(buf2.Bytes())
					layerTar := tar.NewReader(r2)
					for {
						layerTarHeader, e4 := layerTar.Next()
						if e4 == io.EOF {
							// end of layer.tar
							break
						}
						layerTarMap[layerID] = append(layerTarMap[layerID], layerTarHeader)
					}
				}
			}
		}
		first = true

	}
	// fmt.Println("---- createdBy")
	// for _, createdBy := range createdByHistoryList {
	// 	fmt.Println(createdBy)
	// }
	// construct parent map
	//fmt.Println("---- jsonMap")
	var relation = map[string]string{}
	//var key string
	var value string
	var noparentid string
	for _, value = range jsonMap {
		//fmt.Println(key + " -> " + value)
		//dec := json.NewDecoder(v)
		var f interface{}
		//dec.Decode(&d)
		json.Unmarshal([]byte(value), &f)
		//fmt.Printf("%+v\n", d)
		m := f.(map[string]interface{})
		var id = m["id"]
		var parent = m["parent"]
		if parent == nil {
			noparentid = id.(string)
		} else {
			var p = parent.(string)
			_, ok := relation[p]
			if !ok {
				relation[p] = id.(string)
			}
		}
	}

	// fmt.Println("---- tarinfo")
	// fmt.Println("Start from:" + noparentid)
	var currentid = noparentid

	for {
		//fmt.Println(currentid)
		// find next
		_, ok := relation[currentid]
		if !ok {
			break
		}
		currentid = relation[currentid]
	}
	//
	var fileHistoryListMap = map[string][]string{}
	var layerHistoryList = []string{}
	// fmt.Println("---- reconstruct")
	// fmt.Println("Start from:" + noparentid)
	currentid = noparentid
	for {
		//
		for _, layerTarHeader := range layerTarMap[currentid] {
			var filename = layerTarHeader.Name
			filename = strings.Replace(filename, ".wh.", "", -1)
			fileHistoryListMap[filename] = append(fileHistoryListMap[filename], currentid)
		}
		//
		layerHistoryList = append(layerHistoryList, currentid)
		_, ok := relation[currentid]
		if !ok {
			break
		}
		// fmt.Println(currentid + "->" + relation[currentid])
		currentid = relation[currentid]

	}
	//

	//
	// fmt.Println("---- layer")
	// reverse
	// SliceTricks · golang/go Wiki
	// https://github.com/golang/go/wiki/SliceTricks
	for i := len(layerHistoryList)/2 - 1; i >= 0; i-- {
		opp := len(layerHistoryList) - 1 - i
		layerHistoryList[i], layerHistoryList[opp] = layerHistoryList[opp], layerHistoryList[i]
	}
	// for _, layer := range layerHistoryList {
	// 	fmt.Println(layer)
	// }
	// fmt.Println("---- createdBy layer")
	// for _, createdBy := range createdByHistoryList {
	// 	fmt.Println(createdBy)
	// }
	var createdByListMap = map[string][]string{}
	var currentLayerID = ""
	var currentLayerIndex = 0
	for _, createdBy := range createdByHistoryList {
		if strings.Index(createdBy, "#(nop)") != -1 && strings.Index(createdBy, "ADD") == -1 && strings.Index(createdBy, "COPY") == -1 {
			//fmt.Println(strings.Repeat("-", 12) + " " + createdBy)
		} else {
			currentLayerID = layerHistoryList[currentLayerIndex]
			currentLayerIndex++
		}
		createdByListMap[currentLayerID] = append(createdByListMap[currentLayerID], createdBy)
	}
	//
	var layerIndex = 0

	for _, createdBy := range createdByHistoryList {
		if strings.Index(createdBy, "#(nop)") != -1 && strings.Index(createdBy, "ADD") == -1 && strings.Index(createdBy, "COPY") == -1 {
			//fmt.Println(strings.Repeat("-", 12) + " " + createdBy)
		} else {
			var layerID = layerHistoryList[layerIndex]
			for _, savedCreatedBy := range createdByListMap[layerID] {
				fmt.Println(layerID[:12] + "  " + savedCreatedBy)
			}
			//fmt.Println(allJsonMap[layerID])

			for _, layerTarHeader := range layerTarMap[layerID] {
				var filename = layerTarHeader.Name
				var deleteflag = false
				if strings.Index(filename, ".wh.") != -1 {
					deleteflag = true
					filename = strings.Replace(filename, ".wh.", "", -1)
				}
				//
				var status = "A"

				// check add or changes
				var fileHistoryList = fileHistoryListMap[filename]
				var fileHistoryIndex = 0
				var fileSize int64
				fileSize = 0
				for _, fileHistoryID := range fileHistoryList {
					var lTH2Size int64
					lTH2Size = 0
					for _, lTH2 := range layerTarMap[fileHistoryID] {
						if lTH2.Name == layerTarHeader.Name || lTH2.Name == filename {
							lTH2Size = lTH2.Size
							break
						}
					}
					fileSize = lTH2Size - fileSize
					if fileHistoryID == layerID {
						if fileHistoryIndex == 0 {

						} else {
							status = "C"

						}
						break
					}
					fileHistoryIndex++
				}

				if deleteflag {
					status = "D"
				}
				// calc size
				//
				var isOutput = false
				if isFiltering {
					if m, _ := regexp.MatchString(filteringWord, filename); m {
						isOutput = true
					}
				} else {
					isOutput = true
				}
				if isOutput {
					fmt.Println(status + " " + filename + " " + strconv.FormatInt(fileSize, 10) + " " + strconv.Itoa(layerTarHeader.Uid) + "(" + layerTarHeader.Uname + ")" + ":" + strconv.Itoa(layerTarHeader.Gid) + "(" + layerTarHeader.Gname + ")" + " " + strconv.FormatInt(layerTarHeader.Mode, 8))
				}
			}

			layerIndex++
		}
	}

}
<|endoftext|>


<commit_before>// Copyright 2016 Istio 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 template

import (
	"context"
	"fmt"
	"net"

	"github.com/gogo/protobuf/proto"
	multierror "github.com/hashicorp/go-multierror"

	"istio.io/api/mixer/v1/config"
	pb "istio.io/api/mixer/v1/config/descriptor"
	adptTmpl "istio.io/api/mixer/v1/template"
	"istio.io/istio/mixer/pkg/adapter"
	"istio.io/istio/mixer/pkg/attribute"
	"istio.io/istio/mixer/pkg/expr"
	"istio.io/istio/mixer/pkg/il/compiled"
	"istio.io/istio/pkg/log"
)

type (
	// Repository defines all the helper functions to access the generated template specific types and fields.
	Repository interface {
		GetTemplateInfo(template string) (Info, bool)
		SupportsTemplate(hndlrBuilder adapter.HandlerBuilder, tmpl string) (bool, string)
	}
	// TypeEvalFn evaluates an expression and returns the ValueType for the expression.
	TypeEvalFn func(string) (pb.ValueType, error)
	// InferTypeFn does Type inference from the Instance.params proto message.
	InferTypeFn func(proto.Message, TypeEvalFn) (proto.Message, error)
	// SetTypeFn dispatches the inferred types to handlers
	SetTypeFn func(types map[string]proto.Message, builder adapter.HandlerBuilder)

	// ProcessCheckFn instantiates the instance object and dispatches them to the handler.
	ProcessCheckFn func(ctx context.Context, instName string, instCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) (adapter.CheckResult, error)

	// ProcessQuotaFn instantiates the instance object and dispatches them to the handler.
	ProcessQuotaFn func(ctx context.Context, quotaName string, quotaCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler, args adapter.QuotaArgs) (adapter.QuotaResult, error)

	// ProcessReportFn instantiates the instance object and dispatches them to the handler.
	ProcessReportFn func(ctx context.Context, instCfg map[string]proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) error

	// ProcessGenerateAttributesFn instantiates the instance object and dispatches them to the attribute generating handler.
	ProcessGenerateAttributesFn func(ctx context.Context, instName string, instCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) (*attribute.MutableBag, error)

	// BuilderSupportsTemplateFn check if the handlerBuilder supports template.
	BuilderSupportsTemplateFn func(hndlrBuilder adapter.HandlerBuilder) bool

	// HandlerSupportsTemplateFn check if the handler supports template.
	HandlerSupportsTemplateFn func(hndlr adapter.Handler) bool

	// DispatchCheckFn dispatches the instance to the handler.
	DispatchCheckFn func(ctx context.Context, handler adapter.Handler, instance interface{}) (adapter.CheckResult, error)

	// DispatchReportFn dispatches the instances to the handler.
	DispatchReportFn func(ctx context.Context, handler adapter.Handler, instances []interface{}) error

	// DispatchQuotaFn dispatches the instance to the handler.
	DispatchQuotaFn func(ctx context.Context, handler adapter.Handler, instance interface{}, args adapter.QuotaArgs) (adapter.QuotaResult, error)

	// DispatchGenerateAttributesFn dispatches the instance object to the attribute generating handler.
	DispatchGenerateAttributesFn func(ctx context.Context, handler adapter.Handler, instance interface{},
		attrs attribute.Bag, mapper OutputMapperFn) (*attribute.MutableBag, error)

	// InstanceBuilderFn builds and returns an instance, based on the attributes supplied.
	// Typically, InstanceBuilderFn closes over an auto-generated "builder" struct which contains compiled
	// expressions and sub-builders for the instance:
	//
	//  // An InstanceBuilderFn implementation:
	//  func(attrs attribute.Bag) (interface{}, error) {
	//    // myInstanceBuilder is an instance of a builder struct that this function closes over (see below).
	//    return myInstanceBuilder.build(bag)
	//  }
	//
	//  // myInstanceBuilder is an auto-generated struct for building instances. They get instantiated
	//  // based on instance parameters (see CreateInstanceBuilderFn documentation):
	//  type myInstanceBuilder struct {
	//
	//     // field1Builder builds the value of the field field1 of the instance.
	//     field1Builder compiled.Expression
	//     ...
	//  }
	//
	//  func (b *myInstanceBuilder) build(attrs attribute.Bag) (*myInstance, error) {
	//    ...
	//    instance := &myInstance{}
	//
	//    // Build the value of field1
	//    if instance1.field1, err = b.field1Builder.EvaluateString(bag); err != nil {
	//       return nil, err
	//    }
	//    ...
	//    return instance, nil
	//
	InstanceBuilderFn func(attrs attribute.Bag) (interface{}, error)

	// CreateInstanceBuilderFn returns a function that can build instances, based on the instanceParam:
	//
	//  // A CreateInstanceBuilderFn implementation:
	//  func(instanceName string, instanceParam interface{}, builder *compiled.ExpressionBuilder) (InstanceBuilderFn, error) {
	//    // Call an auto-generated function to create a builder struct.
	//    builder, err := newMyInstanceBuilder(instanceName, instanceParam, builder)
	//    if err != nil {
	//       return nil, err
	//    }
	//
	//    // return an InstanceBuilderfn
	//    func(attrs attribute.Bag) (interface{}, error) {
	//      // myInstanceBuilder is an instance of a builder struct that this function closes over (see below).
	//      return myInstanceBuilder.build(bag)
	//    }
	//  }
	//
	//  // Auto-generated method for creating a new builder struct
	//  func newMyInstanceBuilder(instanceName string, instanceParam interface{}, exprBuilder *compiled.ExpressionBuilder) (*myInstanceBuilder, error) {
	//     myInstanceParam := instanceParam.(*myInstanceParam)
	//     builder := &myInstanceBuilder{}
	//
	//     builder.field1Builder, err = exprBuilder.Compile(myInstanceParam.field1Expression)
	//     if err != nil {
	//       return nil, err
	//     }
	//  }
	CreateInstanceBuilderFn func(instanceName string, instanceParam proto.Message, builder *compiled.ExpressionBuilder) (InstanceBuilderFn, error)

	// CreateOutputExpressionsFn builds and returns a map of attribute names to the expression for calculating them.
	//
	//  // A CreateOutputExpressionsFn implementation:
	//  func(instanceParam interface{}, finder expr.AttributeDescriptorFinder, builder *compiled.ExpressionBuilder) (map[string]compiled.Expression, error) {
	//
	//    // Convert the generic instanceParam to its specialized type.
	//     param := instanceParam.(*myInstanceParam)
	//
	//    // Create a mapping of expressions back to the attribute names.
	//    expressions := make(map[string]compiled.Expression, len(param.AttributeBindings))
	//    for attrName, outExpr := range param.AttributeBindings {
	//       // compile an expression and put it in expressions.
	//    }
	//
	//    return expressions, nil
	//  }
	//
	CreateOutputExpressionsFn func(
		instanceParam proto.Message,
		finder expr.AttributeDescriptorFinder,
		expb *compiled.ExpressionBuilder) (map[string]compiled.Expression, error)

	// OutputMapperFn maps the results of an APA output bag, with "$out"s, by processing it through
	// AttributeBindings.
	//
	//  MapperFn: func(attrs attribute.Bag) (*attribute.MutableBag, error) {...}
	//
	//  ProcessGenerateAttributes2Fn(..., attrs attribute.Bag) (*attribute.MutableBag, error) [
	//    // use instance to call into the handler and get back a bag with "$out" values in it.
	//    outBag := ...
	//
	//    // Call an OutputMapperFn to map "$out.<name>" parameters to actual attribute values
	//    resultBag := MapperFn(outBag)
	//    return resultBag, nil
	//  }
	OutputMapperFn func(attrs attribute.Bag) (*attribute.MutableBag, error)

	// Info contains all the information related a template like
	// Default instance params, type inference method etc.
	Info struct {
		Name                    string
		Impl                    string
		Variety                 adptTmpl.TemplateVariety
		BldrInterfaceName       string
		HndlrInterfaceName      string
		CtrCfg                  proto.Message
		InferType               InferTypeFn
		SetType                 SetTypeFn
		BuilderSupportsTemplate BuilderSupportsTemplateFn
		HandlerSupportsTemplate HandlerSupportsTemplateFn
		ProcessReport           ProcessReportFn
		ProcessCheck            ProcessCheckFn
		ProcessQuota            ProcessQuotaFn
		ProcessGenAttrs         ProcessGenerateAttributesFn

		AttributeManifests []*config.AttributeManifest

		DispatchReport   DispatchReportFn
		DispatchCheck    DispatchCheckFn
		DispatchQuota    DispatchQuotaFn
		DispatchGenAttrs DispatchGenerateAttributesFn

		CreateInstanceBuilder   CreateInstanceBuilderFn
		CreateOutputExpressions CreateOutputExpressionsFn
	}

	// templateRepo implements Repository
	repo struct {
		info map[string]Info

		allSupportedTmpls  []string
		tmplToBuilderNames map[string]string
	}
)

func (t repo) GetTemplateInfo(template string) (Info, bool) {
	if v, ok := t.info[template]; ok {
		return v, true
	}
	return Info{}, false
}

// NewRepository returns an implementation of Repository
func NewRepository(templateInfos map[string]Info) Repository {
	if templateInfos == nil {
		return repo{
			info:               make(map[string]Info),
			allSupportedTmpls:  make([]string, 0),
			tmplToBuilderNames: make(map[string]string),
		}
	}

	allSupportedTmpls := make([]string, len(templateInfos))
	tmplToBuilderNames := make(map[string]string)

	for t, v := range templateInfos {
		allSupportedTmpls = append(allSupportedTmpls, t)
		tmplToBuilderNames[t] = v.BldrInterfaceName
	}
	return repo{info: templateInfos, tmplToBuilderNames: tmplToBuilderNames, allSupportedTmpls: allSupportedTmpls}
}

func (t repo) SupportsTemplate(hndlrBuilder adapter.HandlerBuilder, tmpl string) (bool, string) {
	i, ok := t.GetTemplateInfo(tmpl)
	if !ok {
		return false, fmt.Sprintf("Supported template %v is not one of the allowed supported templates %v", tmpl, t.allSupportedTmpls)
	}

	if b := i.BuilderSupportsTemplate(hndlrBuilder); !b {
		return false, fmt.Sprintf("HandlerBuilder does not implement interface %s. "+
			"Therefore, it cannot support template %v", t.tmplToBuilderNames[tmpl], tmpl)
	}

	return true, ""
}

// EvalAll evaluates the value of the expression map using the passed in attributes.
func EvalAll(expressions map[string]string, attrs attribute.Bag, eval expr.Evaluator) (map[string]interface{}, error) {
	result := &multierror.Error{}
	labels := make(map[string]interface{}, len(expressions))
	for label, texpr := range expressions {
		val, err := eval.Eval(texpr, attrs)
		if err != nil {
			result = multierror.Append(result, fmt.Errorf("failed to construct value for label '%s': %v", label, err))
			continue
		}
		labels[label] = val
	}
	return labels, result.ErrorOrNil()
}

// NewOutputMapperFn creates and returns a function that creates new attributes, based on the supplied expression set.
func NewOutputMapperFn(expressions map[string]compiled.Expression) OutputMapperFn {
	return func(attrs attribute.Bag) (*attribute.MutableBag, error) {
		var val interface{}
		var err error

		resultBag := attribute.GetMutableBag(nil)
		for attrName, expr := range expressions {
			if val, err = expr.Evaluate(attrs); err != nil {
				return nil, err
			}

			switch v := val.(type) {
			case net.IP:
				// conversion to []byte necessary based on current IP_ADDRESS handling within Mixer
				// TODO: remove
				log.Info("converting net.IP to []byte")
				if v4 := v.To4(); v4 != nil {
					resultBag.Set(attrName, []byte(v4))
					continue
				}
				resultBag.Set(attrName, []byte(v.To16()))
			default:
				resultBag.Set(attrName, val)
			}
		}

		return resultBag, nil
	}
}
<commit_msg>Remove unguarded log.Info from request path (#3642)<commit_after>// Copyright 2016 Istio 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 template

import (
	"context"
	"fmt"
	"net"

	"github.com/gogo/protobuf/proto"
	multierror "github.com/hashicorp/go-multierror"

	"istio.io/api/mixer/v1/config"
	pb "istio.io/api/mixer/v1/config/descriptor"
	adptTmpl "istio.io/api/mixer/v1/template"
	"istio.io/istio/mixer/pkg/adapter"
	"istio.io/istio/mixer/pkg/attribute"
	"istio.io/istio/mixer/pkg/expr"
	"istio.io/istio/mixer/pkg/il/compiled"
)

type (
	// Repository defines all the helper functions to access the generated template specific types and fields.
	Repository interface {
		GetTemplateInfo(template string) (Info, bool)
		SupportsTemplate(hndlrBuilder adapter.HandlerBuilder, tmpl string) (bool, string)
	}
	// TypeEvalFn evaluates an expression and returns the ValueType for the expression.
	TypeEvalFn func(string) (pb.ValueType, error)
	// InferTypeFn does Type inference from the Instance.params proto message.
	InferTypeFn func(proto.Message, TypeEvalFn) (proto.Message, error)
	// SetTypeFn dispatches the inferred types to handlers
	SetTypeFn func(types map[string]proto.Message, builder adapter.HandlerBuilder)

	// ProcessCheckFn instantiates the instance object and dispatches them to the handler.
	ProcessCheckFn func(ctx context.Context, instName string, instCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) (adapter.CheckResult, error)

	// ProcessQuotaFn instantiates the instance object and dispatches them to the handler.
	ProcessQuotaFn func(ctx context.Context, quotaName string, quotaCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler, args adapter.QuotaArgs) (adapter.QuotaResult, error)

	// ProcessReportFn instantiates the instance object and dispatches them to the handler.
	ProcessReportFn func(ctx context.Context, instCfg map[string]proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) error

	// ProcessGenerateAttributesFn instantiates the instance object and dispatches them to the attribute generating handler.
	ProcessGenerateAttributesFn func(ctx context.Context, instName string, instCfg proto.Message, attrs attribute.Bag,
		mapper expr.Evaluator, handler adapter.Handler) (*attribute.MutableBag, error)

	// BuilderSupportsTemplateFn check if the handlerBuilder supports template.
	BuilderSupportsTemplateFn func(hndlrBuilder adapter.HandlerBuilder) bool

	// HandlerSupportsTemplateFn check if the handler supports template.
	HandlerSupportsTemplateFn func(hndlr adapter.Handler) bool

	// DispatchCheckFn dispatches the instance to the handler.
	DispatchCheckFn func(ctx context.Context, handler adapter.Handler, instance interface{}) (adapter.CheckResult, error)

	// DispatchReportFn dispatches the instances to the handler.
	DispatchReportFn func(ctx context.Context, handler adapter.Handler, instances []interface{}) error

	// DispatchQuotaFn dispatches the instance to the handler.
	DispatchQuotaFn func(ctx context.Context, handler adapter.Handler, instance interface{}, args adapter.QuotaArgs) (adapter.QuotaResult, error)

	// DispatchGenerateAttributesFn dispatches the instance object to the attribute generating handler.
	DispatchGenerateAttributesFn func(ctx context.Context, handler adapter.Handler, instance interface{},
		attrs attribute.Bag, mapper OutputMapperFn) (*attribute.MutableBag, error)

	// InstanceBuilderFn builds and returns an instance, based on the attributes supplied.
	// Typically, InstanceBuilderFn closes over an auto-generated "builder" struct which contains compiled
	// expressions and sub-builders for the instance:
	//
	//  // An InstanceBuilderFn implementation:
	//  func(attrs attribute.Bag) (interface{}, error) {
	//    // myInstanceBuilder is an instance of a builder struct that this function closes over (see below).
	//    return myInstanceBuilder.build(bag)
	//  }
	//
	//  // myInstanceBuilder is an auto-generated struct for building instances. They get instantiated
	//  // based on instance parameters (see CreateInstanceBuilderFn documentation):
	//  type myInstanceBuilder struct {
	//
	//     // field1Builder builds the value of the field field1 of the instance.
	//     field1Builder compiled.Expression
	//     ...
	//  }
	//
	//  func (b *myInstanceBuilder) build(attrs attribute.Bag) (*myInstance, error) {
	//    ...
	//    instance := &myInstance{}
	//
	//    // Build the value of field1
	//    if instance1.field1, err = b.field1Builder.EvaluateString(bag); err != nil {
	//       return nil, err
	//    }
	//    ...
	//    return instance, nil
	//
	InstanceBuilderFn func(attrs attribute.Bag) (interface{}, error)

	// CreateInstanceBuilderFn returns a function that can build instances, based on the instanceParam:
	//
	//  // A CreateInstanceBuilderFn implementation:
	//  func(instanceName string, instanceParam interface{}, builder *compiled.ExpressionBuilder) (InstanceBuilderFn, error) {
	//    // Call an auto-generated function to create a builder struct.
	//    builder, err := newMyInstanceBuilder(instanceName, instanceParam, builder)
	//    if err != nil {
	//       return nil, err
	//    }
	//
	//    // return an InstanceBuilderfn
	//    func(attrs attribute.Bag) (interface{}, error) {
	//      // myInstanceBuilder is an instance of a builder struct that this function closes over (see below).
	//      return myInstanceBuilder.build(bag)
	//    }
	//  }
	//
	//  // Auto-generated method for creating a new builder struct
	//  func newMyInstanceBuilder(instanceName string, instanceParam interface{}, exprBuilder *compiled.ExpressionBuilder) (*myInstanceBuilder, error) {
	//     myInstanceParam := instanceParam.(*myInstanceParam)
	//     builder := &myInstanceBuilder{}
	//
	//     builder.field1Builder, err = exprBuilder.Compile(myInstanceParam.field1Expression)
	//     if err != nil {
	//       return nil, err
	//     }
	//  }
	CreateInstanceBuilderFn func(instanceName string, instanceParam proto.Message, builder *compiled.ExpressionBuilder) (InstanceBuilderFn, error)

	// CreateOutputExpressionsFn builds and returns a map of attribute names to the expression for calculating them.
	//
	//  // A CreateOutputExpressionsFn implementation:
	//  func(instanceParam interface{}, finder expr.AttributeDescriptorFinder, builder *compiled.ExpressionBuilder) (map[string]compiled.Expression, error) {
	//
	//    // Convert the generic instanceParam to its specialized type.
	//     param := instanceParam.(*myInstanceParam)
	//
	//    // Create a mapping of expressions back to the attribute names.
	//    expressions := make(map[string]compiled.Expression, len(param.AttributeBindings))
	//    for attrName, outExpr := range param.AttributeBindings {
	//       // compile an expression and put it in expressions.
	//    }
	//
	//    return expressions, nil
	//  }
	//
	CreateOutputExpressionsFn func(
		instanceParam proto.Message,
		finder expr.AttributeDescriptorFinder,
		expb *compiled.ExpressionBuilder) (map[string]compiled.Expression, error)

	// OutputMapperFn maps the results of an APA output bag, with "$out"s, by processing it through
	// AttributeBindings.
	//
	//  MapperFn: func(attrs attribute.Bag) (*attribute.MutableBag, error) {...}
	//
	//  ProcessGenerateAttributes2Fn(..., attrs attribute.Bag) (*attribute.MutableBag, error) [
	//    // use instance to call into the handler and get back a bag with "$out" values in it.
	//    outBag := ...
	//
	//    // Call an OutputMapperFn to map "$out.<name>" parameters to actual attribute values
	//    resultBag := MapperFn(outBag)
	//    return resultBag, nil
	//  }
	OutputMapperFn func(attrs attribute.Bag) (*attribute.MutableBag, error)

	// Info contains all the information related a template like
	// Default instance params, type inference method etc.
	Info struct {
		Name                    string
		Impl                    string
		Variety                 adptTmpl.TemplateVariety
		BldrInterfaceName       string
		HndlrInterfaceName      string
		CtrCfg                  proto.Message
		InferType               InferTypeFn
		SetType                 SetTypeFn
		BuilderSupportsTemplate BuilderSupportsTemplateFn
		HandlerSupportsTemplate HandlerSupportsTemplateFn
		ProcessReport           ProcessReportFn
		ProcessCheck            ProcessCheckFn
		ProcessQuota            ProcessQuotaFn
		ProcessGenAttrs         ProcessGenerateAttributesFn

		AttributeManifests []*config.AttributeManifest

		DispatchReport   DispatchReportFn
		DispatchCheck    DispatchCheckFn
		DispatchQuota    DispatchQuotaFn
		DispatchGenAttrs DispatchGenerateAttributesFn

		CreateInstanceBuilder   CreateInstanceBuilderFn
		CreateOutputExpressions CreateOutputExpressionsFn
	}

	// templateRepo implements Repository
	repo struct {
		info map[string]Info

		allSupportedTmpls  []string
		tmplToBuilderNames map[string]string
	}
)

func (t repo) GetTemplateInfo(template string) (Info, bool) {
	if v, ok := t.info[template]; ok {
		return v, true
	}
	return Info{}, false
}

// NewRepository returns an implementation of Repository
func NewRepository(templateInfos map[string]Info) Repository {
	if templateInfos == nil {
		return repo{
			info:               make(map[string]Info),
			allSupportedTmpls:  make([]string, 0),
			tmplToBuilderNames: make(map[string]string),
		}
	}

	allSupportedTmpls := make([]string, len(templateInfos))
	tmplToBuilderNames := make(map[string]string)

	for t, v := range templateInfos {
		allSupportedTmpls = append(allSupportedTmpls, t)
		tmplToBuilderNames[t] = v.BldrInterfaceName
	}
	return repo{info: templateInfos, tmplToBuilderNames: tmplToBuilderNames, allSupportedTmpls: allSupportedTmpls}
}

func (t repo) SupportsTemplate(hndlrBuilder adapter.HandlerBuilder, tmpl string) (bool, string) {
	i, ok := t.GetTemplateInfo(tmpl)
	if !ok {
		return false, fmt.Sprintf("Supported template %v is not one of the allowed supported templates %v", tmpl, t.allSupportedTmpls)
	}

	if b := i.BuilderSupportsTemplate(hndlrBuilder); !b {
		return false, fmt.Sprintf("HandlerBuilder does not implement interface %s. "+
			"Therefore, it cannot support template %v", t.tmplToBuilderNames[tmpl], tmpl)
	}

	return true, ""
}

// EvalAll evaluates the value of the expression map using the passed in attributes.
func EvalAll(expressions map[string]string, attrs attribute.Bag, eval expr.Evaluator) (map[string]interface{}, error) {
	result := &multierror.Error{}
	labels := make(map[string]interface{}, len(expressions))
	for label, texpr := range expressions {
		val, err := eval.Eval(texpr, attrs)
		if err != nil {
			result = multierror.Append(result, fmt.Errorf("failed to construct value for label '%s': %v", label, err))
			continue
		}
		labels[label] = val
	}
	return labels, result.ErrorOrNil()
}

// NewOutputMapperFn creates and returns a function that creates new attributes, based on the supplied expression set.
func NewOutputMapperFn(expressions map[string]compiled.Expression) OutputMapperFn {
	return func(attrs attribute.Bag) (*attribute.MutableBag, error) {
		var val interface{}
		var err error

		resultBag := attribute.GetMutableBag(nil)
		for attrName, expr := range expressions {
			if val, err = expr.Evaluate(attrs); err != nil {
				return nil, err
			}

			switch v := val.(type) {
			case net.IP:
				// conversion to []byte necessary based on current IP_ADDRESS handling within Mixer
				if v4 := v.To4(); v4 != nil {
					resultBag.Set(attrName, []byte(v4))
					continue
				}
				resultBag.Set(attrName, []byte(v.To16()))
			default:
				resultBag.Set(attrName, val)
			}
		}

		return resultBag, nil
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Istio Authors. All Rights Reserved.
//
// 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 env

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

// Envoy stores data for Envoy process
type Envoy struct {
	cmd   *exec.Cmd
	ports *Ports
}

// NewEnvoy creates a new Envoy struct and starts envoy.
func (s *TestSetup) NewEnvoy(stress, faultInject bool, mfConf *MixerFilterConf, ports *Ports, epoch int,
	confVersion string) (*Envoy, error) {
	// Asssume test environment has copied latest envoy to $HOME/go/bin in bin/init.sh
	// TODO: use util.IstioBin instead to reduce dependency on PATH
	envoyPath := "envoy"
	// TODO: use util.IstioOut, so generate config is saved
	confPath := fmt.Sprintf("/tmp/config.conf.%v.json", ports.AdminPort)
	log.Printf("Envoy config: in %v\n", confPath)
	if err := s.CreateEnvoyConf(confPath, stress, faultInject, mfConf, ports, confVersion); err != nil {
		return nil, err
	}

	debugLevel := os.Getenv("ENVOY_DEBUG")
	if len(debugLevel) == 0 {
		debugLevel = "info"
	}

	// Don't use hot-start, each Envoy re-start use different base-id
	args := []string{"-c", confPath,
		"--base-id", strconv.Itoa(int(ports.AdminPort) + epoch)}
	if stress {
		args = append(args, "--concurrency", "10")
	} else {
		// debug is far too verbose.
		args = append(args, "-l", debugLevel, "--concurrency", "1")
	}
	if s.EnvoyParams != nil {
		args = append(args, s.EnvoyParams...)
	}
	/* #nosec */
	cmd := exec.Command(envoyPath, args...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return &Envoy{
		cmd:   cmd,
		ports: ports,
	}, nil
}

// Start starts the envoy process
func (s *Envoy) Start() error {
	err := s.cmd.Start()
	if err == nil {
		url := fmt.Sprintf("http://localhost:%v/server_info", s.ports.AdminPort)
		WaitForHTTPServer(url)
		WaitForPort(s.ports.ClientProxyPort)
		WaitForPort(s.ports.ServerProxyPort)
	}
	return err
}

// Stop stops the envoy process
func (s *Envoy) Stop() error {
	log.Printf("Kill Envoy ...\n")
	err := s.cmd.Process.Kill()
	log.Printf("Kill Envoy ... Done\n")
	return err
}
<commit_msg>use configurable paths for envoy and envoy config locations (#5248)<commit_after>// Copyright 2017 Istio Authors. All Rights Reserved.
//
// 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 env

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"

	"istio.io/istio/tests/util"
)

// Envoy stores data for Envoy process
type Envoy struct {
	cmd   *exec.Cmd
	ports *Ports
}

// NewEnvoy creates a new Envoy struct and starts envoy.
func (s *TestSetup) NewEnvoy(stress, faultInject bool, mfConf *MixerFilterConf, ports *Ports, epoch int,
	confVersion string) (*Envoy, error) {
	confPath := filepath.Join(util.IstioOut, fmt.Sprintf("config.conf.%v.json", ports.AdminPort))
	log.Printf("Envoy config: in %v\n", confPath)
	if err := s.CreateEnvoyConf(confPath, stress, faultInject, mfConf, ports, confVersion); err != nil {
		return nil, err
	}

	debugLevel := os.Getenv("ENVOY_DEBUG")
	if len(debugLevel) == 0 {
		debugLevel = "info"
	}

	// Don't use hot-start, each Envoy re-start use different base-id
	args := []string{"-c", confPath,
		"--base-id", strconv.Itoa(int(ports.AdminPort) + epoch)}
	if stress {
		args = append(args, "--concurrency", "10")
	} else {
		// debug is far too verbose.
		args = append(args, "-l", debugLevel, "--concurrency", "1")
	}
	if s.EnvoyParams != nil {
		args = append(args, s.EnvoyParams...)
	}
	/* #nosec */
	envoyPath := filepath.Join(util.IstioBin, "envoy")
	cmd := exec.Command(envoyPath, args...)
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return &Envoy{
		cmd:   cmd,
		ports: ports,
	}, nil
}

// Start starts the envoy process
func (s *Envoy) Start() error {
	err := s.cmd.Start()
	if err == nil {
		url := fmt.Sprintf("http://localhost:%v/server_info", s.ports.AdminPort)
		WaitForHTTPServer(url)
		WaitForPort(s.ports.ClientProxyPort)
		WaitForPort(s.ports.ServerProxyPort)
	}
	return err
}

// Stop stops the envoy process
func (s *Envoy) Stop() error {
	log.Printf("Kill Envoy ...\n")
	err := s.cmd.Process.Kill()
	log.Printf("Kill Envoy ... Done\n")
	return err
}
<|endoftext|>


<commit_before>package riot

import (
	"log"

	"github.com/go-ego/riot/types"
)

type ScoringFields struct {
	A, B, C float32
}

var (
	text1   = "Hello world, 你好世界!"
	textJP  = "こんにちは世界"
	textJP1 = "こんにちは世界, こんにちは"
	reqText = "World人口"
	reqG    = types.SearchReq{Text: "Google"}
	Req1    = types.SearchReq{Text: reqText}

	score1   = ScoringFields{1, 2, 3}
	score091 = ScoringFields{0, 9, 1}
	inxOpts  = &types.IndexerOpts{
		IndexType: types.LocsIndex,
	}
)

var (
	rankOptsMax1 = rankOptsMax(0, 1)

	rankOptsMax10      = rankOptsOrder(false)
	rankOptsMax10Order = rankOptsOrder(true)

	rankOptsMax3 = rankOptsMax(1, 3)
)

var text2 = "在路上, in the way"

func makeDocIds() map[string]bool {
	docIds := make(map[string]bool)
	docIds["5"] = true
	docIds["3"] = true
	docIds["1"] = true
	docIds["2"] = true

	return docIds
}

type RankByTokenProximity struct {
}

func (rule RankByTokenProximity) Score(
	doc types.IndexedDoc, fields interface{}) []float32 {
	if doc.TokenProximity < 0 {
		return []float32{}
	}
	return []float32{1.0 / (float32(doc.TokenProximity) + 1)}
}

func OrderlessOpts(idOnly bool) types.EngineOpts {
	return types.EngineOpts{
		Using:   1,
		IDOnly:  idOnly,
		GseDict: "./testdata/test_dict.txt",
	}
}

func rankEngineOpts(rankOpts types.RankOpts) types.EngineOpts {
	return types.EngineOpts{
		Using:       1,
		GseDict:     "./testdata/test_dict.txt",
		DefRankOpts: &rankOpts,
		IndexerOpts: inxOpts,
	}
}

func rankOptsOrder(order bool) types.RankOpts {
	return types.RankOpts{
		ReverseOrder:    order,
		OutputOffset:    0,
		MaxOutputs:      10,
		ScoringCriteria: &RankByTokenProximity{},
	}
}

func rankOptsMax(output, max int) types.RankOpts {
	return types.RankOpts{
		ReverseOrder:    true,
		OutputOffset:    output,
		MaxOutputs:      max,
		ScoringCriteria: &RankByTokenProximity{},
	}
}

var (
	TestIndexOpts = rankEngineOpts(rankOptsMax10)

	orderOpts = rankEngineOpts(rankOptsMax10Order)
)

func AddDocs(engine *Engine) {
	// docId := uint64(1)
	engine.Index("1", types.DocData{
		Content: "The world, 有七十亿人口人口",
		Fields:  score1,
	})

	// docId++
	engine.IndexDoc("2", types.DocIndexData{
		Content: "The world, 人口",
		Fields:  nil,
	})

	engine.Index("3", types.DocData{
		Content: "The world",
		Fields:  nil,
	})

	engine.Index("4", types.DocData{
		Content: "有人口",
		Fields:  ScoringFields{2, 3, 1},
	})

	engine.Index("5", types.DocData{
		Content: "The world, 七十亿人口",
		Fields:  score091,
	})

	engine.Index("6", types.DocData{
		Content: "有七十亿人口",
		Fields:  ScoringFields{2, 3, 3},
	})

	engine.Flush()
}

func AddDocsWithLabels(engine *Engine) {
	// docId := uint64(1)
	engine.Index("1", types.DocData{
		Content: "《复仇者联盟3：无限战争》是全片使用IMAX摄影机拍摄",
		Labels:  []string{"复仇者", "战争"},
	})
	log.Println("engine.Segment(): ",
		engine.Segment("《复仇者联盟3：无限战争》是全片使用IMAX摄影机拍摄"))

	// docId++
	engine.Index("2", types.DocData{
		Content: "在IMAX影院放映时",
		Labels:  []string{"影院"},
	})

	engine.Index("3", types.DocData{
		Content: " Google 是世界最大搜索引擎, baidu 是最大中文的搜索引擎",
		Labels:  []string{"Google"},
	})

	engine.Index("4", types.DocData{
		Content: "Google 在研制无人汽车",
		Labels:  []string{"Google"},
	})

	engine.Index("5", types.DocData{
		Content: " GAMAF 世界五大互联网巨头, BAT 是中国互联网三巨头",
		Labels:  []string{"互联网"},
	})

	engine.Flush()
}
<commit_msg>update test utils code [ci skip]<commit_after>package riot

import (
	"log"

	"github.com/go-ego/riot/types"
)

type ScoringFields struct {
	A, B, C float32
}

var (
	text1 = "Hello world, 你好世界!"
	text2 = "在路上, in the way"

	textJP  = "こんにちは世界"
	textJP1 = "こんにちは世界, こんにちは"
	reqText = "World人口"

	reqG = types.SearchReq{Text: "Google"}
	Req1 = types.SearchReq{Text: reqText}

	score1   = ScoringFields{1, 2, 3}
	score091 = ScoringFields{0, 9, 1}

	inxOpts = &types.IndexerOpts{
		IndexType: types.LocsIndex,
	}
)

var (
	rankOptsMax1 = rankOptsMax(0, 1)

	rankOptsMax10      = rankOptsOrder(false)
	rankOptsMax10Order = rankOptsOrder(true)

	rankOptsMax3 = rankOptsMax(1, 3)
)

func makeDocIds() map[string]bool {
	docIds := make(map[string]bool)
	docIds["5"] = true
	docIds["3"] = true
	docIds["1"] = true
	docIds["2"] = true

	return docIds
}

type RankByTokenProximity struct {
}

func (rule RankByTokenProximity) Score(
	doc types.IndexedDoc, fields interface{}) []float32 {
	if doc.TokenProximity < 0 {
		return []float32{}
	}
	return []float32{1.0 / (float32(doc.TokenProximity) + 1)}
}

func OrderlessOpts(idOnly bool) types.EngineOpts {
	return types.EngineOpts{
		Using:   1,
		IDOnly:  idOnly,
		GseDict: "./testdata/test_dict.txt",
	}
}

func rankEngineOpts(rankOpts types.RankOpts) types.EngineOpts {
	return types.EngineOpts{
		Using:       1,
		GseDict:     "./testdata/test_dict.txt",
		DefRankOpts: &rankOpts,
		IndexerOpts: inxOpts,
	}
}

func rankOptsOrder(order bool) types.RankOpts {
	return types.RankOpts{
		ReverseOrder:    order,
		OutputOffset:    0,
		MaxOutputs:      10,
		ScoringCriteria: &RankByTokenProximity{},
	}
}

func rankOptsMax(output, max int) types.RankOpts {
	return types.RankOpts{
		ReverseOrder:    true,
		OutputOffset:    output,
		MaxOutputs:      max,
		ScoringCriteria: &RankByTokenProximity{},
	}
}

var (
	TestIndexOpts = rankEngineOpts(rankOptsMax10)

	orderOpts = rankEngineOpts(rankOptsMax10Order)
)

func AddDocs(engine *Engine) {
	// docId := uint64(1)
	engine.Index("1", types.DocData{
		Content: "The world, 有七十亿人口人口",
		Fields:  score1,
	})

	// docId++
	engine.IndexDoc("2", types.DocIndexData{
		Content: "The world, 人口",
		Fields:  nil,
	})

	engine.Index("3", types.DocData{
		Content: "The world",
		Fields:  nil,
	})

	engine.Index("4", types.DocData{
		Content: "有人口",
		Fields:  ScoringFields{2, 3, 1},
	})

	engine.Index("5", types.DocData{
		Content: "The world, 七十亿人口",
		Fields:  score091,
	})

	engine.Index("6", types.DocData{
		Content: "有七十亿人口",
		Fields:  ScoringFields{2, 3, 3},
	})

	engine.Flush()
}

func AddDocsWithLabels(engine *Engine) {
	// docId := uint64(1)
	engine.Index("1", types.DocData{
		Content: "《复仇者联盟3：无限战争》是全片使用IMAX摄影机拍摄",
		Labels:  []string{"复仇者", "战争"},
	})
	log.Println("engine.Segment(): ",
		engine.Segment("《复仇者联盟3：无限战争》是全片使用IMAX摄影机拍摄"))

	// docId++
	engine.Index("2", types.DocData{
		Content: "在IMAX影院放映时",
		Labels:  []string{"影院"},
	})

	engine.Index("3", types.DocData{
		Content: " Google 是世界最大搜索引擎, baidu 是最大中文的搜索引擎",
		Labels:  []string{"Google"},
	})

	engine.Index("4", types.DocData{
		Content: "Google 在研制无人汽车",
		Labels:  []string{"Google"},
	})

	engine.Index("5", types.DocData{
		Content: " GAMAF 世界五大互联网巨头, BAT 是中国互联网三巨头",
		Labels:  []string{"互联网"},
	})

	engine.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"
	"time"
)

var templateContent = `
-- +migrate Up

-- +migrate Down
`
var tpl *template.Template

func init() {
	tpl = template.Must(template.New("new_migration").Parse(templateContent))
}

type NewCommand struct {
}

func (c *NewCommand) Help() string {
	helpText := `
Usage: sql-migrate new [options] name

  Create a new a database migration.

Options:

  -config=dbconfig.yml   Configuration file to use.
  -env="development"     Environment.
  name                   The name of the migration
`
	return strings.TrimSpace(helpText)
}

func (c *NewCommand) Synopsis() string {
	return "Create a new migration"
}

func (c *NewCommand) Run(args []string) int {
	cmdFlags := flag.NewFlagSet("redo", flag.ContinueOnError)
	cmdFlags.Usage = func() { ui.Output(c.Help()) }
	ConfigFlags(cmdFlags)

	if len(args) < 1 {
		err := errors.New("A name for the migration is needed")
		ui.Error(err.Error())
		return 1
	}

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if err := CreateMigration(cmdFlags.Arg(0)); err != nil {
		ui.Error(err.Error())
		return 1
	}
	return 0
}

func CreateMigration(name string) error {
	env, err := GetEnvironment()
	if err != nil {
		return err
	}

	if _, err := os.Stat(env.Dir); os.IsNotExist(err) {
		return err
	}

	fileName := fmt.Sprintf("%s-%s.sql", time.Now().Format("20060201150405"), strings.TrimSpace(name))
	f, err := os.Create(path.Join(env.Dir, fileName))

	if err != nil {
		return err
	}
	defer f.Close()
	return tpl.Execute(f, nil)
}
<commit_msg>Use correct FlagSet name<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"
	"time"
)

var templateContent = `
-- +migrate Up

-- +migrate Down
`
var tpl *template.Template

func init() {
	tpl = template.Must(template.New("new_migration").Parse(templateContent))
}

type NewCommand struct {
}

func (c *NewCommand) Help() string {
	helpText := `
Usage: sql-migrate new [options] name

  Create a new a database migration.

Options:

  -config=dbconfig.yml   Configuration file to use.
  -env="development"     Environment.
  name                   The name of the migration
`
	return strings.TrimSpace(helpText)
}

func (c *NewCommand) Synopsis() string {
	return "Create a new migration"
}

func (c *NewCommand) Run(args []string) int {
	cmdFlags := flag.NewFlagSet("new", flag.ContinueOnError)
	cmdFlags.Usage = func() { ui.Output(c.Help()) }
	ConfigFlags(cmdFlags)

	if len(args) < 1 {
		err := errors.New("A name for the migration is needed")
		ui.Error(err.Error())
		return 1
	}

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if err := CreateMigration(cmdFlags.Arg(0)); err != nil {
		ui.Error(err.Error())
		return 1
	}
	return 0
}

func CreateMigration(name string) error {
	env, err := GetEnvironment()
	if err != nil {
		return err
	}

	if _, err := os.Stat(env.Dir); os.IsNotExist(err) {
		return err
	}

	fileName := fmt.Sprintf("%s-%s.sql", time.Now().Format("20060201150405"), strings.TrimSpace(name))
	f, err := os.Create(path.Join(env.Dir, fileName))

	if err != nil {
		return err
	}
	defer f.Close()
	return tpl.Execute(f, nil)
}
<|endoftext|>


<commit_before>//
// Copyright 2021, Igor Varavko
//
// 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 gitlab

import (
	"fmt"
	"net/http"
	"time"
)

// PipelinesService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type PipelinesService struct {
	client *Client
}

// PipelineVariable represents a pipeline variable.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type PipelineVariable struct {
	Key          string `json:"key"`
	Value        string `json:"value"`
	VariableType string `json:"variable_type"`
}

// Pipeline represents a GitLab pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type Pipeline struct {
	ID             int             `json:"id"`
	IID            int             `json:"iid"`
	ProjectID      int             `json:"project_id"`
	Status         string          `json:"status"`
	Source         string          `json:"source"`
	Ref            string          `json:"ref"`
	SHA            string          `json:"sha"`
	BeforeSHA      string          `json:"before_sha"`
	Tag            bool            `json:"tag"`
	YamlErrors     string          `json:"yaml_errors"`
	User           *BasicUser      `json:"user"`
	UpdatedAt      *time.Time      `json:"updated_at"`
	CreatedAt      *time.Time      `json:"created_at"`
	StartedAt      *time.Time      `json:"started_at"`
	FinishedAt     *time.Time      `json:"finished_at"`
	CommittedAt    *time.Time      `json:"committed_at"`
	Duration       int             `json:"duration"`
	QueuedDuration int             `json:"queued_duration"`
	Coverage       string          `json:"coverage"`
	WebURL         string          `json:"web_url"`
	DetailedStatus *DetailedStatus `json:"detailed_status"`
}

// DetailedStatus contains detailed information about the status of a pipeline.
type DetailedStatus struct {
	Icon         string `json:"icon"`
	Text         string `json:"text"`
	Label        string `json:"label"`
	Group        string `json:"group"`
	Tooltip      string `json:"tooltip"`
	HasDetails   bool   `json:"has_details"`
	DetailsPath  string `json:"details_path"`
	Illustration struct {
		Image string `json:"image"`
	} `json:"illustration"`
	Favicon string `json:"favicon"`
}

func (p Pipeline) String() string {
	return Stringify(p)
}

// PipelineTestReport contains a detailed report of a test run.
type PipelineTestReport struct {
	TotalTime    float64              `json:"total_time"`
	TotalCount   int                  `json:"total_count"`
	SuccessCount int                  `json:"success_count"`
	FailedCount  int                  `json:"failed_count"`
	SkippedCount int                  `json:"skipped_count"`
	ErrorCount   int                  `json:"error_count"`
	TestSuites   []PipelineTestSuites `json:"test_suites"`
}

// PipelineTestSuites contains test suites results.
type PipelineTestSuites struct {
	Name         string              `json:"name"`
	TotalTime    float64             `json:"total_time"`
	TotalCount   int                 `json:"total_count"`
	SuccessCount int                 `json:"success_count"`
	FailedCount  int                 `json:"failed_count"`
	SkippedCount int                 `json:"skipped_count"`
	ErrorCount   int                 `json:"error_count"`
	TestCases    []PipelineTestCases `json:"test_cases"`
}

// PipelineTestCases contains test cases details.
type PipelineTestCases struct {
	Status         string         `json:"status"`
	Name           string         `json:"name"`
	Classname      string         `json:"classname"`
	File           string         `json:"file"`
	ExecutionTime  float64        `json:"execution_time"`
	SystemOutput   string         `json:"system_output"`
	StackTrace     string         `json:"stack_trace"`
	AttachmentURL  string         `json:"attachment_url"`
	RecentFailures RecentFailures `json:"recent_failures"`
}

// RecentFailures contains failures count for the project's default branch.
type RecentFailures struct {
	Count      int    `json:"count"`
	BaseBranch string `json:"base_branch"`
}

func (p PipelineTestReport) String() string {
	return Stringify(p)
}

// PipelineInfo shows the basic entities of a pipeline, mostly used as fields
// on other assets, like Commit.
type PipelineInfo struct {
	ID        int        `json:"id"`
	ProjectID int        `json:"project_id"`
	Status    string     `json:"status"`
	Source    string     `json:"source"`
	Ref       string     `json:"ref"`
	SHA       string     `json:"sha"`
	WebURL    string     `json:"web_url"`
	UpdatedAt *time.Time `json:"updated_at"`
	CreatedAt *time.Time `json:"created_at"`
}

func (p PipelineInfo) String() string {
	return Stringify(p)
}

// ListProjectPipelinesOptions represents the available ListProjectPipelines() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines
type ListProjectPipelinesOptions struct {
	ListOptions
	Scope         *string          `url:"scope,omitempty" json:"scope,omitempty"`
	Status        *BuildStateValue `url:"status,omitempty" json:"status,omitempty"`
	Source        *string          `url:"source,omitempty" json:"source,omitempty"`
	Ref           *string          `url:"ref,omitempty" json:"ref,omitempty"`
	SHA           *string          `url:"sha,omitempty" json:"sha,omitempty"`
	YamlErrors    *bool            `url:"yaml_errors,omitempty" json:"yaml_errors,omitempty"`
	Name          *string          `url:"name,omitempty" json:"name,omitempty"`
	Username      *string          `url:"username,omitempty" json:"username,omitempty"`
	UpdatedAfter  *time.Time       `url:"updated_after,omitempty" json:"updated_after,omitempty"`
	UpdatedBefore *time.Time       `url:"updated_before,omitempty" json:"updated_before,omitempty"`
	OrderBy       *string          `url:"order_by,omitempty" json:"order_by,omitempty"`
	Sort          *string          `url:"sort,omitempty" json:"sort,omitempty"`
}

// ListProjectPipelines gets a list of project piplines.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines
func (s *PipelinesService) ListProjectPipelines(pid interface{}, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines", PathEscape(project))

	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var p []*PipelineInfo
	resp, err := s.client.Do(req, &p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipeline gets a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#get-a-single-pipeline
func (s *PipelinesService) GetPipeline(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipelineVariables gets the variables of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#get-variables-of-a-pipeline
func (s *PipelinesService) GetPipelineVariables(pid interface{}, pipeline int, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/variables", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var p []*PipelineVariable
	resp, err := s.client.Do(req, &p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipelineTestReport gets the test report of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-a-pipelines-test-report
func (s *PipelinesService) GetPipelineTestReport(pid interface{}, pipeline int, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/test_report", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(PipelineTestReport)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// CreatePipelineOptions represents the available CreatePipeline() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline
type CreatePipelineOptions struct {
	Ref       *string              `url:"ref" json:"ref"`
	Variables *[]*PipelineVariable `url:"variables,omitempty" json:"variables,omitempty"`
}

// CreatePipeline creates a new project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline
func (s *PipelinesService) CreatePipeline(pid interface{}, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipeline", PathEscape(project))

	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// RetryPipelineBuild retries failed builds in a pipeline
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/pipelines.html#retry-failed-builds-in-a-pipeline
func (s *PipelinesService) RetryPipelineBuild(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/retry", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// CancelPipelineBuild cancels a pipeline builds
//
// GitLab API docs:
//https://docs.gitlab.com/ce/api/pipelines.html#cancel-a-pipelines-builds
func (s *PipelinesService) CancelPipelineBuild(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/cancel", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// DeletePipeline deletes an existing pipeline.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/pipelines.html#delete-a-pipeline
func (s *PipelinesService) DeletePipeline(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<commit_msg>Introduce a PipelineVariableOptions struct<commit_after>//
// Copyright 2021, Igor Varavko
//
// 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 gitlab

import (
	"fmt"
	"net/http"
	"time"
)

// PipelinesService handles communication with the repositories related
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type PipelinesService struct {
	client *Client
}

// PipelineVariable represents a pipeline variable.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type PipelineVariable struct {
	Key          string `json:"key"`
	Value        string `json:"value"`
	VariableType string `json:"variable_type"`
}

// Pipeline represents a GitLab pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type Pipeline struct {
	ID             int             `json:"id"`
	IID            int             `json:"iid"`
	ProjectID      int             `json:"project_id"`
	Status         string          `json:"status"`
	Source         string          `json:"source"`
	Ref            string          `json:"ref"`
	SHA            string          `json:"sha"`
	BeforeSHA      string          `json:"before_sha"`
	Tag            bool            `json:"tag"`
	YamlErrors     string          `json:"yaml_errors"`
	User           *BasicUser      `json:"user"`
	UpdatedAt      *time.Time      `json:"updated_at"`
	CreatedAt      *time.Time      `json:"created_at"`
	StartedAt      *time.Time      `json:"started_at"`
	FinishedAt     *time.Time      `json:"finished_at"`
	CommittedAt    *time.Time      `json:"committed_at"`
	Duration       int             `json:"duration"`
	QueuedDuration int             `json:"queued_duration"`
	Coverage       string          `json:"coverage"`
	WebURL         string          `json:"web_url"`
	DetailedStatus *DetailedStatus `json:"detailed_status"`
}

// DetailedStatus contains detailed information about the status of a pipeline.
type DetailedStatus struct {
	Icon         string `json:"icon"`
	Text         string `json:"text"`
	Label        string `json:"label"`
	Group        string `json:"group"`
	Tooltip      string `json:"tooltip"`
	HasDetails   bool   `json:"has_details"`
	DetailsPath  string `json:"details_path"`
	Illustration struct {
		Image string `json:"image"`
	} `json:"illustration"`
	Favicon string `json:"favicon"`
}

func (p Pipeline) String() string {
	return Stringify(p)
}

// PipelineTestReport contains a detailed report of a test run.
type PipelineTestReport struct {
	TotalTime    float64              `json:"total_time"`
	TotalCount   int                  `json:"total_count"`
	SuccessCount int                  `json:"success_count"`
	FailedCount  int                  `json:"failed_count"`
	SkippedCount int                  `json:"skipped_count"`
	ErrorCount   int                  `json:"error_count"`
	TestSuites   []PipelineTestSuites `json:"test_suites"`
}

// PipelineTestSuites contains test suites results.
type PipelineTestSuites struct {
	Name         string              `json:"name"`
	TotalTime    float64             `json:"total_time"`
	TotalCount   int                 `json:"total_count"`
	SuccessCount int                 `json:"success_count"`
	FailedCount  int                 `json:"failed_count"`
	SkippedCount int                 `json:"skipped_count"`
	ErrorCount   int                 `json:"error_count"`
	TestCases    []PipelineTestCases `json:"test_cases"`
}

// PipelineTestCases contains test cases details.
type PipelineTestCases struct {
	Status         string         `json:"status"`
	Name           string         `json:"name"`
	Classname      string         `json:"classname"`
	File           string         `json:"file"`
	ExecutionTime  float64        `json:"execution_time"`
	SystemOutput   string         `json:"system_output"`
	StackTrace     string         `json:"stack_trace"`
	AttachmentURL  string         `json:"attachment_url"`
	RecentFailures RecentFailures `json:"recent_failures"`
}

// RecentFailures contains failures count for the project's default branch.
type RecentFailures struct {
	Count      int    `json:"count"`
	BaseBranch string `json:"base_branch"`
}

func (p PipelineTestReport) String() string {
	return Stringify(p)
}

// PipelineInfo shows the basic entities of a pipeline, mostly used as fields
// on other assets, like Commit.
type PipelineInfo struct {
	ID        int        `json:"id"`
	ProjectID int        `json:"project_id"`
	Status    string     `json:"status"`
	Source    string     `json:"source"`
	Ref       string     `json:"ref"`
	SHA       string     `json:"sha"`
	WebURL    string     `json:"web_url"`
	UpdatedAt *time.Time `json:"updated_at"`
	CreatedAt *time.Time `json:"created_at"`
}

func (p PipelineInfo) String() string {
	return Stringify(p)
}

// ListProjectPipelinesOptions represents the available ListProjectPipelines() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines
type ListProjectPipelinesOptions struct {
	ListOptions
	Scope         *string          `url:"scope,omitempty" json:"scope,omitempty"`
	Status        *BuildStateValue `url:"status,omitempty" json:"status,omitempty"`
	Source        *string          `url:"source,omitempty" json:"source,omitempty"`
	Ref           *string          `url:"ref,omitempty" json:"ref,omitempty"`
	SHA           *string          `url:"sha,omitempty" json:"sha,omitempty"`
	YamlErrors    *bool            `url:"yaml_errors,omitempty" json:"yaml_errors,omitempty"`
	Name          *string          `url:"name,omitempty" json:"name,omitempty"`
	Username      *string          `url:"username,omitempty" json:"username,omitempty"`
	UpdatedAfter  *time.Time       `url:"updated_after,omitempty" json:"updated_after,omitempty"`
	UpdatedBefore *time.Time       `url:"updated_before,omitempty" json:"updated_before,omitempty"`
	OrderBy       *string          `url:"order_by,omitempty" json:"order_by,omitempty"`
	Sort          *string          `url:"sort,omitempty" json:"sort,omitempty"`
}

// ListProjectPipelines gets a list of project piplines.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#list-project-pipelines
func (s *PipelinesService) ListProjectPipelines(pid interface{}, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines", PathEscape(project))

	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var p []*PipelineInfo
	resp, err := s.client.Do(req, &p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipeline gets a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#get-a-single-pipeline
func (s *PipelinesService) GetPipeline(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipelineVariables gets the variables of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#get-variables-of-a-pipeline
func (s *PipelinesService) GetPipelineVariables(pid interface{}, pipeline int, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/variables", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var p []*PipelineVariable
	resp, err := s.client.Do(req, &p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// GetPipelineTestReport gets the test report of a single project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/pipelines.html#get-a-pipelines-test-report
func (s *PipelinesService) GetPipelineTestReport(pid interface{}, pipeline int, options ...RequestOptionFunc) (*PipelineTestReport, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/test_report", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(PipelineTestReport)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// CreatePipelineOptions represents the available CreatePipeline() options.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline
type CreatePipelineOptions struct {
	Ref       *string                     `url:"ref" json:"ref"`
	Variables *[]*PipelineVariableOptions `url:"variables,omitempty" json:"variables,omitempty"`
}

// PipelineVariable represents a pipeline variable.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html
type PipelineVariableOptions struct {
	Key          *string `url:"key,omitempty" json:"key,omitempty"`
	Value        *string `url:"value,omitempty" json:"value,omitempty"`
	VariableType *string `url:"variable_type,omitempty" json:"variable_type,omitempty"`
}

// CreatePipeline creates a new project pipeline.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/pipelines.html#create-a-new-pipeline
func (s *PipelinesService) CreatePipeline(pid interface{}, opt *CreatePipelineOptions, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipeline", PathEscape(project))

	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// RetryPipelineBuild retries failed builds in a pipeline
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/pipelines.html#retry-failed-builds-in-a-pipeline
func (s *PipelinesService) RetryPipelineBuild(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/retry", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// CancelPipelineBuild cancels a pipeline builds
//
// GitLab API docs:
//https://docs.gitlab.com/ce/api/pipelines.html#cancel-a-pipelines-builds
func (s *PipelinesService) CancelPipelineBuild(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Pipeline, *Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d/cancel", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	p := new(Pipeline)
	resp, err := s.client.Do(req, p)
	if err != nil {
		return nil, resp, err
	}

	return p, resp, err
}

// DeletePipeline deletes an existing pipeline.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/pipelines.html#delete-a-pipeline
func (s *PipelinesService) DeletePipeline(pid interface{}, pipeline int, options ...RequestOptionFunc) (*Response, error) {
	project, err := parseID(pid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("projects/%s/pipelines/%d", PathEscape(project), pipeline)

	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package model

import (
	owlModel "github.com/Cepave/open-falcon-backend/common/model/owl"
)

type HostsResult struct {
	ID       int                  `gorm:"primary_key:true;column:id" json:"id"`
	Hostname string               `gorm:"column:hostname" json:"hostname" conform:"trim"`
	Groups   []*owlModel.GroupTag `json:"groups"`

	IdsOfGroups   string `gorm:"column:gt_ids"`
	NamesOfGroups string `gorm:"column:gt_names"`
}

func (HostsResult) TableName() string {
	return "host"
}

func (host *HostsResult) AfterLoad() {
	host.Groups = owlModel.SplitToArrayOfGroupTags(
		host.IdsOfGroups, ",",
		host.NamesOfGroups, "\000",
	)
}

type PluginTag struct {
	ID  int32  `json:"id"`
	Dir string `json:"dir"`
}

type HostgroupsResult struct {
	ID      int          `gorm:"primary_key:true;column:id" json:"id"`
	Name    string       `gorm:"column:grp_name" json:"name" conform:"trim"`
	Plugins []*PluginTag `json:"plugins"`

	IdsOfGroups   string `gorm:"column:gt_ids"`
	NamesOfGroups string `gorm:"column:gt_names"`
}

func (HostgroupsResult) TableName() string {
	return "grp"
}

func (hg *HostgroupsResult) AfterLoad() {
	groups := owlModel.SplitToArrayOfGroupTags(
		hg.IdsOfGroups, ",",
		hg.NamesOfGroups, "\000",
	)
	hg.Plugins = make([]*PluginTag, len(groups))
	for idx, val := range groups {
		hg.Plugins[idx] = &PluginTag{
			ID:  val.Id,
			Dir: val.Name,
		}
	}
}
<commit_msg>[OWL-1729] Hide GROUP_CONCAT fields from /api/v1/hostgroups API.<commit_after>package model

import (
	owlModel "github.com/Cepave/open-falcon-backend/common/model/owl"
	json "github.com/bitly/go-simplejson"
)

type HostsResult struct {
	ID       int                  `gorm:"primary_key:true;column:id" json:"id"`
	Hostname string               `gorm:"column:hostname" json:"hostname" conform:"trim"`
	Groups   []*owlModel.GroupTag `json:"groups"`

	IdsOfGroups   string `gorm:"column:gt_ids"`
	NamesOfGroups string `gorm:"column:gt_names"`
}

func (HostsResult) TableName() string {
	return "host"
}

func (host *HostsResult) AfterLoad() {
	host.Groups = owlModel.SplitToArrayOfGroupTags(
		host.IdsOfGroups, ",",
		host.NamesOfGroups, "\000",
	)
}

type PluginTag struct {
	ID  int32  `json:"id"`
	Dir string `json:"dir"`
}

func (pluginTag *PluginTag) ToJson() *json.Json {
	jsonPluginTag := json.New()
	jsonPluginTag.Set("id", pluginTag.ID)
	jsonPluginTag.Set("dir", pluginTag.Dir)

	return jsonPluginTag
}

type PluginTags []*PluginTag

func (pluginTags PluginTags) ToJson() []*json.Json {
	jsonPluginTags := make([]*json.Json, len(pluginTags))
	for idx, tag := range pluginTags {
		jsonPluginTags[idx] = tag.ToJson()
	}

	return jsonPluginTags
}

type HostgroupsResult struct {
	ID      int          `gorm:"primary_key:true;column:id" json:"id"`
	Name    string       `gorm:"column:grp_name" json:"name" conform:"trim"`
	Plugins []*PluginTag `json:"plugins"`

	IdsOfGroups   string `gorm:"column:gt_ids"`
	NamesOfGroups string `gorm:"column:gt_names"`
}

func (HostgroupsResult) TableName() string {
	return "grp"
}

func (hg *HostgroupsResult) ToSimpleJson() *json.Json {
	jsonObject := json.New()
	jsonObject.Set("id", hg.ID)
	jsonObject.Set("name", hg.Name)

	jsonPluginTags := PluginTags(hg.Plugins).ToJson()
	jsonObject.Set("plugins", jsonPluginTags)

	return jsonObject
}

func (hg *HostgroupsResult) MarshalJSON() ([]byte, error) {
	return hg.ToSimpleJson().MarshalJSON()
}

func (hg *HostgroupsResult) AfterLoad() {
	groups := owlModel.SplitToArrayOfGroupTags(
		hg.IdsOfGroups, ",",
		hg.NamesOfGroups, "\000",
	)
	hg.Plugins = make([]*PluginTag, len(groups))
	for idx, val := range groups {
		hg.Plugins[idx] = &PluginTag{
			ID:  val.Id,
			Dir: val.Name,
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 fuse

import (
	"errors"

	"github.com/jacobsa/bazilfuse"
	"golang.org/x/net/context"
)

// A struct representing the status of a mount operation, with methods for
// waiting on the mount to complete, waiting for unmounting, and causing
// unmounting.
type MountedFileSystem struct {
	dir string

	// The result to return from WaitForReady. Not valid until the channel is
	// closed.
	readyStatus          error
	readyStatusAvailable chan struct{}

	// The result to return from Join. Not valid until the channel is closed.
	joinStatus          error
	joinStatusAvailable chan struct{}
}

// Return the directory on which the file system is mounted (or where we
// attempted to mount it.)
func (mfs *MountedFileSystem) Dir() string {
	return mfs.dir
}

// Wait until the mount point is ready to be used. After a successful return
// from this function, the contents of the mounted file system should be
// visible in the directory supplied to NewMountPoint. May be called multiple
// times.
func (mfs *MountedFileSystem) WaitForReady(ctx context.Context) error {
	select {
	case <-mfs.readyStatusAvailable:
		return mfs.readyStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Block until a mounted file system has been unmounted. The return value will
// be non-nil if anything unexpected happened while serving. May be called
// multiple times. Must not be called unless WaitForReady has returned nil.
func (mfs *MountedFileSystem) Join(ctx context.Context) error {
	select {
	case <-mfs.joinStatusAvailable:
		return mfs.joinStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Attempt to unmount the file system. Use Join to wait for it to actually be
// unmounted. You must first call WaitForReady to ensure there is no race with
// mounting.
func (mfs *MountedFileSystem) Unmount() error {
	return bazilfuse.Unmount(mfs.dir)
}

// Runs in the background.
func (mfs *MountedFileSystem) mountAndServe(
	server *server,
	options []bazilfuse.MountOption) {
	logger := getLogger()

	// Open a FUSE connection.
	logger.Println("Opening a FUSE connection.")
	c, err := bazilfuse.Mount(mfs.dir, options...)
	if err != nil {
		mfs.readyStatus = errors.New("bazilfuse.Mount: " + err.Error())
		close(mfs.readyStatusAvailable)
		return
	}

	defer c.Close()

	// Start a goroutine that will notify the MountedFileSystem object when the
	// connection says it is ready (or it fails to become ready).
	go func() {
		logger.Println("Waiting for the FUSE connection to be ready.")
		<-c.Ready
		logger.Println("The FUSE connection is ready.")

		mfs.readyStatus = c.MountError
		close(mfs.readyStatusAvailable)
	}()

	// Serve the connection using the file system object.
	logger.Println("Serving the FUSE connection.")
	if err := server.Serve(c); err != nil {
		mfs.joinStatus = errors.New("Serve: " + err.Error())
		close(mfs.joinStatusAvailable)
		return
	}

	// Signal that everything is okay.
	close(mfs.joinStatusAvailable)
}

// Optional configuration accepted by Mount.
type MountConfig struct {
}

// Convert to mount options to be passed to package bazilfuse.
func (c *MountConfig) bazilfuseOptions() (opts []bazilfuse.MountOption) {
	opts = []bazilfuse.MountOption{
		// Enable permissions checking in the kernel. See the comments on
		// InodeAttributes.Mode.
		bazilfuse.SetOption("default_permissions", ""),
	}

	return
}

// Attempt to mount the supplied file system on the given directory.
// mfs.WaitForReady() must be called to find out whether the mount was
// successful.
func Mount(
	dir string,
	fs FileSystem,
	config *MountConfig) (mfs *MountedFileSystem, err error) {
	// Create a server object.
	server, err := newServer(fs)
	if err != nil {
		return
	}

	// Initialize the struct.
	mfs = &MountedFileSystem{
		dir:                  dir,
		readyStatusAvailable: make(chan struct{}),
		joinStatusAvailable:  make(chan struct{}),
	}

	// Mount in the background.
	go mfs.mountAndServe(server, config.bazilfuseOptions())

	return
}
<commit_msg>Added MountConfig.EnableVnodeCaching.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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 fuse

import (
	"errors"

	"github.com/jacobsa/bazilfuse"
	"golang.org/x/net/context"
)

// A struct representing the status of a mount operation, with methods for
// waiting on the mount to complete, waiting for unmounting, and causing
// unmounting.
type MountedFileSystem struct {
	dir string

	// The result to return from WaitForReady. Not valid until the channel is
	// closed.
	readyStatus          error
	readyStatusAvailable chan struct{}

	// The result to return from Join. Not valid until the channel is closed.
	joinStatus          error
	joinStatusAvailable chan struct{}
}

// Return the directory on which the file system is mounted (or where we
// attempted to mount it.)
func (mfs *MountedFileSystem) Dir() string {
	return mfs.dir
}

// Wait until the mount point is ready to be used. After a successful return
// from this function, the contents of the mounted file system should be
// visible in the directory supplied to NewMountPoint. May be called multiple
// times.
func (mfs *MountedFileSystem) WaitForReady(ctx context.Context) error {
	select {
	case <-mfs.readyStatusAvailable:
		return mfs.readyStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Block until a mounted file system has been unmounted. The return value will
// be non-nil if anything unexpected happened while serving. May be called
// multiple times. Must not be called unless WaitForReady has returned nil.
func (mfs *MountedFileSystem) Join(ctx context.Context) error {
	select {
	case <-mfs.joinStatusAvailable:
		return mfs.joinStatus
	case <-ctx.Done():
		return ctx.Err()
	}
}

// Attempt to unmount the file system. Use Join to wait for it to actually be
// unmounted. You must first call WaitForReady to ensure there is no race with
// mounting.
func (mfs *MountedFileSystem) Unmount() error {
	return bazilfuse.Unmount(mfs.dir)
}

// Runs in the background.
func (mfs *MountedFileSystem) mountAndServe(
	server *server,
	options []bazilfuse.MountOption) {
	logger := getLogger()

	// Open a FUSE connection.
	logger.Println("Opening a FUSE connection.")
	c, err := bazilfuse.Mount(mfs.dir, options...)
	if err != nil {
		mfs.readyStatus = errors.New("bazilfuse.Mount: " + err.Error())
		close(mfs.readyStatusAvailable)
		return
	}

	defer c.Close()

	// Start a goroutine that will notify the MountedFileSystem object when the
	// connection says it is ready (or it fails to become ready).
	go func() {
		logger.Println("Waiting for the FUSE connection to be ready.")
		<-c.Ready
		logger.Println("The FUSE connection is ready.")

		mfs.readyStatus = c.MountError
		close(mfs.readyStatusAvailable)
	}()

	// Serve the connection using the file system object.
	logger.Println("Serving the FUSE connection.")
	if err := server.Serve(c); err != nil {
		mfs.joinStatus = errors.New("Serve: " + err.Error())
		close(mfs.joinStatusAvailable)
		return
	}

	// Signal that everything is okay.
	close(mfs.joinStatusAvailable)
}

// Optional configuration accepted by Mount.
type MountConfig struct {
	// OS X only.
	//
	// Normally on OS X we mount with the novncache option
	// (cf. http://goo.gl/1pTjuk), which disables entry caching in the kernel.
	// This is because osxfuse does not support the entry expiration values we
	// return to it (cf. http://goo.gl/8yR0Ie) and it is probably better to fail
	// to cache than to cache for too long, since the latter is more likely to
	// hide consistency bugs that are difficult to detect and diagnose.
	//
	// This field disables the use of novncache, restoring entry caching. Beware:
	// the value of ChildInodeEntry.EntryExpiration is ignored by the kernel, and
	// entries will be cached for an arbitrarily long time.
	EnableVnodeCaching bool
}

// Convert to mount options to be passed to package bazilfuse.
func (c *MountConfig) bazilfuseOptions() (opts []bazilfuse.MountOption) {
	panic("TODO: Test and support MountConfig.EnableVnodeCaching")

	opts = []bazilfuse.MountOption{
		// Enable permissions checking in the kernel. See the comments on
		// InodeAttributes.Mode.
		bazilfuse.SetOption("default_permissions", ""),
	}

	return
}

// Attempt to mount the supplied file system on the given directory.
// mfs.WaitForReady() must be called to find out whether the mount was
// successful.
func Mount(
	dir string,
	fs FileSystem,
	config *MountConfig) (mfs *MountedFileSystem, err error) {
	// Create a server object.
	server, err := newServer(fs)
	if err != nil {
		return
	}

	// Initialize the struct.
	mfs = &MountedFileSystem{
		dir:                  dir,
		readyStatusAvailable: make(chan struct{}),
		joinStatusAvailable:  make(chan struct{}),
	}

	// Mount in the background.
	go mfs.mountAndServe(server, config.bazilfuseOptions())

	return
}
<|endoftext|>


<commit_before>package poke

import (
	"encoding/json"
	"fmt"
	"gopkg.in/cheggaaa/pb.v1"
	"io/ioutil"
	"net/http"
	"strconv"
)

const CACHED_FILE_LOCATION = "/tmp/pokemon.data"
const POKEMON_API = "https://pokeapi.co/api/v2/pokemon/"
const MOVE_API = "https://pokeapi.co/api/v2/move/"
const NUM_POKEMONS = 150
const NUM_MOVES = 639

func downloadResource(baseUrl string, id int) []byte {
	res, err := http.Get(baseUrl + strconv.Itoa(id))
	Check(err)
	bytes, err := ioutil.ReadAll(res.Body)
	Check(err)
	defer res.Body.Close()
	return bytes
}

func downloadData() PokemonData {
	pokeBar := pb.StartNew(NUM_POKEMONS)
	data := PokemonData{}
	// Keep making API calls and appending to list.
	for i := 1; i <= NUM_POKEMONS; i++ {
		bytes := downloadResource(POKEMON_API, i)

		apiRes := PokemonApiResponse{}
		err := json.Unmarshal(bytes, &apiRes)
		Check(err)
		data.Responses = append(data.Responses, apiRes)

		pokeBar.Increment()
	}
	pokeBar.FinishPrint("Finished downloading pokemons.")

	movesBar := pb.StartNew(NUM_MOVES)
	for i := 1; i <= NUM_MOVES; i++ {
		bytes := downloadResource(MOVE_API, i)

		apiRes := MoveApiResponse{}
		err := json.Unmarshal(bytes, &apiRes)
		Check(err)
		data.Moves = append(data.Moves, apiRes)

		movesBar.Increment()
	}
	movesBar.FinishPrint("Finished downloading moves.")
	return data
}

func MaybeDownloadData() []Pokemon {
	// Check cached location.
	var data PokemonData
	bytes, err := ioutil.ReadFile(CACHED_FILE_LOCATION)
	if err != nil {
		fmt.Println("Downloading data... (this may take a while)")
		data = downloadData()

		bytes, err = json.Marshal(data)
		Check(err)
		err = ioutil.WriteFile(CACHED_FILE_LOCATION, bytes, 0644)
		Check(err)
	} else {
		data = PokemonData{}
		err = json.Unmarshal(bytes, &data)
		Check(err)
	}
	return toPokemonsArray(data)
}

func toPokemonsArray(data PokemonData) []Pokemon {
	movesMap := make(map[string]Attack)
	for _, v := range data.Moves {
		movesMap[v.Name] = v.ToAttack()
	}

	res := make([]Pokemon, len(data.Responses))
	for i, v := range data.Responses {
		res[i] = v.ToPokemon(movesMap)
	}
	return res
}
<commit_msg>Include all pokemons<commit_after>package poke

import (
	"encoding/json"
	"fmt"
	"gopkg.in/cheggaaa/pb.v1"
	"io/ioutil"
	"net/http"
	"strconv"
)

const CACHED_FILE_LOCATION = "/tmp/pokemon.data"
const POKEMON_API = "https://pokeapi.co/api/v2/pokemon/"
const MOVE_API = "https://pokeapi.co/api/v2/move/"
const NUM_POKEMONS = 802
const NUM_MOVES = 639

func downloadResource(baseUrl string, id int) []byte {
	res, err := http.Get(baseUrl + strconv.Itoa(id))
	Check(err)
	bytes, err := ioutil.ReadAll(res.Body)
	Check(err)
	defer res.Body.Close()
	return bytes
}

func downloadData() PokemonData {
	pokeBar := pb.StartNew(NUM_POKEMONS)
	data := PokemonData{}
	// Keep making API calls and appending to list.
	for i := 1; i <= NUM_POKEMONS; i++ {
		bytes := downloadResource(POKEMON_API, i)

		apiRes := PokemonApiResponse{}
		err := json.Unmarshal(bytes, &apiRes)
		Check(err)
		data.Responses = append(data.Responses, apiRes)

		pokeBar.Increment()
	}
	pokeBar.FinishPrint("Finished downloading pokemons.")

	movesBar := pb.StartNew(NUM_MOVES)
	for i := 1; i <= NUM_MOVES; i++ {
		bytes := downloadResource(MOVE_API, i)

		apiRes := MoveApiResponse{}
		err := json.Unmarshal(bytes, &apiRes)
		Check(err)
		data.Moves = append(data.Moves, apiRes)

		movesBar.Increment()
	}
	movesBar.FinishPrint("Finished downloading moves.")
	return data
}

func MaybeDownloadData() []Pokemon {
	// Check cached location.
	var data PokemonData
	bytes, err := ioutil.ReadFile(CACHED_FILE_LOCATION)
	if err != nil {
		fmt.Println("Downloading data... (this may take a while)")
		data = downloadData()

		bytes, err = json.Marshal(data)
		Check(err)
		err = ioutil.WriteFile(CACHED_FILE_LOCATION, bytes, 0644)
		Check(err)
	} else {
		data = PokemonData{}
		err = json.Unmarshal(bytes, &data)
		Check(err)
	}
	return toPokemonsArray(data)
}

func toPokemonsArray(data PokemonData) []Pokemon {
	movesMap := make(map[string]Attack)
	for _, v := range data.Moves {
		movesMap[v.Name] = v.ToAttack()
	}

	res := make([]Pokemon, len(data.Responses))
	for i, v := range data.Responses {
		res[i] = v.ToPokemon(movesMap)
	}
	return res
}
<|endoftext|>