<commit_before>// Copyright 2011 <chaishushan@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package opencv

//#include "opencv.h"
//#cgo linux  pkg-config: opencv
//#cgo darwin pkg-config: opencv
//#cgo freebsd pkg-config: opencv
//#cgo windows LDFLAGS: -lopencv_core242.dll -lopencv_imgproc242.dll -lopencv_photo242.dll -lopencv_highgui242.dll -lstdc++
import "C"
import (
	//"errors"
	"unsafe"
)

func init() {
}

const (
	CV_BGR2GRAY  = C.CV_BGR2GRAY
	CV_BGR2BGRA  = C.CV_BGR2BGRA
	CV_RGBA2BGRA = C.CV_RGBA2BGRA

	CV_BLUR_NO_SCALE = C.CV_BLUR_NO_SCALE
	CV_BLUR          = C.CV_BLUR
	CV_GAUSSIAN      = C.CV_GAUSSIAN
	CV_MEDIAN        = C.CV_MEDIAN
	CV_BILATERAL     = C.CV_BILATERAL

	CV_8U  = C.CV_8U
	CV_8S  = C.CV_8S
	CV_16U = C.CV_16U
	CV_16S = C.CV_16S
	CV_32S = C.CV_32S
	CV_32F = C.CV_32F
	CV_64F = C.CV_64F
)

/* Smoothes array (removes noise) */
func Smooth(src, dst *IplImage, smoothtype,
	param1, param2 int, param3, param4 float64) {
	C.cvSmooth(unsafe.Pointer(src), unsafe.Pointer(dst), C.int(smoothtype),
		C.int(param1), C.int(param2), C.double(param3), C.double(param4),
	)
}

//CVAPI(void) cvSmooth( const CvArr* src, CvArr* dst,
//                      int smoothtype CV_DEFAULT(CV_GAUSSIAN),
//                      int param1 CV_DEFAULT(3),
//                      int param2 CV_DEFAULT(0),
//                      double param3 CV_DEFAULT(0),
//                      double param4 CV_DEFAULT(0));

/*
ConvertScale converts one image to another with optional linear transformation.
*/
func ConvertScale(a, b *IplImage, scale, shift float64) {
	C.cvConvertScale(unsafe.Pointer(a), unsafe.Pointer(b), C.double(scale), C.double(shift))
}

//CVAPI(void)  cvConvertScale( const CvArr* src,
//                             CvArr* dst,
//                             double scale CV_DEFAULT(1),
//                             double shift CV_DEFAULT(0) );

/* Converts input array pixels from one color space to another */
func CvtColor(src, dst *IplImage, code int) {
	C.cvCvtColor(unsafe.Pointer(src), unsafe.Pointer(dst), C.int(code))
}

//CVAPI(void)  cvCvtColor( const CvArr* src, CvArr* dst, int code );

/* Runs canny edge detector */
func Canny(image, edges *IplImage, threshold1, threshold2 float64, aperture_size int) {
	C.cvCanny(unsafe.Pointer(image), unsafe.Pointer(edges),
		C.double(threshold1), C.double(threshold2),
		C.int(aperture_size),
	)
}

//CVAPI(void)  cvCanny( const CvArr* image, CvArr* edges, double threshold1,
//                      double threshold2, int  aperture_size CV_DEFAULT(3) );

/* Calculates the first, second, third, or mixed image derivatives using an
* extended Sobel operator.  */
func Sobel(src, dst *IplImage, xorder, yorder, aperture_size int) {
	C.cvSobel(unsafe.Pointer(src), unsafe.Pointer(dst),
		C.int(xorder), C.int(yorder),
		C.int(aperture_size),
	)
}

// C: void cvSobel(const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 )

const (
	CV_INPAINT_NS    = C.CV_INPAINT_NS
	CV_INPAINT_TELEA = C.CV_INPAINT_TELEA
)

/* Inpaints the selected region in the image */
func Inpaint(src, inpaint_mask, dst *IplImage, inpaintRange float64, flags int) {
	C.cvInpaint(
		unsafe.Pointer(src),
		unsafe.Pointer(inpaint_mask),
		unsafe.Pointer(dst),
		C.double(inpaintRange),
		C.int(flags),
	)
}

//CVAPI(void) cvInpaint( const CvArr* src, const CvArr* inpaint_mask,
//                       CvArr* dst, double inpaintRange, int flags );

const (
	CV_THRESH_BINARY     = C.CV_THRESH_BINARY
	CV_THRESH_BINARY_INV = C.CV_THRESH_BINARY_INV
	CV_THRESH_TRUNC      = C.CV_THRESH_TRUNC
	CV_THRESH_TOZERO     = C.CV_THRESH_TOZERO
	CV_THRESH_TOZERO_INV = C.CV_THRESH_TOZERO_INV
)

/* Applies a fixed-level threshold to each array element. */
func Threshold(src, dst *IplImage, threshold, max_value float64, threshold_type int) {
	C.cvThreshold(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		C.double(threshold),
		C.double(max_value),
		C.int(threshold_type),
	)
}

//CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst, double threshold,
//                           double max_value, int threshold_type );

const (
	CV_ADAPTIVE_THRESH_MEAN_C     = C.CV_ADAPTIVE_THRESH_MEAN_C
	CV_ADAPTIVE_THRESH_GAUSSIAN_C = C.CV_ADAPTIVE_THRESH_GAUSSIAN_C
)

/* Applies an adaptive threshold to an array. */
func AdaptiveThreshold(src, dst *IplImage, max_value float64, adaptive_method,
	threshold_type, block_size int, thresh_C float64) {
	C.cvAdaptiveThreshold(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		C.double(max_value),
		C.int(adaptive_method),
		C.int(threshold_type),
		C.int(block_size),
		C.double(thresh_C),
	)
}

//CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
//                                 int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,
//                                 int threshold_type=CV_THRESH_BINARY,
//                                 int block_size=3, double param1=5 );
<commit_msg>added morphological operations<commit_after>// Copyright 2011 <chaishushan@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package opencv

//#include "opencv.h"
//#cgo linux  pkg-config: opencv
//#cgo darwin pkg-config: opencv
//#cgo freebsd pkg-config: opencv
//#cgo windows LDFLAGS: -lopencv_core242.dll -lopencv_imgproc242.dll -lopencv_photo242.dll -lopencv_highgui242.dll -lstdc++
import "C"
import (
	//"errors"
	"unsafe"
)

func init() {
}

const (
	CV_BGR2GRAY  = C.CV_BGR2GRAY
	CV_BGR2BGRA  = C.CV_BGR2BGRA
	CV_RGBA2BGRA = C.CV_RGBA2BGRA

	CV_BLUR_NO_SCALE = C.CV_BLUR_NO_SCALE
	CV_BLUR          = C.CV_BLUR
	CV_GAUSSIAN      = C.CV_GAUSSIAN
	CV_MEDIAN        = C.CV_MEDIAN
	CV_BILATERAL     = C.CV_BILATERAL

	CV_8U  = C.CV_8U
	CV_8S  = C.CV_8S
	CV_16U = C.CV_16U
	CV_16S = C.CV_16S
	CV_32S = C.CV_32S
	CV_32F = C.CV_32F
	CV_64F = C.CV_64F
)

/* Smoothes array (removes noise) */
func Smooth(src, dst *IplImage, smoothtype,
	param1, param2 int, param3, param4 float64) {
	C.cvSmooth(unsafe.Pointer(src), unsafe.Pointer(dst), C.int(smoothtype),
		C.int(param1), C.int(param2), C.double(param3), C.double(param4),
	)
}

//CVAPI(void) cvSmooth( const CvArr* src, CvArr* dst,
//                      int smoothtype CV_DEFAULT(CV_GAUSSIAN),
//                      int param1 CV_DEFAULT(3),
//                      int param2 CV_DEFAULT(0),
//                      double param3 CV_DEFAULT(0),
//                      double param4 CV_DEFAULT(0));

/*
ConvertScale converts one image to another with optional linear transformation.
*/
func ConvertScale(a, b *IplImage, scale, shift float64) {
	C.cvConvertScale(unsafe.Pointer(a), unsafe.Pointer(b), C.double(scale), C.double(shift))
}

//CVAPI(void)  cvConvertScale( const CvArr* src,
//                             CvArr* dst,
//                             double scale CV_DEFAULT(1),
//                             double shift CV_DEFAULT(0) );

/* Converts input array pixels from one color space to another */
func CvtColor(src, dst *IplImage, code int) {
	C.cvCvtColor(unsafe.Pointer(src), unsafe.Pointer(dst), C.int(code))
}

//CVAPI(void)  cvCvtColor( const CvArr* src, CvArr* dst, int code );

/* Runs canny edge detector */
func Canny(image, edges *IplImage, threshold1, threshold2 float64, aperture_size int) {
	C.cvCanny(unsafe.Pointer(image), unsafe.Pointer(edges),
		C.double(threshold1), C.double(threshold2),
		C.int(aperture_size),
	)
}

//CVAPI(void)  cvCanny( const CvArr* image, CvArr* edges, double threshold1,
//                      double threshold2, int  aperture_size CV_DEFAULT(3) );

/* Calculates the first, second, third, or mixed image derivatives using an
* extended Sobel operator.  */
func Sobel(src, dst *IplImage, xorder, yorder, aperture_size int) {
	C.cvSobel(unsafe.Pointer(src), unsafe.Pointer(dst),
		C.int(xorder), C.int(yorder),
		C.int(aperture_size),
	)
}

// C: void cvSobel(const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 )

const (
	CV_INPAINT_NS    = C.CV_INPAINT_NS
	CV_INPAINT_TELEA = C.CV_INPAINT_TELEA
)

/* Inpaints the selected region in the image */
func Inpaint(src, inpaint_mask, dst *IplImage, inpaintRange float64, flags int) {
	C.cvInpaint(
		unsafe.Pointer(src),
		unsafe.Pointer(inpaint_mask),
		unsafe.Pointer(dst),
		C.double(inpaintRange),
		C.int(flags),
	)
}

//CVAPI(void) cvInpaint( const CvArr* src, const CvArr* inpaint_mask,
//                       CvArr* dst, double inpaintRange, int flags );

const (
	CV_THRESH_BINARY     = C.CV_THRESH_BINARY
	CV_THRESH_BINARY_INV = C.CV_THRESH_BINARY_INV
	CV_THRESH_TRUNC      = C.CV_THRESH_TRUNC
	CV_THRESH_TOZERO     = C.CV_THRESH_TOZERO
	CV_THRESH_TOZERO_INV = C.CV_THRESH_TOZERO_INV
)

/* Applies a fixed-level threshold to each array element. */
func Threshold(src, dst *IplImage, threshold, max_value float64, threshold_type int) {
	C.cvThreshold(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		C.double(threshold),
		C.double(max_value),
		C.int(threshold_type),
	)
}

//CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst, double threshold,
//                           double max_value, int threshold_type );

const (
	CV_ADAPTIVE_THRESH_MEAN_C     = C.CV_ADAPTIVE_THRESH_MEAN_C
	CV_ADAPTIVE_THRESH_GAUSSIAN_C = C.CV_ADAPTIVE_THRESH_GAUSSIAN_C
)

/* Applies an adaptive threshold to an array. */
func AdaptiveThreshold(src, dst *IplImage, max_value float64, adaptive_method,
	threshold_type, block_size int, thresh_C float64) {
	C.cvAdaptiveThreshold(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		C.double(max_value),
		C.int(adaptive_method),
		C.int(threshold_type),
		C.int(block_size),
		C.double(thresh_C),
	)
}

//CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
//                                 int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C,
//                                 int threshold_type=CV_THRESH_BINARY,
//                                 int block_size=3, double param1=5 );

const (
	CV_MORPH_RECT    = 0
	CV_MORPH_ELLIPSE = 1
	CV_MORPH_CROSS   = 2
	//CV_SHAPE_CUSTOM  = 3 // TODO: currently we don't support a fully custom kernel
)

