<commit_before>// Package runtime is the micro runtime
package runtime

import (
	"encoding/json"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"sort"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/micro/cli/v2"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/client"
	"github.com/micro/go-micro/v2/config/cmd"
	log "github.com/micro/go-micro/v2/logger"
	"github.com/micro/go-micro/v2/runtime"
	"github.com/micro/go-micro/v2/runtime/local/git"
	srvRuntime "github.com/micro/go-micro/v2/runtime/service"
	"github.com/micro/go-micro/v2/util/file"
	cliutil "github.com/micro/micro/v2/cli/util"
	"github.com/micro/micro/v2/runtime/handler"
)

const (
	// RunUsage message for the run command
	RunUsage = "Required usage: micro run [source]"
	// KillUsage message for the kill command
	KillUsage = "Require usage: micro kill [source]"
	// UpdateUsage message for the update command
	UpdateUsage = "Require usage: micro update [source]"
	// GetUsage message for micro get command
	GetUsage = "Require usage: micro status [service] [version]"
	// ServicesUsage message for micro services command
	ServicesUsage = "Require usage: micro services"
	// CannotWatch message for the run command
	CannotWatch = "Cannot watch filesystem on this runtime"
)

var (
	// DefaultRetries which should be attempted when starting a service
	DefaultRetries = 3
	// Image to specify if none is specified
	Image = "docker.pkg.github.com/micro/services"
	// Source where we get services from
	Source = "github.com/micro/services"
)

// timeAgo returns the time passed
func timeAgo(v string) string {
	if len(v) == 0 {
		return "unknown"
	}
	t, err := time.Parse(time.RFC3339, v)
	if err != nil {
		return v
	}
	return fmt.Sprintf("%v ago", time.Since(t).Truncate(time.Second))
}

func runtimeFromContext(ctx *cli.Context) runtime.Runtime {
	if cliutil.IsLocal() {
		return *cmd.DefaultCmd.Options().Runtime
	}
	return srvRuntime.NewRuntime()
}

// exists returns whether the given file or directory exists
func dirExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func runService(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	var newSource string
	if source.Local {
		newSource = upload(source)
	}

	typ := ctx.String("type")
	image := ctx.String("image")
	command := strings.TrimSpace(ctx.String("command"))
	args := strings.TrimSpace(ctx.String("args"))

	// load the runtime
	r := runtimeFromContext(ctx)

	var retries = DefaultRetries
	if ctx.IsSet("retries") {
		retries = ctx.Int("retries")
	}

	// set the image if not specified
	if len(image) == 0 {
		formattedName := strings.ReplaceAll(source.Folder, "/", "-")
		// eg. docker.pkg.github.com/micro/services/users-api
		image = fmt.Sprintf("%v/%v", Image, formattedName)
	}

	// specify the options
	opts := []runtime.CreateOption{
		runtime.WithOutput(os.Stdout),
		runtime.WithRetries(retries),
		runtime.CreateImage(image),
		runtime.CreateType(typ),
	}

	// add environment variable passed in via cli
	var environment []string
	for _, evar := range ctx.StringSlice("env") {
		for _, e := range strings.Split(evar, ",") {
			if len(e) > 0 {
				environment = append(environment, strings.TrimSpace(e))
			}
		}
	}

	if len(environment) > 0 {
		opts = append(opts, runtime.WithEnv(environment))
	}

	if len(command) > 0 {
		opts = append(opts, runtime.WithCommand(strings.Split(command, " ")...))
	}

	if len(args) > 0 {
		opts = append(opts, runtime.WithArgs(strings.Split(args, " ")...))
	}

	runtimeSource := source.RuntimeSource()
	if source.Local {
		runtimeSource = newSource
	}
	// run the service
	service := &runtime.Service{
		Name:     source.RuntimeName(),
		Source:   runtimeSource,
		Version:  source.Ref,
		Metadata: make(map[string]string),
	}

	if err := r.Create(service, opts...); err != nil {
		fmt.Println(err)
		return
	}

	if r.String() == "local" {
		// we need to wait
		ch := make(chan os.Signal, 1)
		signal.Notify(ch, os.Interrupt)
		<-ch
		// delete the service
		r.Delete(service)
	}
}

func killService(ctx *cli.Context, srvOpts ...micro.Option) {
	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	service := &runtime.Service{
		Name:    source.RuntimeName(),
		Source:  source.RuntimeSource(),
		Version: source.Ref,
	}

	if err := runtimeFromContext(ctx).Delete(service); err != nil {
		fmt.Println(err)
		return
	}
}

func upload(source *git.Source) string {
	uploadedFileName := strings.ReplaceAll(source.Folder, string(filepath.Separator), "-") + ".tar.gz"
	path := filepath.Join(os.TempDir(), uploadedFileName)
	err := handler.Compress(source.FullPath, path)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	err = file.New("go.micro.server", client.DefaultClient).Upload(uploadedFileName, path)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	return uploadedFileName
}

func updateService(ctx *cli.Context, srvOpts ...micro.Option) {
	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	var newSource string
	if source.Local {
		newSource = upload(source)
	}

	runtimeSource := source.RuntimeSource()
	if source.Local {
		runtimeSource = newSource
	}
	service := &runtime.Service{
		Name:    source.RuntimeName(),
		Source:  runtimeSource,
		Version: source.Ref,
	}

	if err := runtimeFromContext(ctx).Update(service); err != nil {
		fmt.Println(err)
		return
	}
}

func getService(ctx *cli.Context, srvOpts ...micro.Option) {
	name := ""
	version := "latest"
	typ := ctx.String("type")
	r := runtimeFromContext(ctx)

	if ctx.Args().Len() > 0 {
		wd, err := os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		name = source.RuntimeName()
	}
	// set version as second arg
	if ctx.Args().Len() > 1 {
		version = ctx.Args().Get(1)
	}

	// should we list sevices
	var list bool

	// zero args so list all
	if ctx.Args().Len() == 0 {
		list = true
	}

	var services []*runtime.Service
	var readOpts []runtime.ReadOption

	// return a list of services
	switch list {
	case true:
		// return specific type listing
		if len(typ) > 0 {
			readOpts = append(readOpts, runtime.ReadType(typ))
		}
	// return one service
	default:
		// check if service name was passed in
		if len(name) == 0 {
			fmt.Println(GetUsage)
			return
		}

		// get service with name and version
		readOpts = []runtime.ReadOption{
			runtime.ReadService(name),
			runtime.ReadVersion(version),
		}

		// return the runtime services
		if len(typ) > 0 {
			readOpts = append(readOpts, runtime.ReadType(typ))
		}

	}

	// read the service
	services, err := r.Read(readOpts...)
	if err != nil {
		fmt.Println(err)
		return
	}

	// make sure we return UNKNOWN when empty string is supplied
	parse := func(m string) string {
		if len(m) == 0 {
			return "n/a"
		}
		return m
	}

	// don't do anything if there's no services
	if len(services) == 0 {
		return
	}

	sort.Slice(services, func(i, j int) bool { return services[i].Name < services[j].Name })

	writer := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
	fmt.Fprintln(writer, "NAME\tVERSION\tSOURCE\tSTATUS\tBUILD\tUPDATED\tMETADATA")
	for _, service := range services {
		status := parse(service.Metadata["status"])
		if status == "error" {
			status = service.Metadata["error"]
		}

		// cut the commit down to first 7 characters
		build := parse(service.Metadata["build"])
		if len(build) > 7 {
			build = build[:7]
		}

		// parse when the service was started
		updated := parse(timeAgo(service.Metadata["started"]))

		fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
			service.Name,
			parse(service.Version),
			parse(service.Source),
			strings.ToLower(status),
			build,
			updated,
			fmt.Sprintf("owner=%s,group=%s", parse(service.Metadata["owner"]), parse(service.Metadata["group"])))
	}
	writer.Flush()
}

const (
	// logUsage message for logs command
	logUsage = "Required usage: micro log example"
)

func getLogs(ctx *cli.Context, srvOpts ...micro.Option) {
	log.Init(log.WithFields(map[string]interface{}{"service": "runtime"}))
	if ctx.Args().Len() == 0 {
		fmt.Println("Service name is required")
		return
	}

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

	// must specify service name
	if len(name) == 0 {
		fmt.Println(logUsage)
		return
	}

	// get the args
	options := []runtime.LogsOption{}

	count := ctx.Int("lines")
	if count > 0 {
		options = append(options, runtime.LogsCount(int64(count)))
	} else {
		options = append(options, runtime.LogsCount(int64(15)))
	}

	follow := ctx.Bool("follow")

	if follow {
		options = append(options, runtime.LogsStream(follow))
	}

	r := runtimeFromContext(ctx)

	// @todo reintroduce since
	//since := ctx.String("since")
	//var readSince time.Time
	//d, err := time.ParseDuration(since)
	//if err == nil {
	//	readSince = time.Now().Add(-d)
	//}

	logs, err := r.Logs(&runtime.Service{Name: name}, options...)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	output := ctx.String("output")
	for {
		select {
		case record, ok := <-logs.Chan():
			if !ok {
				return
			}
			switch output {
			case "json":
				b, _ := json.Marshal(record)
				fmt.Printf("%v\n", string(b))
			default:
				fmt.Printf("%v\n", record.Message)

			}
		}
	}
}

// logFlags is shared flags so we don't have to continually re-add
func logFlags() []cli.Flag {
	return []cli.Flag{
		&cli.StringFlag{
			Name:  "version",
			Usage: "Set the version of the service to debug",
		},
		&cli.StringFlag{
			Name:    "output",
			Aliases: []string{"o"},
			Usage:   "Set the output format e.g json, text",
		},
		&cli.BoolFlag{
			Name:    "follow",
			Aliases: []string{"f"},
			Usage:   "Set to stream logs continuously (default: true)",
		},
		&cli.StringFlag{
			Name:  "since",
			Usage: "Set to the relative time from which to show the logs for e.g. 1h",
		},
		&cli.IntFlag{
			Name:    "lines",
			Aliases: []string{"n"},
			Usage:   "Set to query the last number of log events",
		},
	}
}
<commit_msg>Runtime CLI: use wrapped client (#869)<commit_after>// Package runtime is the micro runtime
package runtime

import (
	"encoding/json"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"sort"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/micro/cli/v2"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/config/cmd"
	log "github.com/micro/go-micro/v2/logger"
	"github.com/micro/go-micro/v2/runtime"
	"github.com/micro/go-micro/v2/runtime/local/git"
	srvRuntime "github.com/micro/go-micro/v2/runtime/service"
	"github.com/micro/go-micro/v2/util/file"
	cliutil "github.com/micro/micro/v2/cli/util"
	"github.com/micro/micro/v2/internal/client"
	"github.com/micro/micro/v2/runtime/handler"
)

const (
	// RunUsage message for the run command
	RunUsage = "Required usage: micro run [source]"
	// KillUsage message for the kill command
	KillUsage = "Require usage: micro kill [source]"
	// UpdateUsage message for the update command
	UpdateUsage = "Require usage: micro update [source]"
	// GetUsage message for micro get command
	GetUsage = "Require usage: micro status [service] [version]"
	// ServicesUsage message for micro services command
	ServicesUsage = "Require usage: micro services"
	// CannotWatch message for the run command
	CannotWatch = "Cannot watch filesystem on this runtime"
)

var (
	// DefaultRetries which should be attempted when starting a service
	DefaultRetries = 3
	// Image to specify if none is specified
	Image = "docker.pkg.github.com/micro/services"
	// Source where we get services from
	Source = "github.com/micro/services"
)

// timeAgo returns the time passed
func timeAgo(v string) string {
	if len(v) == 0 {
		return "unknown"
	}
	t, err := time.Parse(time.RFC3339, v)
	if err != nil {
		return v
	}
	return fmt.Sprintf("%v ago", time.Since(t).Truncate(time.Second))
}

func runtimeFromContext(ctx *cli.Context) runtime.Runtime {
	if cliutil.IsLocal() {
		return *cmd.DefaultCmd.Options().Runtime
	}
	return srvRuntime.NewRuntime(runtime.WithClient(client.New()))
}

// exists returns whether the given file or directory exists
func dirExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return true, err
}

