<commit_before>package simra

import (
	"image"

	"github.com/pankona/gomo-simra/simra/gomo"
	"github.com/pankona/gomo-simra/simra/peer"
)

// Simra is a struct that provides API interface of simra
type Simra struct {
	driver Driver
}

var simra *Simra

// GetInstance returns instance of Simra.
// It is necessary to call this function to get Simra instance
// since Simra is single instance.
func GetInstance() *Simra {
	peer.LogDebug("IN")
	if simra == nil {
		simra = &Simra{}
	}
	peer.LogDebug("OUT")
	return simra
}

type point struct {
	x, y int
}

func (simra *Simra) onUpdate() {
	if simra.driver != nil {
		simra.driver.Drive()
	}

	// check collision
	for _, v := range comap {
		// TODO: refactor this Fxxkin' part

		x1, y1, w1, h1 := v.c1.GetXYWH()
		x2, y2, w2, h2 := v.c2.GetXYWH()

		p1 := &point{x1 - w1/2, y1 + h1/2}
		p2 := &point{x1 + w1/2, y1 + h1/2}
		p3 := &point{x1 - w1/2, y1 - h1/2}
		p4 := &point{x1 + w1/2, y1 - h1/2}

		if p1.x >= (x2-w2/2) && p1.x <= (x2+w2/2) &&
			p1.y >= (y2-h2/2) && p1.y <= (y2+h2/2) {
			v.listener.OnCollision()
		}
		if p2.x >= (x2-w2/2) && p2.x <= (x2+w2/2) &&
			p2.y >= (y2-h2/2) && p2.y <= (y2+h2/2) {
			v.listener.OnCollision()
		}
		if p3.x >= (x2-w2/2) && p3.x <= (x2+w2/2) &&
			p3.y >= (y2-h2/2) && p3.y <= (y2+h2/2) {
			v.listener.OnCollision()
		}
		if p4.x >= (x2-w2/2) && p4.x <= (x2+w2/2) &&
			p4.y >= (y2-h2/2) && p4.y <= (y2+h2/2) {
			v.listener.OnCollision()
		}
	}
}

func (simra *Simra) onStopped() {
	peer.LogDebug("IN")
	simra.driver = nil
	peer.GetGLPeer().Finalize()
	peer.LogDebug("OUT")
}

// Start needs to call to enable all function belong to simra package.
func (simra *Simra) Start(onStart, onStop chan bool) {
	peer.LogDebug("IN")
	gomo.GetInstance().Initialize(onStart, onStop, simra.onUpdate)
	peer.GetSpriteContainer().Initialize()

	gomo.GetInstance().Start()
	peer.LogDebug("OUT")
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (simra *Simra) SetScene(driver Driver) {
	peer.LogDebug("IN")
	peer.GetGLPeer().Reset()
	peer.GetSpriteContainer().RemoveSprites()

	simra.driver = driver
	driver.Initialize()
	peer.LogDebug("OUT")
}

// AddSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddSprite(assetName string, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (simra *Simra) RemoveSprite(s *Sprite) {
	peer.GetSpriteContainer().RemoveSprite(&s.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (simra *Simra) SetDesiredScreenSize(w, h float32) {
	peer.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (simra *Simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (simra *Simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// LogDebug prints logs.
// From simra, just call peer.LogDebug.
// This is disabled at Release Build.
func LogDebug(format string, a ...interface{}) {
	peer.LogDebug(format, a...)
}

// LogError prints logs.
// From simra, just call peer.LogError.
// This is never disabled even for Release build.
func LogError(format string, a ...interface{}) {
	peer.LogError(format, a...)
}
<commit_msg>[#71] add missing return in collision detection<commit_after>package simra

import (
	"image"

	"github.com/pankona/gomo-simra/simra/gomo"
	"github.com/pankona/gomo-simra/simra/peer"
)

// Simra is a struct that provides API interface of simra
type Simra struct {
	driver Driver
}

var simra *Simra

// GetInstance returns instance of Simra.
// It is necessary to call this function to get Simra instance
// since Simra is single instance.
func GetInstance() *Simra {
	peer.LogDebug("IN")
	if simra == nil {
		simra = &Simra{}
	}
	peer.LogDebug("OUT")
	return simra
}

type point struct {
	x, y int
}

func (simra *Simra) onUpdate() {
	if simra.driver != nil {
		simra.driver.Drive()
	}

	// check collision
	for _, v := range comap {
		// TODO: refactor this Fxxkin' part

		x1, y1, w1, h1 := v.c1.GetXYWH()
		x2, y2, w2, h2 := v.c2.GetXYWH()

		p1 := &point{x1 - w1/2, y1 + h1/2}
		p2 := &point{x1 + w1/2, y1 + h1/2}
		p3 := &point{x1 - w1/2, y1 - h1/2}
		p4 := &point{x1 + w1/2, y1 - h1/2}

		if p1.x >= (x2-w2/2) && p1.x <= (x2+w2/2) &&
			p1.y >= (y2-h2/2) && p1.y <= (y2+h2/2) {
			v.listener.OnCollision()
			return
		}
		if p2.x >= (x2-w2/2) && p2.x <= (x2+w2/2) &&
			p2.y >= (y2-h2/2) && p2.y <= (y2+h2/2) {
			v.listener.OnCollision()
			return
		}
		if p3.x >= (x2-w2/2) && p3.x <= (x2+w2/2) &&
			p3.y >= (y2-h2/2) && p3.y <= (y2+h2/2) {
			v.listener.OnCollision()
			return
		}
		if p4.x >= (x2-w2/2) && p4.x <= (x2+w2/2) &&
			p4.y >= (y2-h2/2) && p4.y <= (y2+h2/2) {
			v.listener.OnCollision()
			return
		}
	}
}

func (simra *Simra) onStopped() {
	peer.LogDebug("IN")
	simra.driver = nil
	peer.GetGLPeer().Finalize()
	peer.LogDebug("OUT")
}

// Start needs to call to enable all function belong to simra package.
func (simra *Simra) Start(onStart, onStop chan bool) {
	peer.LogDebug("IN")
	gomo.GetInstance().Initialize(onStart, onStop, simra.onUpdate)
	peer.GetSpriteContainer().Initialize()

	gomo.GetInstance().Start()
	peer.LogDebug("OUT")
}

// SetScene sets a driver as a scene.
// If a driver is already set, it is replaced with new one.
func (simra *Simra) SetScene(driver Driver) {
	peer.LogDebug("IN")
	peer.GetGLPeer().Reset()
	peer.GetSpriteContainer().RemoveSprites()

	simra.driver = driver
	driver.Initialize()
	peer.LogDebug("OUT")
}

// AddSprite adds a sprite to current scene.
// To call this function, SetScene must be called in advance.
func (simra *Simra) AddSprite(assetName string, rect image.Rectangle, s *Sprite) {
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().AddSprite(&s.Sprite, tex)
}

// RemoveSprite removes specified sprite from current scene.
// Removed sprite will be disappeared.
func (simra *Simra) RemoveSprite(s *Sprite) {
	peer.GetSpriteContainer().RemoveSprite(&s.Sprite)
}

// SetDesiredScreenSize configures virtual screen size.
// This function must be called at least once before calling Start.
func (simra *Simra) SetDesiredScreenSize(w, h float32) {
	peer.SetDesiredScreenSize(w, h)
}

// AddTouchListener registers a listener for notifying touch event.
// Event is notified when "screen" is touched.
func (simra *Simra) AddTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().AddTouchListener(listener)
}

// RemoveTouchListener unregisters a listener for notifying touch event.
func (simra *Simra) RemoveTouchListener(listener peer.TouchListener) {
	peer.GetTouchPeer().RemoveTouchListener(listener)
}

// LogDebug prints logs.
// From simra, just call peer.LogDebug.
// This is disabled at Release Build.
func LogDebug(format string, a ...interface{}) {
	peer.LogDebug(format, a...)
}

// LogError prints logs.
// From simra, just call peer.LogError.
// This is never disabled even for Release build.
func LogError(format string, a ...interface{}) {
	peer.LogError(format, a...)
}
<|endoftext|>


<commit_before>package simra

import (
	"image"

	"github.com/pankona/gomo-simra/simra/peer"
)

type Sprite struct {
	peer.Sprite
}

func (sprite *Sprite) ReplaceTexture(assetName string, rect image.Rectangle) {
	LogDebug("IN")
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().ReplaceTexture(&sprite.Sprite, tex)
	LogDebug("OUT")
}

func (sprite *Sprite) AddTouchListener(listener peer.TouchListener) {
	LogDebug("IN")
	sprite.Sprite.AddTouchListener(listener)
	LogDebug("OUT")
}

func (sprite *Sprite) RemoveAllTouchListener() {
	LogDebug("IN")
	sprite.Sprite.RemoveAllTouchListener()
	LogDebug("OUT")
}
<commit_msg>[#45] add comments for exposed functions of sprite.go<commit_after>package simra

import (
	"image"

	"github.com/pankona/gomo-simra/simra/peer"
)

// Sprite represents a sprite object.
type Sprite struct {
	peer.Sprite
}

// ReplaceTexture replaces sprite's texture with specified image resource.
func (sprite *Sprite) ReplaceTexture(assetName string, rect image.Rectangle) {
	LogDebug("IN")
	tex := peer.GetGLPeer().LoadTexture(assetName, rect)
	peer.GetSpriteContainer().ReplaceTexture(&sprite.Sprite, tex)
	LogDebug("OUT")
}

// AddTouchListener registers a listener for touch event.
// Touch event will be notified when "sprite" is touched.
func (sprite *Sprite) AddTouchListener(listener peer.TouchListener) {
	LogDebug("IN")
	sprite.Sprite.AddTouchListener(listener)
	LogDebug("OUT")
}

// RemoveAllTouchListener removes all listeners already registered.
func (sprite *Sprite) RemoveAllTouchListener() {
	LogDebug("IN")
	sprite.Sprite.RemoveAllTouchListener()
	LogDebug("OUT")
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/bcicen/grmon/agent"
	"github.com/coreos/etcd/clientv3"
	"github.com/fagongzi/gateway/pkg/pb/rpcpb"
	"github.com/fagongzi/gateway/pkg/service"
	"github.com/fagongzi/gateway/pkg/store"
	"github.com/fagongzi/gateway/pkg/util"
	"github.com/fagongzi/grpcx"
	"github.com/fagongzi/log"
	"github.com/labstack/echo"
	"google.golang.org/grpc"
)

var (
	addr           = flag.String("addr", "127.0.0.1:9092", "Addr: client grpc entrypoint")
	addrHTTP       = flag.String("addr-http", "127.0.0.1:9093", "Addr: client http restful entrypoint")
	addrStore      = flag.String("addr-store", "etcd://127.0.0.1:2379", "Addr: store address")
	namespace      = flag.String("namespace", "dev", "The namespace to isolation the environment.")
	discovery      = flag.Bool("discovery", false, "Publish apiserver service via discovery.")
	servicePrefix  = flag.String("service-prefix", "/services", "The prefix for service name.")
	publishLease   = flag.Int64("publish-lease", 10, "Publish service lease seconds")
	publishTimeout = flag.Int("publish-timeout", 30, "Publish service timeout seconds")
	ui             = flag.String("ui", "/app/gateway/ui", "The gateway ui dist dir.")
	uiPrefix       = flag.String("ui-prefix", "/ui", "The gateway ui prefix path.")
	version        = flag.Bool("version", false, "Show version info")
	m              = flag.Bool("m", false, "Show version info")
)

func main() {
	flag.Parse()

	if *version && util.PrintVersion() {
		os.Exit(0)
	}

	if *m {
		grmon.Start()
	}

	log.InitLog()
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.Infof("addr: %s", *addr)
	log.Infof("addr-store: %s", *addrStore)
	log.Infof("namespace: %s", *namespace)
	log.Infof("discovery: %v", *discovery)
	log.Infof("service-prefix: %s", *servicePrefix)
	log.Infof("publish-lease: %d", *publishLease)
	log.Infof("publish-timeout: %d", *publishTimeout)

	db, err := store.GetStoreFrom(*addrStore, fmt.Sprintf("/%s", *namespace))
	if err != nil {
		log.Fatalf("init store failed for %s, errors:\n%+v",
			*addrStore,
			err)
	}

	service.Init(db)

	var opts []grpcx.ServerOption
	if *discovery {
		opts = append(opts, grpcx.WithEtcdPublisher(db.Raw().(*clientv3.Client), *servicePrefix, *publishLease, time.Second*time.Duration(*publishTimeout)))
	}

	if *addrHTTP != "" {
		opts = append(opts, grpcx.WithHTTPServer(*addrHTTP, func(server *echo.Echo) {
			service.InitHTTPRouter(server, *ui, *uiPrefix)
		}))
	}

	s := grpcx.NewGRPCServer(*addr, func(svr *grpc.Server) []grpcx.Service {
		var services []grpcx.Service
		rpcpb.RegisterMetaServiceServer(svr, service.MetaService)
		services = append(services, grpcx.NewService(rpcpb.ServiceMeta, nil))
		return services
	}, opts...)

	log.Infof("api server listen at %s", *addr)
	go s.Start()

	waitStop(s)
}

func waitStop(s *grpcx.GRPCServer) {
	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	sig := <-sc
	s.GracefulStop()
	log.Infof("exit: signal=<%d>.", sig)
	switch sig {
	case syscall.SIGTERM:
		log.Infof("exit: bye :-).")
		os.Exit(0)
	default:
		log.Infof("exit: bye :-(.")
		os.Exit(1)
	}
}
<commit_msg>fix: ci<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/coreos/etcd/clientv3"
	"github.com/fagongzi/gateway/pkg/pb/rpcpb"
	"github.com/fagongzi/gateway/pkg/service"
	"github.com/fagongzi/gateway/pkg/store"
	"github.com/fagongzi/gateway/pkg/util"
	"github.com/fagongzi/grpcx"
	"github.com/fagongzi/log"
	"github.com/labstack/echo"
	"google.golang.org/grpc"
)

var (
	addr           = flag.String("addr", "127.0.0.1:9092", "Addr: client grpc entrypoint")
	addrHTTP       = flag.String("addr-http", "127.0.0.1:9093", "Addr: client http restful entrypoint")
	addrStore      = flag.String("addr-store", "etcd://127.0.0.1:2379", "Addr: store address")
	namespace      = flag.String("namespace", "dev", "The namespace to isolation the environment.")
	discovery      = flag.Bool("discovery", false, "Publish apiserver service via discovery.")
	servicePrefix  = flag.String("service-prefix", "/services", "The prefix for service name.")
	publishLease   = flag.Int64("publish-lease", 10, "Publish service lease seconds")
	publishTimeout = flag.Int("publish-timeout", 30, "Publish service timeout seconds")
	ui             = flag.String("ui", "/app/gateway/ui", "The gateway ui dist dir.")
	uiPrefix       = flag.String("ui-prefix", "/ui", "The gateway ui prefix path.")
	version        = flag.Bool("version", false, "Show version info")
)

func main() {
	flag.Parse()

	if *version && util.PrintVersion() {
		os.Exit(0)
	}

	log.InitLog()
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.Infof("addr: %s", *addr)
	log.Infof("addr-store: %s", *addrStore)
	log.Infof("namespace: %s", *namespace)
	log.Infof("discovery: %v", *discovery)
	log.Infof("service-prefix: %s", *servicePrefix)
	log.Infof("publish-lease: %d", *publishLease)
	log.Infof("publish-timeout: %d", *publishTimeout)

	db, err := store.GetStoreFrom(*addrStore, fmt.Sprintf("/%s", *namespace))
	if err != nil {
		log.Fatalf("init store failed for %s, errors:\n%+v",
			*addrStore,
			err)
	}

	service.Init(db)

	var opts []grpcx.ServerOption
	if *discovery {
		opts = append(opts, grpcx.WithEtcdPublisher(db.Raw().(*clientv3.Client), *servicePrefix, *publishLease, time.Second*time.Duration(*publishTimeout)))
	}

	if *addrHTTP != "" {
		opts = append(opts, grpcx.WithHTTPServer(*addrHTTP, func(server *echo.Echo) {
			service.InitHTTPRouter(server, *ui, *uiPrefix)
		}))
	}

	s := grpcx.NewGRPCServer(*addr, func(svr *grpc.Server) []grpcx.Service {
		var services []grpcx.Service
		rpcpb.RegisterMetaServiceServer(svr, service.MetaService)
		services = append(services, grpcx.NewService(rpcpb.ServiceMeta, nil))
		return services
	}, opts...)

	log.Infof("api server listen at %s", *addr)
	go s.Start()

	waitStop(s)
}

func waitStop(s *grpcx.GRPCServer) {
	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	sig := <-sc
	s.GracefulStop()
	log.Infof("exit: signal=<%d>.", sig)
	switch sig {
	case syscall.SIGTERM:
		log.Infof("exit: bye :-).")
		os.Exit(0)
	default:
		log.Infof("exit: bye :-(.")
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package cmd

import (
	"context"
	"errors"

	"github.com/minio/minio-go/v7/pkg/s3utils"
	"github.com/minio/minio/internal/logger"
	"github.com/minio/minio/internal/sync/errgroup"
)

// list all errors that can be ignore in a bucket operation.
var bucketOpIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied, errUnformattedDisk)

// list all errors that can be ignored in a bucket metadata operation.
var bucketMetadataOpIgnoredErrs = append(bucketOpIgnoredErrs, errVolumeNotFound)

/// Bucket operations

// MakeBucket - make a bucket.
func (er erasureObjects) MakeBucketWithLocation(ctx context.Context, bucket string, opts BucketOptions) error {
	defer NSUpdated(bucket, slashSeparator)

	// Verify if bucket is valid.
	if err := s3utils.CheckValidBucketNameStrict(bucket); err != nil {
		return BucketNameInvalid{Bucket: bucket}
	}

	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))

	// Make a volume entry on all underlying storage disks.
	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] != nil {
				if err := storageDisks[index].MakeVol(ctx, bucket); err != nil {
					if !errors.Is(err, errVolumeExists) {
						logger.LogIf(ctx, err)
					}
					return err
				}
				return nil
			}
			return errDiskNotFound
		}, index)
	}

	writeQuorum := getWriteQuorum(len(storageDisks))
	err := reduceWriteQuorumErrs(ctx, g.Wait(), bucketOpIgnoredErrs, writeQuorum)
	return toObjectErr(err, bucket)
}

