<commit_before>package daemon

import (
	"os"
	"os/signal"

	"github.com/pkg/errors"

	"github.com/spf13/cobra"

	"google.golang.org/grpc"

	"github.com/mutagen-io/mutagen/cmd"
	"github.com/mutagen-io/mutagen/pkg/daemon"
	"github.com/mutagen-io/mutagen/pkg/forwarding"
	"github.com/mutagen-io/mutagen/pkg/grpcutil"
	"github.com/mutagen-io/mutagen/pkg/ipc"
	"github.com/mutagen-io/mutagen/pkg/logging"
	daemonsvc "github.com/mutagen-io/mutagen/pkg/service/daemon"
	forwardingsvc "github.com/mutagen-io/mutagen/pkg/service/forwarding"
	promptsvc "github.com/mutagen-io/mutagen/pkg/service/prompt"
	synchronizationsvc "github.com/mutagen-io/mutagen/pkg/service/synchronization"
	tunnelingsvc "github.com/mutagen-io/mutagen/pkg/service/tunneling"
	"github.com/mutagen-io/mutagen/pkg/synchronization"
	"github.com/mutagen-io/mutagen/pkg/tunneling"

	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/docker"
	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/local"
	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/ssh"
	tunnelforwardingprotocol "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/tunnel"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/docker"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/local"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/ssh"
	tunnelsynchronizationprotocol "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/tunnel"
)

func runMain(command *cobra.Command, arguments []string) error {
	// Validate arguments.
	if len(arguments) != 0 {
		return errors.New("unexpected arguments provided")
	}

	// Attempt to acquire the daemon lock and defer its release.
	lock, err := daemon.AcquireLock()
	if err != nil {
		return errors.Wrap(err, "unable to acquire daemon lock")
	}
	defer lock.Release()

	// Create a channel to track termination signals. We do this before creating
	// and starting other infrastructure so that we can ensure things terminate
	// smoothly, not mid-initialization.
	signalTermination := make(chan os.Signal, 1)
	signal.Notify(signalTermination, cmd.TerminationSignals...)

	// Create a tunnel manager and defer its shutdown.
	tunnelManager, err := tunneling.NewManager(logging.RootLogger.Sublogger("tunneling"))
	if err != nil {
		return errors.Wrap(err, "unable to create tunnel manager")
	}
	defer tunnelManager.Shutdown()

	// Register the tunnel manager as a forwarding and synchronization protocol
	// handler.
	tunnelforwardingprotocol.RegisterManager(tunnelManager)
	tunnelsynchronizationprotocol.RegisterManager(tunnelManager)

	// Create a forwarding session manager and defer its shutdown.
	forwardingManager, err := forwarding.NewManager(logging.RootLogger.Sublogger("forwarding"))
	if err != nil {
		return errors.Wrap(err, "unable to create forwarding session manager")
	}
	defer forwardingManager.Shutdown()

	// Create a synchronization session manager and defer its shutdown.
	synchronizationManager, err := synchronization.NewManager(logging.RootLogger.Sublogger("sync"))
	if err != nil {
		return errors.Wrap(err, "unable to create synchronization session manager")
	}
	defer synchronizationManager.Shutdown()

	// Create the gRPC server and defer its stoppage. We use a hard stop rather
	// than a graceful stop so that it doesn't hang on open requests.
	server := grpc.NewServer(
		grpc.MaxSendMsgSize(grpcutil.MaximumMessageSize),
		grpc.MaxRecvMsgSize(grpcutil.MaximumMessageSize),
	)
	defer server.Stop()

	// Create the daemon server, defer its shutdown, and register it.
	daemonServer := daemonsvc.NewServer()
	defer daemonServer.Shutdown()
	daemonsvc.RegisterDaemonServer(server, daemonServer)

	// Create and register the prompt server.
	promptsvc.RegisterPromptingServer(server, promptsvc.NewServer())

	// Create and register the tunneling server.
	tunnelingServer := tunnelingsvc.NewServer(tunnelManager)
	tunnelingsvc.RegisterTunnelingServer(server, tunnelingServer)

	// Create and register the forwarding server.
	forwardingServer := forwardingsvc.NewServer(forwardingManager)
	forwardingsvc.RegisterForwardingServer(server, forwardingServer)

	// Create and register the synchronization server.
	synchronizationServer := synchronizationsvc.NewServer(synchronizationManager)
	synchronizationsvc.RegisterSynchronizationServer(server, synchronizationServer)

	// Compute the path to the daemon IPC endpoint.
	endpoint, err := daemon.EndpointPath()
	if err != nil {
		return errors.Wrap(err, "unable to compute endpoint path")
	}

	// Create the daemon listener and defer its closure. Since we hold the
	// daemon lock, we preemptively remove any existing socket since it (should)
	// be stale.
	os.Remove(endpoint)
	listener, err := ipc.NewListener(endpoint)
	if err != nil {
		return errors.Wrap(err, "unable to create daemon listener")
	}
	defer listener.Close()

	// Serve incoming connections in a separate Goroutine, watching for serving
	// failure.
	serverErrors := make(chan error, 1)
	go func() {
		serverErrors <- server.Serve(listener)
	}()

	// Wait for termination from a signal, the daemon service, or the gRPC
	// server. We treat termination via the daemon service as a non-error.
	select {
	case sig := <-signalTermination:
		return errors.Errorf("terminated by signal: %s", sig)
	case <-daemonServer.Termination:
		return nil
	case err = <-serverErrors:
		return errors.Wrap(err, "daemon server termination")
	}
}

var runCommand = &cobra.Command{
	Use:          "run",
	Short:        "Run the Mutagen daemon",
	Hidden:       true,
	RunE:         runMain,
	SilenceUsage: true,
}

var runConfiguration struct {
	// help indicates whether or not help information should be shown for the
	// command.
	help bool
}

func init() {
	// Grab a handle for the command line flags.
	flags := runCommand.Flags()

	// Disable alphabetical sorting of flags in help output.
	flags.SortFlags = false

	// Manually add a help flag to override the default message. Cobra will
	// still implement its logic automatically.
	flags.BoolVarP(&runConfiguration.help, "help", "h", false, "Show help information")
}
<commit_msg>Renamed synchronization service logger.<commit_after>package daemon

import (
	"os"
	"os/signal"

	"github.com/pkg/errors"

	"github.com/spf13/cobra"

	"google.golang.org/grpc"

	"github.com/mutagen-io/mutagen/cmd"
	"github.com/mutagen-io/mutagen/pkg/daemon"
	"github.com/mutagen-io/mutagen/pkg/forwarding"
	"github.com/mutagen-io/mutagen/pkg/grpcutil"
	"github.com/mutagen-io/mutagen/pkg/ipc"
	"github.com/mutagen-io/mutagen/pkg/logging"
	daemonsvc "github.com/mutagen-io/mutagen/pkg/service/daemon"
	forwardingsvc "github.com/mutagen-io/mutagen/pkg/service/forwarding"
	promptsvc "github.com/mutagen-io/mutagen/pkg/service/prompt"
	synchronizationsvc "github.com/mutagen-io/mutagen/pkg/service/synchronization"
	tunnelingsvc "github.com/mutagen-io/mutagen/pkg/service/tunneling"
	"github.com/mutagen-io/mutagen/pkg/synchronization"
	"github.com/mutagen-io/mutagen/pkg/tunneling"

	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/docker"
	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/local"
	_ "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/ssh"
	tunnelforwardingprotocol "github.com/mutagen-io/mutagen/pkg/forwarding/protocols/tunnel"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/docker"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/local"
	_ "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/ssh"
	tunnelsynchronizationprotocol "github.com/mutagen-io/mutagen/pkg/synchronization/protocols/tunnel"
)

func runMain(command *cobra.Command, arguments []string) error {
	// Validate arguments.
	if len(arguments) != 0 {
		return errors.New("unexpected arguments provided")
	}

	// Attempt to acquire the daemon lock and defer its release.
	lock, err := daemon.AcquireLock()
	if err != nil {
		return errors.Wrap(err, "unable to acquire daemon lock")
	}
	defer lock.Release()

	// Create a channel to track termination signals. We do this before creating
	// and starting other infrastructure so that we can ensure things terminate
	// smoothly, not mid-initialization.
	signalTermination := make(chan os.Signal, 1)
	signal.Notify(signalTermination, cmd.TerminationSignals...)

	// Create a tunnel manager and defer its shutdown.
	tunnelManager, err := tunneling.NewManager(logging.RootLogger.Sublogger("tunneling"))
	if err != nil {
		return errors.Wrap(err, "unable to create tunnel manager")
	}
	defer tunnelManager.Shutdown()

	// Register the tunnel manager as a forwarding and synchronization protocol
	// handler.
	tunnelforwardingprotocol.RegisterManager(tunnelManager)
	tunnelsynchronizationprotocol.RegisterManager(tunnelManager)

	// Create a forwarding session manager and defer its shutdown.
	forwardingManager, err := forwarding.NewManager(logging.RootLogger.Sublogger("forwarding"))
	if err != nil {
		return errors.Wrap(err, "unable to create forwarding session manager")
	}
	defer forwardingManager.Shutdown()

	// Create a synchronization session manager and defer its shutdown.
	synchronizationManager, err := synchronization.NewManager(logging.RootLogger.Sublogger("synchronization"))
	if err != nil {
		return errors.Wrap(err, "unable to create synchronization session manager")
	}
	defer synchronizationManager.Shutdown()

	// Create the gRPC server and defer its stoppage. We use a hard stop rather
	// than a graceful stop so that it doesn't hang on open requests.
	server := grpc.NewServer(
		grpc.MaxSendMsgSize(grpcutil.MaximumMessageSize),
		grpc.MaxRecvMsgSize(grpcutil.MaximumMessageSize),
	)
	defer server.Stop()

	// Create the daemon server, defer its shutdown, and register it.
	daemonServer := daemonsvc.NewServer()
	defer daemonServer.Shutdown()
	daemonsvc.RegisterDaemonServer(server, daemonServer)

	// Create and register the prompt server.
	promptsvc.RegisterPromptingServer(server, promptsvc.NewServer())

	// Create and register the tunneling server.
	tunnelingServer := tunnelingsvc.NewServer(tunnelManager)
	tunnelingsvc.RegisterTunnelingServer(server, tunnelingServer)

	// Create and register the forwarding server.
	forwardingServer := forwardingsvc.NewServer(forwardingManager)
	forwardingsvc.RegisterForwardingServer(server, forwardingServer)

	// Create and register the synchronization server.
	synchronizationServer := synchronizationsvc.NewServer(synchronizationManager)
	synchronizationsvc.RegisterSynchronizationServer(server, synchronizationServer)

	// Compute the path to the daemon IPC endpoint.
	endpoint, err := daemon.EndpointPath()
	if err != nil {
		return errors.Wrap(err, "unable to compute endpoint path")
	}

	// Create the daemon listener and defer its closure. Since we hold the
	// daemon lock, we preemptively remove any existing socket since it (should)
	// be stale.
	os.Remove(endpoint)
	listener, err := ipc.NewListener(endpoint)
	if err != nil {
		return errors.Wrap(err, "unable to create daemon listener")
	}
	defer listener.Close()

	// Serve incoming connections in a separate Goroutine, watching for serving
	// failure.
	serverErrors := make(chan error, 1)
	go func() {
		serverErrors <- server.Serve(listener)
	}()

	// Wait for termination from a signal, the daemon service, or the gRPC
	// server. We treat termination via the daemon service as a non-error.
	select {
	case sig := <-signalTermination:
		return errors.Errorf("terminated by signal: %s", sig)
	case <-daemonServer.Termination:
		return nil
	case err = <-serverErrors:
		return errors.Wrap(err, "daemon server termination")
	}
}