func runService(ctx *cli.Context, srvOpts ...micro.Option) {
	// Init plugins
	for _, p := range Plugins() {
		p.Init(ctx)
	}

	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	var newSource string
	if source.Local {
		newSource = upload(source)
	}

	typ := ctx.String("type")
	image := ctx.String("image")
	command := strings.TrimSpace(ctx.String("command"))
	args := strings.TrimSpace(ctx.String("args"))

	// load the runtime
	r := runtimeFromContext(ctx)

	var retries = DefaultRetries
	if ctx.IsSet("retries") {
		retries = ctx.Int("retries")
	}

	// set the image if not specified
	if len(image) == 0 {
		formattedName := strings.ReplaceAll(source.Folder, "/", "-")
		// eg. docker.pkg.github.com/micro/services/users-api
		image = fmt.Sprintf("%v/%v", Image, formattedName)
	}

	// specify the options
	opts := []runtime.CreateOption{
		runtime.WithOutput(os.Stdout),
		runtime.WithRetries(retries),
		runtime.CreateImage(image),
		runtime.CreateType(typ),
	}

	// add environment variable passed in via cli
	var environment []string
	for _, evar := range ctx.StringSlice("env") {
		for _, e := range strings.Split(evar, ",") {
			if len(e) > 0 {
				environment = append(environment, strings.TrimSpace(e))
			}
		}
	}

	if len(environment) > 0 {
		opts = append(opts, runtime.WithEnv(environment))
	}

	if len(command) > 0 {
		opts = append(opts, runtime.WithCommand(strings.Split(command, " ")...))
	}

	if len(args) > 0 {
		opts = append(opts, runtime.WithArgs(strings.Split(args, " ")...))
	}

	runtimeSource := source.RuntimeSource()
	if source.Local {
		runtimeSource = newSource
	}
	// run the service
	service := &runtime.Service{
		Name:     source.RuntimeName(),
		Source:   runtimeSource,
		Version:  source.Ref,
		Metadata: make(map[string]string),
	}

	if err := r.Create(service, opts...); err != nil {
		fmt.Println(err)
		return
	}

	if r.String() == "local" {
		// we need to wait
		ch := make(chan os.Signal, 1)
		signal.Notify(ch, os.Interrupt)
		<-ch
		// delete the service
		r.Delete(service)
	}
}

func killService(ctx *cli.Context, srvOpts ...micro.Option) {
	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	service := &runtime.Service{
		Name:    source.RuntimeName(),
		Source:  source.RuntimeSource(),
		Version: source.Ref,
	}

	if err := runtimeFromContext(ctx).Delete(service); err != nil {
		fmt.Println(err)
		return
	}
}

func upload(source *git.Source) string {
	uploadedFileName := strings.ReplaceAll(source.Folder, string(filepath.Separator), "-") + ".tar.gz"
	path := filepath.Join(os.TempDir(), uploadedFileName)
	err := handler.Compress(source.FullPath, path)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	err = file.New("go.micro.server", client.New()).Upload(uploadedFileName, path)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	return uploadedFileName
}

func updateService(ctx *cli.Context, srvOpts ...micro.Option) {
	// we need some args to run
	if ctx.Args().Len() == 0 {
		fmt.Println(RunUsage)
		return
	}

	wd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	var newSource string
	if source.Local {
		newSource = upload(source)
	}

	runtimeSource := source.RuntimeSource()
	if source.Local {
		runtimeSource = newSource
	}
	service := &runtime.Service{
		Name:    source.RuntimeName(),
		Source:  runtimeSource,
		Version: source.Ref,
	}

	if err := runtimeFromContext(ctx).Update(service); err != nil {
		fmt.Println(err)
		return
	}
}

func getService(ctx *cli.Context, srvOpts ...micro.Option) {
	name := ""
	version := "latest"
	typ := ctx.String("type")
	r := runtimeFromContext(ctx)

	if ctx.Args().Len() > 0 {
		wd, err := os.Getwd()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		source, err := git.ParseSourceLocal(wd, ctx.Args().Get(0))
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		name = source.RuntimeName()
	}
	// set version as second arg
	if ctx.Args().Len() > 1 {
		version = ctx.Args().Get(1)
	}

	// should we list sevices
	var list bool

	// zero args so list all
	if ctx.Args().Len() == 0 {
		list = true
	}

	var services []*runtime.Service
	var readOpts []runtime.ReadOption

	// return a list of services
	switch list {
	case true:
		// return specific type listing
		if len(typ) > 0 {
			readOpts = append(readOpts, runtime.ReadType(typ))
		}
	// return one service
	default:
		// check if service name was passed in
		if len(name) == 0 {
			fmt.Println(GetUsage)
			return
		}

		// get service with name and version
		readOpts = []runtime.ReadOption{
			runtime.ReadService(name),
			runtime.ReadVersion(version),
		}

		// return the runtime services
		if len(typ) > 0 {
			readOpts = append(readOpts, runtime.ReadType(typ))
		}

	}

	// read the service
	services, err := r.Read(readOpts...)
	if err != nil {
		fmt.Println(err)
		return
	}

	// make sure we return UNKNOWN when empty string is supplied
	parse := func(m string) string {
		if len(m) == 0 {
			return "n/a"
		}
		return m
	}

	// don't do anything if there's no services
	if len(services) == 0 {
		return
	}

	sort.Slice(services, func(i, j int) bool { return services[i].Name < services[j].Name })

	writer := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
	fmt.Fprintln(writer, "NAME\tVERSION\tSOURCE\tSTATUS\tBUILD\tUPDATED\tMETADATA")
	for _, service := range services {
		status := parse(service.Metadata["status"])
		if status == "error" {
			status = service.Metadata["error"]
		}

		// cut the commit down to first 7 characters
		build := parse(service.Metadata["build"])
		if len(build) > 7 {
			build = build[:7]
		}

		// parse when the service was started
		updated := parse(timeAgo(service.Metadata["started"]))

		fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
			service.Name,
			parse(service.Version),
			parse(service.Source),
			strings.ToLower(status),
			build,
			updated,
			fmt.Sprintf("owner=%s,group=%s", parse(service.Metadata["owner"]), parse(service.Metadata["group"])))
	}
	writer.Flush()
}

const (
	// logUsage message for logs command
	logUsage = "Required usage: micro log example"
)

func getLogs(ctx *cli.Context, srvOpts ...micro.Option) {
	log.Init(log.WithFields(map[string]interface{}{"service": "runtime"}))
	if ctx.Args().Len() == 0 {
		fmt.Println("Service name is required")
		return
	}

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

	// must specify service name
	if len(name) == 0 {
		fmt.Println(logUsage)
		return
	}

	// get the args
	options := []runtime.LogsOption{}

	count := ctx.Int("lines")
	if count > 0 {
		options = append(options, runtime.LogsCount(int64(count)))
	} else {
		options = append(options, runtime.LogsCount(int64(15)))
	}

	follow := ctx.Bool("follow")

	if follow {
		options = append(options, runtime.LogsStream(follow))
	}

	r := runtimeFromContext(ctx)

	// @todo reintroduce since
	//since := ctx.String("since")
	//var readSince time.Time
	//d, err := time.ParseDuration(since)
	//if err == nil {
	//	readSince = time.Now().Add(-d)
	//}

	logs, err := r.Logs(&runtime.Service{Name: name}, options...)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	output := ctx.String("output")
	for {
		select {
		case record, ok := <-logs.Chan():
			if !ok {
				return
			}
			switch output {
			case "json":
				b, _ := json.Marshal(record)
				fmt.Printf("%v\n", string(b))
			default:
				fmt.Printf("%v\n", record.Message)

			}
		}
	}
}

// logFlags is shared flags so we don't have to continually re-add
func logFlags() []cli.Flag {
	return []cli.Flag{
		&cli.StringFlag{
			Name:  "version",
			Usage: "Set the version of the service to debug",
		},
		&cli.StringFlag{
			Name:    "output",
			Aliases: []string{"o"},
			Usage:   "Set the output format e.g json, text",
		},
		&cli.BoolFlag{
			Name:    "follow",
			Aliases: []string{"f"},
			Usage:   "Set to stream logs continuously (default: true)",
		},
		&cli.StringFlag{
			Name:  "since",
			Usage: "Set to the relative time from which to show the logs for e.g. 1h",
		},
		&cli.IntFlag{
			Name:    "lines",
			Aliases: []string{"n"},
			Usage:   "Set to query the last number of log events",
		},
	}
}
<|endoftext|>


<commit_before>package runtime

// Version is the current version of the buffalo binary
var Version = "development"
<commit_msg>Update version.go<commit_after>package runtime

// Version is the current version of the buffalo binary
var Version = "v0.15.3"
<|endoftext|>


<commit_before>package runtime

import (
	"fmt"
	"reflect"

	"github.com/cloudson/gitql/parser"
	"github.com/cloudson/gitql/utilities"
)

func (v *RuntimeVisitor) Visit(n *parser.NodeProgram) error {
	return v.VisitSelect(n.Child.(*parser.NodeSelect))
}

func (v *RuntimeVisitor) VisitSelect(n *parser.NodeSelect) error {
	if builder.isProxyTable(n.Tables[0]) {
		proxyTableName := n.Tables[0]
		// refactor tree
		proxy := builder.proxyTables[proxyTableName]
		if !n.WildCard {
			err := testAllFieldsFromTable(n.Fields, proxyTableName)
			if err != nil {
				return err
			}

		} else {
			n.Fields = builder.possibleTables[proxyTableName]
			n.WildCard = false
		}

		err := testAllFieldsInExpr(n.Where, proxyTableName)
		if err != nil {
			return err
		}

		n.Tables[0] = proxy.table
		var from, to string
		for from, to = range proxy.fields {
			break
		}

		oldWhere := n.Where
		where := new(parser.NodeAnd)
		condition := new(parser.NodeEqual)
		conditionL := new(parser.NodeId)
		conditionL.SetValue(from)
		conditionR := new(parser.NodeLiteral)
		conditionR.SetValue(to)
		condition.SetLeftValue(conditionL)
		condition.SetRightValue(conditionR)

		where.SetLeftValue(condition)
		where.SetRightValue(oldWhere)

		n.Where = where
	}

	table := n.Tables[0]

	var err error
	err = builder.WithTable(table, table)
	if err != nil {
		return err
	}
	return testAllFieldsFromTable(n.Fields, table)
	// Why not visit expression right now ?
	// Because we will, at first, discover the current object
}

func testAllFieldsInExpr(expr parser.NodeExpr, tableName string) error {
	var err error
	if expr != nil {
		switch expr.(type) {
		case *parser.NodeAnd, *parser.NodeOr:
			err = testAllFieldsInExpr(expr.LeftValue(), tableName)
			if err == nil {
				return testAllFieldsInExpr(expr.RightValue(), tableName)
			}
		case *parser.NodeEqual, *parser.NodeGreater, *parser.NodeSmaller, *parser.NodeIn:
			return testAllFieldsInExpr(expr.LeftValue(), tableName)
		case *parser.NodeId:
			field := expr.(*parser.NodeId).Value()
			if !utilities.IsFieldPresentInArray(builder.possibleTables[tableName], field) {
				return fmt.Errorf("Table '%s' has not field '%s'", tableName, field)
			}
		}
	}
	return err
}
func testAllFieldsFromTable(fields []string, table string) error {
	for _, f := range fields {
		err := builder.UseFieldFromTable(f, table)
		if err != nil {
			return err
		}
	}

	return nil
}