func undoDeleteBucket(storageDisks []StorageAPI, bucket string) {
	g := errgroup.WithNErrs(len(storageDisks))
	// Undo previous make bucket entry on all underlying storage disks.
	for index := range storageDisks {
		if storageDisks[index] == nil {
			continue
		}
		index := index
		g.Go(func() error {
			_ = storageDisks[index].MakeVol(context.Background(), bucket)
			return nil
		}, index)
	}

	// Wait for all make vol to finish.
	g.Wait()
}

// getBucketInfo - returns the BucketInfo from one of the load balanced disks.
func (er erasureObjects) getBucketInfo(ctx context.Context, bucketName string) (bucketInfo BucketInfo, err error) {
	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))
	var bucketsInfo = make([]BucketInfo, len(storageDisks))
	// Undo previous make bucket entry on all underlying storage disks.
	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] == nil {
				return errDiskNotFound
			}
			volInfo, err := storageDisks[index].StatVol(ctx, bucketName)
			if err != nil {
				return err
			}
			bucketsInfo[index] = BucketInfo(volInfo)
			return nil
		}, index)
	}

	errs := g.Wait()

	for i, err := range errs {
		if err == nil {
			return bucketsInfo[i], nil
		}
	}

	// If all our errors were ignored, then we try to
	// reduce to one error based on read quorum.
	// `nil` is deliberately passed for ignoredErrs
	// because these errors were already ignored.
	readQuorum := getReadQuorum(len(storageDisks))
	return BucketInfo{}, reduceReadQuorumErrs(ctx, errs, nil, readQuorum)
}

// GetBucketInfo - returns BucketInfo for a bucket.
func (er erasureObjects) GetBucketInfo(ctx context.Context, bucket string) (bi BucketInfo, e error) {
	bucketInfo, err := er.getBucketInfo(ctx, bucket)
	if err != nil {
		return bi, toObjectErr(err, bucket)
	}
	return bucketInfo, nil
}

// DeleteBucket - deletes a bucket.
func (er erasureObjects) DeleteBucket(ctx context.Context, bucket string, opts DeleteBucketOptions) error {
	// Collect if all disks report volume not found.
	defer NSUpdated(bucket, slashSeparator)

	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))

	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] != nil {
				return storageDisks[index].DeleteVol(ctx, bucket, opts.Force)
			}
			return errDiskNotFound
		}, index)
	}

	// Wait for all the delete vols to finish.
	dErrs := g.Wait()

	if opts.Force {
		for _, err := range dErrs {
			if err != nil {
				undoDeleteBucket(storageDisks, bucket)
				return toObjectErr(err, bucket)
			}
		}

		return nil
	}

	writeQuorum := getWriteQuorum(len(storageDisks))
	err := reduceWriteQuorumErrs(ctx, dErrs, bucketOpIgnoredErrs, writeQuorum)
	if err == errErasureWriteQuorum && !opts.NoRecreate {
		undoDeleteBucket(storageDisks, bucket)
	}
	if err != nil {
		return toObjectErr(err, bucket)
	}

	// At this point we have `err == nil` but some errors might be `errVolumeNotEmpty`
	// we should proceed to attempt a force delete of such buckets.
	for index, err := range dErrs {
		if err == errVolumeNotEmpty && storageDisks[index] != nil {
			storageDisks[index].RenameFile(ctx, bucket, "", minioMetaTmpDeletedBucket, mustGetUUID())
		}
	}

	return nil
}

// IsNotificationSupported returns whether bucket notification is applicable for this layer.
func (er erasureObjects) IsNotificationSupported() bool {
	return true
}

// IsListenSupported returns whether listen bucket notification is applicable for this layer.
func (er erasureObjects) IsListenSupported() bool {
	return true
}

// IsEncryptionSupported returns whether server side encryption is implemented for this layer.
func (er erasureObjects) IsEncryptionSupported() bool {
	return true
}

// IsCompressionSupported returns whether compression is applicable for this layer.
func (er erasureObjects) IsCompressionSupported() bool {
	return true
}

// IsTaggingSupported indicates whether erasureObjects implements tagging support.
func (er erasureObjects) IsTaggingSupported() bool {
	return true
}
<commit_msg>fix: clean up dangling buckets during bucket delete (#13523)<commit_after>// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package cmd

import (
	"context"
	"errors"

	"github.com/minio/minio-go/v7/pkg/s3utils"
	"github.com/minio/minio/internal/logger"
	"github.com/minio/minio/internal/sync/errgroup"
)

// list all errors that can be ignore in a bucket operation.
var bucketOpIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied, errUnformattedDisk)

// list all errors that can be ignored in a bucket metadata operation.
var bucketMetadataOpIgnoredErrs = append(bucketOpIgnoredErrs, errVolumeNotFound)

/// Bucket operations

// MakeBucket - make a bucket.
func (er erasureObjects) MakeBucketWithLocation(ctx context.Context, bucket string, opts BucketOptions) error {
	defer NSUpdated(bucket, slashSeparator)

	// Verify if bucket is valid.
	if err := s3utils.CheckValidBucketNameStrict(bucket); err != nil {
		return BucketNameInvalid{Bucket: bucket}
	}

	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))

	// Make a volume entry on all underlying storage disks.
	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] != nil {
				if err := storageDisks[index].MakeVol(ctx, bucket); err != nil {
					if !errors.Is(err, errVolumeExists) {
						logger.LogIf(ctx, err)
					}
					return err
				}
				return nil
			}
			return errDiskNotFound
		}, index)
	}

	writeQuorum := getWriteQuorum(len(storageDisks))
	err := reduceWriteQuorumErrs(ctx, g.Wait(), bucketOpIgnoredErrs, writeQuorum)
	return toObjectErr(err, bucket)
}

func undoDeleteBucket(storageDisks []StorageAPI, bucket string) {
	g := errgroup.WithNErrs(len(storageDisks))
	// Undo previous make bucket entry on all underlying storage disks.
	for index := range storageDisks {
		if storageDisks[index] == nil {
			continue
		}
		index := index
		g.Go(func() error {
			_ = storageDisks[index].MakeVol(context.Background(), bucket)
			return nil
		}, index)
	}

	// Wait for all make vol to finish.
	g.Wait()
}