var runCommand = &cobra.Command{
	Use:          "run",
	Short:        "Run the Mutagen daemon",
	Hidden:       true,
	RunE:         runMain,
	SilenceUsage: true,
}

var runConfiguration struct {
	// help indicates whether or not help information should be shown for the
	// command.
	help bool
}

func init() {
	// Grab a handle for the command line flags.
	flags := runCommand.Flags()

	// Disable alphabetical sorting of flags in help output.
	flags.SortFlags = false

	// Manually add a help flag to override the default message. Cobra will
	// still implement its logic automatically.
	flags.BoolVarP(&runConfiguration.help, "help", "h", false, "Show help information")
}
<|endoftext|>


<commit_before>package verdeps

import (
	"go/ast"
	"go/token"
	"strconv"
	"sync"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestBufferVendorables(t *testing.T) {
	Convey("Given a bunch of import and package specs", t, func() {
		var (
			waitGroup             = &sync.WaitGroup{}
			importCounts          = newSyncedImportCounts()
			inputImportSpecChan   = make(chan *importSpec)
			outputImportSpecChan  = make(chan *importSpec)
			currentVendorContext  = newVendorContext()
			inputPackageSpecChan  = make(chan *packageSpec)
			outputPackageSpecChan = make(chan *packageSpec)
		)

		// Add vendored packages.
		currentVendorContext.add(`github.com/a/b`)
		currentVendorContext.add(`github.com/x/y`)

		// Start buffering in the background.
		waitGroup.Add(1)
		go bufferVendorables(bufferVendorablesArgs{
			waitGroup:             waitGroup,
			importCounts:          importCounts,
			inputImportSpecChan:   inputImportSpecChan,
			outputImportSpecChan:  outputImportSpecChan,
			currentVendorContext:  currentVendorContext,
			inputPackageSpecChan:  inputPackageSpecChan,
			outputPackageSpecChan: outputPackageSpecChan,
		})

		// Add a bunch of specs into the mix.
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/d/e"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath1", 34)
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/f/g"`)
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/g/h"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath2", 17821)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/a/b"`)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/b/c"`)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/c/d"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath3", 1)
		inputImportSpecChan <- generateTestImportSpec("filepath3", `"github.com/x/y"`)

		// Prepare to read outputs.
		close(inputImportSpecChan)
		close(inputPackageSpecChan)

		var (
			outputImportSpecStrings  = make(map[string]bool)
			outputPackageSpecStrings = make(map[string]bool)
		)

		// Read the import specs.
		for spec := range outputImportSpecChan {
			outputImportSpecStrings[spec.filePath+":"+spec.imports.Path.Value] = true
		}
		for spec := range outputPackageSpecChan {
			outputPackageSpecStrings[spec.filePath+":"+strconv.Itoa(spec.startIndex)] = true
		}

		// Make sure everything lines up as expected.
		// TODO(skeswa): continue here.
		Convey("All the right import specs should come through", func() {
			So(outputImportSpecStrings[`filepath1:"github.com/d/e"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath1:"github.com/f/g"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath1:"github.com/f/g"`], ShouldBeTrue)
		})
		Convey("The import counts should be correct", func() {

		})
		Convey("The import counts should be correct", func() {

		})
	})
}

func generateTestPackageSpec(filePath string, startIndex int) *packageSpec {
	return &packageSpec{
		startIndex: startIndex,
		filePath:   filePath,
	}
}

func generateTestImportSpec(filePath, importPath string) *importSpec {
	return &importSpec{
		imports: &ast.ImportSpec{
			Path: &ast.BasicLit{
				Kind:  token.STRING,
				Value: importPath,
			},
		},
		filePath: filePath,
	}
}
<commit_msg>finished the buffer vendorables test<commit_after>package verdeps

import (
	"go/ast"
	"go/token"
	"strconv"
	"sync"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestBufferVendorables(t *testing.T) {
	Convey("Given a bunch of import and package specs", t, func() {
		var (
			waitGroup             = &sync.WaitGroup{}
			importCounts          = newSyncedImportCounts()
			inputImportSpecChan   = make(chan *importSpec)
			outputImportSpecChan  = make(chan *importSpec)
			currentVendorContext  = newVendorContext()
			inputPackageSpecChan  = make(chan *packageSpec)
			outputPackageSpecChan = make(chan *packageSpec)
		)

		// Add vendored packages.
		currentVendorContext.add(`github.com/a/b`)
		currentVendorContext.add(`github.com/x/y`)

		// Start buffering in the background.
		waitGroup.Add(1)
		go bufferVendorables(bufferVendorablesArgs{
			waitGroup:             waitGroup,
			importCounts:          importCounts,
			inputImportSpecChan:   inputImportSpecChan,
			outputImportSpecChan:  outputImportSpecChan,
			currentVendorContext:  currentVendorContext,
			inputPackageSpecChan:  inputPackageSpecChan,
			outputPackageSpecChan: outputPackageSpecChan,
		})

		// Add a bunch of specs into the mix.
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/d/e"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath1", 34)
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/f/g"`)
		inputImportSpecChan <- generateTestImportSpec("filepath1", `"github.com/g/h"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath2", 17821)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/a/b"`)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/b/c"`)
		inputImportSpecChan <- generateTestImportSpec("filepath2", `"github.com/c/d"`)
		inputPackageSpecChan <- generateTestPackageSpec("filepath3", 1)
		inputImportSpecChan <- generateTestImportSpec("filepath3", `"ignore.me/r/s"`)
		inputImportSpecChan <- generateTestImportSpec("filepath3", `"github.com/x/y"`)
		// Prepare to read outputs.
		close(inputImportSpecChan)
		close(inputPackageSpecChan)

		var (
			numberOfImportSpecs         = 8
			numberOfPackageSpecs        = 3
			numberOfVendoredImportSpecs = 2

			outputImportSpecStrings  = make(map[string]bool)
			outputPackageSpecStrings = make(map[string]bool)
		)

		// Make sure these channels get closed before the test completes.
		defer close(outputImportSpecChan)
		defer close(outputPackageSpecChan)

		i := 0
		for spec := range outputImportSpecChan {
			key := spec.filePath + ":" + spec.imports.Path.Value
			outputImportSpecStrings[key] = true

			// Break after all the specs we put in come out again.
			if i++; i >= (numberOfImportSpecs - numberOfVendoredImportSpecs) {
				break
			}
		}

		i = 0
		for spec := range outputPackageSpecChan {
			key := spec.filePath + ":" + strconv.Itoa(spec.startIndex)
			outputPackageSpecStrings[key] = true

			// Break after all the specs we put in come out again.
			if i++; i >= numberOfPackageSpecs {
				break
			}
		}

		// Make sure everything lines up as expected.
		Convey("Function shouldn't deadlock", func() {
			waitGroup.Wait()
		})
		Convey("Unvendored github imports should come through", func() {
			So(outputImportSpecStrings[`filepath1:"github.com/d/e"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath1:"github.com/f/g"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath1:"github.com/g/h"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath2:"github.com/b/c"`], ShouldBeTrue)
			So(outputImportSpecStrings[`filepath2:"github.com/c/d"`], ShouldBeTrue)
		})
		Convey("Vendored imports should be ignored", func() {
			So(outputImportSpecStrings[`filepath2:"github.com/a/b"`], ShouldBeFalse)
			So(outputImportSpecStrings[`filepath3:"github.com/x/y"`], ShouldBeFalse)
		})
		Convey("Non-github imports shouldn't be ignored", func() {
			So(outputImportSpecStrings[`filepath3:"ignore.me/r/s"`], ShouldBeTrue)
		})
		Convey("The import counts should be correct", func() {
			So(importCounts.importCountOf("filepath1"), ShouldEqual, 3)
			So(importCounts.importCountOf("filepath2"), ShouldEqual, 2)
			So(importCounts.importCountOf("filepath3"), ShouldEqual, 1)
		})
	})
}

func generateTestPackageSpec(filePath string, startIndex int) *packageSpec {
	return &packageSpec{
		startIndex: startIndex,
		filePath:   filePath,
	}
}

func generateTestImportSpec(filePath, importPath string) *importSpec {
	return &importSpec{
		imports: &ast.ImportSpec{
			Path: &ast.BasicLit{
				Kind:  token.STRING,
				Value: importPath,
			},
		},
		filePath: filePath,
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 James Hutchinson. All rights reserved.
//
// Use of this source code is governed by the Apache v2
// license that can be found in the LICENSE file.

// Simple module to cast fields in one struct into another

package recode

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
)

func Recode(in, out interface{}) error {
	// Check the input is a struct with arbitrary amount of indirection
	inVal := reflect.ValueOf(in)
	for inVal.Kind() == reflect.Ptr {
		if inVal.IsNil() {
			return errors.New("recode: Recode() expects a non-nil value for in")
		}
		inVal = inVal.Elem()
	}

	if inVal.Kind() != reflect.Struct {
		return fmt.Errorf("recode: Recode() expects a struct for in. Got %v", inVal.Kind())
	}
	// Output should be a struct with one level of indirection
	outVal := reflect.ValueOf(out)
	if outVal.Kind() != reflect.Ptr {
		return fmt.Errorf("recode: Recode() expects a pointer for out. Got %v", outVal.Kind())
	}
	if outVal.Elem().Kind() != reflect.Struct {
		return fmt.Errorf("recode: Recode() expects a pointer to a struct for out. Got pointer to %v", outVal.Elem().Kind())
	}
	return recodeStruct(inVal, outVal.Elem())
}

func recodeStruct(in, out reflect.Value) error {
	t := out.Type()
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if f.PkgPath != "" { // unexported
			continue
		}
		inF := in.FieldByName(f.Name)
		outF := out.FieldByName(f.Name)
		if inF.Kind() == reflect.Invalid {
			return fmt.Errorf("recode: Recode() struct %v has no field %v", in.Type().Name(), f.Name)
		}
		err := recodeField(inF, outF)
		if err != nil {
			return err
		}

	}
	return nil
}