func (v *RuntimeVisitor) VisitExpr(n parser.NodeExpr) error {
	switch reflect.TypeOf(n) {
	case reflect.TypeOf(new(parser.NodeEqual)):
		g := n.(*parser.NodeEqual)
		return v.VisitEqual(g)
	case reflect.TypeOf(new(parser.NodeGreater)):
		g := n.(*parser.NodeGreater)
		return v.VisitGreater(g)
	case reflect.TypeOf(new(parser.NodeSmaller)):
		g := n.(*parser.NodeSmaller)
		return v.VisitSmaller(g)
	case reflect.TypeOf(new(parser.NodeOr)):
		g := n.(*parser.NodeOr)
		return v.VisitOr(g)
	case reflect.TypeOf(new(parser.NodeAnd)):
		g := n.(*parser.NodeAnd)
		return v.VisitAnd(g)
	case reflect.TypeOf(new(parser.NodeIn)):
		g := n.(*parser.NodeIn)
		return v.VisitIn(g)

	}

	return nil
}

func (v *RuntimeVisitor) VisitEqual(n *parser.NodeEqual) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()
	boolRegister = n.Assertion(metadata(lvalue), rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitGreater(n *parser.NodeGreater) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	lvalue = metadata(lvalue)
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()

	boolRegister = n.Assertion(lvalue, rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitSmaller(n *parser.NodeSmaller) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	lvalue = metadata(lvalue)
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()

	boolRegister = n.Assertion(lvalue, rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitOr(n *parser.NodeOr) error {
	v.VisitExpr(n.LeftValue())
	boolLeft := boolRegister
	v.VisitExpr(n.RightValue())
	boolRight := boolRegister

	boolRegister = boolLeft || boolRight
	return nil
}

func (v *RuntimeVisitor) VisitAnd(n *parser.NodeAnd) error {
	v.VisitExpr(n.LeftValue())
	boolLeft := boolRegister
	v.VisitExpr(n.RightValue())
	boolRight := boolRegister

	boolRegister = boolLeft && boolRight
	return nil
}

func (v *RuntimeVisitor) VisitIn(n *parser.NodeIn) error {
	lvalue := n.LeftValue().(*parser.NodeLiteral).Value()
	rvalue := n.RightValue().(*parser.NodeId).Value()
	boolRegister = n.Assertion(lvalue, metadata(rvalue))

	return nil
}

func (v *RuntimeVisitor) Builder() *GitBuilder {
	return nil
}
<commit_msg>Add not equal for where fields validation<commit_after>package runtime

import (
	"fmt"
	"reflect"

	"github.com/cloudson/gitql/parser"
	"github.com/cloudson/gitql/utilities"
)

func (v *RuntimeVisitor) Visit(n *parser.NodeProgram) error {
	return v.VisitSelect(n.Child.(*parser.NodeSelect))
}

func (v *RuntimeVisitor) VisitSelect(n *parser.NodeSelect) error {
	if builder.isProxyTable(n.Tables[0]) {
		proxyTableName := n.Tables[0]
		// refactor tree
		proxy := builder.proxyTables[proxyTableName]
		if !n.WildCard {
			err := testAllFieldsFromTable(n.Fields, proxyTableName)
			if err != nil {
				return err
			}

		} else {
			n.Fields = builder.possibleTables[proxyTableName]
			n.WildCard = false
		}

		err := testAllFieldsInExpr(n.Where, proxyTableName)
		if err != nil {
			return err
		}

		n.Tables[0] = proxy.table
		var from, to string
		for from, to = range proxy.fields {
			break
		}

		oldWhere := n.Where
		where := new(parser.NodeAnd)
		condition := new(parser.NodeEqual)
		conditionL := new(parser.NodeId)
		conditionL.SetValue(from)
		conditionR := new(parser.NodeLiteral)
		conditionR.SetValue(to)
		condition.SetLeftValue(conditionL)
		condition.SetRightValue(conditionR)

		where.SetLeftValue(condition)
		where.SetRightValue(oldWhere)

		n.Where = where
	}

	table := n.Tables[0]

	var err error
	err = builder.WithTable(table, table)
	if err != nil {
		return err
	}
	return testAllFieldsFromTable(n.Fields, table)
	// Why not visit expression right now ?
	// Because we will, at first, discover the current object
}

func testAllFieldsInExpr(expr parser.NodeExpr, tableName string) error {
	var err error
	if expr != nil {
		switch expr.(type) {
		case *parser.NodeAnd, *parser.NodeOr:
			err = testAllFieldsInExpr(expr.LeftValue(), tableName)
			if err == nil {
				return testAllFieldsInExpr(expr.RightValue(), tableName)
			}
		case *parser.NodeEqual, *parser.NodeNotEqual, *parser.NodeGreater, *parser.NodeSmaller, *parser.NodeIn:
			return testAllFieldsInExpr(expr.LeftValue(), tableName)
		case *parser.NodeId:
			field := expr.(*parser.NodeId).Value()
			if !utilities.IsFieldPresentInArray(builder.possibleTables[tableName], field) {
				return fmt.Errorf("Table '%s' has not field '%s'", tableName, field)
			}
		}
	}
	return err
}
func testAllFieldsFromTable(fields []string, table string) error {
	for _, f := range fields {
		err := builder.UseFieldFromTable(f, table)
		if err != nil {
			return err
		}
	}

	return nil
}

func (v *RuntimeVisitor) VisitExpr(n parser.NodeExpr) error {
	switch reflect.TypeOf(n) {
	case reflect.TypeOf(new(parser.NodeEqual)):
		g := n.(*parser.NodeEqual)
		return v.VisitEqual(g)
	case reflect.TypeOf(new(parser.NodeGreater)):
		g := n.(*parser.NodeGreater)
		return v.VisitGreater(g)
	case reflect.TypeOf(new(parser.NodeSmaller)):
		g := n.(*parser.NodeSmaller)
		return v.VisitSmaller(g)
	case reflect.TypeOf(new(parser.NodeOr)):
		g := n.(*parser.NodeOr)
		return v.VisitOr(g)
	case reflect.TypeOf(new(parser.NodeAnd)):
		g := n.(*parser.NodeAnd)
		return v.VisitAnd(g)
	case reflect.TypeOf(new(parser.NodeIn)):
		g := n.(*parser.NodeIn)
		return v.VisitIn(g)

	}

	return nil
}

func (v *RuntimeVisitor) VisitEqual(n *parser.NodeEqual) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()
	boolRegister = n.Assertion(metadata(lvalue), rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitGreater(n *parser.NodeGreater) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	lvalue = metadata(lvalue)
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()

	boolRegister = n.Assertion(lvalue, rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitSmaller(n *parser.NodeSmaller) error {
	lvalue := n.LeftValue().(*parser.NodeId).Value()
	lvalue = metadata(lvalue)
	rvalue := n.RightValue().(*parser.NodeLiteral).Value()

	boolRegister = n.Assertion(lvalue, rvalue)

	return nil
}

func (v *RuntimeVisitor) VisitOr(n *parser.NodeOr) error {
	v.VisitExpr(n.LeftValue())
	boolLeft := boolRegister
	v.VisitExpr(n.RightValue())
	boolRight := boolRegister

	boolRegister = boolLeft || boolRight
	return nil
}

func (v *RuntimeVisitor) VisitAnd(n *parser.NodeAnd) error {
	v.VisitExpr(n.LeftValue())
	boolLeft := boolRegister
	v.VisitExpr(n.RightValue())
	boolRight := boolRegister

	boolRegister = boolLeft && boolRight
	return nil
}

func (v *RuntimeVisitor) VisitIn(n *parser.NodeIn) error {
	lvalue := n.LeftValue().(*parser.NodeLiteral).Value()
	rvalue := n.RightValue().(*parser.NodeId).Value()
	boolRegister = n.Assertion(lvalue, metadata(rvalue))

	return nil
}

func (v *RuntimeVisitor) Builder() *GitBuilder {
	return nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package web

// FormErrors represent structure errors returned by API server to
// request based on HTML form data.
type FormErrors struct {
	Errors      []string            `json:"errors,omitempty"`
	FieldErrors map[string][]string `json:"field-errors,omitempty"`
}

// AddError appends an error to a list of general errors.
func (f *FormErrors) AddError(e string) {
	f.Errors = append(f.Errors, e)
}

// AddFieldError appends an error to a list of field specific errors.
func (f *FormErrors) AddFieldError(field, e string) {
	if f.FieldErrors == nil {
		f.FieldErrors = map[string][]string{}
	}
	if _, ok := f.FieldErrors[field]; !ok {
		f.FieldErrors[field] = []string{}
	}
	f.FieldErrors[field] = append(f.FieldErrors[field], e)
}

// HasErrors returns weather FormErrors instance contains at leas one error.
func (f FormErrors) HasErrors() bool {
	if len(f.Errors) > 0 {
		return true
	}
	for _, v := range f.FieldErrors {
		if len(v) > 0 {
			return true
		}
	}
	return false
}

// NewError initializes FormErrors with one general error.
func NewError(e string) FormErrors {
	errors := FormErrors{}
	errors.AddError(e)
	return errors
}

// NewFieldError initializes FormErrors with one field error.
func NewFieldError(field, e string) FormErrors {
	errors := FormErrors{}
	errors.AddFieldError(field, e)
	return errors
}
<commit_msg>Snake case for FormErrors FieldErrors field<commit_after>// Copyright (c) 2016, Janoš Guljaš <janos@resenje.org>
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package web

// FormErrors represent structure errors returned by API server to
// request based on HTML form data.
type FormErrors struct {
	Errors      []string            `json:"errors,omitempty"`
	FieldErrors map[string][]string `json:"field_errors,omitempty"`
}

// AddError appends an error to a list of general errors.
func (f *FormErrors) AddError(e string) {
	f.Errors = append(f.Errors, e)
}

// AddFieldError appends an error to a list of field specific errors.
func (f *FormErrors) AddFieldError(field, e string) {
	if f.FieldErrors == nil {
		f.FieldErrors = map[string][]string{}
	}
	if _, ok := f.FieldErrors[field]; !ok {
		f.FieldErrors[field] = []string{}
	}
	f.FieldErrors[field] = append(f.FieldErrors[field], e)
}

// HasErrors returns weather FormErrors instance contains at leas one error.
func (f FormErrors) HasErrors() bool {
	if len(f.Errors) > 0 {
		return true
	}
	for _, v := range f.FieldErrors {
		if len(v) > 0 {
			return true
		}
	}
	return false
}

// NewError initializes FormErrors with one general error.
func NewError(e string) FormErrors {
	errors := FormErrors{}
	errors.AddError(e)
	return errors
}

// NewFieldError initializes FormErrors with one field error.
func NewFieldError(field, e string) FormErrors {
	errors := FormErrors{}
	errors.AddFieldError(field, e)
	return errors
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"syscall"

	"github.com/hanwen/go-fuse/fuse"

	"github.com/rfjakob/gocryptfs/internal/exitcodes"
	"github.com/rfjakob/gocryptfs/internal/fusefrontend"
	"github.com/rfjakob/gocryptfs/internal/tlog"
)

type fsckObj struct {
	fs *fusefrontend.FS
	// List of corrupt files
	corruptList []string
	// Protects corruptList
	corruptListLock sync.Mutex
}

func (ck *fsckObj) markCorrupt(path string) {
	ck.corruptListLock.Lock()
	ck.corruptList = append(ck.corruptList, path)
	ck.corruptListLock.Unlock()
}

// Recursively check dir for corruption
func (ck *fsckObj) dir(path string) {
	//fmt.Printf("ck.dir %q\n", path)
	ck.xattrs(path)
	done := make(chan struct{})
	go func() {
		for {
			select {
			case item := <-ck.fs.MitigatedCorruptions:
				fmt.Printf("fsck: corrupt entry in dir %q: %q\n", path, item)
				ck.markCorrupt(filepath.Join(path, item))
			case <-done:
				return
			}
		}
	}()
	entries, status := ck.fs.OpenDir(path, nil)
	done <- struct{}{}
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error opening dir %q: %v\n", path, status)
		return
	}
	// Sort alphabetically
	sort.Sort(sortableDirEntries(entries))
	for _, entry := range entries {
		if entry.Name == "." || entry.Name == ".." {
			continue
		}
		nextPath := filepath.Join(path, entry.Name)
		filetype := entry.Mode & syscall.S_IFMT
		//fmt.Printf("  %q %x\n", entry.Name, entry.Mode)
		switch filetype {
		case syscall.S_IFDIR:
			ck.dir(nextPath)
		case syscall.S_IFREG:
			ck.file(nextPath)
		case syscall.S_IFLNK:
			ck.symlink(nextPath)
		case syscall.S_IFIFO, syscall.S_IFSOCK, syscall.S_IFBLK, syscall.S_IFCHR:
			// nothing to check
		default:
			fmt.Printf("fsck: unhandled file type %x\n", filetype)
		}
	}
}

func (ck *fsckObj) symlink(path string) {
	_, status := ck.fs.Readlink(path, nil)
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error reading symlink %q: %v\n", path, status)
	}
}

// check file for corruption
func (ck *fsckObj) file(path string) {
	//fmt.Printf("ck.file %q\n", path)
	ck.xattrs(path)
	f, status := ck.fs.Open(path, syscall.O_RDONLY, nil)
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error opening file %q: %v\n", path, status)
		return
	}
	defer f.Release()
	buf := make([]byte, fuse.MAX_KERNEL_WRITE)
	var off int64
	done := make(chan struct{})
	go func() {
		for {
			select {
			case item := <-ck.fs.MitigatedCorruptions:
				fmt.Printf("fsck: corrupt file %q (inode %s)\n", path, item)
				ck.markCorrupt(path)
			case <-done:
				return
			}
		}
	}()
	defer func() { done <- struct{}{} }()
	for {
		result, status := f.Read(buf, off)
		if !status.Ok() {
			ck.markCorrupt(path)
			fmt.Printf("fsck: error reading file %q at offset %d: %v\n", path, off, status)
			return
		}
		// EOF
		if result.Size() == 0 {
			return
		}
		off += int64(result.Size())
	}
}

// Check xattrs on file/dir at path
func (ck *fsckObj) xattrs(path string) {
	done := make(chan struct{})
	go func() {
		for {
			select {
			case item := <-ck.fs.MitigatedCorruptions:
				fmt.Printf("fsck: corrupt xattr name on file %q: %q\n", path, item)
				ck.markCorrupt(path + " xattr:" + item)
			case <-done:
				return
			}
		}
	}()
	attrs, status := ck.fs.ListXAttr(path, nil)
	done <- struct{}{}
	if !status.Ok() {
		fmt.Printf("fsck: error listing xattrs on %q: %v\n", path, status)
		ck.markCorrupt(path)
		return
	}
	for _, a := range attrs {
		_, status := ck.fs.GetXAttr(path, a, nil)
		if !status.Ok() {
			fmt.Printf("fsck: error reading xattr %q from %q: %v\n", a, path, status)
			ck.markCorrupt(path)
		}
	}
}

func fsck(args *argContainer) {
	if args.reverse {
		tlog.Fatal.Printf("Running -fsck with -reverse is not supported")
		os.Exit(exitcodes.Usage)
	}
	args.allow_other = false
	pfs, wipeKeys := initFuseFrontend(args)
	fs := pfs.(*fusefrontend.FS)
	fs.MitigatedCorruptions = make(chan string)
	ck := fsckObj{
		fs: fs,
	}
	ck.dir("")
	wipeKeys()
	if len(ck.corruptList) == 0 {
		tlog.Info.Printf("fsck summary: no problems found\n")
		return
	}
	fmt.Printf("fsck summary: %d corrupt files\n", len(ck.corruptList))
	os.Exit(exitcodes.FsckErrors)
}

type sortableDirEntries []fuse.DirEntry

func (s sortableDirEntries) Len() int {
	return len(s)
}

func (s sortableDirEntries) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s sortableDirEntries) Less(i, j int) bool {
	return strings.Compare(s[i].Name, s[j].Name) < 0
}
<commit_msg>fsck: get rid of channel read closures<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"syscall"

	"github.com/hanwen/go-fuse/fuse"

	"github.com/rfjakob/gocryptfs/internal/exitcodes"
	"github.com/rfjakob/gocryptfs/internal/fusefrontend"
	"github.com/rfjakob/gocryptfs/internal/tlog"
)

type fsckObj struct {
	fs *fusefrontend.FS
	// List of corrupt files
	corruptList []string
	// Protects corruptList
	corruptListLock sync.Mutex
	// stop a running watchMitigatedCorruptions thread
	watchDone chan struct{}
}

func (ck *fsckObj) markCorrupt(path string) {
	ck.corruptListLock.Lock()
	ck.corruptList = append(ck.corruptList, path)
	ck.corruptListLock.Unlock()
}

// Watch for mitigated corruptions that occour during OpenDir()
func (ck *fsckObj) watchMitigatedCorruptionsOpenDir(path string) {
	for {
		select {
		case item := <-ck.fs.MitigatedCorruptions:
			fmt.Printf("fsck: corrupt entry in dir %q: %q\n", path, item)
			ck.markCorrupt(filepath.Join(path, item))
		case <-ck.watchDone:
			return
		}
	}
}

// Recursively check dir for corruption
func (ck *fsckObj) dir(path string) {
	//fmt.Printf("ck.dir %q\n", path)
	ck.xattrs(path)
	// Run OpenDir and catch transparently mitigated corruptions
	go ck.watchMitigatedCorruptionsOpenDir(path)
	entries, status := ck.fs.OpenDir(path, nil)
	ck.watchDone <- struct{}{}
	// Also catch non-mitigated corruptions
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error opening dir %q: %v\n", path, status)
		return
	}
	// Sort alphabetically
	sort.Sort(sortableDirEntries(entries))
	for _, entry := range entries {
		if entry.Name == "." || entry.Name == ".." {
			continue
		}
		nextPath := filepath.Join(path, entry.Name)
		filetype := entry.Mode & syscall.S_IFMT
		//fmt.Printf("  %q %x\n", entry.Name, entry.Mode)
		switch filetype {
		case syscall.S_IFDIR:
			ck.dir(nextPath)
		case syscall.S_IFREG:
			ck.file(nextPath)
		case syscall.S_IFLNK:
			ck.symlink(nextPath)
		case syscall.S_IFIFO, syscall.S_IFSOCK, syscall.S_IFBLK, syscall.S_IFCHR:
			// nothing to check
		default:
			fmt.Printf("fsck: unhandled file type %x\n", filetype)
		}
	}
}