// getBucketInfo - returns the BucketInfo from one of the load balanced disks.
func (er erasureObjects) getBucketInfo(ctx context.Context, bucketName string) (bucketInfo BucketInfo, err error) {
	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))
	var bucketsInfo = make([]BucketInfo, len(storageDisks))
	// Undo previous make bucket entry on all underlying storage disks.
	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] == nil {
				return errDiskNotFound
			}
			volInfo, err := storageDisks[index].StatVol(ctx, bucketName)
			if err != nil {
				return err
			}
			bucketsInfo[index] = BucketInfo(volInfo)
			return nil
		}, index)
	}

	errs := g.Wait()

	for i, err := range errs {
		if err == nil {
			return bucketsInfo[i], nil
		}
	}

	// If all our errors were ignored, then we try to
	// reduce to one error based on read quorum.
	// `nil` is deliberately passed for ignoredErrs
	// because these errors were already ignored.
	readQuorum := getReadQuorum(len(storageDisks))
	return BucketInfo{}, reduceReadQuorumErrs(ctx, errs, nil, readQuorum)
}

// GetBucketInfo - returns BucketInfo for a bucket.
func (er erasureObjects) GetBucketInfo(ctx context.Context, bucket string) (bi BucketInfo, e error) {
	bucketInfo, err := er.getBucketInfo(ctx, bucket)
	if err != nil {
		return bi, toObjectErr(err, bucket)
	}
	return bucketInfo, nil
}

// DeleteBucket - deletes a bucket.
func (er erasureObjects) DeleteBucket(ctx context.Context, bucket string, opts DeleteBucketOptions) error {
	// Collect if all disks report volume not found.
	defer NSUpdated(bucket, slashSeparator)

	storageDisks := er.getDisks()

	g := errgroup.WithNErrs(len(storageDisks))

	for index := range storageDisks {
		index := index
		g.Go(func() error {
			if storageDisks[index] != nil {
				return storageDisks[index].DeleteVol(ctx, bucket, opts.Force)
			}
			return errDiskNotFound
		}, index)
	}

	// Wait for all the delete vols to finish.
	dErrs := g.Wait()

	if opts.Force {
		for _, err := range dErrs {
			if err != nil {
				undoDeleteBucket(storageDisks, bucket)
				return toObjectErr(err, bucket)
			}
		}

		return nil
	}

	writeQuorum := getWriteQuorum(len(storageDisks))
	err := reduceWriteQuorumErrs(ctx, dErrs, bucketOpIgnoredErrs, writeQuorum)
	if err == errErasureWriteQuorum && !opts.NoRecreate {
		undoDeleteBucket(storageDisks, bucket)
	}

	if err == nil || errors.Is(err, errVolumeNotFound) {
		var purgedDangling bool
		// At this point we have `err == nil` but some errors might be `errVolumeNotEmpty`
		// we should proceed to attempt a force delete of such buckets.
		for index, err := range dErrs {
			if err == errVolumeNotEmpty && storageDisks[index] != nil {
				storageDisks[index].RenameFile(ctx, bucket, "", minioMetaTmpDeletedBucket, mustGetUUID())
				purgedDangling = true
			}
		}
		// if we purged dangling buckets, ignore errVolumeNotFound error.
		if purgedDangling {
			err = nil
		}

	}

	return toObjectErr(err, bucket)
}

// IsNotificationSupported returns whether bucket notification is applicable for this layer.
func (er erasureObjects) IsNotificationSupported() bool {
	return true
}

// IsListenSupported returns whether listen bucket notification is applicable for this layer.
func (er erasureObjects) IsListenSupported() bool {
	return true
}

// IsEncryptionSupported returns whether server side encryption is implemented for this layer.
func (er erasureObjects) IsEncryptionSupported() bool {
	return true
}

// IsCompressionSupported returns whether compression is applicable for this layer.
func (er erasureObjects) IsCompressionSupported() bool {
	return true
}

// IsTaggingSupported indicates whether erasureObjects implements tagging support.
func (er erasureObjects) IsTaggingSupported() bool {
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"html/template"
	"os"

	"github.com/constabulary/gb"
	"github.com/constabulary/gb/cmd"
	"github.com/constabulary/gb/cmd/gb-vendor/vendor"
)

var format string

var cmdList = &cmd.Command{
	Name:      "list",
	UsageLine: "list [-f format]",
	Short:     "lists dependencies, one per line",
	Long: `gb vendor list formats lists the contents of the manifest file.

The output

Flags:
	-f
		controls the template used for printing each manifest entry. If not supplied
		the default value is "{{.Importpath}}\t{{.Repository}}{{.Path}}\t{{.Branch}}\t{{.Revision}}"

`,
	Run: func(ctx *gb.Context, args []string) error {
		m, err := vendor.ReadManifest(manifestFile(ctx))
		if err != nil {
			return fmt.Errorf("could not load manifest: %v", err)
		}
		tmpl, err := template.New("list").Parse(format)
		if err != nil {
			return fmt.Errorf("unable to parse template %q: %v", format, err)
		}

		for _, dep := range m.Dependencies {
			if err := tmpl.Execute(os.Stdout, dep); err != nil {
				return fmt.Errorf("unable to execute template: %v", err)
			}
			fmt.Fprintln(os.Stdout)
		}
		return nil
	},
	AddFlags: func(fs *flag.FlagSet) {
		fs.StringVar(&format, "f", "{{.Importpath}}\t{{.Repository}}{{.Path}}\t{{.Branch}}\t{{.Revision}}", "format template")
	},
}
<commit_msg>gb vendor list: use tabwriter to format output<commit_after>package main

import (
	"flag"
	"fmt"
	"html/template"
	"os"
	"text/tabwriter"

	"github.com/constabulary/gb"
	"github.com/constabulary/gb/cmd"
	"github.com/constabulary/gb/cmd/gb-vendor/vendor"
)

var format string

var cmdList = &cmd.Command{
	Name:      "list",
	UsageLine: "list [-f format]",
	Short:     "lists dependencies, one per line",
	Long: `gb vendor list formats lists the contents of the manifest file.

The output

Flags:
	-f
		controls the template used for printing each manifest entry. If not supplied
		the default value is "{{.Importpath}}\t{{.Repository}}{{.Path}}\t{{.Branch}}\t{{.Revision}}"

`,
	Run: func(ctx *gb.Context, args []string) error {
		m, err := vendor.ReadManifest(manifestFile(ctx))
		if err != nil {
			return fmt.Errorf("could not load manifest: %v", err)
		}
		tmpl, err := template.New("list").Parse(format)
		if err != nil {
			return fmt.Errorf("unable to parse template %q: %v", format, err)
		}
		w := tabwriter.NewWriter(os.Stdout, 1, 2, 1, ' ', 0)
		for _, dep := range m.Dependencies {
			if err := tmpl.Execute(w, dep); err != nil {
				return fmt.Errorf("unable to execute template: %v", err)
			}
			fmt.Fprintln(w)
		}
		return w.Flush()
	},
	AddFlags: func(fs *flag.FlagSet) {
		fs.StringVar(&format, "f", "{{.Importpath}}\t{{.Repository}}{{.Path}}\t{{.Branch}}\t{{.Revision}}", "format template")
	},
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"path/filepath"
	"time"

	"github.com/cheggaaa/pb"

	"github.com/kopia/kopia/internal/units"

	"github.com/kopia/kopia/fs/repofs"
)

type uploadProgress struct {
	dirLevel     int
	outputPrefix string

	bar *pb.ProgressBar
}

func (p *uploadProgress) Cached(path string, length int64) {
	log.Printf(p.outputPrefix+"Cached: %v %v", path, units.BytesString(length))
}

func (p *uploadProgress) StartedDir(path string) {
	log.Printf("Processing directory: %v", path)
	p.dirLevel++
	p.outputPrefix = p.outputPrefix + "  "
}

func (p *uploadProgress) FinishedDir(path string) {
	log.Printf("Finished directory: %v", path)
	p.outputPrefix = p.outputPrefix[2:]
	p.dirLevel--
}

func (p *uploadProgress) Started(path string, length int64) {
	//log.Printf("STARTED %v %v", path, units.BytesString(length))
	p.bar = pb.New64(length).Prefix(p.outputPrefix + filepath.Base(path))
	p.bar.SetRefreshRate(time.Second)
	p.bar.ShowSpeed = true
	p.bar.ShowTimeLeft = true
	p.bar.SetUnits(pb.U_BYTES)
	p.bar.Start()
}

func (p *uploadProgress) Finished(path string, length int64, err error) {
	if p.bar != nil {
		p.bar.Finish()
		p.bar = nil
	}
	//log.Printf("FINISHED %v %v", path, units.BytesString(length))
}

func (p *uploadProgress) Progress(path string, completed, total int64) {
	//log.Printf("PROGRESS %v %v/%v", path, units.BytesString(completed), units.BytesString(total))
	p.bar.Set64(completed)
}

var up repofs.UploadProgress = &uploadProgress{}
<commit_msg>progress reporting UI tweaks.<commit_after>package main

import (
	"log"
	"path/filepath"
	"time"

	"github.com/cheggaaa/pb"

	"github.com/kopia/kopia/internal/units"

	"github.com/kopia/kopia/fs/repofs"
)

type uploadProgress struct {
	currentDir string

	bar *pb.ProgressBar
}

func (p *uploadProgress) Cached(path string, length int64) {
	log.Printf("  Cached: %v %v", path, units.BytesString(length))
}

func (p *uploadProgress) StartedDir(path string) {
}

func (p *uploadProgress) FinishedDir(path string) {
}

func (p *uploadProgress) Started(path string, length int64) {
	dir := filepath.Dir(path)

	if p.currentDir != dir {
		p.currentDir = dir
		log.Printf("Processing directory: %v", dir)
	}

	p.bar = pb.New64(length).Prefix("  " + filepath.Base(path))
	p.bar.SetRefreshRate(time.Second)
	p.bar.ShowSpeed = true
	p.bar.ShowTimeLeft = true
	p.bar.SetUnits(pb.U_BYTES)
	p.bar.Start()
}

func (p *uploadProgress) Finished(path string, length int64, err error) {
	if p.bar != nil {
		p.bar.Finish()
		p.bar = nil
	}
	//log.Printf("FINISHED %v %v", path, units.BytesString(length))
}

func (p *uploadProgress) Progress(path string, completed, total int64) {
	//log.Printf("PROGRESS %v %v/%v", path, units.BytesString(completed), units.BytesString(total))
	p.bar.Set64(completed)
}

var up repofs.UploadProgress = &uploadProgress{}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/Roasbeef/btcd/wire"
	"github.com/codegangsta/cli"
	"github.com/lightningnetwork/lnd/lnrpc"
	"golang.org/x/net/context"
)

// TODO(roasbeef): cli logic for supporting both positional and unix style
// arguments.

func printRespJson(resp interface{}) {
	b, err := json.Marshal(resp)
	if err != nil {
		fatal(err)
	}

	// TODO(roasbeef): disable 'omitempty' like behavior

	var out bytes.Buffer
	json.Indent(&out, b, "", "\t")
	out.WriteTo(os.Stdout)
}

var ShellCommand = cli.Command{
	Name:  "shell",
	Usage: "enter interactive shell",
	Action: func(c *cli.Context) {
		println("not implemented yet")
	},
}

var NewAddressCommand = cli.Command{
	Name:   "newaddress",
	Usage:  "generates a new address. Three address types are supported: p2wkh, np2wkh, p2pkh",
	Action: newAddress,
}

func newAddress(ctx *cli.Context) {
	client := getClient(ctx)

	stringAddrType := ctx.Args().Get(0)

	// Map the string encoded address type, to the concrete typed address
	// type enum. An unrecognized address type will result in an error.
	var addrType lnrpc.NewAddressRequest_AddressType
	switch stringAddrType { // TODO(roasbeef): make them ints on the cli?
	case "p2wkh":
		addrType = lnrpc.NewAddressRequest_WITNESS_PUBKEY_HASH
	case "np2wkh":
		addrType = lnrpc.NewAddressRequest_NESTED_PUBKEY_HASH
	case "p2pkh":
		addrType = lnrpc.NewAddressRequest_PUBKEY_HASH
	default:
		fatal(fmt.Errorf("invalid address type %v, support address type "+
			"are: p2wkh, np2wkh, p2pkh", stringAddrType))
	}

	ctxb := context.Background()
	addr, err := client.NewAddress(ctxb, &lnrpc.NewAddressRequest{
		Type: addrType,
	})
	if err != nil {
		fatal(err)
	}

	printRespJson(addr)
}

var SendManyCommand = cli.Command{
	Name: "sendmany",
	Usage: "create and broadcast a transaction paying the specified " +
		"amount(s) to the passed address(es)",
	Action: sendMany,
}