func recodeField(in, out reflect.Value) error {
	switch out.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return recodeInt(in, out)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return recodeUint(in, out)
	case reflect.String:
		return recodeString(in, out)
	case reflect.Float32, reflect.Float64:
		return recodeFloat(in, out)
	case reflect.Struct:
		return recodeStruct(in, out)
	case reflect.Interface, reflect.Ptr:
		return recodeField(in, out.Elem())
	default:
		return fmt.Errorf("recode: Recode() cannot map to %v", out.Kind())
	}
}

func recodeInt(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetInt(in.Int())
	case reflect.String:
		i, err := strconv.ParseInt(in.String(), 10, 64)
		if err != nil {
			return err
		}
		out.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetInt(int64(in.Uint()))
	case reflect.Float32, reflect.Float64:
		out.SetInt(int64(in.Float()))
	case reflect.Interface, reflect.Ptr:
		return recodeInt(in.Elem(), out)
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeUint(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetUint(in.Uint())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetUint(uint64(in.Int()))
	case reflect.Float32, reflect.Float64:
		out.SetUint(uint64(in.Float()))
	case reflect.String:
		i, err := strconv.ParseUint(in.String(), 10, 64)
		if err != nil {
			return err
		}
		out.SetUint(i)
	case reflect.Interface, reflect.Ptr:
		return recodeUint(in.Elem(), out)
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeString(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.String:
		out.SetString(in.String())
	case reflect.Interface, reflect.Ptr:
		return recodeString(in.Elem(), out)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetString(strconv.FormatUint(in.Uint(), 10))
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetString(strconv.FormatInt(in.Int(), 10))
	case reflect.Float32, reflect.Float64:
		out.SetString(strconv.FormatFloat(in.Float(), 'f', -1, 64))
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeFloat(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Float32, reflect.Float64:
		out.SetFloat(in.Float())
	case reflect.String:
		f, err := strconv.ParseFloat(in.String(), 64)
		if err != nil {
			return err
		}
		out.SetFloat(f)
	case reflect.Interface, reflect.Ptr:
		return recodeFloat(in.Elem(), out)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetFloat(float64(in.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetFloat(float64(in.Uint()))
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}
<commit_msg>Add array/slice recoding<commit_after>// Copyright 2014 James Hutchinson. All rights reserved.
//
// Use of this source code is governed by the Apache v2
// license that can be found in the LICENSE file.

// Simple module to cast fields in one struct into another

package recode

import (
	"errors"
	"fmt"
	"reflect"
	"strconv"
)

func Recode(in, out interface{}) error {
	// Check the input is a struct with arbitrary amount of indirection
	inVal := reflect.ValueOf(in)
	for inVal.Kind() == reflect.Ptr {
		if inVal.IsNil() {
			return errors.New("recode: Recode() expects a non-nil value for in")
		}
		inVal = inVal.Elem()
	}

	if inVal.Kind() != reflect.Struct {
		return fmt.Errorf("recode: Recode() expects a struct for in. Got %v", inVal.Kind())
	}
	// Output should be a struct with one level of indirection
	outVal := reflect.ValueOf(out)
	if outVal.Kind() != reflect.Ptr {
		return fmt.Errorf("recode: Recode() expects a pointer for out. Got %v", outVal.Kind())
	}
	if outVal.Elem().Kind() != reflect.Struct {
		return fmt.Errorf("recode: Recode() expects a pointer to a struct for out. Got pointer to %v", outVal.Elem().Kind())
	}
	return recodeStruct(inVal, outVal.Elem())
}

func recodeStruct(in, out reflect.Value) error {
	t := out.Type()
	for i := 0; i < t.NumField(); i++ {
		f := t.Field(i)
		if f.PkgPath != "" { // unexported
			continue
		}
		inF := in.FieldByName(f.Name)
		outF := out.FieldByName(f.Name)
		if inF.Kind() == reflect.Invalid {
			return fmt.Errorf("recode: Recode() struct %v has no field %v", in.Type().Name(), f.Name)
		}
		err := recodeField(inF, outF)
		if err != nil {
			return err
		}

	}
	return nil
}

func recodeField(in, out reflect.Value) error {
	switch out.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return recodeInt(in, out)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return recodeUint(in, out)
	case reflect.String:
		return recodeString(in, out)
	case reflect.Float32, reflect.Float64:
		return recodeFloat(in, out)
	case reflect.Struct:
		return recodeStruct(in, out)
	case reflect.Interface, reflect.Ptr:
		return recodeField(in, out.Elem())
	case reflect.Slice:
		return recodeSlice(in, out)
	default:
		return fmt.Errorf("recode: Recode() cannot map to %v", out.Kind())
	}
}

func recodeInt(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetInt(in.Int())
	case reflect.String:
		i, err := strconv.ParseInt(in.String(), 10, 64)
		if err != nil {
			return err
		}
		out.SetInt(i)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetInt(int64(in.Uint()))
	case reflect.Float32, reflect.Float64:
		out.SetInt(int64(in.Float()))
	case reflect.Interface, reflect.Ptr:
		return recodeInt(in.Elem(), out)
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeUint(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetUint(in.Uint())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetUint(uint64(in.Int()))
	case reflect.Float32, reflect.Float64:
		out.SetUint(uint64(in.Float()))
	case reflect.String:
		i, err := strconv.ParseUint(in.String(), 10, 64)
		if err != nil {
			return err
		}
		out.SetUint(i)
	case reflect.Interface, reflect.Ptr:
		return recodeUint(in.Elem(), out)
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeString(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.String:
		out.SetString(in.String())
	case reflect.Interface, reflect.Ptr:
		return recodeString(in.Elem(), out)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetString(strconv.FormatUint(in.Uint(), 10))
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetString(strconv.FormatInt(in.Int(), 10))
	case reflect.Float32, reflect.Float64:
		out.SetString(strconv.FormatFloat(in.Float(), 'f', -1, 64))
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeFloat(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Float32, reflect.Float64:
		out.SetFloat(in.Float())
	case reflect.String:
		f, err := strconv.ParseFloat(in.String(), 64)
		if err != nil {
			return err
		}
		out.SetFloat(f)
	case reflect.Interface, reflect.Ptr:
		return recodeFloat(in.Elem(), out)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		out.SetFloat(float64(in.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		out.SetFloat(float64(in.Uint()))
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}

func recodeSlice(in, out reflect.Value) error {
	switch in.Kind() {
	case reflect.Slice:
		out.Set(reflect.MakeSlice(out.Type(), in.Len(), in.Len()))
		for i := 0; i < in.Len(); i++ {
			err := recodeField(in.Index(i), out.Index(i))
			if err != nil {
				return err
			}
		}
	case reflect.Interface, reflect.Ptr:
		return recodeSlice(in.Elem(), out)
	default:
		return fmt.Errorf("recode: Recode() cannot map %v to %v", in.Kind(), out.Kind())
	}
	return nil
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, 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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/document"
)

var bleveClientUnimplementedErr = errors.New("unimplemented")

// BleveClient implements the Search() and DocCount() subset of the
// bleve.Index interface by accessing a remote cbft server via REST
// protocol.  This allows callers to add a BleveClient as a target of
// a bleve.IndexAlias, and implements cbft protocol features like
// query consistency and auth.
//
// TODO: Implement consistency and auth in BleveClient.
type BleveClient struct {
	QueryURL    string
	CountURL    string
	Consistency *ConsistencyParams
}

func (r *BleveClient) Index(id string, data interface{}) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Delete(id string) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Batch(b *bleve.Batch) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Document(id string) (*document.Document, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DocCount() (uint64, error) {
	if r.CountURL == "" {
		return 0, fmt.Errorf("no CountURL provided")
	}
	resp, err := http.Get(r.CountURL)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return 0, fmt.Errorf("bleveClient.DocCount got status code: %d,"+
			" docCountURL: %s, resp: %#v", resp.StatusCode, r.CountURL, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error reading resp.Body,"+
			" docCountURL: %s, resp: %#v", r.CountURL, resp)
	}
	rv := struct {
		Status string `json:"status"`
		Count  uint64 `json:"count"`
	}{}
	err = json.Unmarshal(respBuf, &rv)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error parsing respBuf: %s,"+
			" docCountURL: %s, resp: %#v", respBuf, r.CountURL, resp)
	}
	return rv.Count, nil
}

func (r *BleveClient) Search(req *bleve.SearchRequest) (*bleve.SearchResult, error) {
	if r.QueryURL == "" {
		return nil, fmt.Errorf("no QueryURL provided")
	}

	bleveQueryParams := &BleveQueryParams{
		Query:       req,
		Consistency: r.Consistency,
	}

	buf, err := json.Marshal(bleveQueryParams)
	if err != nil {
		return nil, err
	}
	resp, err := http.Post(r.QueryURL, "application/json", bytes.NewBuffer(buf))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("bleveClient.Search got status code: %d,"+
			" searchURL: %s, req: %#v, resp: %#v",
			resp.StatusCode, r.QueryURL, req, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error reading resp.Body,"+
			" searchURL: %s, req: %#v, resp: %#v",
			r.QueryURL, req, resp)
	}
	rv := &bleve.SearchResult{}
	err = json.Unmarshal(respBuf, rv)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error parsing respBuf: %s,"+
			" searchURL: %s, req: %#v, resp: %#v",
			respBuf, r.QueryURL, req, resp)
	}
	return rv, nil
}

func (r *BleveClient) Fields() ([]string, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DumpAll() chan interface{} {
	return nil
}

func (r *BleveClient) DumpDoc(id string) chan interface{} {
	return nil
}

func (r *BleveClient) DumpFields() chan interface{} {
	return nil
}

func (r *BleveClient) Close() error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Mapping() *bleve.IndexMapping {
	return nil
}

func (r *BleveClient) Stats() *bleve.IndexStat {
	return nil
}

func (r *BleveClient) GetInternal(key []byte) ([]byte, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) SetInternal(key, val []byte) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) DeleteInternal(key []byte) error {
	return bleveClientUnimplementedErr
}
<commit_msg>update old TODO<commit_after>//  Copyright (c) 2014 Couchbase, 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 main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/blevesearch/bleve"
	"github.com/blevesearch/bleve/document"
)

var bleveClientUnimplementedErr = errors.New("unimplemented")

// BleveClient implements the Search() and DocCount() subset of the
// bleve.Index interface by accessing a remote cbft server via REST
// protocol.  This allows callers to add a BleveClient as a target of
// a bleve.IndexAlias, and implements cbft protocol features like
// query consistency and auth.
//
// TODO: Implement propagating auth info in BleveClient.
type BleveClient struct {
	QueryURL    string
	CountURL    string
	Consistency *ConsistencyParams
}

func (r *BleveClient) Index(id string, data interface{}) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Delete(id string) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Batch(b *bleve.Batch) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Document(id string) (*document.Document, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DocCount() (uint64, error) {
	if r.CountURL == "" {
		return 0, fmt.Errorf("no CountURL provided")
	}
	resp, err := http.Get(r.CountURL)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return 0, fmt.Errorf("bleveClient.DocCount got status code: %d,"+
			" docCountURL: %s, resp: %#v", resp.StatusCode, r.CountURL, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error reading resp.Body,"+
			" docCountURL: %s, resp: %#v", r.CountURL, resp)
	}
	rv := struct {
		Status string `json:"status"`
		Count  uint64 `json:"count"`
	}{}
	err = json.Unmarshal(respBuf, &rv)
	if err != nil {
		return 0, fmt.Errorf("bleveClient.DocCount error parsing respBuf: %s,"+
			" docCountURL: %s, resp: %#v", respBuf, r.CountURL, resp)
	}
	return rv.Count, nil
}

func (r *BleveClient) Search(req *bleve.SearchRequest) (*bleve.SearchResult, error) {
	if r.QueryURL == "" {
		return nil, fmt.Errorf("no QueryURL provided")
	}

	bleveQueryParams := &BleveQueryParams{
		Query:       req,
		Consistency: r.Consistency,
	}

	buf, err := json.Marshal(bleveQueryParams)
	if err != nil {
		return nil, err
	}
	resp, err := http.Post(r.QueryURL, "application/json", bytes.NewBuffer(buf))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("bleveClient.Search got status code: %d,"+
			" searchURL: %s, req: %#v, resp: %#v",
			resp.StatusCode, r.QueryURL, req, resp)
	}
	respBuf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error reading resp.Body,"+
			" searchURL: %s, req: %#v, resp: %#v",
			r.QueryURL, req, resp)
	}
	rv := &bleve.SearchResult{}
	err = json.Unmarshal(respBuf, rv)
	if err != nil {
		return nil, fmt.Errorf("bleveClient.Search error parsing respBuf: %s,"+
			" searchURL: %s, req: %#v, resp: %#v",
			respBuf, r.QueryURL, req, resp)
	}
	return rv, nil
}