func (ck *fsckObj) symlink(path string) {
	_, status := ck.fs.Readlink(path, nil)
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error reading symlink %q: %v\n", path, status)
	}
}

// Watch for mitigated corruptions that occour during Read()
func (ck *fsckObj) watchMitigatedCorruptionsRead(path string) {
	for {
		select {
		case item := <-ck.fs.MitigatedCorruptions:
			fmt.Printf("fsck: corrupt file %q (inode %s)\n", path, item)
			ck.markCorrupt(path)
		case <-ck.watchDone:
			return
		}
	}
}

// Check file for corruption
func (ck *fsckObj) file(path string) {
	//fmt.Printf("ck.file %q\n", path)
	ck.xattrs(path)
	f, status := ck.fs.Open(path, syscall.O_RDONLY, nil)
	if !status.Ok() {
		ck.markCorrupt(path)
		fmt.Printf("fsck: error opening file %q: %v\n", path, status)
		return
	}
	defer f.Release()
	buf := make([]byte, fuse.MAX_KERNEL_WRITE)
	var off int64
	// Read() through the whole file and catch transparently mitigated corruptions
	go ck.watchMitigatedCorruptionsRead(path)
	defer func() { ck.watchDone <- struct{}{} }()
	for {
		result, status := f.Read(buf, off)
		if !status.Ok() {
			ck.markCorrupt(path)
			fmt.Printf("fsck: error reading file %q at offset %d: %v\n", path, off, status)
			return
		}
		// EOF
		if result.Size() == 0 {
			return
		}
		off += int64(result.Size())
	}
}

// Watch for mitigated corruptions that occour during ListXAttr()
func (ck *fsckObj) watchMitigatedCorruptionsListXAttr(path string) {
	for {
		select {
		case item := <-ck.fs.MitigatedCorruptions:
			fmt.Printf("fsck: corrupt xattr name on file %q: %q\n", path, item)
			ck.markCorrupt(path + " xattr:" + item)
		case <-ck.watchDone:
			return
		}
	}
}

// Check xattrs on file/dir at path
func (ck *fsckObj) xattrs(path string) {
	// Run ListXAttr() and catch transparently mitigated corruptions
	go ck.watchMitigatedCorruptionsListXAttr(path)
	attrs, status := ck.fs.ListXAttr(path, nil)
	ck.watchDone <- struct{}{}
	// Also catch non-mitigated corruptions
	if !status.Ok() {
		fmt.Printf("fsck: error listing xattrs on %q: %v\n", path, status)
		ck.markCorrupt(path)
		return
	}
	for _, a := range attrs {
		_, status := ck.fs.GetXAttr(path, a, nil)
		if !status.Ok() {
			fmt.Printf("fsck: error reading xattr %q from %q: %v\n", a, path, status)
			ck.markCorrupt(path)
		}
	}
}

func fsck(args *argContainer) {
	if args.reverse {
		tlog.Fatal.Printf("Running -fsck with -reverse is not supported")
		os.Exit(exitcodes.Usage)
	}
	args.allow_other = false
	pfs, wipeKeys := initFuseFrontend(args)
	fs := pfs.(*fusefrontend.FS)
	fs.MitigatedCorruptions = make(chan string)
	ck := fsckObj{
		fs:        fs,
		watchDone: make(chan struct{}),
	}
	ck.dir("")
	wipeKeys()
	if len(ck.corruptList) == 0 {
		tlog.Info.Printf("fsck summary: no problems found\n")
		return
	}
	fmt.Printf("fsck summary: %d corrupt files\n", len(ck.corruptList))
	os.Exit(exitcodes.FsckErrors)
}

type sortableDirEntries []fuse.DirEntry

func (s sortableDirEntries) Len() int {
	return len(s)
}

func (s sortableDirEntries) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s sortableDirEntries) Less(i, j int) bool {
	return strings.Compare(s[i].Name, s[j].Name) < 0
}
<|endoftext|>


<commit_before>package minion

var ClassifierRegistry []MinionClassifier

// Interface for classifying minion
type MinionClassifier interface {
	// Gets the key of a classifier
	GetKey() (string, error)

	// Gets the description of a classifier
	GetDescription() (string, error)

	// Classifies a minion returning the classifier value
	GetValue(m Minion) (string, error)
}

// Register new classifiers
func RegisterClassifier(c ...MinionClassifier) error {
	ClassifierRegistry = append(ClassifierRegistry, c...)

	return nil
}

// Simple classifier
type SimpleClassifier struct {
	Key, Value, Description string
}

// Creates a new simple classifier
func NewSimpleClassifier(key, value, description string) MinionClassifier {
	c := &SimpleClassifier{
		Key: key,
		Value: value,
		Description: description,
	}

	return c
}

func (c *SimpleClassifier) GetKey() (string, error) {
	return c.Key, nil
}

func (c *SimpleClassifier) GetDescription() (string, error) {
	return c.Description, nil
}

func (c *SimpleClassifier) GetValue(m Minion) (string, error) {
	return c.Value, nil
}

// Classifier that uses callbacks for classifying minions
type cbClassifier func(Minion) (string, error)
type CallbackClassifier struct {
	Key, Description string

	// Callback used to classify the minions
	Callback cbClassifier
}

func NewCallbackClassifier(key, description string, callback cbClassifier) MinionClassifier {
	c := &CallbackClassifier{
		Key:         key,
		Description: description,
		Callback:    callback,
	}

	return c
}

func (c *CallbackClassifier) GetKey() (string, error) {
	return c.Key, nil
}

func (c *CallbackClassifier) GetDescription() (string, error) {
	return c.Description, nil
}

func (c *CallbackClassifier) GetValue(m Minion) (string, error) {
	value, err := c.Callback(m)

	return value, err
}
<commit_msg>Comments update<commit_after>package minion

// Global classifier registry
// Each classifier that is registered in the
// registry is called by the minions in order to
// classify themselves
var ClassifierRegistry []MinionClassifier