func sendMany(ctx *cli.Context) {
	var amountToAddr map[string]int64

	jsonMap := ctx.Args().Get(0)
	if err := json.Unmarshal([]byte(jsonMap), &amountToAddr); err != nil {
		fatal(err)
	}

	ctxb := context.Background()
	client := getClient(ctx)

	txid, err := client.SendMany(ctxb, &lnrpc.SendManyRequest{amountToAddr})
	if err != nil {
		fatal(err)
	}

	printRespJson(txid)
}

var ConnectCommand = cli.Command{
	Name:   "connect",
	Usage:  "connect to a remote lnd peer: <lnid>@host",
	Action: connectPeer,
}

func connectPeer(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	targetAddress := ctx.Args().Get(0)
	splitAddr := strings.Split(targetAddress, "@")
	addr := &lnrpc.LightningAddress{
		PubKeyHash: splitAddr[0],
		Host:       splitAddr[1],
	}
	req := &lnrpc.ConnectPeerRequest{addr}

	lnid, err := client.ConnectPeer(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(lnid)
}

// TODO(roasbeef): default number of confirmations
var OpenChannelCommand = cli.Command{
	Name: "openchannel",
	Description: "Attempt to open a new channel to an existing peer, " +
		"blocking until the channel is 'open'. Once the channel is " +
		"open, a channelPoint (txid:vout) of the funding output is " +
		"returned.",
	Usage: "openchannel --peer_id=X --local_amt=N --remote_amt=N --num_confs=N",
	Flags: []cli.Flag{
		cli.IntFlag{
			Name:  "peer_id",
			Usage: "the id of the peer to open a channel with",
		},
		cli.IntFlag{
			Name:  "local_amt",
			Usage: "the number of satoshis the wallet should commit to the channel",
		},
		cli.IntFlag{
			Name:  "remote_amt",
			Usage: "the number of satoshis the remote peer should commit to the channel",
		},
		cli.IntFlag{
			Name: "num_confs",
			Usage: "the number of confirmations required before the " +
				"channel is considered 'open'",
		},
	},
	Action: openChannel,
}

func openChannel(ctx *cli.Context) {
	// TODO(roasbeef): add deadline to context
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.OpenChannelRequest{
		TargetPeerId:        int32(ctx.Int("peer_id")),
		LocalFundingAmount:  int64(ctx.Int("local_amt")),
		RemoteFundingAmount: int64(ctx.Int("remote_amt")),
		NumConfs:            uint32(ctx.Int("num_confs")),
	}

	resp, err := client.OpenChannel(ctxb, req)
	if err != nil {
		fatal(err)
	}

	txid, err := wire.NewShaHash(resp.ChannelPoint.FundingTxid)
	if err != nil {
		fatal(err)
	}

	index := resp.ChannelPoint.OutputIndex
	printRespJson(struct {
		ChannelPoint string
	}{
		ChannelPoint: fmt.Sprintf("%v:%v", txid, index),
	},
	)
}

// TODO(roasbeef): also allow short relative channel ID.
var CloseChannelCommand = cli.Command{
	Name: "closechannel",
	Description: "Close an existing channel. The channel can be closed either " +
		"cooperatively, or uncooperatively (forced).",
	Usage: "closechannel funding_txid output_index time_limit allow_force",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "funding_txid",
			Usage: "the txid of the channel's funding transaction",
		},
		cli.IntFlag{
			Name: "output_index",
			Usage: "the output index for the funding output of the funding " +
				"transaction",
		},
		cli.StringFlag{
			Name: "time_limit",
			Usage: "a relative deadline afterwhich the attempt should be " +
				"abandonded",
		},
		cli.BoolFlag{
			Name: "force",
			Usage: "after the time limit has passed, attempted an " +
				"uncooperative closure",
		},
	},
	Action: closeChannel,
}

func closeChannel(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	txid, err := wire.NewShaHashFromStr(ctx.String("funding_txid"))
	if err != nil {
		fatal(err)
	}

	req := &lnrpc.CloseChannelRequest{
		ChannelPoint: &lnrpc.ChannelPoint{
			FundingTxid: txid[:],
			OutputIndex: uint32(ctx.Int("output_index")),
		},
	}

	resp, err := client.CloseChannel(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}

var ListPeersCommand = cli.Command{
	Name:        "listpeers",
	Description: "List all active, currently connected peers.",
	Action:      listPeers,
}

func listPeers(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.ListPeersRequest{}
	resp, err := client.ListPeers(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}

var WalletBalanceCommand = cli.Command{
	Name:        "walletbalance",
	Description: "compute and display the wallet's current balance",
	Usage:       "walletbalance --witness_only=[true|false]",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "witness_only",
			Usage: "if only witness outputs should be considered when " +
				"calculating the wallet's balance",
		},
	},
	Action: walletBalance,
}

func walletBalance(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.WalletBalanceRequest{
		WitnessOnly: ctx.Bool("witness_only"),
	}
	resp, err := client.WalletBalance(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}
<commit_msg>cmd/lncli: add json attribute tag for anonymous ChannelPoint struct<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"strings"

	"github.com/Roasbeef/btcd/wire"
	"github.com/codegangsta/cli"
	"github.com/lightningnetwork/lnd/lnrpc"
	"golang.org/x/net/context"
)

// TODO(roasbeef): cli logic for supporting both positional and unix style
// arguments.

func printRespJson(resp interface{}) {
	b, err := json.Marshal(resp)
	if err != nil {
		fatal(err)
	}

	// TODO(roasbeef): disable 'omitempty' like behavior

	var out bytes.Buffer
	json.Indent(&out, b, "", "\t")
	out.WriteTo(os.Stdout)
}

var ShellCommand = cli.Command{
	Name:  "shell",
	Usage: "enter interactive shell",
	Action: func(c *cli.Context) {
		println("not implemented yet")
	},
}

var NewAddressCommand = cli.Command{
	Name:   "newaddress",
	Usage:  "generates a new address. Three address types are supported: p2wkh, np2wkh, p2pkh",
	Action: newAddress,
}

func newAddress(ctx *cli.Context) {
	client := getClient(ctx)

	stringAddrType := ctx.Args().Get(0)

	// Map the string encoded address type, to the concrete typed address
	// type enum. An unrecognized address type will result in an error.
	var addrType lnrpc.NewAddressRequest_AddressType
	switch stringAddrType { // TODO(roasbeef): make them ints on the cli?
	case "p2wkh":
		addrType = lnrpc.NewAddressRequest_WITNESS_PUBKEY_HASH
	case "np2wkh":
		addrType = lnrpc.NewAddressRequest_NESTED_PUBKEY_HASH
	case "p2pkh":
		addrType = lnrpc.NewAddressRequest_PUBKEY_HASH
	default:
		fatal(fmt.Errorf("invalid address type %v, support address type "+
			"are: p2wkh, np2wkh, p2pkh", stringAddrType))
	}

	ctxb := context.Background()
	addr, err := client.NewAddress(ctxb, &lnrpc.NewAddressRequest{
		Type: addrType,
	})
	if err != nil {
		fatal(err)
	}

	printRespJson(addr)
}

var SendManyCommand = cli.Command{
	Name: "sendmany",
	Usage: "create and broadcast a transaction paying the specified " +
		"amount(s) to the passed address(es)",
	Action: sendMany,
}

func sendMany(ctx *cli.Context) {
	var amountToAddr map[string]int64

	jsonMap := ctx.Args().Get(0)
	if err := json.Unmarshal([]byte(jsonMap), &amountToAddr); err != nil {
		fatal(err)
	}

	ctxb := context.Background()
	client := getClient(ctx)

	txid, err := client.SendMany(ctxb, &lnrpc.SendManyRequest{amountToAddr})
	if err != nil {
		fatal(err)
	}

	printRespJson(txid)
}

var ConnectCommand = cli.Command{
	Name:   "connect",
	Usage:  "connect to a remote lnd peer: <lnid>@host",
	Action: connectPeer,
}

func connectPeer(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	targetAddress := ctx.Args().Get(0)
	splitAddr := strings.Split(targetAddress, "@")
	addr := &lnrpc.LightningAddress{
		PubKeyHash: splitAddr[0],
		Host:       splitAddr[1],
	}
	req := &lnrpc.ConnectPeerRequest{addr}

	lnid, err := client.ConnectPeer(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(lnid)
}

// TODO(roasbeef): default number of confirmations
var OpenChannelCommand = cli.Command{
	Name: "openchannel",
	Description: "Attempt to open a new channel to an existing peer, " +
		"blocking until the channel is 'open'. Once the channel is " +
		"open, a channelPoint (txid:vout) of the funding output is " +
		"returned.",
	Usage: "openchannel --peer_id=X --local_amt=N --remote_amt=N --num_confs=N",
	Flags: []cli.Flag{
		cli.IntFlag{
			Name:  "peer_id",
			Usage: "the id of the peer to open a channel with",
		},
		cli.IntFlag{
			Name:  "local_amt",
			Usage: "the number of satoshis the wallet should commit to the channel",
		},
		cli.IntFlag{
			Name:  "remote_amt",
			Usage: "the number of satoshis the remote peer should commit to the channel",
		},
		cli.IntFlag{
			Name: "num_confs",
			Usage: "the number of confirmations required before the " +
				"channel is considered 'open'",
		},
	},
	Action: openChannel,
}

func openChannel(ctx *cli.Context) {
	// TODO(roasbeef): add deadline to context
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.OpenChannelRequest{
		TargetPeerId:        int32(ctx.Int("peer_id")),
		LocalFundingAmount:  int64(ctx.Int("local_amt")),
		RemoteFundingAmount: int64(ctx.Int("remote_amt")),
		NumConfs:            uint32(ctx.Int("num_confs")),
	}

	resp, err := client.OpenChannel(ctxb, req)
	if err != nil {
		fatal(err)
	}

	txid, err := wire.NewShaHash(resp.ChannelPoint.FundingTxid)
	if err != nil {
		fatal(err)
	}

	index := resp.ChannelPoint.OutputIndex
	printRespJson(struct {
		ChannelPoint string `json:"channel_point"`
	}{
		ChannelPoint: fmt.Sprintf("%v:%v", txid, index),
	},
	)
}

// TODO(roasbeef): also allow short relative channel ID.
var CloseChannelCommand = cli.Command{
	Name: "closechannel",
	Description: "Close an existing channel. The channel can be closed either " +
		"cooperatively, or uncooperatively (forced).",
	Usage: "closechannel funding_txid output_index time_limit allow_force",
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "funding_txid",
			Usage: "the txid of the channel's funding transaction",
		},
		cli.IntFlag{
			Name: "output_index",
			Usage: "the output index for the funding output of the funding " +
				"transaction",
		},
		cli.StringFlag{
			Name: "time_limit",
			Usage: "a relative deadline afterwhich the attempt should be " +
				"abandonded",
		},
		cli.BoolFlag{
			Name: "force",
			Usage: "after the time limit has passed, attempted an " +
				"uncooperative closure",
		},
	},
	Action: closeChannel,
}

func closeChannel(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	txid, err := wire.NewShaHashFromStr(ctx.String("funding_txid"))
	if err != nil {
		fatal(err)
	}

	req := &lnrpc.CloseChannelRequest{
		ChannelPoint: &lnrpc.ChannelPoint{
			FundingTxid: txid[:],
			OutputIndex: uint32(ctx.Int("output_index")),
		},
	}

	resp, err := client.CloseChannel(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}

var ListPeersCommand = cli.Command{
	Name:        "listpeers",
	Description: "List all active, currently connected peers.",
	Action:      listPeers,
}

func listPeers(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.ListPeersRequest{}
	resp, err := client.ListPeers(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}

var WalletBalanceCommand = cli.Command{
	Name:        "walletbalance",
	Description: "compute and display the wallet's current balance",
	Usage:       "walletbalance --witness_only=[true|false]",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "witness_only",
			Usage: "if only witness outputs should be considered when " +
				"calculating the wallet's balance",
		},
	},
	Action: walletBalance,
}

func walletBalance(ctx *cli.Context) {
	ctxb := context.Background()
	client := getClient(ctx)

	req := &lnrpc.WalletBalanceRequest{
		WitnessOnly: ctx.Bool("witness_only"),
	}
	resp, err := client.WalletBalance(ctxb, req)
	if err != nil {
		fatal(err)
	}

	printRespJson(resp)
}
<|endoftext|>