/* Returns a structuring element of the specified size and shape for morphological operations. */
func CreateStructuringElement(cols, rows, anchor_x, anchor_y, shape int) *IplConvKernel {
	return (*IplConvKernel)(C.cvCreateStructuringElementEx(
		C.int(cols),
		C.int(rows),
		C.int(anchor_x),
		C.int(anchor_y),
		C.int(shape),
		nil, // TODO: currently we don't support a fully custom kernel
	))
}

//CVAPI(IplConvKernel*) cvCreateStructuringElementEx( int cols, int rows, int anchor_x,
//                                                    int anchor_y, int shape, int* values=NULL )

/* Releases the structuring element */
func (k *IplConvKernel) ReleaseElement() {
	C.cvReleaseStructuringElement(
		(**C.IplConvKernel)(unsafe.Pointer(&k)),
	)
}

//CVAPI(void) cvReleaseStructuringElement( IplConvKernel** element );

/* Dilates an image by using a specific structuring element. */
func Dilate(src, dst *IplImage, element *IplConvKernel, iterations int) {
	C.cvDilate(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		(*C.IplConvKernel)(unsafe.Pointer(element)),
		C.int(iterations),
	)
}

//CVAPI(void) cvDilate( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL,
//                      int iterations=1 );

/* Erodes an image by using a specific structuring element. */
func Erode(src, dst *IplImage, element *IplConvKernel, iterations int) {
	C.cvErode(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		(*C.IplConvKernel)(unsafe.Pointer(element)),
		C.int(iterations),
	)
}

//CVAPI(void) cvErode( const CvArr* src, CvArr* dst, IplConvKernel* element=NULL,
//                     int iterations=1 );

const (
	CV_MORPH_OPEN     = C.CV_MOP_OPEN
	CV_MORPH_CLOSE    = C.CV_MOP_CLOSE
	CV_MORPH_GRADIENT = C.CV_MOP_GRADIENT
	CV_MORPH_TOPHAT   = C.CV_MOP_TOPHAT
	CV_MORPH_BLACKHAT = C.CV_MOP_BLACKHAT
)

/* Performs advanced morphological transformations. */
func MorphologyEx(src, dst, temp *IplImage, element *IplConvKernel, operation int, iterations int) {
	C.cvMorphologyEx(
		unsafe.Pointer(src),
		unsafe.Pointer(dst),
		unsafe.Pointer(temp),
		(*C.IplConvKernel)(unsafe.Pointer(element)),
		C.int(operation),
		C.int(iterations),
	)
}

//CVAPI(void) cvMorphologyEx( const CvArr* src, CvArr* dst, CvArr* temp,
//                            IplConvKernel* element, int operation, int iterations=1 );
<|endoftext|>


<commit_before>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package codegen

import (
	"encoding/json"
	"fmt"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/pkg/errors"
)

const (
	clientInterface = "Client"
	custom          = "custom"
)

// helper struct to pull out the fixture config
type moduleConfig struct {
	Config *config `json:"config"`
}

// config is the struct corresponding to the config field in client-config.json
type config struct {
	CustomImportPath string   `json:"customImportPath"`
	Fixture          *Fixture `json:"fixture"`
}

// Fixture specifies client fixture import path and all scenarios
type Fixture struct {
	// ImportPath is the package where the user-defined Fixture global variable is contained.
	// The Fixture object defines, for a given client, the standardized list of fixture scenarios for that client
	ImportPath string `json:"importPath"`
	// Scenarios is a map from zanzibar's exposed method name to a list of user-defined fixture scenarios for a client
	Scenarios map[string][]string `json:"scenarios"`
}

// Validate the fixture configuration
func (f *Fixture) Validate(methods map[string]interface{}) error {
	if f.ImportPath == "" {
		return errors.New("fixture importPath is empty")
	}
	for m := range f.Scenarios {
		if _, ok := methods[m]; !ok {
			return errors.Errorf("%q is not a valid method", m)
		}
	}
	return nil
}

// ClientMockGenHook returns a PostGenHook to generate client mocks
func ClientMockGenHook(h *PackageHelper, t *Template) (PostGenHook, error) {
	bin, err := NewMockgenBin(h, t)
	if err != nil {
		return nil, errors.Wrap(err, "error building mockgen binary")
	}

	return func(instances map[string][]*ModuleInstance) error {
		clientInstances := instances["client"]
		mockCount := len(clientInstances)
		fmt.Printf("Generating %d client mocks:\n", mockCount)

		importPathMap := make(map[string]string, mockCount)
		fixtureMap := make(map[string]*Fixture, mockCount)
		pathSymbolMap := make(map[string]string)
		for _, instance := range clientInstances {
			key := instance.ClassType + instance.InstanceName
			var mc moduleConfig
			if err := json.Unmarshal(instance.JSONFileRaw, &mc); err != nil {
				return errors.Wrapf(
					err,
					"error parsing client-config.json for client %q",
					instance.InstanceName,
				)
			}

			importPath := instance.PackageInfo.GeneratedPackagePath
			if instance.ClassType == custom {
				importPath = mc.Config.CustomImportPath
			}

			importPathMap[key] = importPath

			// gather all modules that need to generate fixture types
			f := mc.Config.Fixture
			if f != nil && f.Scenarios != nil {
				pathSymbolMap[importPath] = clientInterface
				fixtureMap[key] = f
			}
		}

		// only run reflect program once to gather interface info for all clients
		pkgs, err := ReflectInterface(bin.projRoot, pathSymbolMap)
		if err != nil {
			return errors.Wrap(err, "error parsing Client interfaces")
		}

		var idx int32 = 1
		var files sync.Map
		var wg sync.WaitGroup
		ic := make(chan *ModuleInstance)
		ec := make(chan error, mockCount)
		wg.Add(mockCount)

		// cap the num of goroutines to num of CPU, because
		// bin.GenMock in each goroutine starts a sub process
		n := runtime.GOMAXPROCS(0)
		if n > mockCount {
			n = mockCount
		}
		for i := 0; i < n; i++ {
			go func() {
				defer wg.Done()

				for {
					instance, ok := <-ic
					if !ok {
						return
					}

					key := instance.ClassType + instance.InstanceName
					buildDir := h.CodeGenTargetPath()
					genDir := filepath.Join(buildDir, instance.Directory, "mock-client")

					importPath := importPathMap[key]

					// generate mock client, this starts a sub process
					mock, err := bin.GenMock(importPath, "clientmock", clientInterface)
					if err != nil {
						ec <- errors.Wrapf(
							err,
							"error generating mocks for client %q",
							instance.InstanceName,
						)
						return
					}
					files.Store(filepath.Join(genDir, "mock_client.go"), mock)

					// generate fixture types and augmented mock client
					if f, ok := fixtureMap[key]; ok {
						types, augMock, err := bin.AugmentMockWithFixture(pkgs[importPath], f, clientInterface)
						if err != nil {
							ec <- errors.Wrapf(
								err,
								"error generating fixture types for client %q",
								instance.InstanceName,
							)
							return
						}

						files.Store(filepath.Join(genDir, "types.go"), types)
						files.Store(filepath.Join(genDir, "mock_client_with_fixture.go"), augMock)
					}

					printGenLine(
						"mock",
						instance.ClassName,
						instance.InstanceName,
						path.Join(path.Base(buildDir), instance.Directory, "mock-client"),
						int(atomic.LoadInt32(&idx)), mockCount,
					)
					atomic.AddInt32(&idx, 1)
				}
			}()
		}

		for _, instance := range clientInstances {
			ic <- instance
		}
		close(ic)
		wg.Wait()

		select {
		case err := <-ec:
			close(ec)
			errs := []string{err.Error()}
			for e := range ec {
				errs = append(errs, e.Error())
			}
			return errors.Errorf(
				"encountered %d errors when generating mock clients:\n%s",
				len(errs),
				strings.Join(errs, "\n"),
			)
		default:
		}

		files.Range(func(p, data interface{}) bool {
			if err = writeAndFormat(p.(string), data.([]byte)); err != nil {
				return false
			}
			return true
		})

		return err
	}, nil
}

// ServiceMockGenHook returns a PostGenHook to generate service mocks
func ServiceMockGenHook(h *PackageHelper, t *Template) PostGenHook {
	return func(instances map[string][]*ModuleInstance) error {
		mockCount := len(instances["service"])
		fmt.Printf("Generating %d service mocks:\n", mockCount)
		ec := make(chan error, mockCount)
		var files sync.Map
		var wg sync.WaitGroup
		wg.Add(mockCount)
		for i, instance := range instances["service"] {
			go func(instance *ModuleInstance, i int) {
				defer wg.Done()

				buildDir := h.CodeGenTargetPath()
				genDir := filepath.Join(buildDir, instance.Directory, "mock-service")

				mockInit, err := generateMockInitializer(instance, h, t)
				if err != nil {
					ec <- errors.Wrapf(
						err,
						"Error generating service mock_init.go for %s",
						instance.InstanceName,
					)
					return
				}
				files.Store(filepath.Join(genDir, "mock_init.go"), mockInit)

				mockService, err := t.ExecTemplate("service_mock.tmpl", instance, h)
				if err != nil {
					ec <- errors.Wrapf(
						err,
						"Error generating service mock_service.go for %s",
						instance.InstanceName,
					)
					return
				}
				files.Store(filepath.Join(genDir, "mock_service.go"), mockService)

				printGenLine(
					"mock",
					instance.ClassName,
					instance.InstanceName,
					path.Join(path.Base(buildDir), instance.Directory, "mock-service"),
					i+1, mockCount,
				)
			}(instance, i)
		}
		wg.Wait()

		select {
		case err := <-ec:
			close(ec)
			errs := []string{err.Error()}
			for e := range ec {
				errs = append(errs, e.Error())
			}
			return errors.Errorf(
				"encountered %d errors when generating mock services:\n%s",
				len(errs),
				strings.Join(errs, "\n"),
			)
		default:
		}

		var err error
		files.Range(func(p, data interface{}) bool {
			if err = writeAndFormat(p.(string), data.([]byte)); err != nil {
				return false
			}
			return true
		})

		return err
	}
}

// generateMockInitializer generates code to initialize modules with leaf nodes being mocks
func generateMockInitializer(instance *ModuleInstance, h *PackageHelper, t *Template) ([]byte, error) {
	leafWithFixture := map[string]string{}
	for _, leaf := range instance.RecursiveDependencies["client"] {
		var mc moduleConfig
		if err := json.Unmarshal(leaf.JSONFileRaw, &mc); err != nil {
			return nil, errors.Wrapf(
				err,
				"error parsing client-config.json for client %q",
				instance.InstanceName,
			)
		}
		if mc.Config != nil && mc.Config.Fixture != nil {
			leafWithFixture[leaf.InstanceName] = mc.Config.Fixture.ImportPath
		}
	}
	data := map[string]interface{}{
		"Instance":        instance,
		"LeafWithFixture": leafWithFixture,
	}
	return t.ExecTemplate("module_mock_initializer.tmpl", data, h)
}

// writeAndFormat writes the data to given file path, creates path if it does not exist and formats the file
func writeAndFormat(path string, data []byte) error {
	if err := writeFile(path, data); err != nil {
		return errors.Wrapf(
			err,
			"Error writing to file %q",
			path,
		)
	}
	return FormatGoFile(path)
}
<commit_msg>Set waitgroup counter to number of workers<commit_after>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package codegen

import (
	"encoding/json"
	"fmt"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"

	"github.com/pkg/errors"
)

const (
	clientInterface = "Client"
	custom          = "custom"
)

// helper struct to pull out the fixture config
type moduleConfig struct {
	Config *config `json:"config"`
}

// config is the struct corresponding to the config field in client-config.json
type config struct {
	CustomImportPath string   `json:"customImportPath"`
	Fixture          *Fixture `json:"fixture"`
}