// Interface for classifying minion
type MinionClassifier interface {
	// Gets the key of a classifier
	GetKey() (string, error)

	// Gets the description of a classifier
	GetDescription() (string, error)

	// Classifies a minion returning the classifier value
	GetValue(m Minion) (string, error)
}

// Register new classifiers
func RegisterClassifier(c ...MinionClassifier) error {
	ClassifierRegistry = append(ClassifierRegistry, c...)

	return nil
}

// Simple classifier
type SimpleClassifier struct {
	Key, Value, Description string
}

// Creates a new simple classifier
func NewSimpleClassifier(key, value, description string) MinionClassifier {
	c := &SimpleClassifier{
		Key: key,
		Value: value,
		Description: description,
	}

	return c
}

func (c *SimpleClassifier) GetKey() (string, error) {
	return c.Key, nil
}

func (c *SimpleClassifier) GetDescription() (string, error) {
	return c.Description, nil
}

func (c *SimpleClassifier) GetValue(m Minion) (string, error) {
	return c.Value, nil
}

// Classifier that uses callbacks for classifying minions
type cbClassifier func(Minion) (string, error)
type CallbackClassifier struct {
	Key, Description string

	// Callback used to classify the minions
	Callback cbClassifier
}

func NewCallbackClassifier(key, description string, callback cbClassifier) MinionClassifier {
	c := &CallbackClassifier{
		Key:         key,
		Description: description,
		Callback:    callback,
	}

	return c
}

func (c *CallbackClassifier) GetKey() (string, error) {
	return c.Key, nil
}

func (c *CallbackClassifier) GetDescription() (string, error) {
	return c.Description, nil
}

func (c *CallbackClassifier) GetValue(m Minion) (string, error) {
	value, err := c.Callback(m)

	return value, err
}
<|endoftext|>


<commit_before>package redis

import (
	"bytes"
	"encoding/gob"
	"reflect"
	"time"

	"cloud.google.com/go/datastore"
	"github.com/acoshift/ds"
	"github.com/garyburd/redigo/redis"
)

// Cache implement Cache interface
type Cache struct {
	Pool      *redis.Pool
	Prefix    string
	TTL       time.Duration
	ExtendTTL bool
	Skip      func(*datastore.Key) bool
}

func encode(v interface{}) ([]byte, error) {
	w := &bytes.Buffer{}
	err := gob.NewEncoder(w).Encode(v)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func decode(b []byte, v interface{}) error {
	return gob.NewDecoder(bytes.NewReader(b)).Decode(v)
}

// Get gets data
func (cache *Cache) Get(key *datastore.Key, dst interface{}) error {
	if cache.Skip != nil && cache.Skip(key) {
		return ds.ErrCacheNotFound
	}

	db := cache.Pool.Get()
	defer db.Close()
	k := cache.Prefix + key.String()
	b, err := redis.Bytes(db.Do("GET", k))
	if err != nil {
		return err
	}
	if len(b) == 0 {
		return ds.ErrCacheNotFound
	}
	if cache.ExtendTTL {
		db.Do("EXPIRE", k, int(cache.TTL/time.Second))
	}
	return decode(b, dst)
}

// GetMulti gets multi data
func (cache *Cache) GetMulti(keys []*datastore.Key, dst interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	for _, key := range keys {
		db.Send("GET", cache.Prefix+key.String())
	}
	err := db.Flush()
	if err != nil {
		return err
	}
	for i := range keys {
		b, err := redis.Bytes(db.Receive())
		if err != nil {
			return err
		}
		if len(b) > 0 {
			decode(b, reflect.Indirect(reflect.ValueOf(dst)).Index(i).Interface())
		}
	}
	if cache.ExtendTTL {
		ttl := int(cache.TTL / time.Second)
		for _, key := range keys {
			db.Send("EXPIRE", cache.Prefix+key.String(), ttl)
		}
		db.Flush()
	}
	return nil
}

// Set sets data
func (cache *Cache) Set(key *datastore.Key, src interface{}) error {
	if key == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	b, err := encode(src)
	if err != nil {
		return err
	}
	if cache.TTL > 0 {
		_, err = db.Do("SETEX", cache.Prefix+key.String(), int(cache.TTL/time.Second), b)
		return err
	}
	_, err = db.Do("SET", cache.Prefix+key.String(), b)
	return err
}

// SetMulti sets data
func (cache *Cache) SetMulti(keys []*datastore.Key, src interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	ttl := int(cache.TTL / time.Second)
	db.Send("MULTI")
	for i, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		b, err := encode(reflect.Indirect(reflect.ValueOf(src)).Index(i).Interface())
		if err != nil {
			return err
		}
		if cache.TTL > 0 {
			db.Send("SETEX", cache.Prefix+key.String(), ttl, b)
		} else {
			db.Send("SET", cache.Prefix+key.String(), b)
		}
	}
	_, err := db.Do("EXEC")
	return err
}

// Del dels data
func (cache *Cache) Del(key *datastore.Key) error {
	if key == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", cache.Prefix+key.String())
	return err
}

// DelMulti dels multi data
func (cache *Cache) DelMulti(keys []*datastore.Key) error {
	db := cache.Pool.Get()
	defer db.Close()
	db.Send("MULTI")
	for _, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		db.Send("DEL", cache.Prefix+key.String())
	}
	_, err := db.Do("EXEC")
	return err
}
<commit_msg>fix set when src is nil<commit_after>package redis

import (
	"bytes"
	"encoding/gob"
	"reflect"
	"time"

	"cloud.google.com/go/datastore"
	"github.com/acoshift/ds"
	"github.com/garyburd/redigo/redis"
)

// Cache implement Cache interface
type Cache struct {
	Pool      *redis.Pool
	Prefix    string
	TTL       time.Duration
	ExtendTTL bool
	Skip      func(*datastore.Key) bool
}

func encode(v interface{}) ([]byte, error) {
	w := &bytes.Buffer{}
	err := gob.NewEncoder(w).Encode(v)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func decode(b []byte, v interface{}) error {
	return gob.NewDecoder(bytes.NewReader(b)).Decode(v)
}

// Get gets data
func (cache *Cache) Get(key *datastore.Key, dst interface{}) error {
	if cache.Skip != nil && cache.Skip(key) {
		return ds.ErrCacheNotFound
	}

	db := cache.Pool.Get()
	defer db.Close()
	k := cache.Prefix + key.String()
	b, err := redis.Bytes(db.Do("GET", k))
	if err != nil {
		return err
	}
	if len(b) == 0 {
		return ds.ErrCacheNotFound
	}
	if cache.ExtendTTL {
		db.Do("EXPIRE", k, int(cache.TTL/time.Second))
	}
	return decode(b, dst)
}

// GetMulti gets multi data
func (cache *Cache) GetMulti(keys []*datastore.Key, dst interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	for _, key := range keys {
		db.Send("GET", cache.Prefix+key.String())
	}
	err := db.Flush()
	if err != nil {
		return err
	}
	for i := range keys {
		b, err := redis.Bytes(db.Receive())
		if err != nil {
			return err
		}
		if len(b) > 0 {
			decode(b, reflect.Indirect(reflect.ValueOf(dst)).Index(i).Interface())
		}
	}
	if cache.ExtendTTL {
		ttl := int(cache.TTL / time.Second)
		for _, key := range keys {
			db.Send("EXPIRE", cache.Prefix+key.String(), ttl)
		}
		db.Flush()
	}
	return nil
}

// Set sets data
func (cache *Cache) Set(key *datastore.Key, src interface{}) error {
	if key == nil || src == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	b, err := encode(src)
	if err != nil {
		return err
	}
	if cache.TTL > 0 {
		_, err = db.Do("SETEX", cache.Prefix+key.String(), int(cache.TTL/time.Second), b)
		return err
	}
	_, err = db.Do("SET", cache.Prefix+key.String(), b)
	return err
}

// SetMulti sets data
func (cache *Cache) SetMulti(keys []*datastore.Key, src interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	ttl := int(cache.TTL / time.Second)
	db.Send("MULTI")
	for i, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		s := reflect.Indirect(reflect.ValueOf(src)).Index(i)
		if s.IsNil() {
			continue
		}
		b, err := encode(s.Interface())
		if err != nil {
			return err
		}
		if cache.TTL > 0 {
			db.Send("SETEX", cache.Prefix+key.String(), ttl, b)
		} else {
			db.Send("SET", cache.Prefix+key.String(), b)
		}
	}
	_, err := db.Do("EXEC")
	return err
}

// Del dels data
func (cache *Cache) Del(key *datastore.Key) error {
	if key == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", cache.Prefix+key.String())
	return err
}

// DelMulti dels multi data
func (cache *Cache) DelMulti(keys []*datastore.Key) error {
	db := cache.Pool.Get()
	defer db.Close()
	db.Send("MULTI")
	for _, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		db.Send("DEL", cache.Prefix+key.String())
	}
	_, err := db.Do("EXEC")
	return err
}
<|endoftext|>


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

package hdiutil

import (
	"fmt"
	"strconv"
	"strings"
)

// Usage: hdiutil <verb> <options>
// <verb> is one of the following:
// help                    flatten
// attach                  imageinfo
// detach                  internet-enable
// eject                   isencrypted
// verify                  makehybrid
// create                  mount
// compact                 mountvol
// convert                 unmount
// burn                    plugins
// info                    resize
// checksum                segment
// chpass                  pmap
// erasekeys               udifderez
// unflatten               udifrez
// help                       display more detailed help

// EncryptionType specify a particular type of encryption.
type EncryptionType int

const (
	// AES128 use AES cipher running in CBC mode on 512-byte blocks with a 128-bit key (recommended).
	AES128 EncryptionType = 1 << iota
	// AES256 use AES cipher running in CBC mode on 512-byte blocks with a 256-bit key (more secure, but slower).
	AES256
)

func (e EncryptionType) String() string {
	switch e {
	case AES128:
		return "AES-128"
	case AES256:
		return "AES-256"
	}
	return fmt.Sprintf("EncryptionType(%d)", e)
}

func (e EncryptionType) attachFlag() []string     { return stringFlag("encryption", e.String()) }
func (e EncryptionType) verifyFlag() []string     { return stringFlag("encryption", e.String()) }
func (e EncryptionType) convertFlag() []string    { return stringFlag("encryption", e.String()) }
func (e EncryptionType) makehybridFlag() []string { return stringFlag("encryption", e.String()) }

type plist bool

func (p plist) attachFlag() []string  { return boolFlag("plist", bool(p)) }
func (p plist) verifyFlag() []string  { return boolFlag("plist", bool(p)) }
func (p plist) convertFlag() []string { return boolFlag("plist", bool(p)) }

type puppetstrings bool

func (p puppetstrings) attachFlag() []string     { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) verifyFlag() []string     { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) convertFlag() []string    { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) makehybridFlag() []string { return boolFlag("puppetstrings", bool(p)) }

// Srcimagekey specify a key/value pair for the disk image recognition system. (-imagekey is normally a synonym)
type Srcimagekey map[string]string

func (s Srcimagekey) commonFlag() []string {
	var arg string
	for k, v := range s {
		arg = k + "=" + v
	}
	return stringFlag("srcimagekey", arg)
}
func (s Srcimagekey) attachFlag() []string     { return s.commonFlag() }
func (s Srcimagekey) createFlag() []string     { return s.commonFlag() }
func (s Srcimagekey) convertFlag() []string    { return s.commonFlag() }
func (s Srcimagekey) makehybridFlag() []string { return s.commonFlag() }

// Tgtimagekey specify a key/value pair for any image created. (-imagekey is only a synonym if there is no input image).
type Tgtimagekey map[string]string

func (t Tgtimagekey) commonFlag() []string {
	var arg string
	for k, v := range t {
		arg = k + "=" + v
	}
	return stringFlag("tgtimagekey", arg)
}
func (t Tgtimagekey) attachFlag() []string  { return t.commonFlag() }
func (t Tgtimagekey) createFlag() []string  { return t.commonFlag() }
func (t Tgtimagekey) convertFlag() []string { return t.commonFlag() }