<commit_before>/*
 * Minio Cloud Storage, (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * 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 cmd

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

// toString - Safely convert interface to string without causing panic.
func toString(val interface{}) string {
	switch v := val.(type) {
	case string:
		return v
	}
	return ""
}

// toInteger _ Safely convert interface to integer without causing panic.
func toInteger(val interface{}) int64 {
	switch v := val.(type) {
	case float64:
		return int64(v)
	case int64:
		return v
	case int:
		return int64(v)
	}
	return 0
}

// isString - Safely check if val is of type string without causing panic.
func isString(val interface{}) bool {
	switch val.(type) {
	case string:
		return true
	}
	return false
}

// ContentLengthRange - policy content-length-range field.
type contentLengthRange struct {
	Min   int64
	Max   int64
	Valid bool // If content-length-range was part of policy
}

// PostPolicyForm provides strict static type conversion and validation for Amazon S3's POST policy JSON string.
type PostPolicyForm struct {
	Expiration time.Time // Expiration date and time of the POST policy.
	Conditions struct {  // Conditional policy structure.
		Policies map[string]struct {
			Operator string
			Value    string
		}
		ContentLengthRange contentLengthRange
	}
}

// parsePostPolicyForm - Parse JSON policy string into typed POostPolicyForm structure.
func parsePostPolicyForm(policy string) (PostPolicyForm, error) {
	// Convert po into interfaces and
	// perform strict type conversion using reflection.
	var rawPolicy struct {
		Expiration string        `json:"expiration"`
		Conditions []interface{} `json:"conditions"`
	}

	err := json.Unmarshal([]byte(policy), &rawPolicy)
	if err != nil {
		return PostPolicyForm{}, err
	}

	parsedPolicy := PostPolicyForm{}

	// Parse expiry time.
	parsedPolicy.Expiration, err = time.Parse(time.RFC3339Nano, rawPolicy.Expiration)
	if err != nil {
		return PostPolicyForm{}, err
	}
	parsedPolicy.Conditions.Policies = make(map[string]struct {
		Operator string
		Value    string
	})

	// Parse conditions.
	for _, val := range rawPolicy.Conditions {
		switch condt := val.(type) {
		case map[string]interface{}: // Handle key:value map types.
			for k, v := range condt {
				if !isString(v) { // Pre-check value type.
					// All values must be of type string.
					return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form", reflect.TypeOf(condt).String(), condt)
				}
				// {"acl": "public-read" } is an alternate way to indicate - [ "eq", "$acl", "public-read" ]
				// In this case we will just collapse this into "eq" for all use cases.
				parsedPolicy.Conditions.Policies["$"+k] = struct {
					Operator string
					Value    string
				}{
					Operator: "eq",
					Value:    toString(v),
				}
			}
		case []interface{}: // Handle array types.
			if len(condt) != 3 { // Return error if we have insufficient elements.
				return parsedPolicy, fmt.Errorf("Malformed conditional fields %s of type %s found in POST policy form", condt, reflect.TypeOf(condt).String())
			}
			switch toString(condt[0]) {
			case "eq", "starts-with":
				for _, v := range condt { // Pre-check all values for type.
					if !isString(v) {
						// All values must be of type string.
						return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form", reflect.TypeOf(condt).String(), condt)
					}
				}
				operator, matchType, value := toString(condt[0]), toString(condt[1]), toString(condt[2])
				parsedPolicy.Conditions.Policies[matchType] = struct {
					Operator string
					Value    string
				}{
					Operator: operator,
					Value:    value,
				}
			case "content-length-range":
				parsedPolicy.Conditions.ContentLengthRange = contentLengthRange{
					Min:   toInteger(condt[1]),
					Max:   toInteger(condt[2]),
					Valid: true,
				}
			default:
				// Condition should be valid.
				return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form",
					reflect.TypeOf(condt).String(), condt)
			}
		default:
			return parsedPolicy, fmt.Errorf("Unknown field %s of type %s found in POST policy form",
				condt, reflect.TypeOf(condt).String())
		}
	}
	return parsedPolicy, nil
}

// checkPostPolicy - apply policy conditions and validate input values.
func checkPostPolicy(formValues map[string]string, postPolicyForm PostPolicyForm) APIErrorCode {
	if !postPolicyForm.Expiration.After(time.Now().UTC()) {
		return ErrPolicyAlreadyExpired
	}
	if postPolicyForm.Conditions.Policies["$bucket"].Operator == "eq" {
		if formValues["Bucket"] != postPolicyForm.Conditions.Policies["$bucket"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$x-amz-date"].Operator == "eq" {
		if formValues["X-Amz-Date"] != postPolicyForm.Conditions.Policies["$x-amz-date"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "starts-with" {
		if !strings.HasPrefix(formValues["Content-Type"], postPolicyForm.Conditions.Policies["$Content-Type"].Value) {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "eq" {
		if formValues["Content-Type"] != postPolicyForm.Conditions.Policies["$Content-Type"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$key"].Operator == "starts-with" {
		if !strings.HasPrefix(formValues["Key"], postPolicyForm.Conditions.Policies["$key"].Value) {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$key"].Operator == "eq" {
		if formValues["Key"] != postPolicyForm.Conditions.Policies["$key"].Value {
			return ErrAccessDenied
		}
	}
	return ErrNone
}
<commit_msg>postpolicy: handle Amazon S3 compatible content-length-range condition (#3376)<commit_after>/*
 * Minio Cloud Storage, (C) 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * 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 cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// toString - Safely convert interface to string without causing panic.
func toString(val interface{}) string {
	switch v := val.(type) {
	case string:
		return v
	}
	return ""
}

// toInteger _ Safely convert interface to integer without causing panic.
func toInteger(val interface{}) (int64, error) {
	switch v := val.(type) {
	case float64:
		return int64(v), nil
	case int64:
		return v, nil
	case int:
		return int64(v), nil
	case string:
		i, err := strconv.Atoi(v)
		return int64(i), err
	}

	return 0, errors.New("Invalid number format")
}

// isString - Safely check if val is of type string without causing panic.
func isString(val interface{}) bool {
	switch val.(type) {
	case string:
		return true
	}
	return false
}

// ContentLengthRange - policy content-length-range field.
type contentLengthRange struct {
	Min   int64
	Max   int64
	Valid bool // If content-length-range was part of policy
}

// PostPolicyForm provides strict static type conversion and validation for Amazon S3's POST policy JSON string.
type PostPolicyForm struct {
	Expiration time.Time // Expiration date and time of the POST policy.
	Conditions struct {  // Conditional policy structure.
		Policies map[string]struct {
			Operator string
			Value    string
		}
		ContentLengthRange contentLengthRange
	}
}

// parsePostPolicyForm - Parse JSON policy string into typed POostPolicyForm structure.
func parsePostPolicyForm(policy string) (PostPolicyForm, error) {
	// Convert po into interfaces and
	// perform strict type conversion using reflection.
	var rawPolicy struct {
		Expiration string        `json:"expiration"`
		Conditions []interface{} `json:"conditions"`
	}

	err := json.Unmarshal([]byte(policy), &rawPolicy)
	if err != nil {
		return PostPolicyForm{}, err
	}

	parsedPolicy := PostPolicyForm{}

	// Parse expiry time.
	parsedPolicy.Expiration, err = time.Parse(time.RFC3339Nano, rawPolicy.Expiration)
	if err != nil {
		return PostPolicyForm{}, err
	}
	parsedPolicy.Conditions.Policies = make(map[string]struct {
		Operator string
		Value    string
	})

	// Parse conditions.
	for _, val := range rawPolicy.Conditions {
		switch condt := val.(type) {
		case map[string]interface{}: // Handle key:value map types.
			for k, v := range condt {
				if !isString(v) { // Pre-check value type.
					// All values must be of type string.
					return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form", reflect.TypeOf(condt).String(), condt)
				}
				// {"acl": "public-read" } is an alternate way to indicate - [ "eq", "$acl", "public-read" ]
				// In this case we will just collapse this into "eq" for all use cases.
				parsedPolicy.Conditions.Policies["$"+k] = struct {
					Operator string
					Value    string
				}{
					Operator: "eq",
					Value:    toString(v),
				}
			}
		case []interface{}: // Handle array types.
			if len(condt) != 3 { // Return error if we have insufficient elements.
				return parsedPolicy, fmt.Errorf("Malformed conditional fields %s of type %s found in POST policy form", condt, reflect.TypeOf(condt).String())
			}
			switch toString(condt[0]) {
			case "eq", "starts-with":
				for _, v := range condt { // Pre-check all values for type.
					if !isString(v) {
						// All values must be of type string.
						return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form", reflect.TypeOf(condt).String(), condt)
					}
				}
				operator, matchType, value := toString(condt[0]), toString(condt[1]), toString(condt[2])
				parsedPolicy.Conditions.Policies[matchType] = struct {
					Operator string
					Value    string
				}{
					Operator: operator,
					Value:    value,
				}
			case "content-length-range":
				min, err := toInteger(condt[1])
				if err != nil {
					return parsedPolicy, err
				}

				max, err := toInteger(condt[2])
				if err != nil {
					return parsedPolicy, err
				}

				parsedPolicy.Conditions.ContentLengthRange = contentLengthRange{
					Min:   min,
					Max:   max,
					Valid: true,
				}
			default:
				// Condition should be valid.
				return parsedPolicy, fmt.Errorf("Unknown type %s of conditional field value %s found in POST policy form",
					reflect.TypeOf(condt).String(), condt)
			}
		default:
			return parsedPolicy, fmt.Errorf("Unknown field %s of type %s found in POST policy form",
				condt, reflect.TypeOf(condt).String())
		}
	}
	return parsedPolicy, nil
}

// checkPostPolicy - apply policy conditions and validate input values.
func checkPostPolicy(formValues map[string]string, postPolicyForm PostPolicyForm) APIErrorCode {
	if !postPolicyForm.Expiration.After(time.Now().UTC()) {
		return ErrPolicyAlreadyExpired
	}
	if postPolicyForm.Conditions.Policies["$bucket"].Operator == "eq" {
		if formValues["Bucket"] != postPolicyForm.Conditions.Policies["$bucket"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$x-amz-date"].Operator == "eq" {
		if formValues["X-Amz-Date"] != postPolicyForm.Conditions.Policies["$x-amz-date"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "starts-with" {
		if !strings.HasPrefix(formValues["Content-Type"], postPolicyForm.Conditions.Policies["$Content-Type"].Value) {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "eq" {
		if formValues["Content-Type"] != postPolicyForm.Conditions.Policies["$Content-Type"].Value {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$key"].Operator == "starts-with" {
		if !strings.HasPrefix(formValues["Key"], postPolicyForm.Conditions.Policies["$key"].Value) {
			return ErrAccessDenied
		}
	}
	if postPolicyForm.Conditions.Policies["$key"].Operator == "eq" {
		if formValues["Key"] != postPolicyForm.Conditions.Policies["$key"].Value {
			return ErrAccessDenied
		}
	}
	return ErrNone
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"mime"
	"net/http"

	"github.com/chop-dbhi/sql-agent"

	_ "github.com/denisenkom/go-mssqldb"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-oci8"
	_ "github.com/mattn/go-sqlite3"
)

var usage = `SQL Agent - HTTP interface

This is an HTTP interface for the SQL Agent.

Run:

	sql-agent [-host=<host>] [-port=<port>]

Example:

	POST /
	Content-Type application/json

	{
		"driver": "postgres",
		"connection": {
			"host": "pghost.org",
			"port": 5432,
		},
		"sql": "SELECT * FROM users WHERE zipcode = :zipcode",
		"parameters": {
			"zipcode": 19104
		}
	}
`

const StatusUnprocessableEntity = 422

var (
	defaultMimetype = "application/json"

	mimetypeFormats = map[string]string{
		"text/csv":             "csv",
		"application/json":     "json",
		"application/x-ldjson": "ldjson",
	}
)

// parseMimetype parses a mimetype from the Accept header.
func parseMimetype(mimetype string) string {
	mimetype, params, err := mime.ParseMediaType(mimetype)

	if err != nil {
		return ""
	}

	// No Accept header passed.
	if mimetype == "" {
		return defaultMimetype
	}

	switch mimetype {
	case "application/json":
		if params["boundary"] == "NL" {
			return "application/x-ldjson"
		}
	default:
		if _, ok := mimetypeFormats[mimetype]; !ok {
			return ""
		}
	}

	return mimetype
}

func init() {
	flag.Usage = func() {
		fmt.Println(usage)
		flag.PrintDefaults()
	}

	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func main() {
	var (
		host string
		port int
	)

	flag.StringVar(&host, "host", "localhost", "Host of the agent.")
	flag.IntVar(&port, "port", 5000, "Port of the agent.")

	flag.Parse()

	addr := fmt.Sprintf("%s:%d", host, port)
	log.Printf("* Listening on %s...\n", addr)

	http.HandleFunc("/", handleRequest)

	log.Fatal(http.ListenAndServe(addr, nil))
}

type Payload struct {
	Driver     string
	Connection map[string]interface{}
	SQL        string
	Params     map[string]interface{}
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Validate the Accept header and parse it to ensure it is
	// supported.
	mimetype := r.Header.Get("Accept")

	if mimetype = parseMimetype(mimetype); mimetype == "" {
		w.WriteHeader(http.StatusNotAcceptable)
		return
	}

	var payload Payload

	// Decode the body.
	if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
		w.WriteHeader(StatusUnprocessableEntity)
		w.Write([]byte(fmt.Sprintf("could not decode JSON: %s", err)))
		return
	}

	if _, ok := sqlagent.Drivers[payload.Driver]; !ok {
		w.WriteHeader(StatusUnprocessableEntity)
		w.Write([]byte(fmt.Sprintf("unknown driver: %v", payload.Driver)))
		return
	}

	db, err := sqlagent.Connect(payload.Driver, payload.Connection)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		w.Write([]byte(fmt.Sprintf("problem connecting to database: %s", err)))
		return
	}

	defer db.Close()

	iter, err := sqlagent.Execute(db, payload.SQL, payload.Params)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		w.Write([]byte(fmt.Sprintf("error executing query: %s", err)))
		return
	}

	defer iter.Close()

	w.Header().Set("content-type", mimetype)

	switch mimetypeFormats[mimetype] {
	case "csv":
		err = sqlagent.EncodeCSV(w, iter)
	case "json":
		err = sqlagent.EncodeJSON(w, iter)
	case "ldjson":
		err = sqlagent.EncodeLDJSON(w, iter)
	}

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(fmt.Sprintf("error encoding data: %s", err)))
		return
	}
}
<commit_msg>Match wildcard mimetype to application/json<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"mime"
	"net/http"

	"github.com/chop-dbhi/sql-agent"

	_ "github.com/denisenkom/go-mssqldb"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-oci8"
	_ "github.com/mattn/go-sqlite3"
)

var usage = `SQL Agent - HTTP interface

This is an HTTP interface for the SQL Agent.

Run:

	sql-agent [-host=<host>] [-port=<port>]

Example:

	POST /
	Content-Type application/json

	{
		"driver": "postgres",
		"connection": {
			"host": "pghost.org",
			"port": 5432,
		},
		"sql": "SELECT * FROM users WHERE zipcode = :zipcode",
		"parameters": {
			"zipcode": 19104
		}
	}
`

const StatusUnprocessableEntity = 422

var (
	defaultMimetype = "application/json"

	mimetypeFormats = map[string]string{
		"*/*":                  "json",
		"text/csv":             "csv",
		"application/json":     "json",
		"application/x-ldjson": "ldjson",
	}
)