func (r *BleveClient) Fields() ([]string, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) DumpAll() chan interface{} {
	return nil
}

func (r *BleveClient) DumpDoc(id string) chan interface{} {
	return nil
}

func (r *BleveClient) DumpFields() chan interface{} {
	return nil
}

func (r *BleveClient) Close() error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) Mapping() *bleve.IndexMapping {
	return nil
}

func (r *BleveClient) Stats() *bleve.IndexStat {
	return nil
}

func (r *BleveClient) GetInternal(key []byte) ([]byte, error) {
	return nil, bleveClientUnimplementedErr
}

func (r *BleveClient) SetInternal(key, val []byte) error {
	return bleveClientUnimplementedErr
}

func (r *BleveClient) DeleteInternal(key []byte) error {
	return bleveClientUnimplementedErr
}
<|endoftext|>


<commit_before>// Package render is a middleware for Martini that provides easy JSON serialization and HTML template rendering.
//
//  package main
//
//  import (
//    "encoding/xml"
//
//    "github.com/go-martini/martini"
//    "github.com/martini-contrib/render"
//  )
//
//  type Greeting struct {
//    XMLName xml.Name `xml:"greeting"`
//    One     string   `xml:"one,attr"`
//    Two     string   `xml:"two,attr"`
//  }
//
//  func main() {
//    m := martini.Classic()
//    m.Use(render.Renderer()) // reads "templates" directory by default
//
//    m.Get("/html", func(r render.Render) {
//      r.HTML(200, "mytemplate", nil)
//    })
//
//    m.Get("/json", func(r render.Render) {
//      r.JSON(200, "hello world")
//    })
//
//    m.Get("/xml", func(r render.Render) {
//      r.XML(200, Greeting{One: "hello", Two: "world"})
//    })
//
//    m.Run()
//  }
package render

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
  "io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/oxtoacart/bpool"

	"github.com/go-martini/martini"
)

const (
	ContentType    = "Content-Type"
	ContentLength  = "Content-Length"
	ContentBinary  = "application/octet-stream"
	ContentText    = "text/plain"
	ContentJSON    = "application/json"
	ContentHTML    = "text/html"
	ContentXHTML   = "application/xhtml+xml"
	ContentXML     = "text/xml"
	defaultCharset = "UTF-8"
)

// Provides a temporary buffer to execute templates into and catch errors.
var bufpool *bpool.BufferPool

// Included helper functions for use when rendering html
var helperFuncs = template.FuncMap{
	"yield": func() (string, error) {
		return "", fmt.Errorf("yield called with no layout defined")
	},
	"current": func() (string, error) {
		return "", nil
	},
}

// Render is a service that can be injected into a Martini handler. Render provides functions for easily writing JSON and
// HTML templates out to a http Response.
type Render interface {
	// JSON writes the given status and JSON serialized version of the given value to the http.ResponseWriter.
	JSON(status int, v interface{})
	// HTML renders a html template specified by the name and writes the result and given status to the http.ResponseWriter.
	HTML(status int, name string, v interface{}, htmlOpt ...HTMLOptions)
	// XML writes the given status and XML serialized version of the given value to the http.ResponseWriter.
	XML(status int, v interface{})
	// Data writes the raw byte array to the http.ResponseWriter.
	Data(status int, v []byte)
	// Text writes the given status and plain text to the http.ResponseWriter.
	Text(status int, v string)
	// Error is a convenience function that writes an http status to the http.ResponseWriter.
	Error(status int)
	// Status is an alias for Error (writes an http status to the http.ResponseWriter)
	Status(status int)
	// Redirect is a convienience function that sends an HTTP redirect. If status is omitted, uses 302 (Found)
	Redirect(location string, status ...int)
	// Template returns the internal *template.Template used to render the HTML
	Template() *template.Template
	// Header exposes the header struct from http.ResponseWriter.
	Header() http.Header
}

// Delims represents a set of Left and Right delimiters for HTML template rendering
type Delims struct {
	// Left delimiter, defaults to {{
	Left string
	// Right delimiter, defaults to }}
	Right string
}

// Options is a struct for specifying configuration options for the render.Renderer middleware
type Options struct {
	// Directory to load templates. Default is "templates"
	Directory string
	// Layout template name. Will not render a layout if "". Defaults to "".
	Layout string
	// Extensions to parse template files from. Defaults to [".tmpl"]
	Extensions []string
	// Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Defaults to [].
	Funcs []template.FuncMap
	// Delims sets the action delimiters to the specified strings in the Delims struct.
	Delims Delims
	// Appends the given charset to the Content-Type header. Default is "UTF-8".
	Charset string
	// Outputs human readable JSON
	IndentJSON bool
	// Outputs human readable XML
	IndentXML bool
	// Prefixes the JSON output with the given bytes.
	PrefixJSON []byte
	// Prefixes the XML output with the given bytes.
	PrefixXML []byte
	// Allows changing of output to XHTML instead of HTML. Default is "text/html"
	HTMLContentType string
}

// HTMLOptions is a struct for overriding some rendering Options for specific HTML call
type HTMLOptions struct {
	// Layout template name. Overrides Options.Layout.
	Layout string
}

// Renderer is a Middleware that maps a render.Render service into the Martini handler chain. An single variadic render.Options
// struct can be optionally provided to configure HTML rendering. The default directory for templates is "templates" and the default
// file extension is ".tmpl".
//
// If MARTINI_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
// MARTINI_ENV environment variable to "production"
func Renderer(options ...Options) martini.Handler {
	opt := prepareOptions(options)
	cs := prepareCharset(opt.Charset)
	t := compile(opt)
	bufpool = bpool.NewBufferPool(64)
	return func(res http.ResponseWriter, req *http.Request, c martini.Context) {
		var tc *template.Template
		if martini.Env == martini.Dev {
			// recompile for easy development
			tc = compile(opt)
		} else {
			// use a clone of the initial template
			tc, _ = t.Clone()
		}
		c.MapTo(&renderer{res, req, tc, opt, cs}, (*Render)(nil))
	}
}

func prepareCharset(charset string) string {
	if len(charset) != 0 {
		return "; charset=" + charset
	}

	return "; charset=" + defaultCharset
}

func prepareOptions(options []Options) Options {
	var opt Options
	if len(options) > 0 {
		opt = options[0]
	}

	// Defaults
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.Extensions) == 0 {
		opt.Extensions = []string{".tmpl"}
	}
	if len(opt.HTMLContentType) == 0 {
		opt.HTMLContentType = ContentHTML
	}

	return opt
}

func compile(options Options) *template.Template {
	dir := options.Directory
	t := template.New(dir)
	t.Delims(options.Delims.Left, options.Delims.Right)
	// parse an initial template in case we don't have any
	template.Must(t.Parse("Martini"))

	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		r, err := filepath.Rel(dir, path)
		if err != nil {
			return err
		}

		ext := getExt(r)

		for _, extension := range options.Extensions {
			if ext == extension {

				buf, err := ioutil.ReadFile(path)
				if err != nil {
					panic(err)
				}

				name := (r[0 : len(r)-len(ext)])
				tmpl := t.New(filepath.ToSlash(name))

				// add our funcmaps
				for _, funcs := range options.Funcs {
					tmpl.Funcs(funcs)
				}

				// Bomb out if parse fails. We don't want any silent server starts.
				template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
				break
			}
		}

		return nil
	})

	return t
}

func getExt(s string) string {
	if strings.Index(s, ".") == -1 {
		return ""
	}
	return "." + strings.Join(strings.Split(s, ".")[1:], ".")
}

type renderer struct {
	http.ResponseWriter
	req             *http.Request
	t               *template.Template
	opt             Options
	compiledCharset string
}