// Imagekey is normally a synonym to Srcimagekey, only a synonym Tgtimagekey if there is no input image.
type Imagekey map[string]string

func (i Imagekey) commonFlag() []string {
	var arg string
	for k, v := range i {
		arg = k + "=" + v
	}
	return stringFlag("imagekey", arg)
}
func (i Imagekey) attachFlag() []string { return i.commonFlag() }
func (i Imagekey) createFlag() []string { return i.commonFlag() }

// Encryption specify a particular type of encryption or, if not specified, the default encryption algorithm.
//
// As of OS X 10.7, the default algorithm is the AES cipher running in CBC mode on 512-byte blocks with a 128-bit key.
type Encryption EncryptionType

type stdinpass bool

func (s stdinpass) attachFlag() []string     { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) verifyFlag() []string     { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) convertFlag() []string    { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) makehybridFlag() []string { return boolFlag("stdinpass", bool(s)) }

type agentpass bool

// Recover specify a keychain containing the secret corresponding to the certificate specified with -certificate when the image was created.
type Recover string

func (r Recover) attachFlag() []string { return stringFlag("recover", string(r)) }

// Certificate specify a secondary access certificate for an encrypted image.
// cert_file must be DER-encoded certificate data, which can be created by Keychain Access or openssl(1).
type Certificate string

func (c Certificate) convertFlag() []string { return stringFlag("certificate", string(c)) }

// Pubkey specify a list of public keys, identified by their hexadecimal hashes, to be used to protect the encrypted image being created.
type Pubkey []string

// Cacert specify a certificate authority certificate.
// cert can be either a PEM file or a directory of certificates processed by c_rehash(1).
//
// See also --capath and --cacert in curl(1).
type Cacert string

type insecurehttp bool

// Shadow use a shadow file in conjunction with the data in the primary image file.
// This option prevents modification of the original image and allows read-only images to be attached read/write.
//
// When blocks are being read from the image, blocks present in the shadow file override blocks in the base image.
// All data written to an attached device will be redirected to the shadow file.
// If not specified, shadowfile defaults to image.shadow.
// If the shadow file does not exist, it is created.
//
// hdiutil verbs taking images as input accept -shadow, -cacert, and -insecurehttp.
type Shadow string

func (s Shadow) attachFlag() []string     { return stringFlag("shadow", string(s)) }
func (s Shadow) convertFlag() []string    { return stringFlag("shadow", string(s)) }
func (s Shadow) makehybridFlag() []string { return stringFlag("shadow", string(s)) }

type verbose bool

func (v verbose) attachFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) detachFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) createFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) convertFlag() []string    { return boolFlag("verbose", bool(v)) }
func (v verbose) makehybridFlag() []string { return boolFlag("verbose", bool(v)) }

type quiet bool

func (q quiet) attachFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) detachFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) createFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) makehybridFlag() []string { return boolFlag("quiet", bool(q)) }

type debug bool

func (d debug) attachFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) detachFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) createFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) convertFlag() []string    { return boolFlag("debug", bool(d)) }
func (d debug) makehybridFlag() []string { return boolFlag("debug", bool(d)) }

const (
	// Plist provide result output in plist format.
	// Other programs invoking hdiutil are expected to use -plist rather than try to parse the human-readable output.
	//
	// The usual output is consistent but generally unstructured.
	Plist plist = true

	// Puppetstrings provide progress output that is easy for another program to parse.
	// PERCENTAGE outputs can include the value -1 which means hdiutil is performing an operation that will take an indeterminate amount of time to complete.
	//
	// Any program trying to interpret hdiutil's progress should use -puppetstrings.
	Puppetstrings puppetstrings = true

	// Stdinpass read a null-terminated passphrase from standard input.
	// If the standard input is a tty, the passphrase will be read with readpassphrase(3).
	// Otherwise, the password is read from stdin.
	//
	// -stdinpass replaces -passphrase which has been deprecated.
	// -passphrase is insecure because its argument appears in the output of ps(1) where it is visible to other users and processes on the system.
	Stdinpass stdinpass = true

	// Agentpass force the default behavior of prompting for a passphrase.
	//
	// Useful with -pubkey to create an image protected by both a passphrase and a public key.
	Agentpass agentpass = true

	// Insecurehttp ignore SSL host validation failures.
	// Useful for self-signed servers for which the appropriate certificates are unavailable or if access to a server is desired when the server name doesn't match what is in the certificate.
	Insecurehttp insecurehttp = true

	// Verbose be verbose: produce extra progress output and error diagnostics.
	//
	// This option can help the user decipher why a particular operation failed.
	// At a minimum, the probing of any specified images will be detailed.
	// BUG(zchee): not exit hdiutil command if set.
	Verbose verbose = true

	// Quiet close stdout and stderr, leaving only hdiutil's exit status to indicate success or failure.
	// No /dev entries or mount points will be printed.
	//
	// -debug and -verbose disable -quiet.
	// BUG(zchee): not get the command result such as device node path when attach.
	Quiet quiet = true

	// Debug be very verbose.
	//
	// This option is good if a large amount of progress information is needed.
	// As of Mac OS X 10.6, -debug enables -verbose.
	// BUG(zchee): not exit hdiutil command if set.
	Debug debug = true
)

// RawDeviceNode return the raw device node from the deviceNode.
func RawDeviceNode(deviceNode string) string {
	return strings.Replace(deviceNode, "disk", "rdisk", 1)
}

// DeviceNumber return the device number from the deviceNode.
func DeviceNumber(deviceNode string) int {
	n, err := strconv.Atoi(strings.TrimPrefix(deviceNode, "/dev/disk"))
	if err != nil {
		return 0
	}
	return n
}
<commit_msg>hdiutil: sort by alphabetical order<commit_after>// Copyright 2017 The go-darwin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package hdiutil

import (
	"fmt"
	"strconv"
	"strings"
)

// Usage: hdiutil <verb> <options>
// <verb> is one of the following:
// help                    flatten
// attach                  imageinfo
// detach                  internet-enable
// eject                   isencrypted
// verify                  makehybrid
// create                  mount
// compact                 mountvol
// convert                 unmount
// burn                    plugins
// info                    resize
// checksum                segment
// chpass                  pmap
// erasekeys               udifderez
// unflatten               udifrez
// help                       display more detailed help

// EncryptionType specify a particular type of encryption.
type EncryptionType int

const (
	// AES128 use AES cipher running in CBC mode on 512-byte blocks with a 128-bit key (recommended).
	AES128 EncryptionType = 1 << iota
	// AES256 use AES cipher running in CBC mode on 512-byte blocks with a 256-bit key (more secure, but slower).
	AES256
)

func (e EncryptionType) String() string {
	switch e {
	case AES128:
		return "AES-128"
	case AES256:
		return "AES-256"
	}
	return fmt.Sprintf("EncryptionType(%d)", e)
}

func (e EncryptionType) attachFlag() []string     { return stringFlag("encryption", e.String()) }
func (e EncryptionType) convertFlag() []string    { return stringFlag("encryption", e.String()) }
func (e EncryptionType) makehybridFlag() []string { return stringFlag("encryption", e.String()) }
func (e EncryptionType) verifyFlag() []string     { return stringFlag("encryption", e.String()) }

type plist bool

func (p plist) attachFlag() []string  { return boolFlag("plist", bool(p)) }
func (p plist) convertFlag() []string { return boolFlag("plist", bool(p)) }
func (p plist) verifyFlag() []string  { return boolFlag("plist", bool(p)) }

type puppetstrings bool

func (p puppetstrings) attachFlag() []string     { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) convertFlag() []string    { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) makehybridFlag() []string { return boolFlag("puppetstrings", bool(p)) }
func (p puppetstrings) verifyFlag() []string     { return boolFlag("puppetstrings", bool(p)) }

// Srcimagekey specify a key/value pair for the disk image recognition system. (-imagekey is normally a synonym)
type Srcimagekey map[string]string

func (s Srcimagekey) commonFlag() []string {
	var arg string
	for k, v := range s {
		arg = k + "=" + v
	}
	return stringFlag("srcimagekey", arg)
}
func (s Srcimagekey) attachFlag() []string     { return s.commonFlag() }
func (s Srcimagekey) convertFlag() []string    { return s.commonFlag() }
func (s Srcimagekey) createFlag() []string     { return s.commonFlag() }
func (s Srcimagekey) makehybridFlag() []string { return s.commonFlag() }

// Tgtimagekey specify a key/value pair for any image created. (-imagekey is only a synonym if there is no input image).
type Tgtimagekey map[string]string

func (t Tgtimagekey) commonFlag() []string {
	var arg string
	for k, v := range t {
		arg = k + "=" + v
	}
	return stringFlag("tgtimagekey", arg)
}
func (t Tgtimagekey) attachFlag() []string  { return t.commonFlag() }
func (t Tgtimagekey) convertFlag() []string { return t.commonFlag() }
func (t Tgtimagekey) createFlag() []string  { return t.commonFlag() }

// Imagekey is normally a synonym to Srcimagekey, only a synonym Tgtimagekey if there is no input image.
type Imagekey map[string]string

func (i Imagekey) commonFlag() []string {
	var arg string
	for k, v := range i {
		arg = k + "=" + v
	}
	return stringFlag("imagekey", arg)
}
func (i Imagekey) attachFlag() []string { return i.commonFlag() }
func (i Imagekey) createFlag() []string { return i.commonFlag() }

// Encryption specify a particular type of encryption or, if not specified, the default encryption algorithm.
//
// As of OS X 10.7, the default algorithm is the AES cipher running in CBC mode on 512-byte blocks with a 128-bit key.
type Encryption EncryptionType

type stdinpass bool

func (s stdinpass) attachFlag() []string     { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) convertFlag() []string    { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) makehybridFlag() []string { return boolFlag("stdinpass", bool(s)) }
func (s stdinpass) verifyFlag() []string     { return boolFlag("stdinpass", bool(s)) }

type agentpass bool

// Recover specify a keychain containing the secret corresponding to the certificate specified with -certificate when the image was created.
type Recover string

func (r Recover) attachFlag() []string { return stringFlag("recover", string(r)) }

// Certificate specify a secondary access certificate for an encrypted image.
// cert_file must be DER-encoded certificate data, which can be created by Keychain Access or openssl(1).
type Certificate string

func (c Certificate) convertFlag() []string { return stringFlag("certificate", string(c)) }

// Pubkey specify a list of public keys, identified by their hexadecimal hashes, to be used to protect the encrypted image being created.
type Pubkey []string

// Cacert specify a certificate authority certificate.
// cert can be either a PEM file or a directory of certificates processed by c_rehash(1).
//
// See also --capath and --cacert in curl(1).
type Cacert string

type insecurehttp bool

// Shadow use a shadow file in conjunction with the data in the primary image file.
// This option prevents modification of the original image and allows read-only images to be attached read/write.
//
// When blocks are being read from the image, blocks present in the shadow file override blocks in the base image.
// All data written to an attached device will be redirected to the shadow file.
// If not specified, shadowfile defaults to image.shadow.
// If the shadow file does not exist, it is created.
//
// hdiutil verbs taking images as input accept -shadow, -cacert, and -insecurehttp.
type Shadow string

func (s Shadow) attachFlag() []string     { return stringFlag("shadow", string(s)) }
func (s Shadow) convertFlag() []string    { return stringFlag("shadow", string(s)) }
func (s Shadow) makehybridFlag() []string { return stringFlag("shadow", string(s)) }

type verbose bool

func (v verbose) attachFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) convertFlag() []string    { return boolFlag("verbose", bool(v)) }
func (v verbose) createFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) detachFlag() []string     { return boolFlag("verbose", bool(v)) }
func (v verbose) makehybridFlag() []string { return boolFlag("verbose", bool(v)) }

type quiet bool

func (q quiet) attachFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) createFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) detachFlag() []string     { return boolFlag("quiet", bool(q)) }
func (q quiet) makehybridFlag() []string { return boolFlag("quiet", bool(q)) }