// parseMimetype parses a mimetype from the Accept header.
func parseMimetype(mimetype string) string {
	mimetype, params, err := mime.ParseMediaType(mimetype)

	if err != nil {
		return ""
	}

	// No Accept header passed.
	if mimetype == "" {
		return defaultMimetype
	}

	switch mimetype {
	case "application/json":
		if params["boundary"] == "NL" {
			return "application/x-ldjson"
		}
	default:
		if _, ok := mimetypeFormats[mimetype]; !ok {
			return ""
		}
	}

	return mimetype
}

func init() {
	flag.Usage = func() {
		fmt.Println(usage)
		flag.PrintDefaults()
	}

	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func main() {
	var (
		host string
		port int
	)

	flag.StringVar(&host, "host", "localhost", "Host of the agent.")
	flag.IntVar(&port, "port", 5000, "Port of the agent.")

	flag.Parse()

	addr := fmt.Sprintf("%s:%d", host, port)
	log.Printf("* Listening on %s...\n", addr)

	http.HandleFunc("/", handleRequest)

	log.Fatal(http.ListenAndServe(addr, nil))
}

type Payload struct {
	Driver     string
	Connection map[string]interface{}
	SQL        string
	Params     map[string]interface{}
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	// Validate the Accept header and parse it to ensure it is
	// supported.
	mimetype := r.Header.Get("Accept")

	if mimetype = parseMimetype(mimetype); mimetype == "" {
		w.WriteHeader(http.StatusNotAcceptable)
		return
	}

	var payload Payload

	// Decode the body.
	if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
		w.WriteHeader(StatusUnprocessableEntity)
		w.Write([]byte(fmt.Sprintf("could not decode JSON: %s", err)))
		return
	}

	if _, ok := sqlagent.Drivers[payload.Driver]; !ok {
		w.WriteHeader(StatusUnprocessableEntity)
		w.Write([]byte(fmt.Sprintf("unknown driver: %v", payload.Driver)))
		return
	}

	db, err := sqlagent.Connect(payload.Driver, payload.Connection)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		w.Write([]byte(fmt.Sprintf("problem connecting to database: %s", err)))
		return
	}

	defer db.Close()

	iter, err := sqlagent.Execute(db, payload.SQL, payload.Params)

	if err != nil {
		w.WriteHeader(http.StatusServiceUnavailable)
		w.Write([]byte(fmt.Sprintf("error executing query: %s", err)))
		return
	}

	defer iter.Close()

	w.Header().Set("content-type", mimetype)

	switch mimetypeFormats[mimetype] {
	case "csv":
		err = sqlagent.EncodeCSV(w, iter)
	case "json":
		err = sqlagent.EncodeJSON(w, iter)
	case "ldjson":
		err = sqlagent.EncodeLDJSON(w, iter)
	}

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(fmt.Sprintf("error encoding data: %s", err)))
		return
	}
}
<|endoftext|>


<commit_before>package init

import (
	"errors"
	"flag"
	"path/filepath"

	"github.com/ghthor/journal/git"
	initialize "github.com/ghthor/journal/init"
)

var Cmd = NewCmd(nil)

type cmd struct {
	flagSet *flag.FlagSet

	wd string // working directory

	noCommit bool
}

func NewCmd(flagSet *flag.FlagSet) *cmd {
	if flagSet == nil {
		flagSet = flag.NewFlagSet("init", flag.ExitOnError)
	}

	c := &cmd{
		flagSet: flagSet,
	}

	c.flagSet.BoolVar(&c.noCommit, "no-commit", false, "don't commit the modifications made by initialization to the repository")

	return c
}

func (c *cmd) SetWd(directory string) {
	c.wd = directory
}

func (c *cmd) Exec(args []string) error {
	c.flagSet.Parse(args)

	a := c.flagSet.Args()

	var path string

	switch len(a) {
	case 0:
		path = c.wd
	case 1:
		path = a[0]
		if !filepath.IsAbs(path) {
			path = filepath.Join(c.wd, path)
		}

	default:
		return errors.New("too many arguments")
	}

	commitable, err := initialize.Journal(path)
	if err != nil {
		return err
	}

	if !c.noCommit {
		git.Commit(commitable)
	}

	return nil
}

func (c cmd) Summary() string {
	return "how to use `init` verb"
}
<commit_msg>Added a commit msg sequence and prefix to `init` verb | It follows the standard I set within the `journal/fix` package<commit_after>package init

import (
	"errors"
	"flag"
	"path/filepath"

	"github.com/ghthor/journal/git"
	initialize "github.com/ghthor/journal/init"
)

var Cmd = NewCmd(nil)

type cmd struct {
	flagSet *flag.FlagSet

	wd string // working directory

	noCommit bool
}

func NewCmd(flagSet *flag.FlagSet) *cmd {
	if flagSet == nil {
		flagSet = flag.NewFlagSet("init", flag.ExitOnError)
	}

	c := &cmd{
		flagSet: flagSet,
	}

	c.flagSet.BoolVar(&c.noCommit, "no-commit", false, "don't commit the modifications made by initialization to the repository")

	return c
}

func (c *cmd) SetWd(directory string) {
	c.wd = directory
}

type journalInitCommit struct {
	git.Commitable
}

func (c journalInitCommit) CommitMsg() string {
	return "journal - init - " + c.Commitable.CommitMsg()
}

func (c *cmd) Exec(args []string) error {
	c.flagSet.Parse(args)

	a := c.flagSet.Args()

	var path string

	switch len(a) {
	case 0:
		path = c.wd
	case 1:
		path = a[0]
		if !filepath.IsAbs(path) {
			path = filepath.Join(c.wd, path)
		}

	default:
		return errors.New("too many arguments")
	}

	commitable, err := initialize.Journal(path)
	if err != nil {
		return err
	}

	if !c.noCommit {
		err := git.CommitEmpty(path, "journal - init - begin")
		if err != nil {
			return err
		}

		err = git.Commit(journalInitCommit{commitable})
		if err != nil {
			return err
		}

		err = git.CommitEmpty(path, "journal - init - completed")
		if err != nil {
			return err
		}
	}

	return nil
}

func (c cmd) Summary() string {
	return "how to use `init` verb"
}
<|endoftext|>


<commit_before>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package filter

import (
	"testing"
	"time"
)

func TestFilters(t *testing.T) {
	var success bool
	var failure bool

	fm := New()
	fm.Start()
	fm.Install(Generic{
		Str1: "hello",
		Fn: func(data interface{}) {
			success = data.(bool)
		},
	})
	fm.Install(Generic{
		Str1: "hello1",
		Str2: "hello",
		Fn: func(data interface{}) {
			failure = true
		},
	})
	fm.Notify(Generic{Str1: "hello"}, true)
	fm.Stop()

	time.Sleep(10 * time.Millisecond) // yield to the notifier

	if !success {
		t.Error("expected 'hello' to be posted")
	}

	if failure {
		t.Error("hello1 was triggered")
	}
}
<commit_msg>event/filter: fix data race in the test<commit_after>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package filter

import (
	"testing"
	"time"
)

// Simple test to check if baseline matching/mismatching filtering works.
func TestFilters(t *testing.T) {
	fm := New()
	fm.Start()

	// Register two filters to catch posted data
	first := make(chan struct{})
	fm.Install(Generic{
		Str1: "hello",
		Fn: func(data interface{}) {
			first <- struct{}{}
		},
	})
	second := make(chan struct{})
	fm.Install(Generic{
		Str1: "hello1",
		Str2: "hello",
		Fn: func(data interface{}) {
			second <- struct{}{}
		},
	})
	// Post an event that should only match the first filter
	fm.Notify(Generic{Str1: "hello"}, true)
	fm.Stop()

	// Ensure only the mathcing filters fire
	select {
	case <-first:
	case <-time.After(100 * time.Millisecond):
		t.Error("matching filter timed out")
	}
	select {
	case <-second:
		t.Error("mismatching filter fired")
	case <-time.After(100 * time.Millisecond):
	}
}
<|endoftext|>


<commit_before>package fs

/*
file structure:

mtpt/
	github/
		1000111/
			subject
			message
*/

import (
	"errors"
	"os"
	"strings"
	"time"
)

type Comment interface {
	Key() string
	Message() string
	Creation() time.Time
	LastMod() time.Time
}

type Task interface {
	Key() string
	Subject() string
	Message() string
	PermaLink() string
	Creation() time.Time
	LastMod() time.Time
	Comments() ([]Comment, error)
}

type Service interface {
	Name() string
	List() ([]Task, error)
}

type FileInfo struct {
	Name     string
	Size     int64
	Mode     os.FileMode
	Creation time.Time
	LastMod  time.Time
}

func (f *FileInfo) IsDir() bool {
	return f.Mode&os.ModeDir != 0
}

type Dir interface {
	Node
	Stat() *FileInfo
	ReadDir() ([]Dir, error)
	ReadFile() ([]byte, error)
	Refresh()
}

var errProtocol = errors.New("protocol botch")

type Root struct {
	Node
	FileInfo
	services map[string]Service
}

func NewRoot() *Root {
	now := time.Now()
	return &Root{
		Node: NewNode(),
		FileInfo: FileInfo{
			Mode:     os.ModeDir | 0755,
			Creation: now,
			LastMod:  now,
		},
		services: make(map[string]Service),
	}
}

func (root *Root) CreateService(srv Service) {
	root.services[srv.Name()] = srv
}

func (root *Root) Stat() *FileInfo {
	return &root.FileInfo
}

func (root *Root) ReadDir() ([]Dir, error) {
	now := time.Now()
	dirs := make([]Dir, 0, len(root.services))
	for name, svc := range root.services {
		dir := &ServiceDir{
			Node: NewNode(),
			FileInfo: FileInfo{
				Name:     name,
				Mode:     os.ModeDir | 0755,
				Creation: now,
				LastMod:  now,
			},
			svc: svc,
		}
		dirs = append(dirs, dir)
	}
	return dirs, nil
}