func (r *renderer) JSON(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentJSON {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// json rendered fine, write out the result
	r.Header().Set(ContentType, ContentJSON+r.compiledCharset)
	r.WriteHeader(status)
	if len(r.opt.PrefixJSON) > 0 {
		r.Write(r.opt.PrefixJSON)
	}
	r.Write(result)
}

func (r *renderer) HTML(status int, name string, binding interface{}, htmlOpt ...HTMLOptions) {
	opt := r.prepareHTMLOptions(htmlOpt)
	// assign a layout if there is one
	if len(opt.Layout) > 0 {
		r.addYield(name, binding)
		name = opt.Layout
	}

	buf, err := r.execute(name, binding)
	if err != nil {
		http.Error(r, err.Error(), http.StatusInternalServerError)
		return
	}

	// template rendered fine, write out the result
	r.Header().Set(ContentType, r.opt.HTMLContentType+r.compiledCharset)
	r.WriteHeader(status)
	io.Copy(r, buf)
	bufpool.Put(buf)
}

func (r *renderer) XML(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentXML {
		result, err = xml.MarshalIndent(v, "", "  ")
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// XML rendered fine, write out the result
	r.Header().Set(ContentType, ContentXML+r.compiledCharset)
	r.WriteHeader(status)
	if len(r.opt.PrefixXML) > 0 {
		r.Write(r.opt.PrefixXML)
	}
	r.Write(result)
}

func (r *renderer) Data(status int, v []byte) {
	if r.Header().Get(ContentType) == "" {
		r.Header().Set(ContentType, ContentBinary)
	}
	r.WriteHeader(status)
	r.Write(v)
}

func (r *renderer) Text(status int, v string) {
	if r.Header().Get(ContentType) == "" {
		r.Header().Set(ContentType, ContentText+r.compiledCharset)
	}
	r.WriteHeader(status)
	r.Write([]byte(v))
}

// Error writes the given HTTP status to the current ResponseWriter
func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Status(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Redirect(location string, status ...int) {
	code := http.StatusFound
	if len(status) == 1 {
		code = status[0]
	}

	http.Redirect(r, r.req, location, code)
}

func (r *renderer) Template() *template.Template {
	return r.t
}

func (r *renderer) execute(name string, binding interface{}) (*bytes.Buffer, error) {
	buf := bufpool.Get()
	return buf, r.t.ExecuteTemplate(buf, name, binding)
}

func (r *renderer) addYield(name string, binding interface{}) {
	funcs := template.FuncMap{
		"yield": func() (template.HTML, error) {
			buf, err := r.execute(name, binding)
			// return safe html here since we are rendering our own template
			return template.HTML(buf.String()), err
		},
		"current": func() (string, error) {
			return name, nil
		},
	}
	r.t.Funcs(funcs)
}

func (r *renderer) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
	if len(htmlOpt) > 0 {
		return htmlOpt[0]
	}

	return HTMLOptions{
		Layout: r.opt.Layout,
	}
}
<commit_msg>Removed execute() to permit deferring bufpool.Put()<commit_after>// Package render is a middleware for Martini that provides easy JSON serialization and HTML template rendering.
//
//  package main
//
//  import (
//    "encoding/xml"
//
//    "github.com/go-martini/martini"
//    "github.com/martini-contrib/render"
//  )
//
//  type Greeting struct {
//    XMLName xml.Name `xml:"greeting"`
//    One     string   `xml:"one,attr"`
//    Two     string   `xml:"two,attr"`
//  }
//
//  func main() {
//    m := martini.Classic()
//    m.Use(render.Renderer()) // reads "templates" directory by default
//
//    m.Get("/html", func(r render.Render) {
//      r.HTML(200, "mytemplate", nil)
//    })
//
//    m.Get("/json", func(r render.Render) {
//      r.JSON(200, "hello world")
//    })
//
//    m.Get("/xml", func(r render.Render) {
//      r.XML(200, Greeting{One: "hello", Two: "world"})
//    })
//
//    m.Run()
//  }
package render

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/oxtoacart/bpool"

	"github.com/go-martini/martini"
)

const (
	ContentType    = "Content-Type"
	ContentLength  = "Content-Length"
	ContentBinary  = "application/octet-stream"
	ContentText    = "text/plain"
	ContentJSON    = "application/json"
	ContentHTML    = "text/html"
	ContentXHTML   = "application/xhtml+xml"
	ContentXML     = "text/xml"
	defaultCharset = "UTF-8"
)

// Provides a temporary buffer to execute templates into and catch errors.
var bufpool *bpool.BufferPool

// Included helper functions for use when rendering html
var helperFuncs = template.FuncMap{
	"yield": func() (string, error) {
		return "", fmt.Errorf("yield called with no layout defined")
	},
	"current": func() (string, error) {
		return "", nil
	},
}

// Render is a service that can be injected into a Martini handler. Render provides functions for easily writing JSON and
// HTML templates out to a http Response.
type Render interface {
	// JSON writes the given status and JSON serialized version of the given value to the http.ResponseWriter.
	JSON(status int, v interface{})
	// HTML renders a html template specified by the name and writes the result and given status to the http.ResponseWriter.
	HTML(status int, name string, v interface{}, htmlOpt ...HTMLOptions)
	// XML writes the given status and XML serialized version of the given value to the http.ResponseWriter.
	XML(status int, v interface{})
	// Data writes the raw byte array to the http.ResponseWriter.
	Data(status int, v []byte)
	// Text writes the given status and plain text to the http.ResponseWriter.
	Text(status int, v string)
	// Error is a convenience function that writes an http status to the http.ResponseWriter.
	Error(status int)
	// Status is an alias for Error (writes an http status to the http.ResponseWriter)
	Status(status int)
	// Redirect is a convienience function that sends an HTTP redirect. If status is omitted, uses 302 (Found)
	Redirect(location string, status ...int)
	// Template returns the internal *template.Template used to render the HTML
	Template() *template.Template
	// Header exposes the header struct from http.ResponseWriter.
	Header() http.Header
}

// Delims represents a set of Left and Right delimiters for HTML template rendering
type Delims struct {
	// Left delimiter, defaults to {{
	Left string
	// Right delimiter, defaults to }}
	Right string
}

// Options is a struct for specifying configuration options for the render.Renderer middleware
type Options struct {
	// Directory to load templates. Default is "templates"
	Directory string
	// Layout template name. Will not render a layout if "". Defaults to "".
	Layout string
	// Extensions to parse template files from. Defaults to [".tmpl"]
	Extensions []string
	// Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Defaults to [].
	Funcs []template.FuncMap
	// Delims sets the action delimiters to the specified strings in the Delims struct.
	Delims Delims
	// Appends the given charset to the Content-Type header. Default is "UTF-8".
	Charset string
	// Outputs human readable JSON
	IndentJSON bool
	// Outputs human readable XML
	IndentXML bool
	// Prefixes the JSON output with the given bytes.
	PrefixJSON []byte
	// Prefixes the XML output with the given bytes.
	PrefixXML []byte
	// Allows changing of output to XHTML instead of HTML. Default is "text/html"
	HTMLContentType string
}

// HTMLOptions is a struct for overriding some rendering Options for specific HTML call
type HTMLOptions struct {
	// Layout template name. Overrides Options.Layout.
	Layout string
}

// Renderer is a Middleware that maps a render.Render service into the Martini handler chain. An single variadic render.Options
// struct can be optionally provided to configure HTML rendering. The default directory for templates is "templates" and the default
// file extension is ".tmpl".
//
// If MARTINI_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
// MARTINI_ENV environment variable to "production"
func Renderer(options ...Options) martini.Handler {
	opt := prepareOptions(options)
	cs := prepareCharset(opt.Charset)
	t := compile(opt)
	bufpool = bpool.NewBufferPool(64)
	return func(res http.ResponseWriter, req *http.Request, c martini.Context) {
		var tc *template.Template
		if martini.Env == martini.Dev {
			// recompile for easy development
			tc = compile(opt)
		} else {
			// use a clone of the initial template
			tc, _ = t.Clone()
		}
		c.MapTo(&renderer{res, req, tc, opt, cs}, (*Render)(nil))
	}
}

func prepareCharset(charset string) string {
	if len(charset) != 0 {
		return "; charset=" + charset
	}

	return "; charset=" + defaultCharset
}

func prepareOptions(options []Options) Options {
	var opt Options
	if len(options) > 0 {
		opt = options[0]
	}

	// Defaults
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.Extensions) == 0 {
		opt.Extensions = []string{".tmpl"}
	}
	if len(opt.HTMLContentType) == 0 {
		opt.HTMLContentType = ContentHTML
	}

	return opt
}

func compile(options Options) *template.Template {
	dir := options.Directory
	t := template.New(dir)
	t.Delims(options.Delims.Left, options.Delims.Right)
	// parse an initial template in case we don't have any
	template.Must(t.Parse("Martini"))

	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		r, err := filepath.Rel(dir, path)
		if err != nil {
			return err
		}

		ext := getExt(r)

		for _, extension := range options.Extensions {
			if ext == extension {

				buf, err := ioutil.ReadFile(path)
				if err != nil {
					panic(err)
				}

				name := (r[0 : len(r)-len(ext)])
				tmpl := t.New(filepath.ToSlash(name))

				// add our funcmaps
				for _, funcs := range options.Funcs {
					tmpl.Funcs(funcs)
				}

				// Bomb out if parse fails. We don't want any silent server starts.
				template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
				break
			}
		}

		return nil
	})

	return t
}

func getExt(s string) string {
	if strings.Index(s, ".") == -1 {
		return ""
	}
	return "." + strings.Join(strings.Split(s, ".")[1:], ".")
}

type renderer struct {
	http.ResponseWriter
	req             *http.Request
	t               *template.Template
	opt             Options
	compiledCharset string
}