type debug bool

func (d debug) attachFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) convertFlag() []string    { return boolFlag("debug", bool(d)) }
func (d debug) createFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) detachFlag() []string     { return boolFlag("debug", bool(d)) }
func (d debug) makehybridFlag() []string { return boolFlag("debug", bool(d)) }

const (
	// Plist provide result output in plist format.
	// Other programs invoking hdiutil are expected to use -plist rather than try to parse the human-readable output.
	//
	// The usual output is consistent but generally unstructured.
	Plist plist = true

	// Puppetstrings provide progress output that is easy for another program to parse.
	// PERCENTAGE outputs can include the value -1 which means hdiutil is performing an operation that will take an indeterminate amount of time to complete.
	//
	// Any program trying to interpret hdiutil's progress should use -puppetstrings.
	Puppetstrings puppetstrings = true

	// Stdinpass read a null-terminated passphrase from standard input.
	// If the standard input is a tty, the passphrase will be read with readpassphrase(3).
	// Otherwise, the password is read from stdin.
	//
	// -stdinpass replaces -passphrase which has been deprecated.
	// -passphrase is insecure because its argument appears in the output of ps(1) where it is visible to other users and processes on the system.
	Stdinpass stdinpass = true

	// Agentpass force the default behavior of prompting for a passphrase.
	//
	// Useful with -pubkey to create an image protected by both a passphrase and a public key.
	Agentpass agentpass = true

	// Insecurehttp ignore SSL host validation failures.
	// Useful for self-signed servers for which the appropriate certificates are unavailable or if access to a server is desired when the server name doesn't match what is in the certificate.
	Insecurehttp insecurehttp = true

	// Verbose be verbose: produce extra progress output and error diagnostics.
	//
	// This option can help the user decipher why a particular operation failed.
	// At a minimum, the probing of any specified images will be detailed.
	// BUG(zchee): not exit hdiutil command if set.
	Verbose verbose = true

	// Quiet close stdout and stderr, leaving only hdiutil's exit status to indicate success or failure.
	// No /dev entries or mount points will be printed.
	//
	// -debug and -verbose disable -quiet.
	// BUG(zchee): not get the command result such as device node path when attach.
	Quiet quiet = true

	// Debug be very verbose.
	//
	// This option is good if a large amount of progress information is needed.
	// As of Mac OS X 10.6, -debug enables -verbose.
	// BUG(zchee): not exit hdiutil command if set.
	Debug debug = true
)

// RawDeviceNode return the raw device node from the deviceNode.
func RawDeviceNode(deviceNode string) string {
	return strings.Replace(deviceNode, "disk", "rdisk", 1)
}

// DeviceNumber return the device number from the deviceNode.
func DeviceNumber(deviceNode string) int {
	n, err := strconv.Atoi(strings.TrimPrefix(deviceNode, "/dev/disk"))
	if err != nil {
		return 0
	}
	return n
}
<|endoftext|>


<commit_before>package plugins // import "cirello.io/gochatbot/plugins"

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

	"cirello.io/gochatbot/messages"
)

type Comm struct {
	rpcAddr string
}

func NewComm(rpcAddr string) *Comm {
	return &Comm{rpcAddr}
}

func (p Comm) Pop() (*messages.Message, error) {
	resp, err := http.Get(fmt.Sprint("http://", p.rpcAddr, "/pop"))
	if err != nil {
		return nil, fmt.Errorf("error talking to gochatbot: %v", err)
	}
	defer resp.Body.Close()

	var msg messages.Message
	if err := json.NewDecoder(resp.Body).Decode(&msg); err != nil {
		return nil, fmt.Errorf("error parsing message from gochatbot: %v", err)
	}

	return &msg, nil
}

func (p Comm) Send(msg *messages.Message) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(&msg); err != nil {
		return fmt.Errorf("error serializing message to gochatbot: %v", err)
	}

	resp, err := http.Post(fmt.Sprint("http://", p.rpcAddr, "/send"), "application/json", &buf)
	if err != nil {
		return fmt.Errorf("error talking to gochatbot: %v", err)
	}
	defer resp.Body.Close()

	return nil
}

func (p Comm) MemoryRead(ns, key string) ([]byte, error) {
	resp, err := http.Get(
		fmt.Sprintf("http://%s/memoryRead?namespace=%s&key=%s", p.rpcAddr, url.QueryEscape(ns), url.QueryEscape(key)),
	)
	if err != nil {
		return []byte{}, fmt.Errorf("error talking to gochatbot %v", err)
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return []byte{}, fmt.Errorf("error reading memory from gochatbot: %v", err)
	}

	return b, nil
}

func (p Comm) MemorySave(ns, key string, content []byte) error {
	buf := bytes.NewReader(content)
	resp, err := http.Post(
		fmt.Sprintf("http://%s/memorySave?namespace=%s&key=%s", p.rpcAddr, url.QueryEscape(ns), url.QueryEscape(key)),
		"application/octet-stream",
		buf,
	)
	defer resp.Body.Close()

	if err != nil {
		return fmt.Errorf("error talking to gochatbot: %v", err)
	}

	return nil
}
<commit_msg>Force req.Close on plugin client<commit_after>package plugins // import "cirello.io/gochatbot/plugins"

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

	"cirello.io/gochatbot/messages"
)

type Comm struct {
	rpcAddr string
}

func NewComm(rpcAddr string) *Comm {
	return &Comm{rpcAddr}
}

func (p Comm) Pop() (*messages.Message, error) {
	req, err := http.NewRequest("GET", fmt.Sprint("http://", p.rpcAddr, "/pop"), nil)
	if err != nil {
		return nil, fmt.Errorf("error creating request (pop): %v", err)
	}

	req.Close = true
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error talking to gochatbot (pop): %v", err)
	}
	defer resp.Body.Close()

	var msg messages.Message
	if err := json.NewDecoder(resp.Body).Decode(&msg); err != nil {
		return nil, fmt.Errorf("error parsing message from gochatbot: %v", err)
	}

	return &msg, nil
}

func (p Comm) Send(msg *messages.Message) error {
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(&msg); err != nil {
		return fmt.Errorf("error serializing message to gochatbot: %v", err)
	}

	req, err := http.NewRequest("POST", fmt.Sprint("http://", p.rpcAddr, "/send"), &buf)
	if err != nil {
		return nil, fmt.Errorf("error creating request (send): %v", err)
	}
	req.Close = true
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("error talking to gochatbot (send): %v", err)
	}
	defer resp.Body.Close()

	return nil
}

func (p Comm) MemoryRead(ns, key string) ([]byte, error) {
	req, err := http.NewRequest(
		"GET",
		fmt.Sprintf("http://%s/memoryRead?namespace=%s&key=%s", p.rpcAddr, url.QueryEscape(ns), url.QueryEscape(key)),
		nil,
	)
	if err != nil {
		return nil, fmt.Errorf("error creating request (memory read): %v", err)
	}

	req.Close = true
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return []byte{}, fmt.Errorf("error talking to gochatbot (memory read): %v", err)
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return []byte{}, fmt.Errorf("error reading memory from gochatbot: %v", err)
	}

	return b, nil
}

func (p Comm) MemorySave(ns, key string, content []byte) error {
	buf := bytes.NewReader(content)
	req, err := http.NewRequest(
		"GET",
		fmt.Sprintf("http://%s/memorySave?namespace=%s&key=%s", p.rpcAddr, url.QueryEscape(ns), url.QueryEscape(key)),
		buf,
	)
	if err != nil {
		return nil, fmt.Errorf("error creating request (memory read): %v", err)
	}

	req.Close = true
	resp, err := http.DefaultClient.Do(req)
	defer resp.Body.Close()

	if err != nil {
		return fmt.Errorf("error talking to gochatbot (memory save): %v", err)
	}

	return nil
}
<|endoftext|>


<commit_before>/*
	Copyright (c) 2016, Percona LLC and/or its affiliates. All rights reserved.

	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 pmm

import (
	"errors"
	"fmt"
	"time"
)

const (
	qanAPIBasePath = "qan-api"
	noMonitoring   = "No monitoring registered for this node identified as"
	apiTimeout     = 10 * time.Second
	NameRegex      = `^[-\w:\.]{2,60}$`
)

var (
	// you can use `-ldflags -X github.com/percona/pmm-client/pmm.Version=`
	// to set build version number
	Version = "1.14.0"

	// you can use `-ldflags -X github.com/percona/pmm-client/pmm.RootDir=`
	// to set root filesystem for pmm-admin
	RootDir = ""

	PMMBaseDir   = RootDir + "/usr/local/percona/pmm-client"
	AgentBaseDir = RootDir + "/usr/local/percona/qan-agent"

	ConfigFile  = fmt.Sprintf("%s/pmm.yml", PMMBaseDir)
	SSLCertFile = fmt.Sprintf("%s/server.crt", PMMBaseDir)
	SSLKeyFile  = fmt.Sprintf("%s/server.key", PMMBaseDir)

	ErrDuplicate  = errors.New("there is already one instance with this name under monitoring.")
	ErrNoService  = errors.New("no service found.")
	errNoInstance = errors.New("no instance found on QAN API.")
)

type Errors []error

func (e Errors) Error() string {
	return join(e, ", ")
}

// join concatenates the elements of a to create a single string. The separator string
// sep is placed between elements in the resulting string.
func join(a []error, sep string) string {
	if len(a) == 0 {
		return ""
	}
	if len(a) == 1 {
		return a[0].Error()
	}
	nilErr := fmt.Sprintf("%v", error(nil))
	n := len(sep) * (len(a) - 1)
	for i := 0; i < len(a); i++ {
		if a[i] == nil {
			n += len(nilErr)
		} else {
			n += len(a[i].Error())
		}
	}

	b := make([]byte, n)
	bp := copy(b, a[0].Error())
	for _, s := range a[1:] {
		bp += copy(b[bp:], sep)
		if s == nil {
			bp += copy(b[bp:], nilErr)
		} else {
			bp += copy(b[bp:], s.Error())
		}
	}
	return string(b)
}
<commit_msg>PMM-2960 Update versions to 1.14.1<commit_after>/*
	Copyright (c) 2016, Percona LLC and/or its affiliates. All rights reserved.

	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 pmm

import (
	"errors"
	"fmt"
	"time"
)

const (
	qanAPIBasePath = "qan-api"
	noMonitoring   = "No monitoring registered for this node identified as"
	apiTimeout     = 10 * time.Second
	NameRegex      = `^[-\w:\.]{2,60}$`
)

var (
	// you can use `-ldflags -X github.com/percona/pmm-client/pmm.Version=`
	// to set build version number
	Version = "1.14.1"

	// you can use `-ldflags -X github.com/percona/pmm-client/pmm.RootDir=`
	// to set root filesystem for pmm-admin
	RootDir = ""

	PMMBaseDir   = RootDir + "/usr/local/percona/pmm-client"
	AgentBaseDir = RootDir + "/usr/local/percona/qan-agent"

	ConfigFile  = fmt.Sprintf("%s/pmm.yml", PMMBaseDir)
	SSLCertFile = fmt.Sprintf("%s/server.crt", PMMBaseDir)
	SSLKeyFile  = fmt.Sprintf("%s/server.key", PMMBaseDir)

	ErrDuplicate  = errors.New("there is already one instance with this name under monitoring.")
	ErrNoService  = errors.New("no service found.")
	errNoInstance = errors.New("no instance found on QAN API.")
)

type Errors []error

func (e Errors) Error() string {
	return join(e, ", ")
}

// join concatenates the elements of a to create a single string. The separator string
// sep is placed between elements in the resulting string.
func join(a []error, sep string) string {
	if len(a) == 0 {
		return ""
	}
	if len(a) == 1 {
		return a[0].Error()
	}
	nilErr := fmt.Sprintf("%v", error(nil))
	n := len(sep) * (len(a) - 1)
	for i := 0; i < len(a); i++ {
		if a[i] == nil {
			n += len(nilErr)
		} else {
			n += len(a[i].Error())
		}
	}

	b := make([]byte, n)
	bp := copy(b, a[0].Error())
	for _, s := range a[1:] {
		bp += copy(b[bp:], sep)
		if s == nil {
			bp += copy(b[bp:], nilErr)
		} else {
			bp += copy(b[bp:], s.Error())
		}
	}
	return string(b)
}
<|endoftext|>


<commit_before>/*
	Copyright (C) 2016 - 2017, Lefteris Zafiris <zaf@fastmail.com>

	This program is free software, distributed under the terms of
	the BSD 3-Clause License. See the LICENSE file
	at the top of the source tree.
*/