func (*Root) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

func (*Root) Refresh() {
}

type ServiceDir struct {
	Node
	FileInfo
	svc   Service
	cache []Dir
}

func (dir *ServiceDir) Stat() *FileInfo {
	return &dir.FileInfo
}

func (dir *ServiceDir) ReadDir() ([]Dir, error) {
	if dir.cache != nil {
		return dir.cache, nil
	}
	a, err := dir.svc.List()
	if err != nil {
		return nil, err
	}
	dirs := make([]Dir, len(a)+1)
	for i, task := range a {
		dirs[i] = &TaskDir{
			Node: NewNode(),
			FileInfo: FileInfo{
				Name:     task.Key(),
				Mode:     os.ModeDir | 0755,
				Creation: task.Creation(),
				LastMod:  task.LastMod(),
			},
			task: task,
		}
	}
	now := time.Now()
	dirs[len(dirs)-1] = &Ctl{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     "ctl",
			Mode:     0644,
			Creation: now,
			LastMod:  now,
		},
		parent: dir,
	}
	dir.cache = dirs
	return dirs, nil
}

func (*ServiceDir) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

func (dir *ServiceDir) Refresh() {
	dir.cache = nil
}

type TaskDir struct {
	Node
	FileInfo
	task  Task
	files []Dir
}

func (dir *TaskDir) Stat() *FileInfo {
	return &dir.FileInfo
}

func (dir *TaskDir) ReadDir() ([]Dir, error) {
	if dir.files != nil {
		return dir.files, nil
	}
	a, err := dir.task.Comments()
	if err != nil {
		return nil, err
	}
	kids := make([]Dir, 0, len(a)+3)
	kids = append(kids, dir.newText("subject", dir.task.Subject()))
	kids = append(kids, dir.newText("message", dir.task.Message()))
	kids = append(kids, dir.newText("url", dir.task.PermaLink()))
	for _, c := range a {
		kids = append(kids, NewCommentText(c))
	}
	dir.files = kids
	return dir.files, nil
}

func (*TaskDir) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

func (dir *TaskDir) Refresh() {
}

func (dir *TaskDir) newText(name, s string) *Text {
	data := []byte(s)
	return &Text{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     name,
			Size:     int64(len(data)),
			Mode:     0644,
			Creation: dir.task.Creation(),
			LastMod:  dir.task.LastMod(),
		},
		data: data,
	}
}

type Text struct {
	Node
	FileInfo
	data []byte
}

func (t *Text) Stat() *FileInfo {
	return &t.FileInfo
}

func (t *Text) ReadDir() ([]Dir, error) {
	// this method isn't going to be called.
	return nil, errProtocol
}

func (t *Text) ReadFile() ([]byte, error) {
	return t.data, nil
}

func (t *Text) Refresh() {
}

type CommentText struct {
	Node
	FileInfo
	data []byte
}

func NewCommentText(c Comment) *CommentText {
	data := []byte(c.Message())
	return &CommentText{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     c.Key(),
			Size:     int64(len(data)),
			Mode:     0644,
			Creation: c.Creation(),
			LastMod:  c.LastMod(),
		},
		data: data,
	}
}

func (t *CommentText) Stat() *FileInfo {
	return &t.FileInfo
}

func (t *CommentText) ReadDir() ([]Dir, error) {
	return nil, errProtocol
}

func (t *CommentText) ReadFile() ([]byte, error) {
	return t.data, nil
}

func (t *CommentText) Refresh() {
}

type Ctl struct {
	Node
	FileInfo
	parent Dir
}

func (ctl *Ctl) Stat() *FileInfo {
	return &ctl.FileInfo
}

func (ctl *Ctl) ReadDir() ([]Dir, error) {
	return nil, errProtocol
}

func (ctl *Ctl) ReadFile() ([]byte, error) {
	return []byte{}, nil
}

func (ctl *Ctl) WriteFile(p []byte) error {
	s := string(p)
	a := strings.Fields(s)
	if len(a) == 0 {
		return nil
	}
	switch a[0] {
	case "refresh":
		ctl.parent.Refresh()
	default:
		return errors.New("unknown command")
	}
	return nil
}

func (ctl *Ctl) Refresh() {
}
<commit_msg>refactor: move Refresh method into Ctl.cmds table<commit_after>package fs

/*
file structure:

mtpt/
	github/
		1000111/
			subject
			message
*/

import (
	"errors"
	"os"
	"strings"
	"time"
)

type Comment interface {
	Key() string
	Message() string
	Creation() time.Time
	LastMod() time.Time
}

type Task interface {
	Key() string
	Subject() string
	Message() string
	PermaLink() string
	Creation() time.Time
	LastMod() time.Time
	Comments() ([]Comment, error)
}

type Service interface {
	Name() string
	List() ([]Task, error)
}

type FileInfo struct {
	Name     string
	Size     int64
	Mode     os.FileMode
	Creation time.Time
	LastMod  time.Time
}

func (f *FileInfo) IsDir() bool {
	return f.Mode&os.ModeDir != 0
}

type Dir interface {
	Node
	Stat() *FileInfo
	ReadDir() ([]Dir, error)
	ReadFile() ([]byte, error)
}

var errProtocol = errors.New("protocol botch")

type Root struct {
	Node
	FileInfo
	services map[string]Service
}

func NewRoot() *Root {
	now := time.Now()
	return &Root{
		Node: NewNode(),
		FileInfo: FileInfo{
			Mode:     os.ModeDir | 0755,
			Creation: now,
			LastMod:  now,
		},
		services: make(map[string]Service),
	}
}

func (root *Root) CreateService(srv Service) {
	root.services[srv.Name()] = srv
}

func (root *Root) Stat() *FileInfo {
	return &root.FileInfo
}

func (root *Root) ReadDir() ([]Dir, error) {
	now := time.Now()
	dirs := make([]Dir, 0, len(root.services))
	for name, svc := range root.services {
		dir := &ServiceDir{
			Node: NewNode(),
			FileInfo: FileInfo{
				Name:     name,
				Mode:     os.ModeDir | 0755,
				Creation: now,
				LastMod:  now,
			},
			svc: svc,
		}
		dirs = append(dirs, dir)
	}
	return dirs, nil
}

func (*Root) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

type ServiceDir struct {
	Node
	FileInfo
	svc   Service
	cache []Dir
}

func (dir *ServiceDir) Stat() *FileInfo {
	return &dir.FileInfo
}

func (dir *ServiceDir) ReadDir() ([]Dir, error) {
	if dir.cache != nil {
		return dir.cache, nil
	}
	a, err := dir.svc.List()
	if err != nil {
		return nil, err
	}
	dirs := make([]Dir, len(a)+1)
	for i, task := range a {
		dirs[i] = &TaskDir{
			Node: NewNode(),
			FileInfo: FileInfo{
				Name:     task.Key(),
				Mode:     os.ModeDir | 0755,
				Creation: task.Creation(),
				LastMod:  task.LastMod(),
			},
			task: task,
		}
	}
	now := time.Now()
	dirs[len(dirs)-1] = &Ctl{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     "ctl",
			Mode:     0644,
			Creation: now,
			LastMod:  now,
		},
		parent: dir,
		cmds: map[string]func(args ...string){
			"refresh": dir.refreshDir,
		},
	}
	dir.cache = dirs
	return dirs, nil
}

func (dir *ServiceDir) refreshDir(args ...string) {
	dir.cache = nil
}

func (*ServiceDir) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

type TaskDir struct {
	Node
	FileInfo
	task  Task
	files []Dir
}

func (dir *TaskDir) Stat() *FileInfo {
	return &dir.FileInfo
}

func (dir *TaskDir) ReadDir() ([]Dir, error) {
	if dir.files != nil {
		return dir.files, nil
	}
	a, err := dir.task.Comments()
	if err != nil {
		return nil, err
	}
	kids := make([]Dir, 0, len(a)+3)
	kids = append(kids, dir.newText("subject", dir.task.Subject()))
	kids = append(kids, dir.newText("message", dir.task.Message()))
	kids = append(kids, dir.newText("url", dir.task.PermaLink()))
	for _, c := range a {
		kids = append(kids, NewCommentText(c))
	}
	dir.files = kids
	return dir.files, nil
}

func (*TaskDir) ReadFile() ([]byte, error) {
	return nil, errProtocol
}

func (dir *TaskDir) newText(name, s string) *Text {
	data := []byte(s)
	return &Text{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     name,
			Size:     int64(len(data)),
			Mode:     0644,
			Creation: dir.task.Creation(),
			LastMod:  dir.task.LastMod(),
		},
		data: data,
	}
}

type Text struct {
	Node
	FileInfo
	data []byte
}

func (t *Text) Stat() *FileInfo {
	return &t.FileInfo
}

func (t *Text) ReadDir() ([]Dir, error) {
	// this method isn't going to be called.
	return nil, errProtocol
}

func (t *Text) ReadFile() ([]byte, error) {
	return t.data, nil
}

type CommentText struct {
	Node
	FileInfo
	data []byte
}

func NewCommentText(c Comment) *CommentText {
	data := []byte(c.Message())
	return &CommentText{
		Node: NewNode(),
		FileInfo: FileInfo{
			Name:     c.Key(),
			Size:     int64(len(data)),
			Mode:     0644,
			Creation: c.Creation(),
			LastMod:  c.LastMod(),
		},
		data: data,
	}
}

func (t *CommentText) Stat() *FileInfo {
	return &t.FileInfo
}

func (t *CommentText) ReadDir() ([]Dir, error) {
	return nil, errProtocol
}

func (t *CommentText) ReadFile() ([]byte, error) {
	return t.data, nil
}

type Ctl struct {
	Node
	FileInfo
	parent Dir
	cmds   map[string]func(args ...string)
}

func (ctl *Ctl) Stat() *FileInfo {
	return &ctl.FileInfo
}

func (ctl *Ctl) ReadDir() ([]Dir, error) {
	return nil, errProtocol
}

func (ctl *Ctl) ReadFile() ([]byte, error) {
	return []byte{}, nil
}

func (ctl *Ctl) WriteFile(p []byte) error {
	s := string(p)
	a := strings.Fields(s)
	if len(a) == 0 {
		return nil
	}
	fn, ok := ctl.cmds[a[0]]
	if !ok {
		return errors.New("unknown command")
	}
	fn(a[1:]...)
	return nil
}
<|endoftext|>


<commit_before>//file is borrowed from github.com/kelseyhightower/confd

package main

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/fatih/structs"
)

func newFuncMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["base"] = path.Base
	m["split"] = strings.Split
	m["json"] = UnmarshalJsonObject
	m["jsonArray"] = UnmarshalJsonArray
	m["dir"] = path.Dir
	m["getenv"] = os.Getenv
	m["join"] = strings.Join
	m["atoi"] = strconv.Atoi
	m["where"] = where
	m["datetime"] = time.Now
	m["toUpper"] = strings.ToUpper
	m["toLower"] = strings.ToLower
	m["contains"] = strings.Contains
	m["replace"] = strings.Replace
	return m
}

////////////////////////////////////////////////////////////////////////////////
func where(in interface{}, sliceKey string, sliceVal interface{}) ([]interface{}, error) {
	ret := make([]interface{}, 0)
	if in == nil {
		return ret, errors.New("where: source is nil")
	}
	if sliceKey == "" {
		return ret, errors.New("where: key is empty")
	}
	if sliceVal == nil {
		return ret, errors.New("where: value is nil")
	}

	if reflect.TypeOf(in).Kind() != reflect.Slice {
		return ret, errors.New("where: source is no slice value")
	}

	s := reflect.ValueOf(in)
	for i := 0; i < s.Len(); i++ {
		val := s.Index(i)
		st := structs.New(val)
		field, ok := st.FieldOk(sliceKey)
		if !ok {
			return ret, errors.New("where: invalid input type")
		}
		if field.Value() == sliceVal {
			ret = append(ret, val)
		}
	}

	return ret, nil
}

func addFuncs(out, in map[string]interface{}) {
	for name, fn := range in {
		out[name] = fn
	}
}

func UnmarshalJsonObject(data string) (map[string]interface{}, error) {
	var ret map[string]interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}

func UnmarshalJsonArray(data string) ([]interface{}, error) {
	var ret []interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}
<commit_msg>autopush@1446222868<commit_after>//file is borrowed from github.com/kelseyhightower/confd

package main