func (r *renderer) JSON(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentJSON {
		result, err = json.MarshalIndent(v, "", "  ")
	} else {
		result, err = json.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// json rendered fine, write out the result
	r.Header().Set(ContentType, ContentJSON+r.compiledCharset)
	r.WriteHeader(status)
	if len(r.opt.PrefixJSON) > 0 {
		r.Write(r.opt.PrefixJSON)
	}
	r.Write(result)
}

func (r *renderer) HTML(status int, name string, binding interface{}, htmlOpt ...HTMLOptions) {
	opt := r.prepareHTMLOptions(htmlOpt)
	// assign a layout if there is one
	if len(opt.Layout) > 0 {
		r.addYield(name, binding)
		name = opt.Layout
	}

	buf := bufpool.Get()
	defer bufpool.Put(buf)

	err := r.t.ExecuteTemplate(buf, name, binding)
	if err != nil {
		http.Error(r, err.Error(), http.StatusInternalServerError)
		return
	}

	// template rendered fine, write out the result
	r.Header().Set(ContentType, r.opt.HTMLContentType+r.compiledCharset)
	r.WriteHeader(status)
	io.Copy(r, buf)
}

func (r *renderer) XML(status int, v interface{}) {
	var result []byte
	var err error
	if r.opt.IndentXML {
		result, err = xml.MarshalIndent(v, "", "  ")
	} else {
		result, err = xml.Marshal(v)
	}
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// XML rendered fine, write out the result
	r.Header().Set(ContentType, ContentXML+r.compiledCharset)
	r.WriteHeader(status)
	if len(r.opt.PrefixXML) > 0 {
		r.Write(r.opt.PrefixXML)
	}
	r.Write(result)
}

func (r *renderer) Data(status int, v []byte) {
	if r.Header().Get(ContentType) == "" {
		r.Header().Set(ContentType, ContentBinary)
	}
	r.WriteHeader(status)
	r.Write(v)
}

func (r *renderer) Text(status int, v string) {
	if r.Header().Get(ContentType) == "" {
		r.Header().Set(ContentType, ContentText+r.compiledCharset)
	}
	r.WriteHeader(status)
	r.Write([]byte(v))
}

// Error writes the given HTTP status to the current ResponseWriter
func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Status(status int) {
	r.WriteHeader(status)
}

func (r *renderer) Redirect(location string, status ...int) {
	code := http.StatusFound
	if len(status) == 1 {
		code = status[0]
	}

	http.Redirect(r, r.req, location, code)
}

func (r *renderer) Template() *template.Template {
	return r.t
}

func (r *renderer) addYield(name string, binding interface{}) {
	funcs := template.FuncMap{
		"yield": func() (template.HTML, error) {
			buf := bufpool.Get()
			defer bufpool.Put(buf)

			err := r.t.ExecuteTemplate(buf, name, binding)
			// return safe html here since we are rendering our own template
			return template.HTML(buf.String()), err
		},
		"current": func() (string, error) {
			return name, nil
		},
	}
	r.t.Funcs(funcs)
}

func (r *renderer) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
	if len(htmlOpt) > 0 {
		return htmlOpt[0]
	}

	return HTMLOptions{
		Layout: r.opt.Layout,
	}
}
<|endoftext|>


<commit_before>package reopen

import (
	"bufio"
	"io"
	"os"
	"sync"
	"time"
)

// Reopener interface defines something that can be reopened
type Reopener interface {
	Reopen() error
}

// Writer is a writer that also can be reopened
type Writer interface {
	Reopener
	io.Writer
}

// WriteCloser is a io.WriteCloser that can also be reopened
type WriteCloser interface {
	Reopener
	io.Writer
	io.Closer
}

// FileWriter that can also be reopened
type FileWriter struct {
	mu   sync.Mutex // ensures close / reopen / write are not called at the same time, protects f
	f    *os.File
	mode os.FileMode
	name string
}

// Close calls the underlyding File.Close()
func (f *FileWriter) Close() error {
	f.mu.Lock()
	err := f.f.Close()
	f.mu.Unlock()
	return err
}

// mutex free version
func (f *FileWriter) reopen() error {
	if f.f != nil {
		f.f.Close()
		f.f = nil
	}
	newf, err := os.OpenFile(f.name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, f.mode)
	if err != nil {
		f.f = nil
		return err
	}
	f.f = newf

	return nil
}

// Reopen the file
func (f *FileWriter) Reopen() error {
	f.mu.Lock()
	err := f.reopen()
	f.mu.Unlock()
	return err
}

// Write implements the stander io.Writer interface
func (f *FileWriter) Write(p []byte) (int, error) {
	f.mu.Lock()
	n, err := f.f.Write(p)
	f.mu.Unlock()
	return n, err
}

// NewFileWriter opens a file for appending and writing and can be reopened.
// it is a ReopenWriteCloser...
func NewFileWriter(name string) (*FileWriter, error) {
	// Standard default mode
	return NewFileWriterMode(name, 0666)
}

// NewFileWriterMode opens a Reopener file with a specific permission
func NewFileWriterMode(name string, mode os.FileMode) (*FileWriter, error) {
	writer := FileWriter{
		f:    nil,
		name: name,
		mode: mode,
	}
	err := writer.reopen()
	if err != nil {
		return nil, err
	}
	return &writer, nil
}

// BufferedFileWriter is buffer writer than can be reopned
type BufferedFileWriter struct {
	mu         sync.Mutex
	OrigWriter *FileWriter
	BufWriter  *bufio.Writer
}

// Reopen implement Reopener
func (bw *BufferedFileWriter) Reopen() error {
	bw.mu.Lock()
	bw.BufWriter.Flush()

	// use non-mutex version since we are using this one
	err := bw.OrigWriter.reopen()

	bw.BufWriter.Reset(io.Writer(bw.OrigWriter))
	bw.mu.Unlock()

	return err
}

// Close flushes the internal buffer and closes the destination file
func (bw *BufferedFileWriter) Close() error {
	bw.mu.Lock()
	bw.BufWriter.Flush()
	bw.OrigWriter.f.Close()
	bw.mu.Unlock()
	return nil
}

// Write implements io.Writer (and reopen.Writer)
func (bw *BufferedFileWriter) Write(p []byte) (int, error) {
	bw.mu.Lock()
	n, err := bw.BufWriter.Write(p)

	// Special Case... if the used space in the buffer is LESS than
	// the input, then we did a flush in the middle of the line
	// and the full log line was not sent on its way.
	if bw.BufWriter.Buffered() < len(p) {
		bw.BufWriter.Flush()
	}

	bw.mu.Unlock()
	return n, err
}

// flushDaemon periodically flushes the log file buffers.
//  props to glog
func (bw *BufferedFileWriter) flushDaemon() {
	for range time.NewTicker(flushInterval).C {
		bw.mu.Lock()
		bw.BufWriter.Flush()
		bw.OrigWriter.f.Sync()
		bw.mu.Unlock()
	}
}

const bufferSize = 256 * 1024
const flushInterval = 30 * time.Second

// NewBufferedFileWriter opens a buffered file that is periodically
//  flushed.
// TODO: allow size and interval to be passed in.
func NewBufferedFileWriter(w *FileWriter) *BufferedFileWriter {
	bw := BufferedFileWriter{
		OrigWriter: w,
		BufWriter:  bufio.NewWriterSize(w, bufferSize),
	}
	go bw.flushDaemon()
	return &bw
}

type multiReopenWriter struct {
	writers []Writer
}

// Reopen reopens all child Reopeners
func (t *multiReopenWriter) Reopen() error {
	for _, w := range t.writers {
		err := w.Reopen()
		if err != nil {
			return err
		}
	}
	return nil
}

// Write implements standard io.Write and reopen.Write
func (t *multiReopenWriter) Write(p []byte) (int, error) {
	for _, w := range t.writers {
		n, err := w.Write(p)
		if err != nil {
			return n, err
		}
		if n != len(p) {
			return n, io.ErrShortWrite
		}
	}
	return len(p), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
//  Also allow reopen
func MultiWriter(writers ...Writer) Writer {
	w := make([]Writer, len(writers))
	copy(w, writers)
	return &multiReopenWriter{w}
}

type nopReopenWriter struct {
	io.Writer
}

func (nopReopenWriter) Reopen() error {
	return nil
}

// NopWriter turns a normal writer into a ReopenWriter
//  by doing a NOP on Reopen
// TODO: better name
func NopWriter(w io.Writer) Writer {
	return nopReopenWriter{w}
}

// Reopenable versions of os.Stdout and os.Stderr (reopen does nothing)
var (
	Stdout = NopWriter(os.Stdout)
	Stderr = NopWriter(os.Stderr)
)
<commit_msg>make Stderr, Stdout work more like a file<commit_after>package reopen

import (
	"bufio"
	"io"
	"os"
	"sync"
	"time"
)

// Reopener interface defines something that can be reopened
type Reopener interface {
	Reopen() error
}

// Writer is a writer that also can be reopened
type Writer interface {
	Reopener
	io.Writer
}

// WriteCloser is a io.WriteCloser that can also be reopened
type WriteCloser interface {
	Reopener
	io.WriteCloser
}

// FileWriter that can also be reopened
type FileWriter struct {
	mu   sync.Mutex // ensures close / reopen / write are not called at the same time, protects f
	f    *os.File
	mode os.FileMode
	name string
}

// Close calls the underlyding File.Close()
func (f *FileWriter) Close() error {
	f.mu.Lock()
	err := f.f.Close()
	f.mu.Unlock()
	return err
}

// mutex free version
func (f *FileWriter) reopen() error {
	if f.f != nil {
		f.f.Close()
		f.f = nil
	}
	newf, err := os.OpenFile(f.name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, f.mode)
	if err != nil {
		f.f = nil
		return err
	}
	f.f = newf

	return nil
}

// Reopen the file
func (f *FileWriter) Reopen() error {
	f.mu.Lock()
	err := f.reopen()
	f.mu.Unlock()
	return err
}

// Write implements the stander io.Writer interface
func (f *FileWriter) Write(p []byte) (int, error) {
	f.mu.Lock()
	n, err := f.f.Write(p)
	f.mu.Unlock()
	return n, err
}

// NewFileWriter opens a file for appending and writing and can be reopened.
// it is a ReopenWriteCloser...
func NewFileWriter(name string) (*FileWriter, error) {
	// Standard default mode
	return NewFileWriterMode(name, 0666)
}

// NewFileWriterMode opens a Reopener file with a specific permission
func NewFileWriterMode(name string, mode os.FileMode) (*FileWriter, error) {
	writer := FileWriter{
		f:    nil,
		name: name,
		mode: mode,
	}
	err := writer.reopen()
	if err != nil {
		return nil, err
	}
	return &writer, nil
}

// BufferedFileWriter is buffer writer than can be reopned
type BufferedFileWriter struct {
	mu         sync.Mutex
	OrigWriter *FileWriter
	BufWriter  *bufio.Writer
}

// Reopen implement Reopener
func (bw *BufferedFileWriter) Reopen() error {
	bw.mu.Lock()
	bw.BufWriter.Flush()

	// use non-mutex version since we are using this one
	err := bw.OrigWriter.reopen()

	bw.BufWriter.Reset(io.Writer(bw.OrigWriter))
	bw.mu.Unlock()

	return err
}

// Close flushes the internal buffer and closes the destination file
func (bw *BufferedFileWriter) Close() error {
	bw.mu.Lock()
	bw.BufWriter.Flush()
	bw.OrigWriter.f.Close()
	bw.mu.Unlock()
	return nil
}

// Write implements io.Writer (and reopen.Writer)
func (bw *BufferedFileWriter) Write(p []byte) (int, error) {
	bw.mu.Lock()
	n, err := bw.BufWriter.Write(p)

	// Special Case... if the used space in the buffer is LESS than
	// the input, then we did a flush in the middle of the line
	// and the full log line was not sent on its way.
	if bw.BufWriter.Buffered() < len(p) {
		bw.BufWriter.Flush()
	}

	bw.mu.Unlock()
	return n, err
}

// flushDaemon periodically flushes the log file buffers.
//  props to glog
func (bw *BufferedFileWriter) flushDaemon() {
	for range time.NewTicker(flushInterval).C {
		bw.mu.Lock()
		bw.BufWriter.Flush()
		bw.OrigWriter.f.Sync()
		bw.mu.Unlock()
	}
}

const bufferSize = 256 * 1024
const flushInterval = 30 * time.Second

// NewBufferedFileWriter opens a buffered file that is periodically
//  flushed.
// TODO: allow size and interval to be passed in.
func NewBufferedFileWriter(w *FileWriter) *BufferedFileWriter {
	bw := BufferedFileWriter{
		OrigWriter: w,
		BufWriter:  bufio.NewWriterSize(w, bufferSize),
	}
	go bw.flushDaemon()
	return &bw
}

type multiReopenWriter struct {
	writers []Writer
}

// Reopen reopens all child Reopeners
func (t *multiReopenWriter) Reopen() error {
	for _, w := range t.writers {
		err := w.Reopen()
		if err != nil {
			return err
		}
	}
	return nil
}

// Write implements standard io.Write and reopen.Write
func (t *multiReopenWriter) Write(p []byte) (int, error) {
	for _, w := range t.writers {
		n, err := w.Write(p)
		if err != nil {
			return n, err
		}
		if n != len(p) {
			return n, io.ErrShortWrite
		}
	}
	return len(p), nil
}

// MultiWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command.
//  Also allow reopen
func MultiWriter(writers ...Writer) Writer {
	w := make([]Writer, len(writers))
	copy(w, writers)
	return &multiReopenWriter{w}
}

type nopReopenWriteCloser struct {
	io.Writer
}

func (nopReopenWriteCloser) Reopen() error {
	return nil
}

func (nopReopenWriteCloser) Close() error {
	return nil
}

// NopWriter turns a normal writer into a ReopenWriter
//  by doing a NOP on Reopen
// TODO: better name
func NopWriter(w io.Writer) WriteCloser {
	return nopReopenWriteCloser{w}
}

// Reopenable versions of os.Stdout and os.Stderr (reopen does nothing)
var (
	Stdout = NopWriter(os.Stdout)
	Stderr = NopWriter(os.Stderr)
)
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"os"
	"path/filepath"
	"regexp"

	"github.com/disintegration/imaging"
)