// Fixture specifies client fixture import path and all scenarios
type Fixture struct {
	// ImportPath is the package where the user-defined Fixture global variable is contained.
	// The Fixture object defines, for a given client, the standardized list of fixture scenarios for that client
	ImportPath string `json:"importPath"`
	// Scenarios is a map from zanzibar's exposed method name to a list of user-defined fixture scenarios for a client
	Scenarios map[string][]string `json:"scenarios"`
}

// Validate the fixture configuration
func (f *Fixture) Validate(methods map[string]interface{}) error {
	if f.ImportPath == "" {
		return errors.New("fixture importPath is empty")
	}
	for m := range f.Scenarios {
		if _, ok := methods[m]; !ok {
			return errors.Errorf("%q is not a valid method", m)
		}
	}
	return nil
}

// ClientMockGenHook returns a PostGenHook to generate client mocks
func ClientMockGenHook(h *PackageHelper, t *Template) (PostGenHook, error) {
	bin, err := NewMockgenBin(h, t)
	if err != nil {
		return nil, errors.Wrap(err, "error building mockgen binary")
	}

	return func(instances map[string][]*ModuleInstance) error {
		clientInstances := instances["client"]
		mockCount := len(clientInstances)
		fmt.Printf("Generating %d client mocks:\n", mockCount)

		importPathMap := make(map[string]string, mockCount)
		fixtureMap := make(map[string]*Fixture, mockCount)
		pathSymbolMap := make(map[string]string)
		for _, instance := range clientInstances {
			key := instance.ClassType + instance.InstanceName
			var mc moduleConfig
			if err := json.Unmarshal(instance.JSONFileRaw, &mc); err != nil {
				return errors.Wrapf(
					err,
					"error parsing client-config.json for client %q",
					instance.InstanceName,
				)
			}

			importPath := instance.PackageInfo.GeneratedPackagePath
			if instance.ClassType == custom {
				importPath = mc.Config.CustomImportPath
			}

			importPathMap[key] = importPath

			// gather all modules that need to generate fixture types
			f := mc.Config.Fixture
			if f != nil && f.Scenarios != nil {
				pathSymbolMap[importPath] = clientInterface
				fixtureMap[key] = f
			}
		}

		// only run reflect program once to gather interface info for all clients
		pkgs, err := ReflectInterface(bin.projRoot, pathSymbolMap)
		if err != nil {
			return errors.Wrap(err, "error parsing Client interfaces")
		}

		var idx int32 = 1
		var files sync.Map
		var wg sync.WaitGroup
		ic := make(chan *ModuleInstance)
		ec := make(chan error, mockCount)

		// cap the num of goroutines to num of CPU, because
		// bin.GenMock in each goroutine starts a sub process
		n := runtime.GOMAXPROCS(0)
		if n > mockCount {
			n = mockCount
		}
		wg.Add(n)

		for i := 0; i < n; i++ {
			go func() {
				defer wg.Done()

				for {
					instance, ok := <-ic
					if !ok {
						return
					}

					key := instance.ClassType + instance.InstanceName
					buildDir := h.CodeGenTargetPath()
					genDir := filepath.Join(buildDir, instance.Directory, "mock-client")

					importPath := importPathMap[key]

					// generate mock client, this starts a sub process
					mock, err := bin.GenMock(importPath, "clientmock", clientInterface)
					if err != nil {
						ec <- errors.Wrapf(
							err,
							"error generating mocks for client %q",
							instance.InstanceName,
						)
						return
					}
					files.Store(filepath.Join(genDir, "mock_client.go"), mock)

					// generate fixture types and augmented mock client
					if f, ok := fixtureMap[key]; ok {
						types, augMock, err := bin.AugmentMockWithFixture(pkgs[importPath], f, clientInterface)
						if err != nil {
							ec <- errors.Wrapf(
								err,
								"error generating fixture types for client %q",
								instance.InstanceName,
							)
							return
						}

						files.Store(filepath.Join(genDir, "types.go"), types)
						files.Store(filepath.Join(genDir, "mock_client_with_fixture.go"), augMock)
					}

					printGenLine(
						"mock",
						instance.ClassName,
						instance.InstanceName,
						path.Join(path.Base(buildDir), instance.Directory, "mock-client"),
						int(atomic.LoadInt32(&idx)), mockCount,
					)
					atomic.AddInt32(&idx, 1)
				}
			}()
		}

		for _, instance := range clientInstances {
			ic <- instance
		}
		close(ic)
		wg.Wait()

		select {
		case err := <-ec:
			close(ec)
			errs := []string{err.Error()}
			for e := range ec {
				errs = append(errs, e.Error())
			}
			return errors.Errorf(
				"encountered %d errors when generating mock clients:\n%s",
				len(errs),
				strings.Join(errs, "\n"),
			)
		default:
		}

		files.Range(func(p, data interface{}) bool {
			if err = writeAndFormat(p.(string), data.([]byte)); err != nil {
				return false
			}
			return true
		})

		return err
	}, nil
}

// ServiceMockGenHook returns a PostGenHook to generate service mocks
func ServiceMockGenHook(h *PackageHelper, t *Template) PostGenHook {
	return func(instances map[string][]*ModuleInstance) error {
		mockCount := len(instances["service"])
		fmt.Printf("Generating %d service mocks:\n", mockCount)
		ec := make(chan error, mockCount)
		var files sync.Map
		var wg sync.WaitGroup
		wg.Add(mockCount)
		for i, instance := range instances["service"] {
			go func(instance *ModuleInstance, i int) {
				defer wg.Done()

				buildDir := h.CodeGenTargetPath()
				genDir := filepath.Join(buildDir, instance.Directory, "mock-service")

				mockInit, err := generateMockInitializer(instance, h, t)
				if err != nil {
					ec <- errors.Wrapf(
						err,
						"Error generating service mock_init.go for %s",
						instance.InstanceName,
					)
					return
				}
				files.Store(filepath.Join(genDir, "mock_init.go"), mockInit)

				mockService, err := t.ExecTemplate("service_mock.tmpl", instance, h)
				if err != nil {
					ec <- errors.Wrapf(
						err,
						"Error generating service mock_service.go for %s",
						instance.InstanceName,
					)
					return
				}
				files.Store(filepath.Join(genDir, "mock_service.go"), mockService)

				printGenLine(
					"mock",
					instance.ClassName,
					instance.InstanceName,
					path.Join(path.Base(buildDir), instance.Directory, "mock-service"),
					i+1, mockCount,
				)
			}(instance, i)
		}
		wg.Wait()

		select {
		case err := <-ec:
			close(ec)
			errs := []string{err.Error()}
			for e := range ec {
				errs = append(errs, e.Error())
			}
			return errors.Errorf(
				"encountered %d errors when generating mock services:\n%s",
				len(errs),
				strings.Join(errs, "\n"),
			)
		default:
		}

		var err error
		files.Range(func(p, data interface{}) bool {
			if err = writeAndFormat(p.(string), data.([]byte)); err != nil {
				return false
			}
			return true
		})

		return err
	}
}

// generateMockInitializer generates code to initialize modules with leaf nodes being mocks
func generateMockInitializer(instance *ModuleInstance, h *PackageHelper, t *Template) ([]byte, error) {
	leafWithFixture := map[string]string{}
	for _, leaf := range instance.RecursiveDependencies["client"] {
		var mc moduleConfig
		if err := json.Unmarshal(leaf.JSONFileRaw, &mc); err != nil {
			return nil, errors.Wrapf(
				err,
				"error parsing client-config.json for client %q",
				instance.InstanceName,
			)
		}
		if mc.Config != nil && mc.Config.Fixture != nil {
			leafWithFixture[leaf.InstanceName] = mc.Config.Fixture.ImportPath
		}
	}
	data := map[string]interface{}{
		"Instance":        instance,
		"LeafWithFixture": leafWithFixture,
	}
	return t.ExecTemplate("module_mock_initializer.tmpl", data, h)
}

// writeAndFormat writes the data to given file path, creates path if it does not exist and formats the file
func writeAndFormat(path string, data []byte) error {
	if err := writeFile(path, data); err != nil {
		return errors.Wrapf(
			err,
			"Error writing to file %q",
			path,
		)
	}
	return FormatGoFile(path)
}
<|endoftext|>


<commit_before>package horizon

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"

	"github.com/PuerkitoBio/throttled"
	"github.com/stellar/horizon/render/problem"
	"github.com/stellar/horizon/test"
)

func NewTestApp() *App {
	app, err := NewApp(NewTestConfig())

	if err != nil {
		log.Panic(err)
	}

	return app
}

func NewTestConfig() Config {
	return Config{
		DatabaseUrl:            test.DatabaseUrl(),
		StellarCoreDatabaseUrl: test.StellarCoreDatabaseUrl(),
		RateLimit:              throttled.PerHour(1000),
	}
}

func NewRequestHelper(app *App) test.RequestHelper {
	return test.NewRequestHelper(app.web.router)
}

func ShouldBePageOf(actual interface{}, options ...interface{}) string {
	body := actual.(*bytes.Buffer)
	expected := options[0].(int)

	var result map[string]interface{}
	err := json.Unmarshal(body.Bytes(), &result)

	if err != nil {
		return fmt.Sprintf("Could not unmarshal json:\n%s\n", body.String())
	}

	embedded, ok := result["_embedded"]

	if !ok {
		return "No _embedded key in response"
	}

	records, ok := embedded.(map[string]interface{})["records"]

	if !ok {
		return "No records key in _embedded"
	}

	length := len(records.([]interface{}))

	if length != expected {
		return fmt.Sprintf("Expected %d records in page, got %d", expected, length)
	}

	return ""
}

func ShouldBeProblem(a interface{}, options ...interface{}) string {
	body := a.(*bytes.Buffer)
	expected := options[0].(problem.P)

	var actual problem.P
	err := json.Unmarshal(body.Bytes(), &actual)

	if err != nil {
		return fmt.Sprintf("Could not unmarshal json into problem struct:\n%s\n", body.String())
	}

	if expected.Type != "" && actual.Type != expected.Type {
		return fmt.Sprintf("Mismatched problem type: %s expected, got %s", expected.Type, actual.Type)
	}

	if expected.Status != 0 && actual.Status != expected.Status {
		return fmt.Sprintf("Mismatched problem status: %s expected, got %s", expected.Status, actual.Status)
	}

	return ""
}
<commit_msg>Inflate problems in test, fixing failure<commit_after>package horizon

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"

	"github.com/PuerkitoBio/throttled"
	"github.com/stellar/horizon/render/problem"
	"github.com/stellar/horizon/test"
)

func NewTestApp() *App {
	app, err := NewApp(NewTestConfig())

	if err != nil {
		log.Panic(err)
	}

	return app
}

func NewTestConfig() Config {
	return Config{
		DatabaseUrl:            test.DatabaseUrl(),
		StellarCoreDatabaseUrl: test.StellarCoreDatabaseUrl(),
		RateLimit:              throttled.PerHour(1000),
	}
}

func NewRequestHelper(app *App) test.RequestHelper {
	return test.NewRequestHelper(app.web.router)
}

func ShouldBePageOf(actual interface{}, options ...interface{}) string {
	body := actual.(*bytes.Buffer)
	expected := options[0].(int)

	var result map[string]interface{}
	err := json.Unmarshal(body.Bytes(), &result)

	if err != nil {
		return fmt.Sprintf("Could not unmarshal json:\n%s\n", body.String())
	}

	embedded, ok := result["_embedded"]

	if !ok {
		return "No _embedded key in response"
	}

	records, ok := embedded.(map[string]interface{})["records"]

	if !ok {
		return "No records key in _embedded"
	}

	length := len(records.([]interface{}))

	if length != expected {
		return fmt.Sprintf("Expected %d records in page, got %d", expected, length)
	}

	return ""
}