import (
	"encoding/json"
	"errors"
	"os"
	"path"
	"reflect"
	"strconv"
	"strings"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/fatih/structs"
)

////////////////////////////////////////////////////////////////////////////////
func Inspect(args ...interface{}) {
	spew.Dump(args)
}

func newFuncMap() map[string]interface{} {
	m := make(map[string]interface{})
	m["base"] = path.Base
	m["split"] = strings.Split
	m["json"] = UnmarshalJsonObject
	m["jsonArray"] = UnmarshalJsonArray
	m["dir"] = path.Dir
	m["getenv"] = os.Getenv
	m["join"] = strings.Join
	m["atoi"] = strconv.Atoi
	m["where"] = where
	m["datetime"] = time.Now
	m["toUpper"] = strings.ToUpper
	m["toLower"] = strings.ToLower
	m["contains"] = strings.Contains
	m["replace"] = strings.Replace
	return m
}

////////////////////////////////////////////////////////////////////////////////
func where(in interface{}, sliceKey string, sliceVal interface{}) ([]interface{}, error) {
	ret := make([]interface{}, 0)
	if in == nil {
		return ret, errors.New("where: source is nil")
	}
	if sliceKey == "" {
		return ret, errors.New("where: key is empty")
	}
	if sliceVal == nil {
		return ret, errors.New("where: value is nil")
	}

	if reflect.TypeOf(in).Kind() != reflect.Slice {
		return ret, errors.New("where: source is no slice value")
	}

	s := reflect.ValueOf(in)
	for i := 0; i < s.Len(); i++ {
		val := s.Index(i)

		Inspect(val)
		st := structs.New(val)
		field, ok := st.FieldOk(sliceKey)
		if !ok {
			return ret, errors.New("where: invalid input type")
		}
		if field.Value() == sliceVal {
			ret = append(ret, val)
		}
	}

	return ret, nil
}

func addFuncs(out, in map[string]interface{}) {
	for name, fn := range in {
		out[name] = fn
	}
}

func UnmarshalJsonObject(data string) (map[string]interface{}, error) {
	var ret map[string]interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}

func UnmarshalJsonArray(data string) ([]interface{}, error) {
	var ret []interface{}
	err := json.Unmarshal([]byte(data), &ret)
	return ret, err
}
<|endoftext|>


<commit_before>package main

/*
Adapted from this tutorial: http://www.learnopengl.com/#!Getting-started/Hello-Triangle
*/

import (
	"log"
	"runtime"
	"unsafe"

	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
)

const windowWidth = 800
const windowHeight = 600

func init() {
	// GLFW event handling must be run on the main OS thread
	runtime.LockOSThread()
}

func main() {
	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to inifitialize glfw:", err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "Hello!", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// Initialize Glow (go function bindings)
	if err := gl.Init(); err != nil {
		panic(err)
	}

	window.SetKeyCallback(keyCallback)

	programLoop(window)
}

var vertexShaderSource = `
#version 410 core

layout (location = 0) in vec3 position;

void main()
{
    gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
`

var fragmentShaderSource = `
#version 410 core

out vec4 color;

void main()
{
    color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
`

type getGlParam func(uint32, uint32, *int32)
type getInfoLog func(uint32, int32, *int32, *uint8)

func checkGlError(glObject uint32, errorParam uint32, getParamFn getGlParam,
	getInfoLogFn getInfoLog, failMsg string) {

	var success int32
	getParamFn(glObject, errorParam, &success)
	if success != 1 {
		var infoLog [512]byte
		getInfoLogFn(glObject, 512, nil, (*uint8)(unsafe.Pointer(&infoLog)))
		log.Fatalln(failMsg, "\n", string(infoLog[:512]))
	}
}

func checkShaderCompileErrors(shader uint32) {
	checkGlError(shader, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog,
		"ERROR::SHADER::COMPILE_FAILURE")
}

func checkProgramLinkErrors(program uint32) {
	checkGlError(program, gl.LINK_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog,
		"ERROR::PROGRAM::LINKING_FAILURE")
}

func compileShaders() []uint32 {
	// create the vertex shader
	vertexShader := gl.CreateShader(gl.VERTEX_SHADER)
	gl.ShaderSource(vertexShader, 1, (**uint8)(unsafe.Pointer(&vertexShaderSource)), nil)
	gl.CompileShader(vertexShader)
	checkShaderCompileErrors(vertexShader)

	// create the fragment shader
	fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER)
	gl.ShaderSource(fragmentShader, 1, (**uint8)(unsafe.Pointer(&fragmentShaderSource)), nil)
	gl.CompileShader(fragmentShader)
	checkShaderCompileErrors(fragmentShader)

	return []uint32{vertexShader, fragmentShader}
}

/*
 * Link the provided shaders in the order they were given and return the linked program.
 */
func linkShaders(shaders []uint32) uint32 {
	program := gl.CreateProgram()
	for _, shader := range shaders {
		gl.AttachShader(program, shader)
	}
	gl.LinkProgram(program)
	checkProgramLinkErrors(program)

	// shader objects are not needed after they are linked into a program object
	for _, shader := range shaders {
		gl.DeleteShader(shader)
	}

	return program
}

/*
 * Creates the Vertex Array Object for a triangle.
 */
func createTriangleVAO() uint32 {
	vertices := [9]float32{
		-0.5, -0.5, 0.0,
		0.5, -0.5, 0.0,
		0.0, 0.5, 0.0,
	}

	var VAO uint32
	gl.GenVertexArrays(1, &VAO)

	var VBO uint32
	gl.GenBuffers(1, &VBO)

	// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers()
	gl.BindVertexArray(VAO)

	// copy vertices data into VBO (it needs to be bound first)
	gl.BindBuffer(gl.ARRAY_BUFFER, VBO)
	gl.BufferData(gl.ARRAY_BUFFER, int(unsafe.Sizeof(vertices)), unsafe.Pointer(&vertices), gl.STATIC_DRAW)

	// specify the format of our vertex input
	// (shader) input 0
	// vertex has size 3
	// vertex items are of type FLOAT
	// do not normalize (already done)
	// stride of 3 * sizeof(float) (separation of vertices)
	// offset of where the position data starts (0 for the beginning)
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
	gl.EnableVertexAttribArray(0)

	// unbind the VAO (safe practice so we don't accidentally (mis)configure it later)
	gl.BindVertexArray(0)

	return VAO
}

func programLoop(window *glfw.Window) {

	// the linked shader program determines how the data will be rendered
	shaders := compileShaders()
	shaderProgram := linkShaders(shaders)

	// VAO contains all the information about the data to be rendered
	VAO := createTriangleVAO()

	for !window.ShouldClose() {
		// poll events and call their registered callbacks
		glfw.PollEvents()

		// perform rendering
		gl.ClearColor(0.2, 0.5, 0.5, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT)

		// draw loop
		gl.UseProgram(shaderProgram)        // ensure the right shader program is being used
		gl.BindVertexArray(VAO)             // bind data
		gl.DrawArrays(gl.TRIANGLES, 0, 3)   // perform draw call
		gl.BindVertexArray(0)               // unbind data (so we don't mistakenly use/modify it)
		// end of draw loop

		// swap in the rendered buffer
		window.SwapBuffers()
	}
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action,
	mods glfw.ModifierKey) {

	// When a user presses the escape key, we set the WindowShouldClose property to true,
	// which closes the application
	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}
}
<commit_msg>fixes to hello-triangle<commit_after>package main

/*
Adapted from this tutorial: http://www.learnopengl.com/#!Getting-started/Hello-Triangle
*/

import (
	"log"
	"runtime"
	"unsafe"

	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
)

const windowWidth = 800
const windowHeight = 600

func init() {
	// GLFW event handling must be run on the main OS thread
	runtime.LockOSThread()
}

func main() {
	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to inifitialize glfw:", err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "Hello!", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// Initialize Glow (go function bindings)
	if err := gl.Init(); err != nil {
		panic(err)
	}

	window.SetKeyCallback(keyCallback)

	programLoop(window)
}

var vertexShaderSource = `
#version 410 core

layout (location = 0) in vec3 position;

void main()
{
    gl_Position = vec4(position.x, position.y, position.z, 1.0);
}
`

var fragmentShaderSource = `
#version 410 core

out vec4 color;

void main()
{
    color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
`

type getGlParam func(uint32, uint32, *int32)
type getInfoLog func(uint32, int32, *int32, *uint8)

func checkGlError(glObject uint32, errorParam uint32, getParamFn getGlParam,
	getInfoLogFn getInfoLog, failMsg string) {

	var success int32
	getParamFn(glObject, errorParam, &success)
	if success != 1 {
		var infoLog [512]byte
		getInfoLogFn(glObject, 512, nil, (*uint8)(unsafe.Pointer(&infoLog)))
		log.Fatalln(failMsg, "\n", string(infoLog[:512]))
	}
}

func checkShaderCompileErrors(shader uint32) {
	checkGlError(shader, gl.COMPILE_STATUS, gl.GetShaderiv, gl.GetShaderInfoLog,
		"ERROR::SHADER::COMPILE_FAILURE")
}

func checkProgramLinkErrors(program uint32) {
	checkGlError(program, gl.LINK_STATUS, gl.GetProgramiv, gl.GetProgramInfoLog,
		"ERROR::PROGRAM::LINKING_FAILURE")
}

func compileShaders() []uint32 {

	// create the vertex shader
	vertexShader := gl.CreateShader(gl.VERTEX_SHADER)
	shaderSourceChars := gl.Str(vertexShaderSource + "\x00")
	gl.ShaderSource(vertexShader, 1, &shaderSourceChars, nil)
	gl.CompileShader(vertexShader)
	checkShaderCompileErrors(vertexShader)

	// create the fragment shader
	fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER)
	shaderSourceChars = gl.Str(fragmentShaderSource + "\x00")
	gl.ShaderSource(fragmentShader, 1, &shaderSourceChars, nil)
	gl.CompileShader(fragmentShader)
	checkShaderCompileErrors(fragmentShader)

	return []uint32{vertexShader, fragmentShader}
}

/*
 * Link the provided shaders in the order they were given and return the linked program.
 */
func linkShaders(shaders []uint32) uint32 {
	program := gl.CreateProgram()
	for _, shader := range shaders {
		gl.AttachShader(program, shader)
	}
	gl.LinkProgram(program)
	checkProgramLinkErrors(program)

	// shader objects are not needed after they are linked into a program object
	for _, shader := range shaders {
		gl.DeleteShader(shader)
	}

	return program
}

/*
 * Creates the Vertex Array Object for a triangle.
 */
func createTriangleVAO() uint32 {
	vertices := []float32{
		-0.5, -0.5, 0.0,
		0.5, -0.5, 0.0,
		0.0, 0.5, 0.0,
	}

	var VAO uint32
	gl.GenVertexArrays(1, &VAO)

	var VBO uint32
	gl.GenBuffers(1, &VBO)

	// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers()
	gl.BindVertexArray(VAO)

	// copy vertices data into VBO (it needs to be bound first)
	gl.BindBuffer(gl.ARRAY_BUFFER, VBO)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	// specify the format of our vertex input
	// (shader) input 0
	// vertex has size 3
	// vertex items are of type FLOAT
	// do not normalize (already done)
	// stride of 3 * sizeof(float) (separation of vertices)
	// offset of where the position data starts (0 for the beginning)
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 3*4, gl.PtrOffset(0))
	gl.EnableVertexAttribArray(0)

	// unbind the VAO (safe practice so we don't accidentally (mis)configure it later)
	gl.BindVertexArray(0)

	return VAO
}

func programLoop(window *glfw.Window) {

	// the linked shader program determines how the data will be rendered
	shaders := compileShaders()
	shaderProgram := linkShaders(shaders)

	// VAO contains all the information about the data to be rendered
	VAO := createTriangleVAO()

	for !window.ShouldClose() {
		// poll events and call their registered callbacks
		glfw.PollEvents()

		// perform rendering
		gl.ClearColor(0.2, 0.5, 0.5, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT)

		// draw loop
		gl.UseProgram(shaderProgram)        // ensure the right shader program is being used
		gl.BindVertexArray(VAO)             // bind data
		gl.DrawArrays(gl.TRIANGLES, 0, 3)   // perform draw call
		gl.BindVertexArray(0)               // unbind data (so we don't mistakenly use/modify it)
		// end of draw loop

		// swap in the rendered buffer
		window.SwapBuffers()
	}
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action,
	mods glfw.ModifierKey) {

	// When a user presses the escape key, we set the WindowShouldClose property to true,
	// which closes the application
	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}
}
<|endoftext|>