var width = flag.Int("width", math.MaxInt16, "Output image width")
var height = flag.Int("height", math.MaxInt16, "Output image height")
var output = flag.String("type", "png", "Output image format")
var destination = flag.String("destination", "", "Output image folder")

func main() {
	flag.Parse()

	if len(*destination) > 0 {
		err := os.MkdirAll(*destination, os.ModePerm)
		if err != nil {
			fmt.Printf("Unable to create destination: %s\n", err)
			os.Exit(1)
		}
	}

	extMatch := regexp.MustCompile(`\.[a-zA-Z0-9]+$`)

	filelist := flag.Args()
	if len(filelist) == 0 {
		filelist = []string{"./*.*"}
	}

	for _, srcArg := range filelist {
		srcFilenames, err := filepath.Glob(srcArg)
		if err != nil {
			log.Printf("Glob error: %s\n", err)
			continue
		}
		for _, srcFilename := range srcFilenames {
			fmt.Printf("Processing [%s]... ", srcFilename)
			src, err := imaging.Open(srcFilename)
			if err != nil {
				log.Printf("error: %s\n", err)
				continue
			}
			dest := imaging.Fit(src, *width, *height, imaging.MitchellNetravali)
			destFilename := extMatch.ReplaceAllString(srcFilename, "") + fmt.Sprintf("-%dx%d.%s", dest.Bounds().Dx(), dest.Bounds().Dy(), *output)
			if len(*destination) > 0 {
				_, file := filepath.Split(destFilename)
				destFilename = filepath.Join(*destination, file)
			}
			err = imaging.Save(dest, destFilename)
			if err != nil {
				log.Printf("error: %s\n", err)
				continue
			}
			fmt.Printf("OK; written to %s\n", destFilename)
		}
	}
}
<commit_msg>Removed default selection of all files within pwd<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"os"
	"path/filepath"
	"regexp"

	"github.com/disintegration/imaging"
)

var width = flag.Int("width", math.MaxInt16, "Output image width")
var height = flag.Int("height", math.MaxInt16, "Output image height")
var output = flag.String("type", "png", "Output image format")
var destination = flag.String("destination", "", "Output image folder")

func main() {
	flag.Parse()

	if len(*destination) > 0 {
		err := os.MkdirAll(*destination, os.ModePerm)
		if err != nil {
			fmt.Printf("Unable to create destination: %s\n", err)
			os.Exit(1)
		}
	}

	extMatch := regexp.MustCompile(`\.[a-zA-Z0-9]+$`)

	filelist := flag.Args()
	// if len(filelist) == 0 {
	// 	filelist = []string{"./*.*"}
	// }

	for _, srcArg := range filelist {
		srcFilenames, err := filepath.Glob(srcArg)
		if err != nil {
			log.Printf("Glob error: %s\n", err)
			continue
		}
		for _, srcFilename := range srcFilenames {
			fmt.Printf("Processing [%s]... ", srcFilename)
			src, err := imaging.Open(srcFilename)
			if err != nil {
				log.Printf("error: %s\n", err)
				continue
			}
			dest := imaging.Fit(src, *width, *height, imaging.MitchellNetravali)
			destFilename := extMatch.ReplaceAllString(srcFilename, "") + fmt.Sprintf("-%dx%d.%s", dest.Bounds().Dx(), dest.Bounds().Dy(), *output)
			if len(*destination) > 0 {
				_, file := filepath.Split(destFilename)
				destFilename = filepath.Join(*destination, file)
			}
			err = imaging.Save(dest, destFilename)
			if err != nil {
				log.Printf("error: %s\n", err)
				continue
			}
			fmt.Printf("OK; written to %s\n", destFilename)
		}
	}
}
<|endoftext|>


<commit_before>package ripple

import (
	"code.google.com/p/go.net/websocket"
	"encoding/json"
	"fmt"
	"io"
	"math/big"
	"strconv"
)

type Amount struct {
	Currency string
	Issuer   string
	Value    big.Rat
}

func (a *Amount) UnmarshalJSON(b []byte) (err error) {

	// Try interpret as IOU
	var m map[string]string
	err = json.Unmarshal(b, &m)
	if err == nil {
		a.Currency = m["currency"]
		_, success := a.Value.SetString(m["value"])
		if !success {
			panic(fmt.Sprintf("Could not interpret value: %s", m["value"]))
		}
		a.Issuer = m["issuer"]
		return
	}

	// Try interpret as XRP in drips
	var s string
	err = json.Unmarshal(b, &s)
	if err == nil {
		dripValue, success := a.Value.SetString(s)
		if !success {
			panic(fmt.Sprintf("Could not interpret value: %s", s))
		}
		a.Value.Quo(dripValue, big.NewRat(1000000, 1))
		a.Currency = "XRP"
		return
	}

	panic(fmt.Sprintf("Could not unmarshal amount: %s", b))
	return
}

type Transaction struct {
	Account         string
	Amount          Amount
	Date            int
	Destination     string
	DestinationTag  int
	Fee             string
	Flags           int
	Hash            string
	SendMax         *Amount
	Sequence        int
	SingingPubKey   string
	TransactionType string
	TxnSignature    string
}

type Message struct {
	LedgerHash  string `json:"ledger_hash"`
	LedgerIndex int    `json:"ledger_index"`
	Status      string
	Transaction *Transaction
	Type        string
}

func (m *Message) String() string {
	if m.Type == "transaction" {
		t := m.Transaction

		if t.TransactionType == "Payment" {
			return ("Payment " + t.Hash +
				" from " + t.Account + " to " +
				t.Destination + " " +
				strconv.Itoa(t.DestinationTag) + " " +
				t.Amount.Value.FloatString(5) + " " +
				t.Amount.Currency)
		}

		return t.TransactionType + " " + t.Hash
	}

	return m.Type
}

type Connection struct {
	Messages chan *Message

	conn *websocket.Conn
}

func (r *Connection) Connect(uri string) {
	var err error

	// Connect to websocket server
	r.conn, err = websocket.Dial(uri, "", "http://localhost")
	if err != nil {
		panic("Could not connect: " + err.Error())
	}

	// Subscribe to all transactions
	msg := "{\"command\":\"subscribe\",\"id\":1,\"streams\":[\"transactions\"]}"
	err = websocket.Message.Send(r.conn, msg)
	if err != nil {
		panic("Could not subscribe: " + err.Error())
	}

	// Wait for ack
	var m Message
	err = websocket.JSON.Receive(r.conn, &m)
	if err != nil {
		panic("Could not receive subscribe ack: " + err.Error())
	}

	if m.Type != "response" || m.Status != "success" {
		panic("Failed to subscribe")
	}
}

func (r *Connection) Monitor() {
	for {
		var err error
		var m Message
		err = websocket.JSON.Receive(r.conn, &m)
		if err != nil {
			if err == io.EOF {
				// graceful shutdown by server
				break
			}
			fmt.Println("Could not receive: " + err.Error())
			break
		}
		r.Messages <- &m
	}
}
<commit_msg>Return err instead of panicking<commit_after>package ripple

import (
	"code.google.com/p/go.net/websocket"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"math/big"
	"strconv"
)

type Amount struct {
	Currency string
	Issuer   string
	Value    big.Rat
}

func (a *Amount) UnmarshalJSON(b []byte) (err error) {

	// Try interpret as IOU
	var m map[string]string
	err = json.Unmarshal(b, &m)
	if err == nil {
		a.Currency = m["currency"]
		_, success := a.Value.SetString(m["value"])
		if !success {
			return fmt.Errorf("Could not interpret value: %s", m["value"])
		}
		a.Issuer = m["issuer"]
		return
	}

	// Try interpret as XRP in drips
	var s string
	err = json.Unmarshal(b, &s)
	if err == nil {
		dripValue, success := a.Value.SetString(s)
		if !success {
			return fmt.Errorf("Could not interpret value: %s", s)
		}
		a.Value.Quo(dripValue, big.NewRat(1000000, 1))
		a.Currency = "XRP"
		return
	}

	return fmt.Errorf("Could not unmarshal amount: %s", b)
}

type Transaction struct {
	Account         string
	Amount          Amount
	Date            int
	Destination     string
	DestinationTag  int
	Fee             string
	Flags           int
	Hash            string
	SendMax         *Amount
	Sequence        int
	SingingPubKey   string
	TransactionType string
	TxnSignature    string
}

type Message struct {
	LedgerHash  string `json:"ledger_hash"`
	LedgerIndex int    `json:"ledger_index"`
	Status      string
	Transaction *Transaction
	Type        string
}