func ShouldBeProblem(a interface{}, options ...interface{}) string {
	body := a.(*bytes.Buffer)
	expected := options[0].(problem.P)

	problem.Inflate(test.Context(), &expected)

	var actual problem.P
	err := json.Unmarshal(body.Bytes(), &actual)

	if err != nil {
		return fmt.Sprintf("Could not unmarshal json into problem struct:\n%s\n", body.String())
	}

	if expected.Type != "" && actual.Type != expected.Type {
		return fmt.Sprintf("Mismatched problem type: %s expected, got %s", expected.Type, actual.Type)
	}

	if expected.Status != 0 && actual.Status != expected.Status {
		return fmt.Sprintf("Mismatched problem status: %s expected, got %s", expected.Status, actual.Status)
	}

	return ""
}
<|endoftext|>


<commit_before>package collector

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

	"github.com/openconfig/gnmi/proto/gnmi"
)

const (
	subscriptionDefaultMode       = "STREAM"
	subscriptionDefaultStreamMode = "TARGET_DEFINED"
	subscriptionDefaultEncoding   = "JSON"
)

// SubscriptionConfig //
type SubscriptionConfig struct {
	Name              string         `mapstructure:"name,omitempty" json:"name,omitempty"`
	Models            []string       `mapstructure:"models,omitempty" json:"models,omitempty"`
	Prefix            string         `mapstructure:"prefix,omitempty" json:"prefix,omitempty"`
	Target            string         `mapstructure:"target,omitempty" json:"target,omitempty"`
	SetTarget         bool           `mapstructure:"set-target,omitempty" json:"set-target,omitempty"`
	Paths             []string       `mapstructure:"paths,omitempty" json:"paths,omitempty"`
	Mode              string         `mapstructure:"mode,omitempty" json:"mode,omitempty"`
	StreamMode        string         `mapstructure:"stream-mode,omitempty" json:"stream-mode,omitempty"`
	Encoding          string         `mapstructure:"encoding,omitempty" json:"encoding,omitempty"`
	Qos               *uint32        `mapstructure:"qos,omitempty" json:"qos,omitempty"`
	SampleInterval    *time.Duration `mapstructure:"sample-interval,omitempty" json:"sample-interval,omitempty"`
	HeartbeatInterval *time.Duration `mapstructure:"heartbeat-interval,omitempty" json:"heartbeat-interval,omitempty"`
	SuppressRedundant bool           `mapstructure:"suppress-redundant,omitempty" json:"suppress-redundant,omitempty"`
	UpdatesOnly       bool           `mapstructure:"updates-only,omitempty" json:"updates-only,omitempty"`
}
type subscriptionRequest struct {
	name string
	req  *gnmi.SubscribeRequest
}

// String //
func (sc *SubscriptionConfig) String() string {
	b, err := json.Marshal(sc)
	if err != nil {
		return ""
	}
	return string(b)
}

func (sc *SubscriptionConfig) setDefaults() error {
	if len(sc.Paths) == 0 {
		return fmt.Errorf("missing path(s) in subscription '%s'", sc.Name)
	}
	if sc.Mode == "" {
		sc.Mode = subscriptionDefaultMode
	}
	if strings.ToUpper(sc.Mode) == "STREAM" && sc.StreamMode == "" {
		sc.StreamMode = subscriptionDefaultStreamMode
	}
	if sc.Encoding == "" {
		sc.Encoding = subscriptionDefaultEncoding
	}
	return nil
}

// CreateSubscribeRequest validates the SubscriptionConfig and creates gnmi.SubscribeRequest
func (sc *SubscriptionConfig) CreateSubscribeRequest(target string) (*gnmi.SubscribeRequest, error) {
	if err := sc.setDefaults(); err != nil {
		return nil, err
	}
	gnmiPrefix, err := sc.createPrefix(target)
	if err != nil {
		return nil, fmt.Errorf("prefix parse error: %v", err)
	}
	encodingVal, ok := gnmi.Encoding_value[strings.Replace(strings.ToUpper(sc.Encoding), "-", "_", -1)]
	if !ok {
		return nil, fmt.Errorf("subscription '%s' invalid encoding type '%s'", sc.Name, sc.Encoding)
	}
	modeVal, ok := gnmi.SubscriptionList_Mode_value[strings.ToUpper(sc.Mode)]
	if !ok {
		return nil, fmt.Errorf("subscription '%s' invalid subscription list type '%s'", sc.Name, sc.Mode)
	}
	var qos *gnmi.QOSMarking
	if sc.Qos != nil {
		qos = &gnmi.QOSMarking{Marking: *sc.Qos}
	}

	subscriptions := make([]*gnmi.Subscription, len(sc.Paths))
	for i, p := range sc.Paths {
		gnmiPath, err := ParsePath(strings.TrimSpace(p))
		if err != nil {
			return nil, fmt.Errorf("path '%s' parse error: %v", p, err)
		}
		subscriptions[i] = &gnmi.Subscription{Path: gnmiPath}
		switch gnmi.SubscriptionList_Mode(modeVal) {
		case gnmi.SubscriptionList_STREAM:
			mode, ok := gnmi.SubscriptionMode_value[strings.Replace(strings.ToUpper(sc.StreamMode), "-", "_", -1)]
			if !ok {
				return nil, fmt.Errorf("invalid streamed subscription mode %s", sc.Mode)
			}
			subscriptions[i].Mode = gnmi.SubscriptionMode(mode)
			switch gnmi.SubscriptionMode(mode) {
			case gnmi.SubscriptionMode_ON_CHANGE:
				if sc.HeartbeatInterval != nil {
					subscriptions[i].HeartbeatInterval = uint64(sc.HeartbeatInterval.Nanoseconds())
				}
			case gnmi.SubscriptionMode_SAMPLE, gnmi.SubscriptionMode_TARGET_DEFINED:
				if sc.SampleInterval != nil {
					subscriptions[i].SampleInterval = uint64(sc.SampleInterval.Nanoseconds())
				}
				subscriptions[i].SuppressRedundant = sc.SuppressRedundant
				if subscriptions[i].SuppressRedundant {
					subscriptions[i].HeartbeatInterval = uint64(sc.HeartbeatInterval.Nanoseconds())
				}
			}
		}
	}
	models := make([]*gnmi.ModelData, 0, len(sc.Models))
	for _, m := range sc.Models {
		models = append(models, &gnmi.ModelData{Name: m})
	}
	return &gnmi.SubscribeRequest{
		Request: &gnmi.SubscribeRequest_Subscribe{
			Subscribe: &gnmi.SubscriptionList{
				Prefix:       gnmiPrefix,
				Mode:         gnmi.SubscriptionList_Mode(modeVal),
				Encoding:     gnmi.Encoding(encodingVal),
				Subscription: subscriptions,
				Qos:          qos,
				UpdatesOnly:  sc.UpdatesOnly,
				UseModels:    models,
			},
		},
	}, nil
}

func (sc *SubscriptionConfig) createPrefix(target string) (*gnmi.Path, error) {
	if sc.Target != "" {
		return CreatePrefix(sc.Prefix, sc.Target)
	}
	if sc.SetTarget {
		return CreatePrefix(sc.Prefix, target)
	}
	return CreatePrefix(sc.Prefix, "")
}

// SubscribeResponse //
type SubscribeResponse struct {
	SubscriptionName   string
	SubscriptionConfig *SubscriptionConfig
	Response           *gnmi.SubscribeResponse
}

func (sc *SubscriptionConfig) PathsString() string {
	return fmt.Sprintf("- %s", strings.Join(sc.Paths, "\n- "))
}

func (sc *SubscriptionConfig) PrefixString() string {
	if sc.Prefix == "" {
		return "NA"
	}
	return sc.Prefix
}

func (sc *SubscriptionConfig) ModeString() string {
	if strings.ToLower(sc.Mode) == "stream" {
		return fmt.Sprintf("%s/%s", strings.ToLower(sc.Mode), strings.ToLower(sc.StreamMode))
	}
	return strings.ToLower(sc.Mode)
}

func (sc *SubscriptionConfig) SampleIntervalString() string {
	if strings.ToLower(sc.Mode) == "stream" && strings.ToLower(sc.StreamMode) == "sample" {
		return sc.SampleInterval.String()
	}
	return "NA"
}

func (sc *SubscriptionConfig) ModelsString() string {
	return fmt.Sprintf("- %s", strings.Join(sc.Models, "\n- "))
}

func (sc *SubscriptionConfig) QosString() string {
	if sc.Qos == nil {
		return "NA"
	}
	return fmt.Sprintf("%d", *sc.Qos)
}

func (sc *SubscriptionConfig) HeartbeatIntervalString() string {
	return sc.HeartbeatInterval.String()
}

func (sc *SubscriptionConfig) SuppressRedundantString() string {
	return fmt.Sprintf("%t", sc.SuppressRedundant)
}

func (sc *SubscriptionConfig) UpdatesOnlyString() string {
	return fmt.Sprintf("%t", sc.UpdatesOnly)
}
<commit_msg>fix subscribe request creation when suppress-redundant is set but not heartbeat-interval<commit_after>package collector

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

	"github.com/openconfig/gnmi/proto/gnmi"
)

const (
	subscriptionDefaultMode       = "STREAM"
	subscriptionDefaultStreamMode = "TARGET_DEFINED"
	subscriptionDefaultEncoding   = "JSON"
)

// SubscriptionConfig //
type SubscriptionConfig struct {
	Name              string         `mapstructure:"name,omitempty" json:"name,omitempty"`
	Models            []string       `mapstructure:"models,omitempty" json:"models,omitempty"`
	Prefix            string         `mapstructure:"prefix,omitempty" json:"prefix,omitempty"`
	Target            string         `mapstructure:"target,omitempty" json:"target,omitempty"`
	SetTarget         bool           `mapstructure:"set-target,omitempty" json:"set-target,omitempty"`
	Paths             []string       `mapstructure:"paths,omitempty" json:"paths,omitempty"`
	Mode              string         `mapstructure:"mode,omitempty" json:"mode,omitempty"`
	StreamMode        string         `mapstructure:"stream-mode,omitempty" json:"stream-mode,omitempty"`
	Encoding          string         `mapstructure:"encoding,omitempty" json:"encoding,omitempty"`
	Qos               *uint32        `mapstructure:"qos,omitempty" json:"qos,omitempty"`
	SampleInterval    *time.Duration `mapstructure:"sample-interval,omitempty" json:"sample-interval,omitempty"`
	HeartbeatInterval *time.Duration `mapstructure:"heartbeat-interval,omitempty" json:"heartbeat-interval,omitempty"`
	SuppressRedundant bool           `mapstructure:"suppress-redundant,omitempty" json:"suppress-redundant,omitempty"`
	UpdatesOnly       bool           `mapstructure:"updates-only,omitempty" json:"updates-only,omitempty"`
}
type subscriptionRequest struct {
	name string
	req  *gnmi.SubscribeRequest
}

// String //
func (sc *SubscriptionConfig) String() string {
	b, err := json.Marshal(sc)
	if err != nil {
		return ""
	}
	return string(b)
}

func (sc *SubscriptionConfig) setDefaults() error {
	if len(sc.Paths) == 0 {
		return fmt.Errorf("missing path(s) in subscription '%s'", sc.Name)
	}
	if sc.Mode == "" {
		sc.Mode = subscriptionDefaultMode
	}
	if strings.ToUpper(sc.Mode) == "STREAM" && sc.StreamMode == "" {
		sc.StreamMode = subscriptionDefaultStreamMode
	}
	if sc.Encoding == "" {
		sc.Encoding = subscriptionDefaultEncoding
	}
	return nil
}