/*
	Package g711 implements encoding and decoding of G711.0 compressed sound data.
	G.711 is an ITU-T standard for audio companding.

*/

package g711

import (
	"bytes"
	"errors"
	"io"
)

const (
	// Input and output formats
	Alaw = iota // Alaw G711 encoded PCM data
	Ulaw        // Ulaw G711  encoded PCM data
	Lpcm        // Lpcm 16bit signed linear data
)

type encoder func(int16) uint8
type decoder func(uint8) int16
type transcoder func(uint8) uint8

// Reader reads G711 PCM data and decodes it to 16bit LPCM or directly transcodes between A-law and u-law
type Reader struct {
	input  int           // source format
	output int           // output format
	source io.Reader     // source data
	buf    *bytes.Buffer // local buffer
}

// Writer encodes 16bit LPCM data to G711 PCM or directly transcodes between A-law and u-law
type Writer struct {
	input       int           // source format
	output      int           // output format
	destination io.Writer     // output data
	buf         *bytes.Buffer //local buffer
}

// NewAlawDecoder returns a pointer to a Reader that decodes or trans-codes A-law data.
// It takes as input the source data Reader and the output encoding fomrat.
func NewAlawDecoder(reader io.Reader, output int) (*Reader, error) {
	if output != Ulaw && output != Lpcm {
		return nil, errors.New("Invalid output format")
	}
	b := new(bytes.Buffer)
	return &Reader{input: Alaw, output: output, source: reader, buf: b}, nil
}

// NewUlawDecoder returns a pointer to a Reader that decodes or trans-codes u-law data.
// It takes as input the source data Reader and the output encoding fomrat.
func NewUlawDecoder(reader io.Reader, output int) (*Reader, error) {
	if output != Alaw && output != Lpcm {
		return nil, errors.New("Invalid output format")
	}
	b := new(bytes.Buffer)
	return &Reader{input: Ulaw, output: output, source: reader, buf: b}, nil
}

// NewAlawEncoder returns a pointer to a Writer that encodes data to A-law.
// It takes as input the destination data Writer and the input encoding fomrat.
func NewAlawEncoder(writer io.Writer, input int) (*Writer, error) {
	if input != Ulaw && input != Lpcm {
		return nil, errors.New("Invalid input format")
	}
	b := new(bytes.Buffer)
	return &Writer{input: input, output: Alaw, destination: writer, buf: b}, nil
}

// NewUlawEncoder returns a pointer to a Writer that encodes data to u-law.
// It takes as input the destination data Writer and the input encoding fomrat.
func NewUlawEncoder(writer io.Writer, input int) (*Writer, error) {
	if input != Alaw && input != Lpcm {
		return nil, errors.New("Invalid input format")
	}
	b := new(bytes.Buffer)
	return &Writer{input: input, output: Ulaw, destination: writer, buf: b}, nil
}

// Reset discards the Reader state. This permits reusing a Reader rather than allocating a new one.
func (r *Reader) Reset(reader io.Reader) {
	r.buf.Reset()
	r.source = reader
}

// Reset discards the Writer state. This permits reusing a Writer rather than allocating a new one.
func (w *Writer) Reset(writer io.Writer) {
	w.buf.Reset()
	w.destination = writer
}

// Read decodes G711 data. Reads up to len(p) bytes into p, returns the number
// of bytes read and any error encountered.
func (r *Reader) Read(p []byte) (int, error) {
	var dec decoder
	var tr transcoder
	if r.input == Alaw {
		dec = DecodeAlaw
		tr = Alaw2Ulaw
	} else {
		dec = DecodeUlaw
		tr = Ulaw2Alaw
	}
	var i int
	var err error
	_, err = r.buf.ReadFrom(r.source)
	if err != nil {
		return i, err
	}
	var frame byte
	if r.output == Lpcm { // Decode G711 data to LPCM
		for i = 0; i < len(p)-2; i = i + 2 {
			frame, err = r.buf.ReadByte()
			if err != nil {
				break
			}
			decoded := dec(frame)
			p[i] = byte(decoded)
			p[i+1] = byte(decoded >> 8)
		}
	} else { // Trans-code
		for i = 0; i < len(p); i++ {
			frame, err = r.buf.ReadByte()
			if err != nil {
				break
			}
			p[i] = tr(frame)
		}
	}
	return i, err
}

// Write encodes G711 Data. Writes len(p) bytes from p to the underlying data stream,
// returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered
// that caused the write to stop early.
func (w *Writer) Write(p []byte) (int, error) {
	var err, wrErr error
	var enc encoder
	var tr transcoder
	if w.output == Alaw {
		enc = EncodeAlaw
		tr = Ulaw2Alaw
	} else {
		enc = EncodeUlaw
		tr = Alaw2Ulaw
	}
	if w.input == Lpcm { // Encode LPCM data to G711
		for i := 0; i <= len(p)-2; i = i + 2 {
			wrErr = w.buf.WriteByte(enc(int16(p[i]) | int16(p[i+1])<<8))
			if wrErr != nil {
				break
			}
		}
	} else { // Trans-code
		for _, data := range p {
			wrErr = w.buf.WriteByte(tr(data))
			if wrErr != nil {
				break
			}
		}
	}
	i, err := w.buf.WriteTo(w.destination)
	if err == nil {
		err = wrErr
	}
	if w.input == Lpcm {
		i *= 2 // Report back the correct number of bytes written from p
	}
	return int(i), err
}

// Flush flushes any pending data to the underlying writer.
func (w *Writer) Flush() (err error) {
	if w.buf.Len() > 0 {
		_, err = w.buf.WriteTo(w.destination)
	}
	return
}
<commit_msg>Some updates to Reader and Writer sturct members<commit_after>/*
	Copyright (C) 2016 - 2017, Lefteris Zafiris <zaf@fastmail.com>

	This program is free software, distributed under the terms of
	the BSD 3-Clause License. See the LICENSE file
	at the top of the source tree.
*/

/*
	Package g711 implements encoding and decoding of G711.0 compressed sound data.
	G.711 is an ITU-T standard for audio companding.

*/

package g711

import (
	"bytes"
	"errors"
	"io"
)

const (
	// Input and output formats
	Alaw = iota // Alaw G711 encoded PCM data
	Ulaw        // Ulaw G711  encoded PCM data
	Lpcm        // Lpcm 16bit signed linear data
)

// Reader reads G711 PCM data and decodes it to 16bit LPCM or directly transcodes between A-law and u-law
type Reader struct {
	output    int               // output format
	decode    func(uint8) int16 // decoding function
	transcode func(uint8) uint8 // transcoding function
	source    io.Reader         // source data
	buf       *bytes.Buffer     // local buffer
}

// Writer encodes 16bit LPCM data to G711 PCM or directly transcodes between A-law and u-law
type Writer struct {
	input       int               // input format
	encode      func(int16) uint8 // encoding function
	transcode   func(uint8) uint8 // transcoding function
	destination io.Writer         // output data
	buf         *bytes.Buffer     //local buffer
}

// NewAlawDecoder returns a pointer to a Reader that decodes or trans-codes A-law data.
// It takes as input the source data Reader and the output encoding fomrat.
func NewAlawDecoder(reader io.Reader, output int) (*Reader, error) {
	if output != Ulaw && output != Lpcm {
		return nil, errors.New("Invalid output format")
	}
	r := Reader{
		output:    output,
		decode:    DecodeAlaw,
		transcode: Alaw2Ulaw,
		source:    reader,
		buf:       new(bytes.Buffer),
	}
	return &r, nil
}

// NewUlawDecoder returns a pointer to a Reader that decodes or trans-codes u-law data.
// It takes as input the source data Reader and the output encoding fomrat.
func NewUlawDecoder(reader io.Reader, output int) (*Reader, error) {
	if output != Alaw && output != Lpcm {
		return nil, errors.New("Invalid output format")
	}
	r := Reader{
		output:    output,
		decode:    DecodeUlaw,
		transcode: Ulaw2Alaw,
		source:    reader,
		buf:       new(bytes.Buffer),
	}
	return &r, nil
}

// NewAlawEncoder returns a pointer to a Writer that encodes data to A-law.
// It takes as input the destination data Writer and the input encoding fomrat.
func NewAlawEncoder(writer io.Writer, input int) (*Writer, error) {
	if input != Ulaw && input != Lpcm {
		return nil, errors.New("Invalid input format")
	}
	w := Writer{
		input:       input,
		encode:      EncodeAlaw,
		transcode:   Ulaw2Alaw,
		destination: writer,
		buf:         new(bytes.Buffer),
	}
	return &w, nil
}

// NewUlawEncoder returns a pointer to a Writer that encodes data to u-law.
// It takes as input the destination data Writer and the input encoding fomrat.
func NewUlawEncoder(writer io.Writer, input int) (*Writer, error) {
	if input != Alaw && input != Lpcm {
		return nil, errors.New("Invalid input format")
	}
	w := Writer{
		input:       input,
		encode:      EncodeUlaw,
		transcode:   Alaw2Ulaw,
		destination: writer,
		buf:         new(bytes.Buffer),
	}
	return &w, nil
}

// Reset discards the Reader state. This permits reusing a Reader rather than allocating a new one.
func (r *Reader) Reset(reader io.Reader) {
	r.buf.Reset()
	r.source = reader
}

// Reset discards the Writer state. This permits reusing a Writer rather than allocating a new one.
func (w *Writer) Reset(writer io.Writer) {
	w.buf.Reset()
	w.destination = writer
}

// Read decodes G711 data. Reads up to len(p) bytes into p, returns the number
// of bytes read and any error encountered.
func (r *Reader) Read(p []byte) (int, error) {
	var i int
	var err error
	_, err = r.buf.ReadFrom(r.source)
	if err != nil {
		return i, err
	}
	var frame byte
	if r.output == Lpcm { // Decode G711 data to LPCM
		for i = 0; i < len(p)-2; i = i + 2 {
			frame, err = r.buf.ReadByte()
			if err != nil {
				break
			}
			decoded := r.decode(frame)
			p[i] = byte(decoded)
			p[i+1] = byte(decoded >> 8)
		}
	} else { // Trans-code
		for i = 0; i < len(p); i++ {
			frame, err = r.buf.ReadByte()
			if err != nil {
				break
			}
			p[i] = r.transcode(frame)
		}
	}
	return i, err
}

// Write encodes G711 Data. Writes len(p) bytes from p to the underlying data stream,
// returns the number of bytes written from p (0 <= n <= len(p)) and any error encountered
// that caused the write to stop early.
func (w *Writer) Write(p []byte) (int, error) {
	var err, wrErr error
	if w.input == Lpcm { // Encode LPCM data to G711
		for i := 0; i <= len(p)-2; i = i + 2 {
			wrErr = w.buf.WriteByte(w.encode(int16(p[i]) | int16(p[i+1])<<8))
			if wrErr != nil {
				break
			}
		}
	} else { // Trans-code
		for _, data := range p {
			wrErr = w.buf.WriteByte(w.transcode(data))
			if wrErr != nil {
				break
			}
		}
	}
	i, err := w.buf.WriteTo(w.destination)
	if err == nil {
		err = wrErr
	}
	if w.input == Lpcm {
		i *= 2 // Report back the correct number of bytes written from p
	}
	return int(i), err
}

// Flush flushes any pending data to the underlying writer.
func (w *Writer) Flush() (err error) {
	if w.buf.Len() > 0 {
		_, err = w.buf.WriteTo(w.destination)
	}
	return
}
<|endoftext|>