func (m *Message) String() string {
	if m.Type == "transaction" {
		t := m.Transaction

		if t.TransactionType == "Payment" {
			return ("Payment " + t.Hash +
				" from " + t.Account + " to " +
				t.Destination + " " +
				strconv.Itoa(t.DestinationTag) + " " +
				t.Amount.Value.FloatString(5) + " " +
				t.Amount.Currency)
		}

		return t.TransactionType + " " + t.Hash
	}

	return m.Type
}

type Connection struct {
	Messages chan *Message

	conn *websocket.Conn
}

func (r *Connection) Connect(uri string) (err error) {

	// Connect to websocket server
	r.conn, err = websocket.Dial(uri, "", "http://localhost")
	if err != nil {
		return err
	}

	// Subscribe to all transactions
	msg := "{\"command\":\"subscribe\",\"id\":1,\"streams\":[\"transactions\"]}"
	err = websocket.Message.Send(r.conn, msg)
	if err != nil {
		return err
	}

	// Wait for ack
	var m Message
	err = websocket.JSON.Receive(r.conn, &m)
	if err != nil {
		return err
	}

	if m.Type != "response" || m.Status != "success" {
		return errors.New("Failed to subscribe")
	}

	return
}

func (r *Connection) Monitor() {
	for {
		var err error
		var m Message
		err = websocket.JSON.Receive(r.conn, &m)
		if err != nil {
			if err == io.EOF {
				// graceful shutdown by server
				break
			}
			fmt.Println("Could not receive: " + err.Error())
			break
		}
		r.Messages <- &m
	}
}
<|endoftext|>


<commit_before>package caffmux

import (
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"strings"
)

type ControllerInfo struct {
	regex  *regexp.Regexp
	params map[int]string
	cType  reflect.Type
}

type ControllerRegistor struct {
	routers []*ControllerInfo
}

func NewControllerRegistor() *ControllerRegistor {
	return &ControllerRegistor{}
}

// According to the rules set by the pattern to add a routing
func (cr *ControllerRegistor) Add(pattern string, c ControllerInterface) {
	parts := strings.Split(pattern, "/")
	j := 0
	params := make(map[int]string)
	for i, part := range parts {
		if strings.HasPrefix(part, ":") {
			expr := "([^/]+)"
			// eg: (?i)^/hello/:id([0-9]+)/:name(\\w+)
			// The expression of extract parameter name and parameter values
			if index := strings.Index(part, "("); index >= 3 {
				expr = part[index:]
				part = part[1:index]
			}
			params[j] = part
			parts[i] = expr
			j++
		}
	}
	pattern = strings.Join(parts, "/")
	Debug(pattern)
	regex, regexErr := regexp.Compile(pattern)
	if regexErr != nil {
		panic(regexErr)
		return
	}
	t := reflect.Indirect(reflect.ValueOf(c)).Type()
	route := &ControllerInfo{}
	route.regex = regex
	route.params = params
	route.cType = t
	cr.routers = append(cr.routers, route)
}

// Implement a Handler interface
func (cr *ControllerRegistor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Server", "caffmux")
	w.Header().Set("Developer", "tangjizhong")
	var started bool
	// Set the static directory
	for prefix, staticPath := range StaticPath {
		if strings.HasPrefix(r.URL.Path, prefix) {
			file := staticPath + r.URL.Path[len(prefix):]
			http.ServeFile(w, r, file)
			started = true
			return
		}
	}
	requestPath := r.URL.Path
	Debug(requestPath)
	for _, route := range cr.routers {
		// Validation request path are legal
		if !route.regex.MatchString(requestPath) {
			continue
		}
		matches := route.regex.FindStringSubmatch(requestPath)
		if len(matches[0]) != len(requestPath) {
			continue
		}
		params := make(map[string]string)
		if len(route.params) > 0 {
			values := r.URL.Query()
			for i, match := range matches[1:] {
				values.Add(route.params[i], match)
				params[route.params[i]] = match
			}
			// The restful style in the url query parameter combination
			r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
		}
		c := reflect.New(route.cType)
		init := c.MethodByName("Init")
		in := make([]reflect.Value, 2)
		in[0] = reflect.ValueOf(route.cType.Name())
		in[1] = reflect.ValueOf(&Context{r, w, params})
		init.Call(in)
		in = make([]reflect.Value, 0)
		actionName := ""
		// Through the request path for the action name
		actionNames := strings.Split(requestPath, "!")
		if len(actionNames) > 1 && actionNames[1] != "" {
			actionName = actionNames[1]
		} else {
			actionNames = strings.Split(requestPath, "/")
			length := len(actionNames)
			if length > 1 && actionNames[length-1] != "" {
				actionName = actionNames[length-1]
			}
		}
		Debug("actionName = " + actionName)
		if actionName != "" {
			numMethod := c.NumMethod()
			t := c.Type()
			// Iterate through all the methods
			cFlag := false
			for i := 0; i < numMethod; i++ {
				// Implement actionName case-insensitive
				if strings.ToUpper(t.Method(i).Name) == strings.ToUpper(actionName) {
					cFlag = true
					c.Method(i).Call(in)
					break
				}
			}
			if !cFlag {
				callMethod(r, c, in)
			}
		} else {
			callMethod(r, c, in)
		}
		started = true
	}
	if !started {
		http.NotFound(w, r)
	}
}

func callMethod(r *http.Request, c reflect.Value, in []reflect.Value) {
	method := c.MethodByName("Prepare")
	method.Call(in)
	if r.Method == "GET" {
		method = c.MethodByName("Get")
		method.Call(in)
	} else if r.Method == "POST" {
		method = c.MethodByName("Post")
		method.Call(in)
	} else if r.Method == "HEAD" {
		method = c.MethodByName("Head")
		method.Call(in)
	} else if r.Method == "DELETE" {
		method = c.MethodByName("Delete")
		method.Call(in)
	} else if r.Method == "PUT" {
		method = c.MethodByName("Put")
		method.Call(in)
	} else if r.Method == "PATCH" {
		method = c.MethodByName("Patch")
		method.Call(in)
	} else if r.Method == "OPTIONS" {
		method = c.MethodByName("Options")
		method.Call(in)
	}
	method = c.MethodByName("Finish")
	method.Call(in)
}
<commit_msg>update version<commit_after>package caffmux

import (
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"strings"
)

type ControllerInfo struct {
	regex  *regexp.Regexp
	params map[int]string
	cType  reflect.Type
}

type ControllerRegistor struct {
	routers []*ControllerInfo
}

func NewControllerRegistor() *ControllerRegistor {
	return &ControllerRegistor{}
}

// According to the rules set by the pattern to add a routing
func (cr *ControllerRegistor) Add(pattern string, c ControllerInterface) {
	parts := strings.Split(pattern, "/")
	j := 0
	params := make(map[int]string)
	for i, part := range parts {
		if strings.HasPrefix(part, ":") {
			expr := "([^/]+)"
			// eg: (?i)^/hello/:id([0-9]+)/:name(\\w+)
			// The expression of extract parameter name and parameter values
			if index := strings.Index(part, "("); index >= 3 {
				expr = part[index:]
				part = part[1:index]
			}
			params[j] = part
			parts[i] = expr
			j++
		}
	}
	pattern = strings.Join(parts, "/")
	Debug(pattern)
	regex, regexErr := regexp.Compile(pattern)
	if regexErr != nil {
		panic(regexErr)
		return
	}
	t := reflect.Indirect(reflect.ValueOf(c)).Type()
	route := &ControllerInfo{}
	route.regex = regex
	route.params = params
	route.cType = t
	cr.routers = append(cr.routers, route)
}

// Implement a Handler interface
func (cr *ControllerRegistor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Server", "caffmux 1.0.0")
	w.Header().Set("Developer", "tangjizhong")
	var started bool
	// Set the static directory
	for prefix, staticPath := range StaticPath {
		if strings.HasPrefix(r.URL.Path, prefix) {
			file := staticPath + r.URL.Path[len(prefix):]
			http.ServeFile(w, r, file)
			started = true
			return
		}
	}
	requestPath := r.URL.Path
	Debug(requestPath)
	for _, route := range cr.routers {
		// Validation request path are legal
		if !route.regex.MatchString(requestPath) {
			continue
		}
		matches := route.regex.FindStringSubmatch(requestPath)
		if len(matches[0]) != len(requestPath) {
			continue
		}
		params := make(map[string]string)
		if len(route.params) > 0 {
			values := r.URL.Query()
			for i, match := range matches[1:] {
				values.Add(route.params[i], match)
				params[route.params[i]] = match
			}
			// The restful style in the url query parameter combination
			r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
		}
		c := reflect.New(route.cType)
		init := c.MethodByName("Init")
		in := make([]reflect.Value, 2)
		in[0] = reflect.ValueOf(route.cType.Name())
		in[1] = reflect.ValueOf(&Context{r, w, params})
		init.Call(in)
		in = make([]reflect.Value, 0)
		actionName := ""
		// Through the request path for the action name
		actionNames := strings.Split(requestPath, "!")
		if len(actionNames) > 1 && actionNames[1] != "" {
			actionName = actionNames[1]
		} else {
			actionNames = strings.Split(requestPath, "/")
			length := len(actionNames)
			if length > 1 && actionNames[length-1] != "" {
				actionName = actionNames[length-1]
			}
		}
		Debug("actionName = " + actionName)
		if actionName != "" {
			numMethod := c.NumMethod()
			t := c.Type()
			// Iterate through all the methods
			cFlag := false
			for i := 0; i < numMethod; i++ {
				// Implement actionName case-insensitive
				if strings.ToUpper(t.Method(i).Name) == strings.ToUpper(actionName) {
					cFlag = true
					c.Method(i).Call(in)
					break
				}
			}
			if !cFlag {
				callMethod(r, c, in)
			}
		} else {
			callMethod(r, c, in)
		}
		started = true
	}
	if !started {
		http.NotFound(w, r)
	}
}

func callMethod(r *http.Request, c reflect.Value, in []reflect.Value) {
	method := c.MethodByName("Prepare")
	method.Call(in)
	if r.Method == "GET" {
		method = c.MethodByName("Get")
		method.Call(in)
	} else if r.Method == "POST" {
		method = c.MethodByName("Post")
		method.Call(in)
	} else if r.Method == "HEAD" {
		method = c.MethodByName("Head")
		method.Call(in)
	} else if r.Method == "DELETE" {
		method = c.MethodByName("Delete")
		method.Call(in)
	} else if r.Method == "PUT" {
		method = c.MethodByName("Put")
		method.Call(in)
	} else if r.Method == "PATCH" {
		method = c.MethodByName("Patch")
		method.Call(in)
	} else if r.Method == "OPTIONS" {
		method = c.MethodByName("Options")
		method.Call(in)
	}
	method = c.MethodByName("Finish")
	method.Call(in)
}
<|endoftext|>