// CreateSubscribeRequest validates the SubscriptionConfig and creates gnmi.SubscribeRequest
func (sc *SubscriptionConfig) CreateSubscribeRequest(target string) (*gnmi.SubscribeRequest, error) {
	if err := sc.setDefaults(); err != nil {
		return nil, err
	}
	gnmiPrefix, err := sc.createPrefix(target)
	if err != nil {
		return nil, fmt.Errorf("prefix parse error: %v", err)
	}
	encodingVal, ok := gnmi.Encoding_value[strings.Replace(strings.ToUpper(sc.Encoding), "-", "_", -1)]
	if !ok {
		return nil, fmt.Errorf("subscription '%s' invalid encoding type '%s'", sc.Name, sc.Encoding)
	}
	modeVal, ok := gnmi.SubscriptionList_Mode_value[strings.ToUpper(sc.Mode)]
	if !ok {
		return nil, fmt.Errorf("subscription '%s' invalid subscription list type '%s'", sc.Name, sc.Mode)
	}
	var qos *gnmi.QOSMarking
	if sc.Qos != nil {
		qos = &gnmi.QOSMarking{Marking: *sc.Qos}
	}

	subscriptions := make([]*gnmi.Subscription, len(sc.Paths))
	for i, p := range sc.Paths {
		gnmiPath, err := ParsePath(strings.TrimSpace(p))
		if err != nil {
			return nil, fmt.Errorf("path '%s' parse error: %v", p, err)
		}
		subscriptions[i] = &gnmi.Subscription{Path: gnmiPath}
		switch gnmi.SubscriptionList_Mode(modeVal) {
		case gnmi.SubscriptionList_STREAM:
			mode, ok := gnmi.SubscriptionMode_value[strings.Replace(strings.ToUpper(sc.StreamMode), "-", "_", -1)]
			if !ok {
				return nil, fmt.Errorf("invalid streamed subscription mode %s", sc.Mode)
			}
			subscriptions[i].Mode = gnmi.SubscriptionMode(mode)
			switch gnmi.SubscriptionMode(mode) {
			case gnmi.SubscriptionMode_ON_CHANGE:
				if sc.HeartbeatInterval != nil {
					subscriptions[i].HeartbeatInterval = uint64(sc.HeartbeatInterval.Nanoseconds())
				}
			case gnmi.SubscriptionMode_SAMPLE, gnmi.SubscriptionMode_TARGET_DEFINED:
				if sc.SampleInterval != nil {
					subscriptions[i].SampleInterval = uint64(sc.SampleInterval.Nanoseconds())
				}
				subscriptions[i].SuppressRedundant = sc.SuppressRedundant
				if subscriptions[i].SuppressRedundant && sc.HeartbeatInterval != nil {
					subscriptions[i].HeartbeatInterval = uint64(sc.HeartbeatInterval.Nanoseconds())
				}
			}
		}
	}
	models := make([]*gnmi.ModelData, 0, len(sc.Models))
	for _, m := range sc.Models {
		models = append(models, &gnmi.ModelData{Name: m})
	}
	return &gnmi.SubscribeRequest{
		Request: &gnmi.SubscribeRequest_Subscribe{
			Subscribe: &gnmi.SubscriptionList{
				Prefix:       gnmiPrefix,
				Mode:         gnmi.SubscriptionList_Mode(modeVal),
				Encoding:     gnmi.Encoding(encodingVal),
				Subscription: subscriptions,
				Qos:          qos,
				UpdatesOnly:  sc.UpdatesOnly,
				UseModels:    models,
			},
		},
	}, nil
}

func (sc *SubscriptionConfig) createPrefix(target string) (*gnmi.Path, error) {
	if sc.Target != "" {
		return CreatePrefix(sc.Prefix, sc.Target)
	}
	if sc.SetTarget {
		return CreatePrefix(sc.Prefix, target)
	}
	return CreatePrefix(sc.Prefix, "")
}

// SubscribeResponse //
type SubscribeResponse struct {
	SubscriptionName   string
	SubscriptionConfig *SubscriptionConfig
	Response           *gnmi.SubscribeResponse
}

func (sc *SubscriptionConfig) PathsString() string {
	return fmt.Sprintf("- %s", strings.Join(sc.Paths, "\n- "))
}

func (sc *SubscriptionConfig) PrefixString() string {
	if sc.Prefix == "" {
		return "NA"
	}
	return sc.Prefix
}

func (sc *SubscriptionConfig) ModeString() string {
	if strings.ToLower(sc.Mode) == "stream" {
		return fmt.Sprintf("%s/%s", strings.ToLower(sc.Mode), strings.ToLower(sc.StreamMode))
	}
	return strings.ToLower(sc.Mode)
}

func (sc *SubscriptionConfig) SampleIntervalString() string {
	if strings.ToLower(sc.Mode) == "stream" && strings.ToLower(sc.StreamMode) == "sample" {
		return sc.SampleInterval.String()
	}
	return "NA"
}

func (sc *SubscriptionConfig) ModelsString() string {
	return fmt.Sprintf("- %s", strings.Join(sc.Models, "\n- "))
}

func (sc *SubscriptionConfig) QosString() string {
	if sc.Qos == nil {
		return "NA"
	}
	return fmt.Sprintf("%d", *sc.Qos)
}

func (sc *SubscriptionConfig) HeartbeatIntervalString() string {
	return sc.HeartbeatInterval.String()
}

func (sc *SubscriptionConfig) SuppressRedundantString() string {
	return fmt.Sprintf("%t", sc.SuppressRedundant)
}

func (sc *SubscriptionConfig) UpdatesOnlyString() string {
	return fmt.Sprintf("%t", sc.UpdatesOnly)
}
<|endoftext|>


<commit_before>package system

import (
	"fmt"
	"strings"

	"golang.org/x/net/context"

	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/cli/command/inspect"
	apiclient "github.com/docker/docker/client"
	"github.com/spf13/cobra"
)

type inspectOptions struct {
	format      string
	inspectType string
	size        bool
	ids         []string
}

// NewInspectCommand creates a new cobra.Command for `docker inspect`
func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts inspectOptions

	cmd := &cobra.Command{
		Use: "inspect [OPTIONS] NAME|ID [NAME|ID...]",
		Short: strings.Join([]string{
			"Return low-level information on Docker object(s) (e.g. container, image, volume,",
			"\nnetwork, node, service, or task) identified by name or ID",
		}, ""),
		Args: cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.ids = args
			return runInspect(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
	flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
	flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")

	return cmd
}

func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
	var elementSearcher inspect.GetRefFunc
	switch opts.inspectType {
	case "", "container", "image", "node", "network", "service", "volume", "task":
		elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
	default:
		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
	}
	return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
}

func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
	}
}

func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ImageInspectWithRaw(ctx, ref)
	}
}

func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().NetworkInspectWithRaw(ctx, ref)
	}
}

func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().NodeInspectWithRaw(ctx, ref)
	}
}

func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ServiceInspectWithRaw(ctx, ref)
	}
}

func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().TaskInspectWithRaw(ctx, ref)
	}
}

func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().VolumeInspectWithRaw(ctx, ref)
	}
}

func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
	var inspectAutodetect = []struct {
		ObjectType      string
		IsSizeSupported bool
		ObjectInspector func(string) (interface{}, []byte, error)
	}{
		{"container", true, inspectContainers(ctx, dockerCli, getSize)},
		{"image", false, inspectImages(ctx, dockerCli)},
		{"network", false, inspectNetwork(ctx, dockerCli)},
		{"volume", false, inspectVolume(ctx, dockerCli)},
		{"service", false, inspectService(ctx, dockerCli)},
		{"task", false, inspectTasks(ctx, dockerCli)},
		{"node", false, inspectNode(ctx, dockerCli)},
	}

	isErrNotSwarmManager := func(err error) bool {
		return strings.Contains(err.Error(), "This node is not a swarm manager")
	}

	return func(ref string) (interface{}, []byte, error) {
		for _, inspectData := range inspectAutodetect {
			if typeConstraint != "" && inspectData.ObjectType != typeConstraint {
				continue
			}
			v, raw, err := inspectData.ObjectInspector(ref)
			if err != nil {
				if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) {
					continue
				}
				return v, raw, err
			}
			if getSize && !inspectData.IsSizeSupported {
				fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType)
			}
			return v, raw, err
		}
		return nil, nil, fmt.Errorf("Error: No such object: %s", ref)
	}
}
<commit_msg>cli: shorten description of "inspect" subcommand<commit_after>package system

import (
	"fmt"
	"strings"

	"golang.org/x/net/context"

	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/cli/command/inspect"
	apiclient "github.com/docker/docker/client"
	"github.com/spf13/cobra"
)

type inspectOptions struct {
	format      string
	inspectType string
	size        bool
	ids         []string
}

// NewInspectCommand creates a new cobra.Command for `docker inspect`
func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts inspectOptions

	cmd := &cobra.Command{
		Use:   "inspect [OPTIONS] NAME|ID [NAME|ID...]",
		Short: "Return low-level information on Docker objects",
		Args:  cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.ids = args
			return runInspect(dockerCli, opts)
		},
	}

	flags := cmd.Flags()
	flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
	flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
	flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")

	return cmd
}

func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
	var elementSearcher inspect.GetRefFunc
	switch opts.inspectType {
	case "", "container", "image", "node", "network", "service", "volume", "task":
		elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
	default:
		return fmt.Errorf("%q is not a valid value for --type", opts.inspectType)
	}
	return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
}

func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
	}
}

func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ImageInspectWithRaw(ctx, ref)
	}
}

func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().NetworkInspectWithRaw(ctx, ref)
	}
}

func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().NodeInspectWithRaw(ctx, ref)
	}
}

func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().ServiceInspectWithRaw(ctx, ref)
	}
}

func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().TaskInspectWithRaw(ctx, ref)
	}
}

func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		return dockerCli.Client().VolumeInspectWithRaw(ctx, ref)
	}
}

func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc {
	var inspectAutodetect = []struct {
		ObjectType      string
		IsSizeSupported bool
		ObjectInspector func(string) (interface{}, []byte, error)
	}{
		{"container", true, inspectContainers(ctx, dockerCli, getSize)},
		{"image", false, inspectImages(ctx, dockerCli)},
		{"network", false, inspectNetwork(ctx, dockerCli)},
		{"volume", false, inspectVolume(ctx, dockerCli)},
		{"service", false, inspectService(ctx, dockerCli)},
		{"task", false, inspectTasks(ctx, dockerCli)},
		{"node", false, inspectNode(ctx, dockerCli)},
	}

	isErrNotSwarmManager := func(err error) bool {
		return strings.Contains(err.Error(), "This node is not a swarm manager")
	}

	return func(ref string) (interface{}, []byte, error) {
		for _, inspectData := range inspectAutodetect {
			if typeConstraint != "" && inspectData.ObjectType != typeConstraint {
				continue
			}
			v, raw, err := inspectData.ObjectInspector(ref)
			if err != nil {
				if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSwarmManager(err)) {
					continue
				}
				return v, raw, err
			}
			if getSize && !inspectData.IsSizeSupported {
				fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.ObjectType)
			}
			return v, raw, err
		}
		return nil, nil, fmt.Errorf("Error: No such object: %s", ref)
	}
}
<|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 output contains helper methods for pretty-printing code reviews.
package output

import (
	"fmt"
	"github.com/google/git-appraise/review"
	"strconv"
	"strings"
	"time"
)

const (
	// Template for printing the summary of a code review.
	reviewSummaryTemplate = `[%s] %.12s
  %s
`
	// Template for printing the summary of a code review.
	reviewDetailsTemplate = `  %q -> %q
  reviewers: %q
  requester: %q
  build status: %s
`
	// Template for printing the location of an inline comment
	commentLocationTemplate = `%s%q@%.12s
`
	// Template for printing a single comment.
	commentTemplate = `comment: %s
author: %s
time:   %s
status: %s
%s`
	// Template for displaying the summary of the comment threads for a review
	commentSummaryTemplate = `  comments (%d threads):
`
	// Number of lines of context to print for inline comments
	contextLineCount = 5
)

// getStatusString returns a human friendly string encapsulating both the review's
// resolved status, and its submitted status.
func getStatusString(r *review.Summary) string {
	if r.Resolved == nil && r.Submitted {
		return "tbr"
	}
	if r.Resolved == nil {
		return "pending"
	}
	if *r.Resolved && r.Submitted {
		return "submitted"
	}
	if *r.Resolved {
		return "accepted"
	}
	if r.Submitted {
		return "danger"
	}
	if r.Request.TargetRef == "" {
		return "abandon"
	}
	return "rejected"
}

// PrintSummary prints a single-line summary of a review.
func PrintSummary(r *review.Summary) {
	statusString := getStatusString(r)
	indentedDescription := strings.Replace(r.Request.Description, "\n", "\n  ", -1)
	fmt.Printf(reviewSummaryTemplate, statusString, r.Revision, indentedDescription)
}

// reformatTimestamp takes a timestamp string of the form "0123456789" and changes it
// to the form "Mon Jan _2 13:04:05 UTC 2006".
//
// Timestamps that are not in the format we expect are left alone.
func reformatTimestamp(timestamp string) string {
	parsedTimestamp, err := strconv.ParseInt(timestamp, 10, 64)
	if err != nil {
		// The timestamp is an unexpected format, so leave it alone
		return timestamp
	}
	t := time.Unix(parsedTimestamp, 0)
	return t.Format(time.UnixDate)
}

// showThread prints the detailed output for an entire comment thread.
func showThread(r *review.Review, thread review.CommentThread) error {
	comment := thread.Comment
	indent := "    "
	if comment.Location != nil && comment.Location.Path != "" && comment.Location.Range != nil && comment.Location.Range.StartLine > 0 {
		contents, err := r.Repo.Show(comment.Location.Commit, comment.Location.Path)
		if err != nil {
			return err
		}
		lines := strings.Split(contents, "\n")
		if comment.Location.Range.StartLine <= uint32(len(lines)) {
			var firstLine uint32
			lastLine := comment.Location.Range.StartLine
			if lastLine > contextLineCount {
				firstLine = lastLine - contextLineCount
			}
			fmt.Printf(commentLocationTemplate, indent, comment.Location.Path, comment.Location.Commit)
			fmt.Println(indent + "|" + strings.Join(lines[firstLine:lastLine], "\n"+indent+"|"))
		}
	}
	return showSubThread(r, thread, indent)
}

// showSubThread prints the given comment (sub)thread, indented by the given prefix string.
func showSubThread(r *review.Review, thread review.CommentThread, indent string) error {
	statusString := "fyi"
	if thread.Resolved != nil {
		if *thread.Resolved {
			statusString = "lgtm"
		} else {
			statusString = "needs work"
		}
	}
	comment := thread.Comment
	threadHash, err := comment.Hash()
	if err != nil {
		return err
	}

	timestamp := reformatTimestamp(comment.Timestamp)
	commentSummary := fmt.Sprintf(indent+commentTemplate, threadHash, comment.Author, timestamp, statusString, comment.Description)
	indent = indent + "  "
	indentedSummary := strings.Replace(commentSummary, "\n", "\n"+indent, -1)
	fmt.Println(indentedSummary)
	for _, child := range thread.Children {
		err := showSubThread(r, child, indent)
		if err != nil {
			return err
		}
	}
	return nil
}

// printAnalyses prints the static analysis results for the latest commit in the review.
func printAnalyses(r *review.Review) {
	fmt.Println("  analyses: ", r.GetAnalysesMessage())
}

// printComments prints all of the comments for the review, with snippets of the preceding source code.
func printComments(r *review.Review) error {
	fmt.Printf(commentSummaryTemplate, len(r.Comments))
	for _, thread := range r.Comments {
		err := showThread(r, thread)
		if err != nil {
			return err
		}
	}
	return nil
}

// PrintDetails prints a multi-line overview of a review, including all comments.
func PrintDetails(r *review.Review) error {
	PrintSummary(r.Summary)
	fmt.Printf(reviewDetailsTemplate, r.Request.ReviewRef, r.Request.TargetRef,
		strings.Join(r.Request.Reviewers, ", "),
		r.Request.Requester, r.GetBuildStatusMessage())
	printAnalyses(r)
	if err := printComments(r); err != nil {
		return err
	}
	return nil
}

// PrintJSON pretty prints the given review in JSON format.
func PrintJSON(r *review.Review) error {
	json, err := r.GetJSON()
	if err != nil {
		return err
	}
	fmt.Println(json)
	return nil
}

// PrintDiff prints the diff of the review.
func PrintDiff(r *review.Review, diffArgs ...string) error {
	diff, err := r.GetDiff(diffArgs...)
	if err != nil {
		return err
	}
	fmt.Println(diff)
	return nil
}
<commit_msg>Update comment display to respect line range<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 output contains helper methods for pretty-printing code reviews.
package output

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/google/git-appraise/review"
)

const (
	// Template for printing the summary of a code review.
	reviewSummaryTemplate = `[%s] %.12s
  %s
`
	// Template for printing the summary of a code review.
	reviewDetailsTemplate = `  %q -> %q
  reviewers: %q
  requester: %q
  build status: %s
`
	// Template for printing the location of an inline comment
	commentLocationTemplate = `%s%q@%.12s
`
	// Template for printing a single comment.
	commentTemplate = `comment: %s
author: %s
time:   %s
status: %s
%s`
	// Template for displaying the summary of the comment threads for a review
	commentSummaryTemplate = `  comments (%d threads):
`
	// Number of lines of context to print for inline comments
	contextLineCount = 5
)

// getStatusString returns a human friendly string encapsulating both the review's
// resolved status, and its submitted status.
func getStatusString(r *review.Summary) string {
	if r.Resolved == nil && r.Submitted {
		return "tbr"
	}
	if r.Resolved == nil {
		return "pending"
	}
	if *r.Resolved && r.Submitted {
		return "submitted"
	}
	if *r.Resolved {
		return "accepted"
	}
	if r.Submitted {
		return "danger"
	}
	if r.Request.TargetRef == "" {
		return "abandon"
	}
	return "rejected"
}

// PrintSummary prints a single-line summary of a review.
func PrintSummary(r *review.Summary) {
	statusString := getStatusString(r)
	indentedDescription := strings.Replace(r.Request.Description, "\n", "\n  ", -1)
	fmt.Printf(reviewSummaryTemplate, statusString, r.Revision, indentedDescription)
}

// reformatTimestamp takes a timestamp string of the form "0123456789" and changes it
// to the form "Mon Jan _2 13:04:05 UTC 2006".
//
// Timestamps that are not in the format we expect are left alone.
func reformatTimestamp(timestamp string) string {
	parsedTimestamp, err := strconv.ParseInt(timestamp, 10, 64)
	if err != nil {
		// The timestamp is an unexpected format, so leave it alone
		return timestamp
	}
	t := time.Unix(parsedTimestamp, 0)
	return t.Format(time.UnixDate)
}

// showThread prints the detailed output for an entire comment thread.
func showThread(r *review.Review, thread review.CommentThread) error {
	comment := thread.Comment
	indent := "    "
	if comment.Location != nil && comment.Location.Path != "" && comment.Location.Range != nil && comment.Location.Range.StartLine > 0 {
		contents, err := r.Repo.Show(comment.Location.Commit, comment.Location.Path)
		if err != nil {
			return err
		}
		lines := strings.Split(contents, "\n")
		if comment.Location.Range.StartLine <= uint32(len(lines)) {
			firstLine := comment.Location.Range.StartLine
			lastLine := comment.Location.Range.EndLine

			if firstLine == 0 {
				firstLine = 1
			}

			if lastLine == 0 {
				lastLine = firstLine
			}

			if lastLine == firstLine {
				minLine := int(lastLine) - int(contextLineCount)
				if minLine <= 0 {
					minLine = 1
				}
				firstLine = uint32(minLine)
			}

			fmt.Printf(commentLocationTemplate, indent, comment.Location.Path, comment.Location.Commit)
			fmt.Println(indent + "|" + strings.Join(lines[firstLine-1:lastLine], "\n"+indent+"|"))
		}
	}
	return showSubThread(r, thread, indent)
}

// showSubThread prints the given comment (sub)thread, indented by the given prefix string.
func showSubThread(r *review.Review, thread review.CommentThread, indent string) error {
	statusString := "fyi"
	if thread.Resolved != nil {
		if *thread.Resolved {
			statusString = "lgtm"
		} else {
			statusString = "needs work"
		}
	}
	comment := thread.Comment
	threadHash, err := comment.Hash()
	if err != nil {
		return err
	}

	timestamp := reformatTimestamp(comment.Timestamp)
	commentSummary := fmt.Sprintf(indent+commentTemplate, threadHash, comment.Author, timestamp, statusString, comment.Description)
	indent = indent + "  "
	indentedSummary := strings.Replace(commentSummary, "\n", "\n"+indent, -1)
	fmt.Println(indentedSummary)
	for _, child := range thread.Children {
		err := showSubThread(r, child, indent)
		if err != nil {
			return err
		}
	}
	return nil
}

// printAnalyses prints the static analysis results for the latest commit in the review.
func printAnalyses(r *review.Review) {
	fmt.Println("  analyses: ", r.GetAnalysesMessage())
}

// printComments prints all of the comments for the review, with snippets of the preceding source code.
func printComments(r *review.Review) error {
	fmt.Printf(commentSummaryTemplate, len(r.Comments))
	for _, thread := range r.Comments {
		err := showThread(r, thread)
		if err != nil {
			return err
		}
	}
	return nil
}

// PrintDetails prints a multi-line overview of a review, including all comments.
func PrintDetails(r *review.Review) error {
	PrintSummary(r.Summary)
	fmt.Printf(reviewDetailsTemplate, r.Request.ReviewRef, r.Request.TargetRef,
		strings.Join(r.Request.Reviewers, ", "),
		r.Request.Requester, r.GetBuildStatusMessage())
	printAnalyses(r)
	if err := printComments(r); err != nil {
		return err
	}
	return nil
}

// PrintJSON pretty prints the given review in JSON format.
func PrintJSON(r *review.Review) error {
	json, err := r.GetJSON()
	if err != nil {
		return err
	}
	fmt.Println(json)
	return nil
}

// PrintDiff prints the diff of the review.
func PrintDiff(r *review.Review, diffArgs ...string) error {
	diff, err := r.GetDiff(diffArgs...)
	if err != nil {
		return err
	}
	fmt.Println(diff)
	return nil
}
<|endoftext|>


<commit_before>package httpToFirehose

import (
	"encoding/json"
	firehosePool "github.com/gabrielperezs/streamspooler/firehose"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/gallir/smart-relayer/lib"
	"github.com/gin-gonic/gin"
)

// Server is the thread that listen for clients' connections
type Server struct {
	sync.Mutex
	config  lib.RelayerConfig
	done    chan bool
	exiting bool
	engine  *gin.Engine

	fh             *firehosePool.Server
	lastConnection time.Time
	lastError      time.Time
}

var (
	defaultTimeout          = 5 * time.Second
	defaultMaxResults int64 = 100
)

// New creates a new http local server
func New(c lib.RelayerConfig, done chan bool) (*Server, error) {
	srv := &Server{
		done: done,
	}

	srv.Reload(&c)

	return srv, nil
}

// Reload the configuration
func (srv *Server) Reload(c *lib.RelayerConfig) (err error) {
	srv.Lock()
	defer srv.Unlock()

	srv.config = *c

	fhConfig := firehosePool.Config{
		Profile:       srv.config.Profile,
		Region:        srv.config.Region,
		StreamName:    srv.config.StreamName,
		MaxWorkers:    srv.config.MaxConnections,
		MaxRecords:    srv.config.MaxRecords,
		Buffer:        srv.config.Buffer,
		ConcatRecords: srv.config.Concat,
		Critical:      srv.config.Critical,
	}

	if srv.fh == nil {
		srv.fh = firehosePool.New(fhConfig)
	} else {
		go srv.fh.Reload(&fhConfig)
	}

	return nil
}

// Start accepts incoming connections on the Listener
func (srv *Server) Start() (e error) {
	srv.Lock()
	defer srv.Unlock()

	if srv.engine != nil {
		return nil
	}

	gin.SetMode(gin.ReleaseMode)
	srv.engine = gin.New()
	srv.engine.POST("/firehose_raw", srv.submitRaw)
	srv.engine.POST("/firehose", srv.submit)
	srv.engine.GET("/ping", srv.ok)
	go func() {
		switch {
		case strings.HasPrefix(srv.config.Listen, "tcp://"):
			e = srv.engine.Run(srv.config.Listen[6:])
		case strings.HasPrefix(srv.config.Listen, "unix://"):
			e = srv.engine.RunUnix(srv.config.Listen[7:])
		}
	}()
	return e
}

// Exit closes the listener and send done to main
func (srv *Server) Exit() {
	srv.exiting = true

	if srv.engine != nil {
		// finish gin
	}

	// finishing the server
	srv.done <- true
}

func (srv *Server) ok(ctx *gin.Context) {
	ctx.IndentedJSON(http.StatusOK, map[string]interface{}{
		"status": "success",
	})
}

func (srv *Server) submitRaw(ctx *gin.Context) {

	b, err := ioutil.ReadAll(ctx.Request.Body)
	if err != nil {
		ctx.String(http.StatusBadRequest, err.Error())
		return
	}

	if err != nil {
		ctx.IndentedJSON(http.StatusBadRequest, map[string]interface{}{
			"Error": err.Error(),
		})
		return
	}

	srv.sendBytes(b) // Does not check if the data is a valid json.

	ctx.IndentedJSON(http.StatusOK, map[string]interface{}{
		"status": "success",
	})
}

func (srv *Server) submit(ctx *gin.Context) {

	b, err := ioutil.ReadAll(ctx.Request.Body)
	if err != nil {
		ctx.String(http.StatusBadRequest, err.Error())
		return
	}

	if err != nil {
		ctx.IndentedJSON(http.StatusBadRequest, map[string]interface{}{
			"Error": err.Error(),
		})
		return
	}
	var parsedJson map[string]interface{}

	err = json.Unmarshal(b, &parsedJson)
	if err != nil {
		ctx.IndentedJSON(http.StatusBadRequest, map[string]interface{}{
			"Error": err.Error(),
		})
		return
	}

	var rowWithTimestamp = lib.NewInterRecord()
	rowWithTimestamp.SetData(parsedJson)
	srv.sendRecord(rowWithTimestamp)

	ctx.IndentedJSON(http.StatusOK, map[string]interface{}{
		"status": "success",
	})
}

func (srv *Server) sendRecord(r *lib.InterRecord) {
	if srv.exiting {
		return
	}

	// It blocks until the message can be delivered, for critical logs
	if srv.config.Critical || srv.config.Mode != "smart" {
		srv.fh.C <- r.Bytes()
		return
	}

	select {
	case srv.fh.C <- r.Bytes():
	default:
		log.Printf("Firehose: channel is full, discarded. Queued messages %d", len(srv.fh.C))
	}
}

func (srv *Server) sendBytes(b []byte) {
	r := lib.NewInterRecord()
	r.Types = 1
	r.Raw = b
	srv.sendRecord(r)
}
<commit_msg>Changed httpToFirehose from gin to fasthttp<commit_after>package httpToFirehose

import (
	"encoding/json"
	firehosePool "github.com/gabrielperezs/streamspooler/firehose"
	"log"
	"os"
	"strings"
	"sync"
	"time"

	"github.com/fasthttp/router"
	"github.com/gallir/smart-relayer/lib"
	"github.com/valyala/fasthttp"
)

// Server is the thread that listen for clients' connections
type Server struct {
	sync.Mutex
	config  lib.RelayerConfig
	done    chan bool
	exiting bool
	engine  *fasthttp.Server

	fh             *firehosePool.Server
	lastConnection time.Time
	lastError      time.Time
}

var (
	defaultTimeout          = 5 * time.Second
	defaultMaxResults int64 = 100
)

// New creates a new http local server
func New(c lib.RelayerConfig, done chan bool) (*Server, error) {
	srv := &Server{
		done: done,
	}

	srv.Reload(&c)

	return srv, nil
}

// Reload the configuration
func (srv *Server) Reload(c *lib.RelayerConfig) (err error) {
	srv.Lock()
	defer srv.Unlock()

	srv.config = *c

	fhConfig := firehosePool.Config{
		Profile:       srv.config.Profile,
		Region:        srv.config.Region,
		StreamName:    srv.config.StreamName,
		MaxWorkers:    srv.config.MaxConnections,
		MaxRecords:    srv.config.MaxRecords,
		Buffer:        srv.config.Buffer,
		ConcatRecords: srv.config.Concat,
		Critical:      srv.config.Critical,
	}

	if srv.fh == nil {
		srv.fh = firehosePool.New(fhConfig)
	} else {
		go srv.fh.Reload(&fhConfig)
	}

	return nil
}

// Start accepts incoming connections on the Listener
func (srv *Server) Start() (e error) {
	srv.Lock()
	defer srv.Unlock()

	if srv.engine != nil {
		return nil
	}

	r := router.New()
	r.GET("/ping", srv.ok)
	r.POST("/firehose_raw", srv.submitRaw)
	r.POST("/firehose", srv.submit)

	srv.engine = &fasthttp.Server{
		Handler: r.Handler,
	}

	go func() {
		switch {
		case strings.HasPrefix(srv.config.Listen, "tcp://"):
			e = srv.engine.ListenAndServe(srv.config.Listen[6:])
		case strings.HasPrefix(srv.config.Listen, "unix://"):
			e = srv.engine.ListenAndServeUNIX(srv.config.Listen[7:], os.FileMode(0666))
		}
	}()
	return e
}

// Exit closes the listener and send done to main
func (srv *Server) Exit() {
	srv.exiting = true

	if srv.engine != nil {
		if e := srv.engine.Shutdown(); e != nil {
			log.Println("httpToFirehose ERROR: shutting down failed", e)
		}
	}

	// finishing the server
	srv.done <- true
}

func (srv *Server) ok(ctx *fasthttp.RequestCtx) {
	ctx.SetContentType("application/json")
	ctx.SetStatusCode(fasthttp.StatusOK)
	ctx.SetBody([]byte("{\"status\": \"success\"}"))
}

func (srv *Server) submitRaw(ctx *fasthttp.RequestCtx) {
	srv.sendBytes(ctx.Request.Body()) // Does not check if the data is a valid json.

	ctx.SetContentType("application/json")
	ctx.SetStatusCode(fasthttp.StatusOK)
	ctx.SetBody([]byte("{\"status\": \"success\"}"))
}

func (srv *Server) submit(ctx *fasthttp.RequestCtx) {
	ctx.SetContentType("application/json")

	var parsedJson map[string]interface{}
	err := json.Unmarshal(ctx.Request.Body(), &parsedJson)
	if err != nil {
		ctx.SetStatusCode(fasthttp.StatusBadRequest)
		ctx.SetBody([]byte("{\"status\": \"invalid_json\"}"))
		return
	}

	var rowWithTimestamp = lib.NewInterRecord()
	rowWithTimestamp.SetData(parsedJson)
	srv.sendRecord(rowWithTimestamp)

	ctx.SetStatusCode(fasthttp.StatusOK)
	ctx.SetBody([]byte("{\"status\": \"success\"}"))
}

func (srv *Server) sendRecord(r *lib.InterRecord) {
	if srv.exiting {
		return
	}

	// It blocks until the message can be delivered, for critical logs
	if srv.config.Critical || srv.config.Mode != "smart" {
		srv.fh.C <- r.Bytes()
		return
	}

	select {
	case srv.fh.C <- r.Bytes():
	default:
		log.Printf("Firehose: channel is full, discarded. Queued messages %d", len(srv.fh.C))
	}
}

func (srv *Server) sendBytes(b []byte) {
	r := lib.NewInterRecord()
	r.Types = 1
	r.Raw = b
	srv.sendRecord(r)
}
<|endoftext|>


<commit_before>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build go1.2,!go1.4

package config

import (
	"fmt"
	"log"
	"reflect"
	"testing"
)

var emptyContext map[string]string

type testElem struct {
	key           string
	expectedValue interface{}
}

// func Lookup(context map[string]string, key string) interface{}
var testsLookup = []struct {
	key           string
	expectedValue interface{}
}{
	{
		key:           "TestLookup",
		expectedValue: "this can be anything you can imagine, but now it's just a string",
	},
	{
		key:           "NotExisting",
		expectedValue: nil,
	},
}

func TestLookup(t *testing.T) {
	for i, e := range testsLookup {
		v := Lookup(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupString(context map[string]string, key string) string
var testsLookupString = []struct {
	key           string
	expectedValue string
}{
	{
		key:           "TestLookupString",
		expectedValue: "this should be a string",
	},
	{
		key:           "NotExisting",
		expectedValue: "",
	},
}

func TestLookupString(t *testing.T) {
	for i, e := range testsLookupString {
		v := LookupString(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupStringSlice(context map[string]string, key string) []string
var testsLookupStringSlice = []struct {
	key           string
	expectedValue []string
}{
	{
		// TestLookupStringSlice return slice is ordered
		key:           "TestLookupStringSlice",
		expectedValue: []string{"a", "am", "be", "going", "i", "slice", "to"},
	},
	{
		key:           "NotExisting",
		expectedValue: []string{""},
	},
}

func TestLookupStringSlice(t *testing.T) {
	for i, e := range testsLookupStringSlice {
		v := LookupStringSlice(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupStringMap(context map[string]string, key string) map[string]bool
var testsLookupStringMap = []struct {
	key           string
	expectedValue map[string]bool
}{
	{
		key: "TestLookupStringMap",
		expectedValue: map[string]bool{
			"to":              true,
			"be":              true,
			"a":               true,
			"map[string]bool": true,
			"I":               true,
			"want":            true,
		},
	},
	{
		key:           "NotExisting",
		expectedValue: map[string]bool{},
	},
}

func TestLookupStringMap(t *testing.T) {
	for i, e := range testsLookupStringMap {
		v := LookupStringMap(emptyContext, e.key)
		if !reflect.DeepEqual(v, e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

type nullWriter int

func (nullWriter) Write([]byte) (int, error) { return 0, nil }

func configLookupHelper(map[string]string) []string {
	return []string{"this/thing/does/not/exist.json", ".testconfig.json"}
}

func init() {
	SetFileListBuilder(configLookupHelper)
	log.SetOutput(nullWriter)
}
<commit_msg>Try and try again.<commit_after>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// +build go1.2,!go1.4

package config

import (
	"fmt"
	"log"
	"reflect"
	"testing"
)

var emptyContext map[string]string

type testElem struct {
	key           string
	expectedValue interface{}
}

// func Lookup(context map[string]string, key string) interface{}
var testsLookup = []struct {
	key           string
	expectedValue interface{}
}{
	{
		key:           "TestLookup",
		expectedValue: "this can be anything you can imagine, but now it's just a string",
	},
	{
		key:           "NotExisting",
		expectedValue: nil,
	},
}

func TestLookup(t *testing.T) {
	for i, e := range testsLookup {
		v := Lookup(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupString(context map[string]string, key string) string
var testsLookupString = []struct {
	key           string
	expectedValue string
}{
	{
		key:           "TestLookupString",
		expectedValue: "this should be a string",
	},
	{
		key:           "NotExisting",
		expectedValue: "",
	},
}

func TestLookupString(t *testing.T) {
	for i, e := range testsLookupString {
		v := LookupString(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupStringSlice(context map[string]string, key string) []string
var testsLookupStringSlice = []struct {
	key           string
	expectedValue []string
}{
	{
		// TestLookupStringSlice return slice is ordered
		key:           "TestLookupStringSlice",
		expectedValue: []string{"a", "am", "be", "going", "i", "slice", "to"},
	},
	{
		key:           "NotExisting",
		expectedValue: []string{""},
	},
}

func TestLookupStringSlice(t *testing.T) {
	for i, e := range testsLookupStringSlice {
		v := LookupStringSlice(emptyContext, e.key)
		if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

// func LookupStringMap(context map[string]string, key string) map[string]bool
var testsLookupStringMap = []struct {
	key           string
	expectedValue map[string]bool
}{
	{
		key: "TestLookupStringMap",
		expectedValue: map[string]bool{
			"to":              true,
			"be":              true,
			"a":               true,
			"map[string]bool": true,
			"I":               true,
			"want":            true,
		},
	},
	{
		key:           "NotExisting",
		expectedValue: map[string]bool{},
	},
}

func TestLookupStringMap(t *testing.T) {
	for i, e := range testsLookupStringMap {
		v := LookupStringMap(emptyContext, e.key)
		if !reflect.DeepEqual(v, e.expectedValue) {
			t.Log("test#", i+1, "Lookup key", e.key)
			t.Logf("expected: %+v\n", e.expectedValue)
			t.Logf("result  : %+v\n", v)
			t.Fail()
		}
	}
}

type nullWriter int

func (nullWriter) Write([]byte) (int, error) { return 0, nil }

func configLookupHelper(map[string]string) []string {
	return []string{"this/thing/does/not/exist.json", ".testconfig.json"}
}

func init() {
	SetFileListBuilder(configLookupHelper)
	log.SetOutput(new(nullWriter))
}
<|endoftext|>


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

// +build darwin freebsd

package osext

import (
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"unsafe"
)

var startUpcwd, getwdError = os.Getwd()

func executable() (string, error) {
	var mib [4]int32
	switch runtime.GOOS {
	case "freebsd":
		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
	case "darwin":
		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
	}

	n := uintptr(0)
	// get length
	_, _, err := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
	if err != 0 {
		return "", err
	}
	if n == 0 { // shouldn't happen
		return "", nil
	}
	buf := make([]byte, n)
	_, _, err = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
	if err != 0 {
		return "", err
	}
	if n == 0 { // shouldn't happen
		return "", nil
	}
	for i, v := range buf {
		if v == 0 {
			buf = buf[:i]
			break
		}
	}
	var strpath string
	if buf[0] != '/' {
		var e error
		if strpath, e = getAbs(buf); e != nil {
			return strpath, e
		}
	} else {
		strpath = string(buf)
	}
	// darwin KERN_PROCARGS may return the path to a symlink rather than the
	// actual executable
	if runtime.GOOS == "darwin" {
		if strpath, err := filepath.EvalSymlinks(strpath); err != nil {
			return strpath, err
		}
	}
	return strpath, nil
}

func getAbs(buf []byte) (string, error) {
	if getwdError != nil {
		return string(buf), getwdError
	} else {
		if buf[0] == '.' {
			buf = buf[1:]
		}
		if startUpcwd[len(startUpcwd)-1] != '/' && buf[0] != '/' {
			return startUpcwd + "/" + string(buf), nil
		}
		return startUpcwd + string(buf), nil
	}
}
<commit_msg>osext: for sysctl use filepath.<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin freebsd

package osext

import (
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"unsafe"
)

var initCwd, initCwdErr = os.Getwd()

func executable() (string, error) {
	var mib [4]int32
	switch runtime.GOOS {
	case "freebsd":
		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
	case "darwin":
		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
	}

	n := uintptr(0)
	// Get length.
	_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	buf := make([]byte, n)
	_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	for i, v := range buf {
		if v == 0 {
			buf = buf[:i]
			break
		}
	}
	var err error
	execPath := string(buf)
	// execPath will not be empty due to above checks.
	if execPath[0] != '/' {
		execPath, err = getAbs(execPath)
		if err != nil {
			return execPath, err
		}
	}
	// For darwin KERN_PROCARGS may return the path to a symlink rather than the
	// actual executable.
	if runtime.GOOS == "darwin" {
		if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
			return execPath, err
		}
	}
	return execPath, nil
}

func getAbs(execPath string) (string, error) {
	if initCwdErr != nil {
		return execPath, initCwdErr
	}
	return filepath.Join(initCwd, filepath.Clean(execPath)), nil
}
<|endoftext|>


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

// +build darwin freebsd

package osext

import (
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"unsafe"
)

var initCwd, initCwdErr = os.Getwd()

func executable() (string, error) {
	var mib [4]int32
	switch runtime.GOOS {
	case "freebsd":
		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
	case "darwin":
		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
	}

	n := uintptr(0)
	// Get length.
	_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	buf := make([]byte, n)
	_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	for i, v := range buf {
		if v == 0 {
			buf = buf[:i]
			break
		}
	}
	var err error
	execPath := string(buf)
	// execPath will not be empty due to above checks.
	if execPath[0] != '/' {
		execPath, err = getAbs(execPath)
		if err != nil {
			return execPath, err
		}
	}
	// For darwin KERN_PROCARGS may return the path to a symlink rather than the
	// actual executable.
	if runtime.GOOS == "darwin" {
		if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
			return execPath, err
		}
	}
	return execPath, nil
}

func getAbs(execPath string) (string, error) {
	if initCwdErr != nil {
		return execPath, initCwdErr
	}
	return filepath.Join(initCwd, filepath.Clean(execPath)), nil
}
<commit_msg>osext: add more comments to sysctl.<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin freebsd

package osext

import (
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"unsafe"
)

var initCwd, initCwdErr = os.Getwd()

func executable() (string, error) {
	var mib [4]int32
	switch runtime.GOOS {
	case "freebsd":
		mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
	case "darwin":
		mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
	}

	n := uintptr(0)
	// Get length.
	_, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	buf := make([]byte, n)
	_, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
	if errNum != 0 {
		return "", errNum
	}
	if n == 0 { // This shouldn't happen.
		return "", nil
	}
	for i, v := range buf {
		if v == 0 {
			buf = buf[:i]
			break
		}
	}
	var err error
	execPath := string(buf)
	// execPath will not be empty due to above checks.
	// Try to get the absolute path if the execPath is not rooted.
	if execPath[0] != '/' {
		execPath, err = getAbs(execPath)
		if err != nil {
			return execPath, err
		}
	}
	// For darwin KERN_PROCARGS may return the path to a symlink rather than the
	// actual executable.
	if runtime.GOOS == "darwin" {
		if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
			return execPath, err
		}
	}
	return execPath, nil
}

func getAbs(execPath string) (string, error) {
	if initCwdErr != nil {
		return execPath, initCwdErr
	}
	// The execPath may begin with a "../" or a "./" so clean it first.
	// Join the two paths, trailing and starting slashes undetermined, so use
	// the generic Join function.
	return filepath.Join(initCwd, filepath.Clean(execPath)), nil
}
<|endoftext|>


<commit_before>//go:build bindata
// +build bindata

package module

import (
	//"github.com/admpub/nging/v4/application/library/bindata"
	"github.com/admpub/nging/v4/application/library/common"
	"github.com/admpub/nging/v4/application/library/config"
	"github.com/admpub/nging/v4/application/library/route"
	"github.com/admpub/nging/v4/application/registry/dashboard"
	"github.com/admpub/nging/v4/application/registry/navigate"
)

func SetTemplate(pa ntemplate.PathAliases, key string, templatePath string) {
}

func SetAssets(so *middleware.StaticOptions, assetsPath string) {
}
<commit_msg>update<commit_after>//go:build bindata
// +build bindata

package module

import (
	"github.com/admpub/nging/v4/application/library/ntemplate"
	"github.com/webx-top/echo/middleware"
)

func SetTemplate(pa ntemplate.PathAliases, key string, templatePath string) {
}

func SetAssets(so *middleware.StaticOptions, assetsPath string) {
}
<|endoftext|>


<commit_before>// Copyright 2016 The prometheus-operator 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 updater

import (
	"log"
	"os"
	"path/filepath"

	"github.com/coreos/prometheus-operator/contrib/grafana-watcher/grafana"
)

type GrafanaDatasourceUpdater struct {
	client grafana.DatasourcesInterface
	glob   string
}

func NewGrafanaDatasourceUpdater(c grafana.DatasourcesInterface, g string) Updater {
	return &GrafanaDatasourceUpdater{
		client: c,
		glob:   g,
	}
}

func (u *GrafanaDatasourceUpdater) Init() error {
	return u.updateDatasources()
}

func (u *GrafanaDatasourceUpdater) OnModify() error {
	return u.updateDatasources()
}

func (u *GrafanaDatasourceUpdater) updateDatasources() error {
	err := u.deleteAllDatasources()
	if err != nil {
		return err
	}
	err = u.createDatasourcesFromFiles()
	if err != nil {
		return err
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) deleteAllDatasources() error {
	log.Println("Retrieving existing datasources")
	datasources, err := u.client.All()
	if err != nil {
		return err
	}

	log.Printf("Deleting %d datasources\n", len(datasources))
	for _, d := range datasources {
		log.Println("Deleting datasource:", d.Id)

		err := u.client.Delete(d.Id)
		if err != nil {
			return err
		}
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) createDatasourcesFromFiles() error {
	filePaths, err := filepath.Glob(u.glob)
	if err != nil {
		return err
	}

	for _, fp := range filePaths {
		u.createDatasourceFromFile(fp)
		if err != nil {
			return err
		}
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) createDatasourceFromFile(filePath string) error {
	log.Println("Creating datasource from:", filePath)

	f, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer f.Close()

	return u.client.Create(f)
}
<commit_msg>Check createDatasourceFromFile error<commit_after>// Copyright 2016 The prometheus-operator 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 updater

import (
	"log"
	"os"
	"path/filepath"

	"github.com/coreos/prometheus-operator/contrib/grafana-watcher/grafana"
)

type GrafanaDatasourceUpdater struct {
	client grafana.DatasourcesInterface
	glob   string
}

func NewGrafanaDatasourceUpdater(c grafana.DatasourcesInterface, g string) Updater {
	return &GrafanaDatasourceUpdater{
		client: c,
		glob:   g,
	}
}

func (u *GrafanaDatasourceUpdater) Init() error {
	return u.updateDatasources()
}

func (u *GrafanaDatasourceUpdater) OnModify() error {
	return u.updateDatasources()
}

func (u *GrafanaDatasourceUpdater) updateDatasources() error {
	err := u.deleteAllDatasources()
	if err != nil {
		return err
	}
	err = u.createDatasourcesFromFiles()
	if err != nil {
		return err
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) deleteAllDatasources() error {
	log.Println("Retrieving existing datasources")
	datasources, err := u.client.All()
	if err != nil {
		return err
	}

	log.Printf("Deleting %d datasources\n", len(datasources))
	for _, d := range datasources {
		log.Println("Deleting datasource:", d.Id)

		err := u.client.Delete(d.Id)
		if err != nil {
			return err
		}
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) createDatasourcesFromFiles() error {
	filePaths, err := filepath.Glob(u.glob)
	if err != nil {
		return err
	}

	for _, fp := range filePaths {
		err = u.createDatasourceFromFile(fp)
		if err != nil {
			return err
		}
	}

	return nil
}

func (u *GrafanaDatasourceUpdater) createDatasourceFromFile(filePath string) error {
	log.Println("Creating datasource from:", filePath)

	f, err := os.Open(filePath)
	if err != nil {
		return err
	}
	defer f.Close()

	return u.client.Create(f)
}
<|endoftext|>