<commit_before>package build // import "github.com/docker/docker/api/server/router/build"

import (
	"bufio"
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"runtime"
	"strconv"
	"strings"
	"sync"

	"github.com/docker/docker/api/server/httputils"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/backend"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/versions"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/ioutils"
	"github.com/docker/docker/pkg/progress"
	"github.com/docker/docker/pkg/streamformatter"
	units "github.com/docker/go-units"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

type invalidIsolationError string

func (e invalidIsolationError) Error() string {
	return fmt.Sprintf("Unsupported isolation: %q", string(e))
}

func (e invalidIsolationError) InvalidParameter() {}

func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
	version := httputils.VersionFromContext(ctx)
	options := &types.ImageBuildOptions{}
	if httputils.BoolValue(r, "forcerm") && versions.GreaterThanOrEqualTo(version, "1.12") {
		options.Remove = true
	} else if r.FormValue("rm") == "" && versions.GreaterThanOrEqualTo(version, "1.12") {
		options.Remove = true
	} else {
		options.Remove = httputils.BoolValue(r, "rm")
	}
	if httputils.BoolValue(r, "pull") && versions.GreaterThanOrEqualTo(version, "1.16") {
		options.PullParent = true
	}

	options.Dockerfile = r.FormValue("dockerfile")
	options.SuppressOutput = httputils.BoolValue(r, "q")
	options.NoCache = httputils.BoolValue(r, "nocache")
	options.ForceRemove = httputils.BoolValue(r, "forcerm")
	options.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
	options.Memory = httputils.Int64ValueOrZero(r, "memory")
	options.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
	options.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
	options.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
	options.CPUSetCPUs = r.FormValue("cpusetcpus")
	options.CPUSetMems = r.FormValue("cpusetmems")
	options.CgroupParent = r.FormValue("cgroupparent")
	options.NetworkMode = r.FormValue("networkmode")
	options.Tags = r.Form["t"]
	options.ExtraHosts = r.Form["extrahosts"]
	options.SecurityOpt = r.Form["securityopt"]
	options.Squash = httputils.BoolValue(r, "squash")
	options.Target = r.FormValue("target")
	options.RemoteContext = r.FormValue("remote")
	if versions.GreaterThanOrEqualTo(version, "1.32") {
		options.Platform = r.FormValue("platform")
	}

	if r.Form.Get("shmsize") != "" {
		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
		if err != nil {
			return nil, err
		}
		options.ShmSize = shmSize
	}

	if i := container.Isolation(r.FormValue("isolation")); i != "" {
		if !container.Isolation.IsValid(i) {
			return nil, invalidIsolationError(i)
		}
		options.Isolation = i
	}

	if runtime.GOOS != "windows" && options.SecurityOpt != nil {
		return nil, errdefs.InvalidParameter(errors.New("The daemon on this platform does not support setting security options on build"))
	}

	var buildUlimits = []*units.Ulimit{}
	ulimitsJSON := r.FormValue("ulimits")
	if ulimitsJSON != "" {
		if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading ulimit settings")
		}
		options.Ulimits = buildUlimits
	}

	// Note that there are two ways a --build-arg might appear in the
	// json of the query param:
	//     "foo":"bar"
	// and "foo":nil
	// The first is the normal case, ie. --build-arg foo=bar
	// or  --build-arg foo
	// where foo's value was picked up from an env var.
	// The second ("foo":nil) is where they put --build-arg foo
	// but "foo" isn't set as an env var. In that case we can't just drop
	// the fact they mentioned it, we need to pass that along to the builder
	// so that it can print a warning about "foo" being unused if there is
	// no "ARG foo" in the Dockerfile.
	buildArgsJSON := r.FormValue("buildargs")
	if buildArgsJSON != "" {
		var buildArgs = map[string]*string{}
		if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading build args")
		}
		options.BuildArgs = buildArgs
	}

	labelsJSON := r.FormValue("labels")
	if labelsJSON != "" {
		var labels = map[string]string{}
		if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading labels")
		}
		options.Labels = labels
	}

	cacheFromJSON := r.FormValue("cachefrom")
	if cacheFromJSON != "" {
		var cacheFrom = []string{}
		if err := json.Unmarshal([]byte(cacheFromJSON), &cacheFrom); err != nil {
			return nil, err
		}
		options.CacheFrom = cacheFrom
	}
	options.SessionID = r.FormValue("session")
	options.BuildID = r.FormValue("buildid")
	builderVersion, err := parseVersion(r.FormValue("version"))
	if err != nil {
		return nil, err
	}
	options.Version = builderVersion

	return options, nil
}

func parseVersion(s string) (types.BuilderVersion, error) {
	if s == "" || s == string(types.BuilderV1) {
		return types.BuilderV1, nil
	}
	if s == string(types.BuilderBuildKit) {
		return types.BuilderBuildKit, nil
	}
	return "", errors.Errorf("invalid version %s", s)
}

func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	report, err := br.backend.PruneCache(ctx)
	if err != nil {
		return err
	}
	return httputils.WriteJSON(w, http.StatusOK, report)
}

func (br *buildRouter) postCancel(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	w.Header().Set("Content-Type", "application/json")

	id := r.FormValue("id")
	if id == "" {
		return errors.Errorf("build ID not provided")
	}

	return br.backend.Cancel(ctx, id)
}

func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	var (
		notVerboseBuffer = bytes.NewBuffer(nil)
		version          = httputils.VersionFromContext(ctx)
	)

	w.Header().Set("Content-Type", "application/json")

	body := r.Body
	var ww io.Writer = w
	if body != nil {
		// there is a possibility that output is written before request body
		// has been fully read so we need to protect against it.
		// this can be removed when
		// https://github.com/golang/go/issues/15527
		// https://github.com/golang/go/issues/22209
		// has been fixed
		body, ww = wrapOutputBufferedUntilRequestRead(body, ww)
	}

	output := ioutils.NewWriteFlusher(ww)
	defer output.Close()

	errf := func(err error) error {

		if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
			output.Write(notVerboseBuffer.Bytes())
		}

		// Do not write the error in the http output if it's still empty.
		// This prevents from writing a 200(OK) when there is an internal error.
		if !output.Flushed() {
			return err
		}
		_, err = output.Write(streamformatter.FormatError(err))
		if err != nil {
			logrus.Warnf("could not write error response: %v", err)
		}
		return nil
	}

	buildOptions, err := newImageBuildOptions(ctx, r)
	if err != nil {
		return errf(err)
	}
	buildOptions.AuthConfigs = getAuthConfigs(r.Header)

	if buildOptions.Squash && !br.daemon.HasExperimental() {
		return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
	}

	// check if the builder feature has been enabled from daemon as well.
	if buildOptions.Version == types.BuilderBuildKit &&
		(br.builderVersion != types.BuilderBuildKit || !br.daemon.HasExperimental()) {
		return errdefs.InvalidParameter(errors.New("buildkit is not enabled on daemon"))
	}

	out := io.Writer(output)
	if buildOptions.SuppressOutput {
		out = notVerboseBuffer
	}

	// Currently, only used if context is from a remote url.
	// Look at code in DetectContextFromRemoteURL for more information.
	createProgressReader := func(in io.ReadCloser) io.ReadCloser {
		progressOutput := streamformatter.NewJSONProgressOutput(out, true)
		return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", buildOptions.RemoteContext)
	}

	wantAux := versions.GreaterThanOrEqualTo(version, "1.30")

	imgID, err := br.backend.Build(ctx, backend.BuildConfig{
		Source:         body,
		Options:        buildOptions,
		ProgressWriter: buildProgressWriter(out, wantAux, createProgressReader),
	})
	if err != nil {
		return errf(err)
	}

	// Everything worked so if -q was provided the output from the daemon
	// should be just the image ID and we'll print that to stdout.
	if buildOptions.SuppressOutput {
		fmt.Fprintln(streamformatter.NewStdoutWriter(output), imgID)
	}
	return nil
}

func getAuthConfigs(header http.Header) map[string]types.AuthConfig {
	authConfigs := map[string]types.AuthConfig{}
	authConfigsEncoded := header.Get("X-Registry-Config")

	if authConfigsEncoded == "" {
		return authConfigs
	}

	authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authConfigsEncoded))
	// Pulling an image does not error when no auth is provided so to remain
	// consistent with the existing api decode errors are ignored
	json.NewDecoder(authConfigsJSON).Decode(&authConfigs)
	return authConfigs
}

type syncWriter struct {
	w  io.Writer
	mu sync.Mutex
}

func (s *syncWriter) Write(b []byte) (count int, err error) {
	s.mu.Lock()
	count, err = s.w.Write(b)
	s.mu.Unlock()
	return
}

func buildProgressWriter(out io.Writer, wantAux bool, createProgressReader func(io.ReadCloser) io.ReadCloser) backend.ProgressWriter {
	out = &syncWriter{w: out}

	var aux *streamformatter.AuxFormatter
	if wantAux {
		aux = &streamformatter.AuxFormatter{Writer: out}
	}

	return backend.ProgressWriter{
		Output:             out,
		StdoutFormatter:    streamformatter.NewStdoutWriter(out),
		StderrFormatter:    streamformatter.NewStderrWriter(out),
		AuxFormatter:       aux,
		ProgressReaderFunc: createProgressReader,
	}
}

type flusher interface {
	Flush()
}

func wrapOutputBufferedUntilRequestRead(rc io.ReadCloser, out io.Writer) (io.ReadCloser, io.Writer) {
	var fl flusher = &ioutils.NopFlusher{}
	if f, ok := out.(flusher); ok {
		fl = f
	}

	w := &wcf{
		buf:     bytes.NewBuffer(nil),
		Writer:  out,
		flusher: fl,
	}
	r := bufio.NewReader(rc)
	_, err := r.Peek(1)
	if err != nil {
		return rc, out
	}
	rc = &rcNotifier{
		Reader: r,
		Closer: rc,
		notify: w.notify,
	}
	return rc, w
}

type rcNotifier struct {
	io.Reader
	io.Closer
	notify func()
}

func (r *rcNotifier) Read(b []byte) (int, error) {
	n, err := r.Reader.Read(b)
	if err != nil {
		r.notify()
	}
	return n, err
}

func (r *rcNotifier) Close() error {
	r.notify()
	return r.Closer.Close()
}

type wcf struct {
	io.Writer
	flusher
	mu      sync.Mutex
	ready   bool
	buf     *bytes.Buffer
	flushed bool
}

func (w *wcf) Flush() {
	w.mu.Lock()
	w.flushed = true
	if !w.ready {
		w.mu.Unlock()
		return
	}
	w.mu.Unlock()
	w.flusher.Flush()
}

func (w *wcf) Flushed() bool {
	w.mu.Lock()
	b := w.flushed
	w.mu.Unlock()
	return b
}

func (w *wcf) Write(b []byte) (int, error) {
	w.mu.Lock()
	if !w.ready {
		n, err := w.buf.Write(b)
		w.mu.Unlock()
		return n, err
	}
	w.mu.Unlock()
	return w.Writer.Write(b)
}

func (w *wcf) notify() {
	w.mu.Lock()
	if !w.ready {
		if w.buf.Len() > 0 {
			io.Copy(w.Writer, w.buf)
		}
		if w.flushed {
			w.flusher.Flush()
		}
		w.ready = true
	}
	w.mu.Unlock()
}
<commit_msg>remove experimental guard for buildkit<commit_after>package build // import "github.com/docker/docker/api/server/router/build"

import (
	"bufio"
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"runtime"
	"strconv"
	"strings"
	"sync"

	"github.com/docker/docker/api/server/httputils"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/backend"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/versions"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/ioutils"
	"github.com/docker/docker/pkg/progress"
	"github.com/docker/docker/pkg/streamformatter"
	units "github.com/docker/go-units"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

type invalidIsolationError string

func (e invalidIsolationError) Error() string {
	return fmt.Sprintf("Unsupported isolation: %q", string(e))
}

func (e invalidIsolationError) InvalidParameter() {}

func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
	version := httputils.VersionFromContext(ctx)
	options := &types.ImageBuildOptions{}
	if httputils.BoolValue(r, "forcerm") && versions.GreaterThanOrEqualTo(version, "1.12") {
		options.Remove = true
	} else if r.FormValue("rm") == "" && versions.GreaterThanOrEqualTo(version, "1.12") {
		options.Remove = true
	} else {
		options.Remove = httputils.BoolValue(r, "rm")
	}
	if httputils.BoolValue(r, "pull") && versions.GreaterThanOrEqualTo(version, "1.16") {
		options.PullParent = true
	}

	options.Dockerfile = r.FormValue("dockerfile")
	options.SuppressOutput = httputils.BoolValue(r, "q")
	options.NoCache = httputils.BoolValue(r, "nocache")
	options.ForceRemove = httputils.BoolValue(r, "forcerm")
	options.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
	options.Memory = httputils.Int64ValueOrZero(r, "memory")
	options.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
	options.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
	options.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
	options.CPUSetCPUs = r.FormValue("cpusetcpus")
	options.CPUSetMems = r.FormValue("cpusetmems")
	options.CgroupParent = r.FormValue("cgroupparent")
	options.NetworkMode = r.FormValue("networkmode")
	options.Tags = r.Form["t"]
	options.ExtraHosts = r.Form["extrahosts"]
	options.SecurityOpt = r.Form["securityopt"]
	options.Squash = httputils.BoolValue(r, "squash")
	options.Target = r.FormValue("target")
	options.RemoteContext = r.FormValue("remote")
	if versions.GreaterThanOrEqualTo(version, "1.32") {
		options.Platform = r.FormValue("platform")
	}

	if r.Form.Get("shmsize") != "" {
		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
		if err != nil {
			return nil, err
		}
		options.ShmSize = shmSize
	}

	if i := container.Isolation(r.FormValue("isolation")); i != "" {
		if !container.Isolation.IsValid(i) {
			return nil, invalidIsolationError(i)
		}
		options.Isolation = i
	}

	if runtime.GOOS != "windows" && options.SecurityOpt != nil {
		return nil, errdefs.InvalidParameter(errors.New("The daemon on this platform does not support setting security options on build"))
	}

	var buildUlimits = []*units.Ulimit{}
	ulimitsJSON := r.FormValue("ulimits")
	if ulimitsJSON != "" {
		if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading ulimit settings")
		}
		options.Ulimits = buildUlimits
	}

	// Note that there are two ways a --build-arg might appear in the
	// json of the query param:
	//     "foo":"bar"
	// and "foo":nil
	// The first is the normal case, ie. --build-arg foo=bar
	// or  --build-arg foo
	// where foo's value was picked up from an env var.
	// The second ("foo":nil) is where they put --build-arg foo
	// but "foo" isn't set as an env var. In that case we can't just drop
	// the fact they mentioned it, we need to pass that along to the builder
	// so that it can print a warning about "foo" being unused if there is
	// no "ARG foo" in the Dockerfile.
	buildArgsJSON := r.FormValue("buildargs")
	if buildArgsJSON != "" {
		var buildArgs = map[string]*string{}
		if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading build args")
		}
		options.BuildArgs = buildArgs
	}

	labelsJSON := r.FormValue("labels")
	if labelsJSON != "" {
		var labels = map[string]string{}
		if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil {
			return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading labels")
		}
		options.Labels = labels
	}

	cacheFromJSON := r.FormValue("cachefrom")
	if cacheFromJSON != "" {
		var cacheFrom = []string{}
		if err := json.Unmarshal([]byte(cacheFromJSON), &cacheFrom); err != nil {
			return nil, err
		}
		options.CacheFrom = cacheFrom
	}
	options.SessionID = r.FormValue("session")
	options.BuildID = r.FormValue("buildid")
	builderVersion, err := parseVersion(r.FormValue("version"))
	if err != nil {
		return nil, err
	}
	options.Version = builderVersion

	return options, nil
}

func parseVersion(s string) (types.BuilderVersion, error) {
	if s == "" || s == string(types.BuilderV1) {
		return types.BuilderV1, nil
	}
	if s == string(types.BuilderBuildKit) {
		return types.BuilderBuildKit, nil
	}
	return "", errors.Errorf("invalid version %s", s)
}

func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	report, err := br.backend.PruneCache(ctx)
	if err != nil {
		return err
	}
	return httputils.WriteJSON(w, http.StatusOK, report)
}

func (br *buildRouter) postCancel(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	w.Header().Set("Content-Type", "application/json")

	id := r.FormValue("id")
	if id == "" {
		return errors.Errorf("build ID not provided")
	}

	return br.backend.Cancel(ctx, id)
}

func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	var (
		notVerboseBuffer = bytes.NewBuffer(nil)
		version          = httputils.VersionFromContext(ctx)
	)

	w.Header().Set("Content-Type", "application/json")

	body := r.Body
	var ww io.Writer = w
	if body != nil {
		// there is a possibility that output is written before request body
		// has been fully read so we need to protect against it.
		// this can be removed when
		// https://github.com/golang/go/issues/15527
		// https://github.com/golang/go/issues/22209
		// has been fixed
		body, ww = wrapOutputBufferedUntilRequestRead(body, ww)
	}

	output := ioutils.NewWriteFlusher(ww)
	defer output.Close()

	errf := func(err error) error {

		if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
			output.Write(notVerboseBuffer.Bytes())
		}

		// Do not write the error in the http output if it's still empty.
		// This prevents from writing a 200(OK) when there is an internal error.
		if !output.Flushed() {
			return err
		}
		_, err = output.Write(streamformatter.FormatError(err))
		if err != nil {
			logrus.Warnf("could not write error response: %v", err)
		}
		return nil
	}

	buildOptions, err := newImageBuildOptions(ctx, r)
	if err != nil {
		return errf(err)
	}
	buildOptions.AuthConfigs = getAuthConfigs(r.Header)

	if buildOptions.Squash && !br.daemon.HasExperimental() {
		return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode"))
	}

	// check if the builder feature has been enabled from daemon as well.
	if buildOptions.Version == types.BuilderBuildKit && br.builderVersion != types.BuilderBuildKit {
		return errdefs.InvalidParameter(errors.New("buildkit is not enabled on daemon"))
	}

	out := io.Writer(output)
	if buildOptions.SuppressOutput {
		out = notVerboseBuffer
	}

	// Currently, only used if context is from a remote url.
	// Look at code in DetectContextFromRemoteURL for more information.
	createProgressReader := func(in io.ReadCloser) io.ReadCloser {
		progressOutput := streamformatter.NewJSONProgressOutput(out, true)
		return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", buildOptions.RemoteContext)
	}

	wantAux := versions.GreaterThanOrEqualTo(version, "1.30")

	imgID, err := br.backend.Build(ctx, backend.BuildConfig{
		Source:         body,
		Options:        buildOptions,
		ProgressWriter: buildProgressWriter(out, wantAux, createProgressReader),
	})
	if err != nil {
		return errf(err)
	}

	// Everything worked so if -q was provided the output from the daemon
	// should be just the image ID and we'll print that to stdout.
	if buildOptions.SuppressOutput {
		fmt.Fprintln(streamformatter.NewStdoutWriter(output), imgID)
	}
	return nil
}

func getAuthConfigs(header http.Header) map[string]types.AuthConfig {
	authConfigs := map[string]types.AuthConfig{}
	authConfigsEncoded := header.Get("X-Registry-Config")

	if authConfigsEncoded == "" {
		return authConfigs
	}

	authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authConfigsEncoded))
	// Pulling an image does not error when no auth is provided so to remain
	// consistent with the existing api decode errors are ignored
	json.NewDecoder(authConfigsJSON).Decode(&authConfigs)
	return authConfigs
}

type syncWriter struct {
	w  io.Writer
	mu sync.Mutex
}

func (s *syncWriter) Write(b []byte) (count int, err error) {
	s.mu.Lock()
	count, err = s.w.Write(b)
	s.mu.Unlock()
	return
}

func buildProgressWriter(out io.Writer, wantAux bool, createProgressReader func(io.ReadCloser) io.ReadCloser) backend.ProgressWriter {
	out = &syncWriter{w: out}

	var aux *streamformatter.AuxFormatter
	if wantAux {
		aux = &streamformatter.AuxFormatter{Writer: out}
	}

	return backend.ProgressWriter{
		Output:             out,
		StdoutFormatter:    streamformatter.NewStdoutWriter(out),
		StderrFormatter:    streamformatter.NewStderrWriter(out),
		AuxFormatter:       aux,
		ProgressReaderFunc: createProgressReader,
	}
}

type flusher interface {
	Flush()
}

func wrapOutputBufferedUntilRequestRead(rc io.ReadCloser, out io.Writer) (io.ReadCloser, io.Writer) {
	var fl flusher = &ioutils.NopFlusher{}
	if f, ok := out.(flusher); ok {
		fl = f
	}

	w := &wcf{
		buf:     bytes.NewBuffer(nil),
		Writer:  out,
		flusher: fl,
	}
	r := bufio.NewReader(rc)
	_, err := r.Peek(1)
	if err != nil {
		return rc, out
	}
	rc = &rcNotifier{
		Reader: r,
		Closer: rc,
		notify: w.notify,
	}
	return rc, w
}

type rcNotifier struct {
	io.Reader
	io.Closer
	notify func()
}

func (r *rcNotifier) Read(b []byte) (int, error) {
	n, err := r.Reader.Read(b)
	if err != nil {
		r.notify()
	}
	return n, err
}

func (r *rcNotifier) Close() error {
	r.notify()
	return r.Closer.Close()
}

type wcf struct {
	io.Writer
	flusher
	mu      sync.Mutex
	ready   bool
	buf     *bytes.Buffer
	flushed bool
}

func (w *wcf) Flush() {
	w.mu.Lock()
	w.flushed = true
	if !w.ready {
		w.mu.Unlock()
		return
	}
	w.mu.Unlock()
	w.flusher.Flush()
}

func (w *wcf) Flushed() bool {
	w.mu.Lock()
	b := w.flushed
	w.mu.Unlock()
	return b
}

func (w *wcf) Write(b []byte) (int, error) {
	w.mu.Lock()
	if !w.ready {
		n, err := w.buf.Write(b)
		w.mu.Unlock()
		return n, err
	}
	w.mu.Unlock()
	return w.Writer.Write(b)
}

func (w *wcf) notify() {
	w.mu.Lock()
	if !w.ready {
		if w.buf.Len() > 0 {
			io.Copy(w.Writer, w.buf)
		}
		if w.flushed {
			w.flusher.Flush()
		}
		w.ready = true
	}
	w.mu.Unlock()
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Nick Patavalis (npat@efault.net).
// All rights reserved.
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

// +build linux freebsd netbsd openbsd darwin dragonfly solaris

// !! Tests are necessarily superficial !!

package termios_test

import (
	"os"
	"syscall"
	"testing"
	"time"

	"github.com/npat-efault/serial/termios"
)

func TestFlags(t *testing.T) {
	ti := termios.Termios{}
	if *ti.IFlag() != 0 || *ti.OFlag() != 0 ||
		*ti.CFlag() != 0 || *ti.LFlag() != 0 {
		t.Fatalf("Termios struct not zero: %+v", ti)
	}
	ti.CFlag().Clr(termios.CSIZE).Set(termios.CS8)
	if ti.CFlag().Msk(termios.CSIZE) != termios.CS8 {
		t.Fatalf("Bad CFlag: %b", *ti.CFlag())
	}
	if !ti.CFlag().Set(termios.CLOCAL).Any(termios.CLOCAL | termios.HUPCL) {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
	if ti.CFlag().All(termios.CLOCAL | termios.HUPCL) {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
}

func TestMakeRaw(t *testing.T) {
	ti := termios.Termios{}
	ti.MakeRaw()
	// Check some arbitrary fields
	if ti.CFlag().Msk(termios.CSIZE) != termios.CS8 {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
	/*
		if !ti.CFlag().All(termios.CREAD) {
			t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
		}
	*/
	if ti.Cc(termios.VMIN) != 1 {
		t.Fatalf("Bad VMIN: %b", ti.Cc(termios.VMIN))
	}
	if ti.Cc(termios.VTIME) != 0 {
		t.Fatalf("Bad VTIME: %b", ti.Cc(termios.VTIME))
	}
}

func TestSpeed(t *testing.T) {
	ti := termios.Termios{}
	spds_ok := []int{1200, 4800, 9600, 19200, 38400}
	spds_fail := []int{-1, -2, -3}
	for _, s := range spds_ok {
		// Output Speeds
		if err := ti.SetOSpeed(s); err != nil {
			t.Fatalf("Cannot set out speed %d: %v", s, err)
		}
		s1, err := ti.GetOSpeed()
		if err != nil {
			t.Fatalf("Cannot get out speed %d: %v", s, err)
		}
		if s1 != s {
			t.Fatalf("Out speed: %d != %d", s1, s)
		}
		// Input Speeds
		if err := ti.SetISpeed(s); err != nil {
			t.Fatalf("Cannot set in speed %d: %v", s, err)
		}
		s1, err = ti.GetISpeed()
		if err != nil {
			t.Fatalf("Cannot get in speed %d: %v", s, err)
		}
		if s1 != s {
			t.Fatalf("In speed: %d != %d", s1, s)
		}
	}
	for _, s := range spds_fail {
		if err := ti.SetOSpeed(s); err != syscall.EINVAL {
			t.Fatalf("Set bad out speed %d", s)
		}
		if err := ti.SetISpeed(s); err != syscall.EINVAL {
			t.Fatalf("Set bad in speed %d", s)
		}
	}
}

var dev = os.Getenv("TEST_SERIAL_DEV")

func TestSetGet(t *testing.T) {
	if dev == "" {
		t.Skip("No TEST_SERIAL_DEV variable set.")
	}
	f, err := os.Open(dev)
	if err != nil {
		t.Fatal("Open:", err)
	}
	defer f.Close()

	var ti termios.Termios
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	err = ti.SetOSpeed(19200)
	if err != nil {
		t.Fatal("Cannot set speed to 19200:", err)
	}
	err = ti.SetFd(int(f.Fd()), termios.TCSAFLUSH)
	if err != nil {
		t.Fatal("Cannot set termios:", err)
	}
	ti = termios.Termios{}
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	spd, err := ti.GetOSpeed()
	if err != nil {
		t.Fatal("Cannot get speed:", err)
	}
	if spd != 19200 {
		t.Fatalf("Bad speed: %d != %d", spd, 19200)
	}
}

func TestMisc(t *testing.T) {
	if dev == "" {
		t.Skip("No TEST_SERIAL_DEV variable set.")
	}
	f, err := os.OpenFile(dev, os.O_RDWR, 0)
	if err != nil {
		t.Fatal("Open:", err)
	}
	defer f.Close()

	var ti termios.Termios
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	/* Set low baudrate */
	baudrate := 1200
	ti.SetOSpeed(baudrate)
	/* Disable flow control */
	ti.CFlag().Clr(termios.CRTSCTS)
	ti.IFlag().Clr(termios.IXON | termios.IXOFF | termios.IXANY)
	err = ti.SetFd(int(f.Fd()), termios.TCSANOW)
	if err != nil {
		t.Fatal("Cannot set termios:", err)
	}

	/* Try to test Drain */
	b := make([]byte, 600)
	start := time.Now()
	if _, err := f.Write(b); err != nil {
		t.Fatal("Cannot write:", err)
	}
	err = termios.Drain(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot drain:", err)
	}
	dur := time.Since(start)
	charTime := 10 * time.Second / time.Duration(baudrate)
	chars := int(dur / charTime)
	// Allow some fuzz for h/w queues and stuff.
	if chars < len(b)-16 || chars > len(b)+16 {
		t.Logf("Invalid tx time %v (%d chars):", dur, chars)
	}

	/* Try to test SendBreak */
	start = time.Now()
	termios.SendBreak(int(f.Fd()))
	dur = time.Since(start)
	// POSIX says SendBreak should last between 0.25 and 1 Sec.
	if dur < 200*time.Millisecond || dur > 1100*time.Millisecond {
		t.Log("Bad SendBreak duration:", dur)
	}

	// Just call Flush
	if err := termios.Flush(int(f.Fd()), termios.TCIFLUSH); err != nil {
		t.Fatal("Flush In failed:", err)
	}
	if err := termios.Flush(int(f.Fd()), termios.TCOFLUSH); err != nil {
		t.Fatal("Flush Out failed:", err)
	}
	if err := termios.Flush(int(f.Fd()), termios.TCIOFLUSH); err != nil {
		t.Fatal("Flush InOut failed:", err)
	}
	// This should normally fail (depends on system tcflush()
	// implementation)
	if err := termios.Flush(int(f.Fd()), 4242); err == nil {
		t.Logf("Flush 4242 should fail!")
	}
}
<commit_msg>Set both I and O port speeds when testing<commit_after>// Copyright (c) 2015, Nick Patavalis (npat@efault.net).
// All rights reserved.
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

// +build linux freebsd netbsd openbsd darwin dragonfly solaris

// !! Tests are necessarily superficial !!

package termios_test

import (
	"os"
	"syscall"
	"testing"
	"time"

	"github.com/npat-efault/serial/termios"
)

func TestFlags(t *testing.T) {
	ti := termios.Termios{}
	if *ti.IFlag() != 0 || *ti.OFlag() != 0 ||
		*ti.CFlag() != 0 || *ti.LFlag() != 0 {
		t.Fatalf("Termios struct not zero: %+v", ti)
	}
	ti.CFlag().Clr(termios.CSIZE).Set(termios.CS8)
	if ti.CFlag().Msk(termios.CSIZE) != termios.CS8 {
		t.Fatalf("Bad CFlag: %b", *ti.CFlag())
	}
	if !ti.CFlag().Set(termios.CLOCAL).Any(termios.CLOCAL | termios.HUPCL) {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
	if ti.CFlag().All(termios.CLOCAL | termios.HUPCL) {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
}

func TestMakeRaw(t *testing.T) {
	ti := termios.Termios{}
	ti.MakeRaw()
	// Check some arbitrary fields
	if ti.CFlag().Msk(termios.CSIZE) != termios.CS8 {
		t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
	}
	/*
		if !ti.CFlag().All(termios.CREAD) {
			t.Fatalf("Bad CFlag: %b", ti.CFlag().Val())
		}
	*/
	if ti.Cc(termios.VMIN) != 1 {
		t.Fatalf("Bad VMIN: %b", ti.Cc(termios.VMIN))
	}
	if ti.Cc(termios.VTIME) != 0 {
		t.Fatalf("Bad VTIME: %b", ti.Cc(termios.VTIME))
	}
}

func TestSpeed(t *testing.T) {
	ti := termios.Termios{}
	spds_ok := []int{1200, 4800, 9600, 19200, 38400}
	spds_fail := []int{-1, -2, -3}
	for _, s := range spds_ok {
		// Output Speeds
		if err := ti.SetOSpeed(s); err != nil {
			t.Fatalf("Cannot set out speed %d: %v", s, err)
		}
		s1, err := ti.GetOSpeed()
		if err != nil {
			t.Fatalf("Cannot get out speed %d: %v", s, err)
		}
		if s1 != s {
			t.Fatalf("Out speed: %d != %d", s1, s)
		}
		// Input Speeds
		if err := ti.SetISpeed(s); err != nil {
			t.Fatalf("Cannot set in speed %d: %v", s, err)
		}
		s1, err = ti.GetISpeed()
		if err != nil {
			t.Fatalf("Cannot get in speed %d: %v", s, err)
		}
		if s1 != s {
			t.Fatalf("In speed: %d != %d", s1, s)
		}
	}
	for _, s := range spds_fail {
		if err := ti.SetOSpeed(s); err != syscall.EINVAL {
			t.Fatalf("Set bad out speed %d", s)
		}
		if err := ti.SetISpeed(s); err != syscall.EINVAL {
			t.Fatalf("Set bad in speed %d", s)
		}
	}
}

var dev = os.Getenv("TEST_SERIAL_DEV")

func TestSetGet(t *testing.T) {
	if dev == "" {
		t.Skip("No TEST_SERIAL_DEV variable set.")
	}
	f, err := os.Open(dev)
	if err != nil {
		t.Fatal("Open:", err)
	}
	defer f.Close()

	var ti termios.Termios
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	err = ti.SetOSpeed(19200)
	if err != nil {
		t.Fatal("Cannot set O speed to 19200:", err)
	}
	ti.SetISpeed(0) // Same as O-speed
	err = ti.SetFd(int(f.Fd()), termios.TCSAFLUSH)
	if err != nil {
		t.Fatal("Cannot set termios:", err)
	}
	ti = termios.Termios{}
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	spd, err := ti.GetOSpeed()
	if err != nil {
		t.Fatal("Cannot get O speed:", err)
	}
	if spd != 19200 {
		t.Fatalf("Bad O speed: %d != %d", spd, 19200)
	}
	spd, err = ti.GetISpeed()
	if err != nil {
		t.Fatal("Cannot get I speed:", err)
	}
	if spd != 19200 && spd != 0 {
		t.Fatalf("Bad I speed: %d != %d", spd, 19200)
	}
}

func TestMisc(t *testing.T) {
	if dev == "" {
		t.Skip("No TEST_SERIAL_DEV variable set.")
	}
	f, err := os.OpenFile(dev, os.O_RDWR, 0)
	if err != nil {
		t.Fatal("Open:", err)
	}
	defer f.Close()

	var ti termios.Termios
	err = ti.GetFd(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot get termios:", err)
	}
	/* Set low baudrate */
	baudrate := 1200
	ti.SetOSpeed(baudrate)
	ti.SetISpeed(0) // Same as O-speed
	/* Disable flow control */
	ti.CFlag().Clr(termios.CRTSCTS)
	ti.IFlag().Clr(termios.IXON | termios.IXOFF | termios.IXANY)
	err = ti.SetFd(int(f.Fd()), termios.TCSANOW)
	if err != nil {
		t.Fatal("Cannot set termios:", err)
	}

	/* Try to test Drain */
	b := make([]byte, 600)
	start := time.Now()
	if _, err := f.Write(b); err != nil {
		t.Fatal("Cannot write:", err)
	}
	err = termios.Drain(int(f.Fd()))
	if err != nil {
		t.Fatal("Cannot drain:", err)
	}
	dur := time.Since(start)
	charTime := 10 * time.Second / time.Duration(baudrate)
	chars := int(dur / charTime)
	// Allow some fuzz for h/w queues and stuff.
	if chars < len(b)-16 || chars > len(b)+16 {
		t.Logf("Invalid tx time %v (%d chars):", dur, chars)
	}

	/* Try to test SendBreak */
	start = time.Now()
	termios.SendBreak(int(f.Fd()))
	dur = time.Since(start)
	// POSIX says SendBreak should last between 0.25 and 1 Sec.
	if dur < 200*time.Millisecond || dur > 1100*time.Millisecond {
		t.Log("Bad SendBreak duration:", dur)
	}

	// Just call Flush
	if err := termios.Flush(int(f.Fd()), termios.TCIFLUSH); err != nil {
		t.Fatal("Flush In failed:", err)
	}
	if err := termios.Flush(int(f.Fd()), termios.TCOFLUSH); err != nil {
		t.Fatal("Flush Out failed:", err)
	}
	if err := termios.Flush(int(f.Fd()), termios.TCIOFLUSH); err != nil {
		t.Fatal("Flush InOut failed:", err)
	}
	// This should normally fail (depends on system tcflush()
	// implementation)
	if err := termios.Flush(int(f.Fd()), 4242); err == nil {
		t.Logf("Flush 4242 should fail!")
	}
}
<|endoftext|>


<commit_before>// This program reads all assertion functions from the assert package and
// automatically generates the corersponding requires and forwarded assertions

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
	"text/template"

	"github.com/ernesto-jimenez/gogen/imports"
)

var (
	pkg       = flag.String("assert-path", "github.com/stretchr/testify/assert", "Path to the assert package")
	outputPkg = flag.String("output-package", "", "package for the resulting code")
	tmplFile  = flag.String("template", "", "What file to load the function template from")
	out       = flag.String("out", "", "What file to write the source code to")
)

func main() {
	flag.Parse()

	scope, docs, err := parsePackageSource(*pkg)
	if err != nil {
		log.Fatal(err)
	}

	importer, funcs, err := analyzeCode(scope, docs)
	if err != nil {
		log.Fatal(err)
	}

	if err := generateCode(importer, funcs); err != nil {
		log.Fatal(err)
	}
}

func generateCode(importer imports.Importer, funcs []testFunc) error {
	buff := bytes.NewBuffer(nil)

	tmplHead, tmplFunc, err := parseTemplates()
	if err != nil {
		return err
	}

	// Generate header
	if err := tmplHead.Execute(buff, struct {
		Name    string
		Imports map[string]string
	}{
		*outputPkg,
		importer.Imports(),
	}); err != nil {
		return err
	}

	// Generate funcs
	for _, fn := range funcs {
		buff.Write([]byte("\n\n"))
		if err := tmplFunc.Execute(buff, &fn); err != nil {
			return err
		}
	}

	// Write file
	output, err := outputFile()
	if err != nil {
		return err
	}
	defer output.Close()
	_, err = io.Copy(output, buff)
	return err
}

func parseTemplates() (*template.Template, *template.Template, error) {
	tmplHead, err := template.New("header").Parse(headerTemplate)
	if err != nil {
		return nil, nil, err
	}
	if *tmplFile != "" {
		f, err := ioutil.ReadFile(*tmplFile)
		if err != nil {
			return nil, nil, err
		}
		funcTemplate = string(f)
	}
	tmpl, err := template.New("function").Parse(funcTemplate)
	if err != nil {
		return nil, nil, err
	}
	return tmplHead, tmpl, nil
}

func outputFile() (*os.File, error) {
	filename := *out
	if filename == "-" || (filename == "" && *tmplFile == "") {
		return os.Stdout, nil
	}
	if filename == "" {
		filename = strings.TrimSuffix(strings.TrimSuffix(*tmplFile, ".tmpl"), ".go") + ".go"
	}
	return os.Create(filename)
}

// analyzeCode takes the types scope and the docs and returns the import
// information and information about all the assertion functions.
func analyzeCode(scope *types.Scope, docs *doc.Package) (imports.Importer, []testFunc, error) {
	testingT := scope.Lookup("TestingT").Type().Underlying().(*types.Interface)

	importer := imports.New(*outputPkg)
	var funcs []testFunc
	// Go through all the top level functions
	for _, fdocs := range docs.Funcs {
		// Find the function
		obj := scope.Lookup(fdocs.Name)

		fn, ok := obj.(*types.Func)
		if !ok {
			continue
		}
		// Check function signatuer has at least two arguments
		sig := fn.Type().(*types.Signature)
		if sig.Params().Len() < 2 {
			continue
		}
		// Check first argument is of type testingT
		first, ok := sig.Params().At(0).Type().(*types.Named)
		if !ok {
			continue
		}
		firstType, ok := first.Underlying().(*types.Interface)
		if !ok {
			continue
		}
		if !types.Implements(firstType, testingT) {
			continue
		}

		funcs = append(funcs, testFunc{*outputPkg, fdocs, fn})
		importer.AddImportsFrom(sig.Params())
	}
	return importer, funcs, nil
}

// parsePackageSource returns the types scope and the package documentation from the pa
func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
	pd, err := build.Import(pkg, ".", 0)
	if err != nil {
		return nil, nil, err
	}

	fset := token.NewFileSet()
	files := make(map[string]*ast.File)
	fileList := make([]*ast.File, len(pd.GoFiles))
	for i, fname := range pd.GoFiles {
		src, err := ioutil.ReadFile(path.Join(pd.SrcRoot, pd.ImportPath, fname))
		if err != nil {
			return nil, nil, err
		}
		f, err := parser.ParseFile(fset, fname, src, parser.ParseComments|parser.AllErrors)
		if err != nil {
			return nil, nil, err
		}
		files[fname] = f
		fileList[i] = f
	}

	cfg := types.Config{
		Importer: importer.Default(),
	}
	info := types.Info{
		Defs: make(map[*ast.Ident]types.Object),
	}
	tp, err := cfg.Check(pkg, fset, fileList, &info)
	if err != nil {
		return nil, nil, err
	}

	scope := tp.Scope()

	ap, _ := ast.NewPackage(fset, files, nil, nil)
	docs := doc.New(ap, pkg, 0)

	return scope, docs, nil
}

type testFunc struct {
	CurrentPkg string
	DocInfo    *doc.Func
	TypeInfo   *types.Func
}

func (f *testFunc) Qualifier(p *types.Package) string {
	if p == nil || p.Name() == f.CurrentPkg {
		return ""
	}
	return p.Name()
}

func (f *testFunc) Params() string {
	sig := f.TypeInfo.Type().(*types.Signature)
	params := sig.Params()
	p := ""
	comma := ""
	to := params.Len()
	var i int

	if sig.Variadic() {
		to--
	}
	for i = 1; i < to; i++ {
		param := params.At(i)
		p += fmt.Sprintf("%s%s %s", comma, param.Name(), types.TypeString(param.Type(), f.Qualifier))
		comma = ", "
	}
	if sig.Variadic() {
		param := params.At(params.Len() - 1)
		p += fmt.Sprintf("%s%s ...%s", comma, param.Name(), types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier))
	}
	return p
}

func (f *testFunc) ForwardedParams() string {
	sig := f.TypeInfo.Type().(*types.Signature)
	params := sig.Params()
	p := ""
	comma := ""
	to := params.Len()
	var i int

	if sig.Variadic() {
		to--
	}
	for i = 1; i < to; i++ {
		param := params.At(i)
		p += fmt.Sprintf("%s%s", comma, param.Name())
		comma = ", "
	}
	if sig.Variadic() {
		param := params.At(params.Len() - 1)
		p += fmt.Sprintf("%s%s...", comma, param.Name())
	}
	return p
}

func (f *testFunc) Comment() string {
	return "// " + strings.Replace(strings.TrimSpace(f.DocInfo.Doc), "\n", "\n// ", -1)
}

func (f *testFunc) CommentWithoutT(receiver string) string {
	search := fmt.Sprintf("assert.%s(t, ", f.DocInfo.Name)
	replace := fmt.Sprintf("%s.%s(", receiver, f.DocInfo.Name)
	return strings.Replace(f.Comment(), search, replace, -1)
}

var headerTemplate = `/*
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/

package {{.Name}}

import (
{{range $path, $name := .Imports}}
	{{$name}} "{{$path}}"{{end}}
)
`

var funcTemplate = `{{.Comment}}
func (fwd *AssertionsForwarder) {{.DocInfo.Name}}({{.Params}}) bool {
	return assert.{{.DocInfo.Name}}({{.ForwardedParams}})
}`
<commit_msg>run go/format on generated code<commit_after>// This program reads all assertion functions from the assert package and
// automatically generates the corersponding requires and forwarded assertions

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/doc"
	"go/format"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"
	"text/template"

	"github.com/ernesto-jimenez/gogen/imports"
)

var (
	pkg       = flag.String("assert-path", "github.com/stretchr/testify/assert", "Path to the assert package")
	outputPkg = flag.String("output-package", "", "package for the resulting code")
	tmplFile  = flag.String("template", "", "What file to load the function template from")
	out       = flag.String("out", "", "What file to write the source code to")
)

func main() {
	flag.Parse()

	scope, docs, err := parsePackageSource(*pkg)
	if err != nil {
		log.Fatal(err)
	}

	importer, funcs, err := analyzeCode(scope, docs)
	if err != nil {
		log.Fatal(err)
	}

	if err := generateCode(importer, funcs); err != nil {
		log.Fatal(err)
	}
}

func generateCode(importer imports.Importer, funcs []testFunc) error {
	buff := bytes.NewBuffer(nil)

	tmplHead, tmplFunc, err := parseTemplates()
	if err != nil {
		return err
	}

	// Generate header
	if err := tmplHead.Execute(buff, struct {
		Name    string
		Imports map[string]string
	}{
		*outputPkg,
		importer.Imports(),
	}); err != nil {
		return err
	}

	// Generate funcs
	for _, fn := range funcs {
		buff.Write([]byte("\n\n"))
		if err := tmplFunc.Execute(buff, &fn); err != nil {
			return err
		}
	}

	code, err := format.Source(buff.Bytes())
	if err != nil {
		return err
	}

	// Write file
	output, err := outputFile()
	if err != nil {
		return err
	}
	defer output.Close()
	_, err = io.Copy(output, bytes.NewReader(code))
	return err
}

func parseTemplates() (*template.Template, *template.Template, error) {
	tmplHead, err := template.New("header").Parse(headerTemplate)
	if err != nil {
		return nil, nil, err
	}
	if *tmplFile != "" {
		f, err := ioutil.ReadFile(*tmplFile)
		if err != nil {
			return nil, nil, err
		}
		funcTemplate = string(f)
	}
	tmpl, err := template.New("function").Parse(funcTemplate)
	if err != nil {
		return nil, nil, err
	}
	return tmplHead, tmpl, nil
}

func outputFile() (*os.File, error) {
	filename := *out
	if filename == "-" || (filename == "" && *tmplFile == "") {
		return os.Stdout, nil
	}
	if filename == "" {
		filename = strings.TrimSuffix(strings.TrimSuffix(*tmplFile, ".tmpl"), ".go") + ".go"
	}
	return os.Create(filename)
}

// analyzeCode takes the types scope and the docs and returns the import
// information and information about all the assertion functions.
func analyzeCode(scope *types.Scope, docs *doc.Package) (imports.Importer, []testFunc, error) {
	testingT := scope.Lookup("TestingT").Type().Underlying().(*types.Interface)

	importer := imports.New(*outputPkg)
	var funcs []testFunc
	// Go through all the top level functions
	for _, fdocs := range docs.Funcs {
		// Find the function
		obj := scope.Lookup(fdocs.Name)

		fn, ok := obj.(*types.Func)
		if !ok {
			continue
		}
		// Check function signatuer has at least two arguments
		sig := fn.Type().(*types.Signature)
		if sig.Params().Len() < 2 {
			continue
		}
		// Check first argument is of type testingT
		first, ok := sig.Params().At(0).Type().(*types.Named)
		if !ok {
			continue
		}
		firstType, ok := first.Underlying().(*types.Interface)
		if !ok {
			continue
		}
		if !types.Implements(firstType, testingT) {
			continue
		}

		funcs = append(funcs, testFunc{*outputPkg, fdocs, fn})
		importer.AddImportsFrom(sig.Params())
	}
	return importer, funcs, nil
}

// parsePackageSource returns the types scope and the package documentation from the pa
func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
	pd, err := build.Import(pkg, ".", 0)
	if err != nil {
		return nil, nil, err
	}

	fset := token.NewFileSet()
	files := make(map[string]*ast.File)
	fileList := make([]*ast.File, len(pd.GoFiles))
	for i, fname := range pd.GoFiles {
		src, err := ioutil.ReadFile(path.Join(pd.SrcRoot, pd.ImportPath, fname))
		if err != nil {
			return nil, nil, err
		}
		f, err := parser.ParseFile(fset, fname, src, parser.ParseComments|parser.AllErrors)
		if err != nil {
			return nil, nil, err
		}
		files[fname] = f
		fileList[i] = f
	}

	cfg := types.Config{
		Importer: importer.Default(),
	}
	info := types.Info{
		Defs: make(map[*ast.Ident]types.Object),
	}
	tp, err := cfg.Check(pkg, fset, fileList, &info)
	if err != nil {
		return nil, nil, err
	}

	scope := tp.Scope()

	ap, _ := ast.NewPackage(fset, files, nil, nil)
	docs := doc.New(ap, pkg, 0)

	return scope, docs, nil
}

type testFunc struct {
	CurrentPkg string
	DocInfo    *doc.Func
	TypeInfo   *types.Func
}

func (f *testFunc) Qualifier(p *types.Package) string {
	if p == nil || p.Name() == f.CurrentPkg {
		return ""
	}
	return p.Name()
}

func (f *testFunc) Params() string {
	sig := f.TypeInfo.Type().(*types.Signature)
	params := sig.Params()
	p := ""
	comma := ""
	to := params.Len()
	var i int

	if sig.Variadic() {
		to--
	}
	for i = 1; i < to; i++ {
		param := params.At(i)
		p += fmt.Sprintf("%s%s %s", comma, param.Name(), types.TypeString(param.Type(), f.Qualifier))
		comma = ", "
	}
	if sig.Variadic() {
		param := params.At(params.Len() - 1)
		p += fmt.Sprintf("%s%s ...%s", comma, param.Name(), types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier))
	}
	return p
}

func (f *testFunc) ForwardedParams() string {
	sig := f.TypeInfo.Type().(*types.Signature)
	params := sig.Params()
	p := ""
	comma := ""
	to := params.Len()
	var i int

	if sig.Variadic() {
		to--
	}
	for i = 1; i < to; i++ {
		param := params.At(i)
		p += fmt.Sprintf("%s%s", comma, param.Name())
		comma = ", "
	}
	if sig.Variadic() {
		param := params.At(params.Len() - 1)
		p += fmt.Sprintf("%s%s...", comma, param.Name())
	}
	return p
}

func (f *testFunc) Comment() string {
	return "// " + strings.Replace(strings.TrimSpace(f.DocInfo.Doc), "\n", "\n// ", -1)
}

func (f *testFunc) CommentWithoutT(receiver string) string {
	search := fmt.Sprintf("assert.%s(t, ", f.DocInfo.Name)
	replace := fmt.Sprintf("%s.%s(", receiver, f.DocInfo.Name)
	return strings.Replace(f.Comment(), search, replace, -1)
}

var headerTemplate = `/*
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
* THIS FILE MUST NOT BE EDITED BY HAND
*/

package {{.Name}}

import (
{{range $path, $name := .Imports}}
	{{$name}} "{{$path}}"{{end}}
)
`

var funcTemplate = `{{.Comment}}
func (fwd *AssertionsForwarder) {{.DocInfo.Name}}({{.Params}}) bool {
	return assert.{{.DocInfo.Name}}({{.ForwardedParams}})
}`
<|endoftext|>


<commit_before>package packer

import (
	"bytes"
	"fmt"
)

// The git commit that is being compiled. This will be filled in by the
// compiler for source builds.
var GitCommit string

// The version of packer.
const Version = "0.2.4"

// Any pre-release marker for the version. If this is "" (empty string),
// then it means that it is a final release. Otherwise, this is the
// pre-release marker.
const VersionPrerelease = "dev"

type versionCommand byte

func (versionCommand) Help() string {
	return `usage: packer version

Outputs the version of Packer that is running. There are no additional
command-line flags for this command.`
}

func (versionCommand) Run(env Environment, args []string) int {
	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "Packer v%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, ".%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	env.Ui().Say(versionString.String())
	return 0
}

func (versionCommand) Synopsis() string {
	return "print Packer version"
}
<commit_msg>packer: version machine-readable output<commit_after>package packer

import (
	"bytes"
	"fmt"
)

// The git commit that is being compiled. This will be filled in by the
// compiler for source builds.
var GitCommit string

// The version of packer.
const Version = "0.2.4"

// Any pre-release marker for the version. If this is "" (empty string),
// then it means that it is a final release. Otherwise, this is the
// pre-release marker.
const VersionPrerelease = "dev"

type versionCommand byte

func (versionCommand) Help() string {
	return `usage: packer version

Outputs the version of Packer that is running. There are no additional
command-line flags for this command.`
}

func (versionCommand) Run(env Environment, args []string) int {
	env.Ui().Machine("version", Version)
	env.Ui().Machine("version-prelease", VersionPrerelease)
	env.Ui().Machine("version-commit", GitCommit)

	var versionString bytes.Buffer
	fmt.Fprintf(&versionString, "Packer v%s", Version)
	if VersionPrerelease != "" {
		fmt.Fprintf(&versionString, ".%s", VersionPrerelease)

		if GitCommit != "" {
			fmt.Fprintf(&versionString, " (%s)", GitCommit)
		}
	}

	env.Ui().Say(versionString.String())
	return 0
}

func (versionCommand) Synopsis() string {
	return "print Packer version"
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"golang.org/x/crypto/openpgp"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

const jaegerTemplateExtension = ".jgrt"
const jaegerDBExtension = ".jgrdb"
const jaegerDBDescription = "JaegerDB - Jaeger database management program\n\nJaeger is a JSON encoded GPG encrypted key value store. It is useful for separating development with operations and keeping configuration files secure."
const jaegerQuote = "\"Stacker Pentecost: Haven't you heard Mr. Beckett? The world is coming to an end. So where would you rather die? Here? Or in a Jaeger!\" - Pacific Rim"
const jaegerDBRecommendedUsage = "RECOMMENDED:\n    jaegerdb -j file.txt.jgrdb -a \"Field1\" -v \"Secret value\"\n\nThis will run JaegerDB with the default options and assume the following:\n    Keyring file: ~/.gnupg/jaeger_pubring.gpg"

var debug debugging = false

type debugging bool

func (d debugging) Printf(format string, args ...interface{}) {
	// From: https://groups.google.com/forum/#!msg/golang-nuts/gU7oQGoCkmg/BNIl-TqB-4wJ
	if d {
		log.Printf(format, args...)
	}
}

type Data struct {
	Properties []Property
}

type Property struct {
	Name           string `json:"Name"`
	EncryptedValue string `json:"EncryptedValue"`
}

func main() {
	// Define flags
	// TODO: View individual property and unencrypted value. 'get'
	var (
		addKey         = flag.String("a", "", "Add property")
		changeKey      = flag.String("c", "", "Change property")
		debugFlag      = flag.Bool("d", false, "Enable Debug")
		deleteKey      = flag.String("delete", "", "Delete property")
		initializeFlag = flag.Bool("init", false, "Create an initial blank JSON GPG database file")
		jsonGPGDB      = flag.String("j", "", "JSON GPG database file. eg. file.txt.jgrdb")
		keyringFile    = flag.String("k", "", "Keyring file. Public key in ASCII armored format. eg. pubring.asc")
		value          = flag.String("v", "", "Value for property to use")
	)

	flag.Usage = func() {
		fmt.Printf("%s\n%s\n\n%s\n\n", jaegerDBDescription, jaegerQuote, jaegerDBRecommendedUsage)
		fmt.Fprintf(os.Stderr, "OPTIONS:\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if *debugFlag {
		debug = true
	}

	if *jsonGPGDB == "" {
		assumedJaegerDB, err := checkExistsJaegerDB()
		if err != nil {
			flag.Usage()
			log.Fatalf("\n\nError: %s", err)
		}
		*jsonGPGDB = assumedJaegerDB
	}

	if *initializeFlag {
		err := initializeJSONGPGDB(jsonGPGDB)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Initialized JSON GPG database and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *deleteKey != "" {
		err := deleteKeyJaegerDB(deleteKey, jsonGPGDB)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Deleted property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	var entitylist openpgp.EntityList

	if *keyringFile == "" {
		_, entitylist = processPublicKeyRing()
	} else {
		_, entitylist = processArmoredKeyRingFile(keyringFile)
	}

	if *addKey != "" {
		if *value == "" {
			flag.Usage()
			log.Fatalf("\n\nError: No value for add key operation specified")
		}
		err := addKeyJaegerDB(addKey, value, jsonGPGDB, entitylist)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Added property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *changeKey != "" {
		if *value == "" {
			flag.Usage()
			log.Fatalf("\n\nError: No value for change key operation specified")
		}
		err := changeKeyJaegerDB(changeKey, value, jsonGPGDB, entitylist)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Changed property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *deleteKey == "" && *addKey == "" && *changeKey == "" {
		log.Fatalf("\n\nError: No JSON GPG database operations specified")
	}

}

func checkExistsJaegerT() (string, error) {
	// Check that one template file is in the current directory and use that file
	files, err := filepath.Glob("*.jgrt")
	if err != nil {
		return "", err
	}
	if len(files) == 1 {
		return files[0], nil
	}
	return "", fmt.Errorf("No input template file specified")
}

func checkExistsJaegerDB() (string, error) {
	// If no JSON GPG database file is explicitly specified, check that one JSON GPG database file is in the
	// current directory and use that file
	files, err := filepath.Glob("*.jgrdb")
	if err != nil {
		return "", err
	}
	if len(files) == 1 {
		return files[0], nil
	}

	assumedTemplate, err := checkExistsJaegerT()

	if assumedTemplate != "" {
		fmt.Println("assumedTemplate:", assumedTemplate)
		basefilename := strings.TrimSuffix(assumedTemplate, jaegerTemplateExtension)
		jsonGPGDB := fmt.Sprintf("%v%v", basefilename, jaegerDBExtension)
		return jsonGPGDB, nil
	}

	return "", fmt.Errorf("Please specify a JSON GPG database file")
}

func initializeJSONGPGDB(jsonGPGDB *string) error {
	if _, err := os.Stat(*jsonGPGDB); err == nil {
		return fmt.Errorf("ERR: File already exists: %v", *jsonGPGDB)
	}

	var newP []Property

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func encodeBase64EncryptedMessage(s string, entitylist openpgp.EntityList) string {
	// Encrypt message using public key and then encode with base64
	debug.Printf("entitylist: #%v", entitylist)
	buf := new(bytes.Buffer)
	w, err := openpgp.Encrypt(buf, entitylist, nil, nil, nil)
	if err != nil {
		log.Fatalln("ERR: Error encrypting message - ", err)
	}

	_, err = w.Write([]byte(s))
	if err != nil {
	}
	err = w.Close()
	if err != nil {
	}

	// Output as base64 encoded string
	bytes, err := ioutil.ReadAll(buf)
	str := base64.StdEncoding.EncodeToString(bytes)

	debug.Printf("Public key encrypted message (base64 encoded): %v", str)

	return str
}

func processPublicKeyRing() (entity *openpgp.Entity, entitylist openpgp.EntityList) {
	// TODO: Handle a specified recipient
	// Get default public keyring location
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}

	jaegerPublicKeyRing := fmt.Sprintf("%v/.gnupg/jaeger_pubring.gpg", usr.HomeDir)
	publicKeyRing := ""

	if _, err := os.Stat(jaegerPublicKeyRing); err == nil {
		publicKeyRing = jaegerPublicKeyRing
	} else {
		publicKeyRing = fmt.Sprintf("%v/.gnupg/pubring.gpg", usr.HomeDir)
	}

	debug.Printf("publicKeyRing file:", publicKeyRing)
	publicKeyRingBuffer, err := os.Open(publicKeyRing)
	if err != nil {
		panic(err)
	}
	entitylist, err = openpgp.ReadKeyRing(publicKeyRingBuffer)
	if err != nil {
		log.Fatal(err)
	}

	entity = entitylist[0]
	debug.Printf("Public key default keyring:", entity.Identities)

	return entity, entitylist
}

func processArmoredKeyRingFile(keyringFile *string) (entity *openpgp.Entity, entitylist openpgp.EntityList) {
	keyringFileBuffer, err := os.Open(*keyringFile)
	if err != nil {
		log.Fatalln("ERROR: Unable to read keyring file")
	}
	entitylist, err = openpgp.ReadArmoredKeyRing(keyringFileBuffer)
	if err != nil {
		log.Fatal(err)
	}
	entity = entitylist[0]
	debug.Printf("Public key from ASCII armored string:", entity.Identities)

	return entity, entitylist
}

func addKeyJaegerDB(key *string, value *string, jsonGPGDB *string, entitylist openpgp.EntityList) error {
	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	found := false

	var newP []Property

	p := Property{Name: *key, EncryptedValue: encodeBase64EncryptedMessage(*value, entitylist)}

	// Search
	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			j.Properties[i] = p
			found = true
			break
		}
	}

	if found {
		return fmt.Errorf("\n\nError: Property '%s' already exists.", *key)
	}

	newP = append(j.Properties, p)

	debug.Printf("new properties: %v", newP)

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func changeKeyJaegerDB(key *string, value *string, jsonGPGDB *string, entitylist openpgp.EntityList) error {
	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	found := false

	// New property to replace the old
	p := Property{Name: *key, EncryptedValue: encodeBase64EncryptedMessage(*value, entitylist)}

	// Search and replace
	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			j.Properties[i] = p
			found = true
			break
		}
	}

	if !found {
		return fmt.Errorf("\n\nError: Property '%s' not found.", *key)
	}

	bytes, err := json.MarshalIndent(j, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func deleteKeyJaegerDB(key *string, jsonGPGDB *string) error {
	debug.Printf("deleteKeyJaegerDB key: %v", *key)

	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	var newP []Property
	found := false

	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			// https://code.google.com/p/go-wiki/wiki/SliceTricks
			newP = j.Properties[:i+copy(j.Properties[i:], j.Properties[i+1:])]
			found = true
			break
		}
	}

	if !found {
		return fmt.Errorf("\n\nError: Property '%s' not found.", *key)
	}

	debug.Printf("new properties: %v", newP)

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}
<commit_msg>Remove debugging line<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"golang.org/x/crypto/openpgp"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

const jaegerTemplateExtension = ".jgrt"
const jaegerDBExtension = ".jgrdb"
const jaegerDBDescription = "JaegerDB - Jaeger database management program\n\nJaeger is a JSON encoded GPG encrypted key value store. It is useful for separating development with operations and keeping configuration files secure."
const jaegerQuote = "\"Stacker Pentecost: Haven't you heard Mr. Beckett? The world is coming to an end. So where would you rather die? Here? Or in a Jaeger!\" - Pacific Rim"
const jaegerDBRecommendedUsage = "RECOMMENDED:\n    jaegerdb -j file.txt.jgrdb -a \"Field1\" -v \"Secret value\"\n\nThis will run JaegerDB with the default options and assume the following:\n    Keyring file: ~/.gnupg/jaeger_pubring.gpg"

var debug debugging = false

type debugging bool

func (d debugging) Printf(format string, args ...interface{}) {
	// From: https://groups.google.com/forum/#!msg/golang-nuts/gU7oQGoCkmg/BNIl-TqB-4wJ
	if d {
		log.Printf(format, args...)
	}
}

type Data struct {
	Properties []Property
}

type Property struct {
	Name           string `json:"Name"`
	EncryptedValue string `json:"EncryptedValue"`
}

func main() {
	// Define flags
	// TODO: View individual property and unencrypted value. 'get'
	var (
		addKey         = flag.String("a", "", "Add property")
		changeKey      = flag.String("c", "", "Change property")
		debugFlag      = flag.Bool("d", false, "Enable Debug")
		deleteKey      = flag.String("delete", "", "Delete property")
		initializeFlag = flag.Bool("init", false, "Create an initial blank JSON GPG database file")
		jsonGPGDB      = flag.String("j", "", "JSON GPG database file. eg. file.txt.jgrdb")
		keyringFile    = flag.String("k", "", "Keyring file. Public key in ASCII armored format. eg. pubring.asc")
		value          = flag.String("v", "", "Value for property to use")
	)

	flag.Usage = func() {
		fmt.Printf("%s\n%s\n\n%s\n\n", jaegerDBDescription, jaegerQuote, jaegerDBRecommendedUsage)
		fmt.Fprintf(os.Stderr, "OPTIONS:\n")
		flag.PrintDefaults()
	}

	flag.Parse()

	if *debugFlag {
		debug = true
	}

	if *jsonGPGDB == "" {
		assumedJaegerDB, err := checkExistsJaegerDB()
		if err != nil {
			flag.Usage()
			log.Fatalf("\n\nError: %s", err)
		}
		*jsonGPGDB = assumedJaegerDB
	}

	if *initializeFlag {
		err := initializeJSONGPGDB(jsonGPGDB)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Initialized JSON GPG database and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *deleteKey != "" {
		err := deleteKeyJaegerDB(deleteKey, jsonGPGDB)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Deleted property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	var entitylist openpgp.EntityList

	if *keyringFile == "" {
		_, entitylist = processPublicKeyRing()
	} else {
		_, entitylist = processArmoredKeyRingFile(keyringFile)
	}

	if *addKey != "" {
		if *value == "" {
			flag.Usage()
			log.Fatalf("\n\nError: No value for add key operation specified")
		}
		err := addKeyJaegerDB(addKey, value, jsonGPGDB, entitylist)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Added property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *changeKey != "" {
		if *value == "" {
			flag.Usage()
			log.Fatalf("\n\nError: No value for change key operation specified")
		}
		err := changeKeyJaegerDB(changeKey, value, jsonGPGDB, entitylist)
		if err != nil {
			log.Fatal(err)
		} else {
			fmt.Println("Changed property and wrote to file:", *jsonGPGDB)
			os.Exit(0)
		}
	}

	if *deleteKey == "" && *addKey == "" && *changeKey == "" {
		log.Fatalf("\n\nError: No JSON GPG database operations specified")
	}

}

func checkExistsJaegerT() (string, error) {
	// Check that one template file is in the current directory and use that file
	files, err := filepath.Glob("*.jgrt")
	if err != nil {
		return "", err
	}
	if len(files) == 1 {
		return files[0], nil
	}
	return "", fmt.Errorf("No input template file specified")
}

func checkExistsJaegerDB() (string, error) {
	// If no JSON GPG database file is explicitly specified, check that one JSON GPG database file is in the
	// current directory and use that file
	files, err := filepath.Glob("*.jgrdb")
	if err != nil {
		return "", err
	}
	if len(files) == 1 {
		return files[0], nil
	}

	assumedTemplate, err := checkExistsJaegerT()

	if assumedTemplate != "" {
		basefilename := strings.TrimSuffix(assumedTemplate, jaegerTemplateExtension)
		jsonGPGDB := fmt.Sprintf("%v%v", basefilename, jaegerDBExtension)
		return jsonGPGDB, nil
	}

	return "", fmt.Errorf("Please specify a JSON GPG database file")
}

func initializeJSONGPGDB(jsonGPGDB *string) error {
	if _, err := os.Stat(*jsonGPGDB); err == nil {
		return fmt.Errorf("ERR: File already exists: %v", *jsonGPGDB)
	}

	var newP []Property

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func encodeBase64EncryptedMessage(s string, entitylist openpgp.EntityList) string {
	// Encrypt message using public key and then encode with base64
	debug.Printf("entitylist: #%v", entitylist)
	buf := new(bytes.Buffer)
	w, err := openpgp.Encrypt(buf, entitylist, nil, nil, nil)
	if err != nil {
		log.Fatalln("ERR: Error encrypting message - ", err)
	}

	_, err = w.Write([]byte(s))
	if err != nil {
	}
	err = w.Close()
	if err != nil {
	}

	// Output as base64 encoded string
	bytes, err := ioutil.ReadAll(buf)
	str := base64.StdEncoding.EncodeToString(bytes)

	debug.Printf("Public key encrypted message (base64 encoded): %v", str)

	return str
}

func processPublicKeyRing() (entity *openpgp.Entity, entitylist openpgp.EntityList) {
	// TODO: Handle a specified recipient
	// Get default public keyring location
	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}

	jaegerPublicKeyRing := fmt.Sprintf("%v/.gnupg/jaeger_pubring.gpg", usr.HomeDir)
	publicKeyRing := ""

	if _, err := os.Stat(jaegerPublicKeyRing); err == nil {
		publicKeyRing = jaegerPublicKeyRing
	} else {
		publicKeyRing = fmt.Sprintf("%v/.gnupg/pubring.gpg", usr.HomeDir)
	}

	debug.Printf("publicKeyRing file:", publicKeyRing)
	publicKeyRingBuffer, err := os.Open(publicKeyRing)
	if err != nil {
		panic(err)
	}
	entitylist, err = openpgp.ReadKeyRing(publicKeyRingBuffer)
	if err != nil {
		log.Fatal(err)
	}

	entity = entitylist[0]
	debug.Printf("Public key default keyring:", entity.Identities)

	return entity, entitylist
}

func processArmoredKeyRingFile(keyringFile *string) (entity *openpgp.Entity, entitylist openpgp.EntityList) {
	keyringFileBuffer, err := os.Open(*keyringFile)
	if err != nil {
		log.Fatalln("ERROR: Unable to read keyring file")
	}
	entitylist, err = openpgp.ReadArmoredKeyRing(keyringFileBuffer)
	if err != nil {
		log.Fatal(err)
	}
	entity = entitylist[0]
	debug.Printf("Public key from ASCII armored string:", entity.Identities)

	return entity, entitylist
}

func addKeyJaegerDB(key *string, value *string, jsonGPGDB *string, entitylist openpgp.EntityList) error {
	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	found := false

	var newP []Property

	p := Property{Name: *key, EncryptedValue: encodeBase64EncryptedMessage(*value, entitylist)}

	// Search
	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			j.Properties[i] = p
			found = true
			break
		}
	}

	if found {
		return fmt.Errorf("\n\nError: Property '%s' already exists.", *key)
	}

	newP = append(j.Properties, p)

	debug.Printf("new properties: %v", newP)

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func changeKeyJaegerDB(key *string, value *string, jsonGPGDB *string, entitylist openpgp.EntityList) error {
	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	found := false

	// New property to replace the old
	p := Property{Name: *key, EncryptedValue: encodeBase64EncryptedMessage(*value, entitylist)}

	// Search and replace
	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			j.Properties[i] = p
			found = true
			break
		}
	}

	if !found {
		return fmt.Errorf("\n\nError: Property '%s' not found.", *key)
	}

	bytes, err := json.MarshalIndent(j, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}

func deleteKeyJaegerDB(key *string, jsonGPGDB *string) error {
	debug.Printf("deleteKeyJaegerDB key: %v", *key)

	// json handling
	jsonGPGDBBuffer, err := ioutil.ReadFile(*jsonGPGDB)
	if err != nil {
		return fmt.Errorf("ERROR: Unable to read JSON GPG DB file")
	}

	var j Data
	if err := json.Unmarshal(jsonGPGDBBuffer, &j); err != nil {
		return fmt.Errorf("error:", err)
	}
	debug.Printf("json unmarshal: %v", j)

	var newP []Property
	found := false

	for i, _ := range j.Properties {
		property := &j.Properties[i]
		debug.Printf("i: %v, Name: %#v, EncryptedValue: %#v\n", i, property.Name, property.EncryptedValue)
		if property.Name == *key {
			// https://code.google.com/p/go-wiki/wiki/SliceTricks
			newP = j.Properties[:i+copy(j.Properties[i:], j.Properties[i+1:])]
			found = true
			break
		}
	}

	if !found {
		return fmt.Errorf("\n\nError: Property '%s' not found.", *key)
	}

	debug.Printf("new properties: %v", newP)

	newData := Data{newP}

	bytes, err := json.MarshalIndent(newData, "", "    ")
	if err != nil {
		return fmt.Errorf("error:", err)
	}

	debug.Printf("b: %v", string(bytes))

	// Writing file
	// To handle large files, use a file buffer: http://stackoverflow.com/a/9739903/603745
	if err := ioutil.WriteFile(*jsonGPGDB, bytes, 0644); err != nil {
		return fmt.Errorf("error:", err)
	}

	return nil
}
<|endoftext|>


<commit_before>package path

import (
	"go/build"
	"os"
	"path/filepath"
	"testing"
)

func TestSunplateDir(t *testing.T) {
	p := filepath.Join(build.Default.GOPATH, "src", spImp)

	if v := SunplateDir(); v != p {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, p, v)
	}

	hp := filepath.Join(p, "generation", "handlers")
	if v := SunplateDir("generation", "handlers"); v != hp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, hp, v)
	}
}

func TestSunplateImport(t *testing.T) {
	p := spImp

	if v := SunplateImport(); v != p {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, p, v)
	}

	hp := filepath.Join(p, "generation", "handlers")
	if v := SunplateImport("generation", "handlers"); v != hp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, hp, v)
	}
}

func TestWorkingDir(t *testing.T) {
	p := filepath.Join(build.Default.GOPATH, "src")
	os.Chdir(p)

	if v := WorkingDir(); v != p {
		t.Errorf(`Incorrectly detected working directory. Expected "%s", got "%s"`, p, v)
	}
}

func TestAbsoluteImport_AbsImportArgument(t *testing.T) {
	if v := AbsoluteImport(spImp); v != "github.com/anonx/sunplate" {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, spImp, v)
	}

	if v := AbsoluteImport(""); v != "" {
		t.Errorf(`Empty input: empty output expected, got "%s".`, v)
	}
}

func TestAbsoluteImport_OutsideGOPATH(t *testing.T) {
	p := filepath.Join(build.Default.GOPATH, "../")
	os.Chdir(p)

	defer func() {
		if err := recover(); err == nil {
			t.Errorf(`Start outside of $GOPATH: "%s", panic expected.`, p)
		}
	}()
	AbsoluteImport("./strings")
}

func TestAbsoluteImport(t *testing.T) {
	os.Chdir(filepath.Join(build.Default.GOPATH, "src", spImp))

	d := "./generation"
	exp := filepath.Join(spImp, d)
	if v := AbsoluteImport(d); v != exp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, exp, v)
	}

	d = "/string"
	exp = "string"
	if v := AbsoluteImport(d); v != exp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, exp, v)
	}
}

func TestPrefixless(t *testing.T) {
	p := "/anonx/sunplate"
	if v := Prefixless(filepath.Join("github.com", p), "github.com"); v != p {
		t.Errorf(`Inncorrect result. Expected "%s", got %s.`, p, v)
	}
}

var spImp = "github.com/anonx/sunplate"
<commit_msg>Use linux like paths in tests of path package<commit_after>package path

import (
	"go/build"
	"os"
	"path/filepath"
	"testing"
)

func TestSunplateDir(t *testing.T) {
	p := filepath.ToSlash(filepath.Join(build.Default.GOPATH, "src", spImp))

	if v := SunplateDir(); v != p {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, p, v)
	}

	hp := filepath.ToSlash(filepath.Join(p, "generation", "handlers"))
	if v := SunplateDir("generation", "handlers"); v != hp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, hp, v)
	}
}

func TestSunplateImport(t *testing.T) {
	p := spImp

	if v := SunplateImport(); v != p {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, p, v)
	}

	hp := filepath.ToSlash(filepath.Join(p, "generation", "handlers"))
	if v := SunplateImport("generation", "handlers"); v != hp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, hp, v)
	}
}

func TestWorkingDir(t *testing.T) {
	p := filepath.ToSlash(filepath.Join(build.Default.GOPATH, "src"))
	os.Chdir(p)

	if v := WorkingDir(); v != p {
		t.Errorf(`Incorrectly detected working directory. Expected "%s", got "%s"`, p, v)
	}
}

func TestAbsoluteImport_AbsImportArgument(t *testing.T) {
	if v := AbsoluteImport(spImp); v != "github.com/anonx/sunplate" {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, spImp, v)
	}

	if v := AbsoluteImport(""); v != "" {
		t.Errorf(`Empty input: empty output expected, got "%s".`, v)
	}
}

func TestAbsoluteImport_OutsideGOPATH(t *testing.T) {
	p := filepath.ToSlash(filepath.Join(build.Default.GOPATH, "../"))
	os.Chdir(p)

	defer func() {
		if err := recover(); err == nil {
			t.Errorf(`Start outside of $GOPATH: "%s", panic expected.`, p)
		}
	}()
	AbsoluteImport("./strings")
}

func TestAbsoluteImport(t *testing.T) {
	os.Chdir(filepath.Join(build.Default.GOPATH, "src", spImp))

	d := "./generation"
	exp := filepath.Join(spImp, d)
	if v := AbsoluteImport(d); v != exp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, exp, v)
	}

	d = "/string"
	exp = "string"
	if v := AbsoluteImport(d); v != exp {
		t.Errorf(`Incorrect result. Expected "%s", got "%s".`, exp, v)
	}
}

func TestPrefixless(t *testing.T) {
	p := "/anonx/sunplate"
	if v := Prefixless(filepath.ToSlash(filepath.Join("github.com", p)), "github.com"); v != p {
		t.Errorf(`Inncorrect result. Expected "%s", got %s.`, p, v)
	}
}

var spImp = "github.com/anonx/sunplate"
<|endoftext|>


<commit_before>package pdf417

import (
	"fmt"

	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/utils"
)

const (
	padding_codeword = 900
)

// Encodes the given data as PDF417 barcode.
// securityLevel should be between 0 and 8. The higher the number, the more
// additional error-correction codes are added.
func Encode(data string, securityLevel byte) (barcode.Barcode, error) {
	if securityLevel >= 9 {
		return nil, fmt.Errorf("Invalid security level %d", securityLevel)
	}

	sl := securitylevel(securityLevel)

	dataWords, err := highlevelEncode(data)
	if err != nil {
		return nil, err
	}

	columns, rows := calcDimensions(len(dataWords), sl.ErrorCorrectionWordCount())
	if columns < minCols || columns > maxCols || rows < minRows || rows > maxRows {
		return nil, fmt.Errorf("Unable to fit data in barcode")
	}

	barcode := new(pdfBarcode)
	barcode.data = data

	codeWords, err := encodeData(dataWords, columns, sl)
	if err != nil {
		return nil, err
	}

	grid := [][]int{}
	for i := 0; i < len(codeWords); i += columns {
		grid = append(grid, codeWords[i:min(i+columns, len(codeWords))])
	}

	codes := [][]int{}

	for rowNum, row := range grid {
		table := rowNum % 3
		rowCodes := make([]int, 0, columns+4)

		rowCodes = append(rowCodes, start_word)
		rowCodes = append(rowCodes, getCodeword(table, getLeftCodeWord(rowNum, rows, columns, securityLevel)))

		for _, word := range row {
			rowCodes = append(rowCodes, getCodeword(table, word))
		}

		rowCodes = append(rowCodes, getCodeword(table, getRightCodeWord(rowNum, rows, columns, securityLevel)))
		rowCodes = append(rowCodes, stop_word)

		codes = append(codes, rowCodes)
	}

	barcode.code = renderBarcode(codes)
	barcode.width = (columns+4)*17 + 1

	return barcode, nil
}

func encodeData(dataWords []int, columns int, sl securitylevel) ([]int, error) {
	dataCount := len(dataWords)

	ecCount := sl.ErrorCorrectionWordCount()

	padWords := getPadding(dataCount, ecCount, columns)
	dataWords = append(dataWords, padWords...)

	length := len(dataWords) + 1
	dataWords = append([]int{length}, dataWords...)

	ecWords := sl.Compute(dataWords)

	return append(dataWords, ecWords...), nil
}

func getLeftCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
	tableId := rowNum % 3

	var x int

	switch tableId {
	case 0:
		x = (rows - 3) / 3
	case 1:
		x = int(securityLevel) * 3
		x += (rows - 1) % 3
	case 2:
		x = columns - 1
	}

	return 30*(rowNum/3) + x
}

func getRightCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
	tableId := rowNum % 3

	var x int

	switch tableId {
	case 0:
		x = columns - 1
	case 1:
		x = (rows - 1) / 3
	case 2:
		x = int(securityLevel) * 3
		x += (rows - 1) % 3
	}

	return 30*(rowNum/3) + x
}

func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

func getPadding(dataCount int, ecCount int, columns int) []int {
	totalCount := dataCount + ecCount + 1
	mod := totalCount % columns

	padding := []int{}

	if mod > 0 {
		padCount := columns - mod
		padding = make([]int, padCount)
		for i := 0; i < padCount; i++ {
			padding[i] = padding_codeword
		}
	}

	return padding
}

func renderBarcode(codes [][]int) *utils.BitList {
	bl := new(utils.BitList)
	for _, row := range codes {
		lastIdx := len(row) - 1
		for i, col := range row {
			if i == lastIdx {
				bl.AddBits(col, 18)
			} else {
				bl.AddBits(col, 17)
			}
		}
	}
	return bl
}
<commit_msg>added package comment<commit_after>// Package pdf417 can create PDF-417 barcodes
package pdf417

import (
	"fmt"

	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/utils"
)

const (
	padding_codeword = 900
)

// Encodes the given data as PDF417 barcode.
// securityLevel should be between 0 and 8. The higher the number, the more
// additional error-correction codes are added.
func Encode(data string, securityLevel byte) (barcode.Barcode, error) {
	if securityLevel >= 9 {
		return nil, fmt.Errorf("Invalid security level %d", securityLevel)
	}

	sl := securitylevel(securityLevel)

	dataWords, err := highlevelEncode(data)
	if err != nil {
		return nil, err
	}

	columns, rows := calcDimensions(len(dataWords), sl.ErrorCorrectionWordCount())
	if columns < minCols || columns > maxCols || rows < minRows || rows > maxRows {
		return nil, fmt.Errorf("Unable to fit data in barcode")
	}

	barcode := new(pdfBarcode)
	barcode.data = data

	codeWords, err := encodeData(dataWords, columns, sl)
	if err != nil {
		return nil, err
	}

	grid := [][]int{}
	for i := 0; i < len(codeWords); i += columns {
		grid = append(grid, codeWords[i:min(i+columns, len(codeWords))])
	}

	codes := [][]int{}

	for rowNum, row := range grid {
		table := rowNum % 3
		rowCodes := make([]int, 0, columns+4)

		rowCodes = append(rowCodes, start_word)
		rowCodes = append(rowCodes, getCodeword(table, getLeftCodeWord(rowNum, rows, columns, securityLevel)))

		for _, word := range row {
			rowCodes = append(rowCodes, getCodeword(table, word))
		}

		rowCodes = append(rowCodes, getCodeword(table, getRightCodeWord(rowNum, rows, columns, securityLevel)))
		rowCodes = append(rowCodes, stop_word)

		codes = append(codes, rowCodes)
	}

	barcode.code = renderBarcode(codes)
	barcode.width = (columns+4)*17 + 1

	return barcode, nil
}

func encodeData(dataWords []int, columns int, sl securitylevel) ([]int, error) {
	dataCount := len(dataWords)

	ecCount := sl.ErrorCorrectionWordCount()

	padWords := getPadding(dataCount, ecCount, columns)
	dataWords = append(dataWords, padWords...)

	length := len(dataWords) + 1
	dataWords = append([]int{length}, dataWords...)

	ecWords := sl.Compute(dataWords)

	return append(dataWords, ecWords...), nil
}

func getLeftCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
	tableId := rowNum % 3

	var x int

	switch tableId {
	case 0:
		x = (rows - 3) / 3
	case 1:
		x = int(securityLevel) * 3
		x += (rows - 1) % 3
	case 2:
		x = columns - 1
	}

	return 30*(rowNum/3) + x
}

func getRightCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
	tableId := rowNum % 3

	var x int

	switch tableId {
	case 0:
		x = columns - 1
	case 1:
		x = (rows - 1) / 3
	case 2:
		x = int(securityLevel) * 3
		x += (rows - 1) % 3
	}

	return 30*(rowNum/3) + x
}

func min(a, b int) int {
	if a <= b {
		return a
	}
	return b
}

func getPadding(dataCount int, ecCount int, columns int) []int {
	totalCount := dataCount + ecCount + 1
	mod := totalCount % columns

	padding := []int{}

	if mod > 0 {
		padCount := columns - mod
		padding = make([]int, padCount)
		for i := 0; i < padCount; i++ {
			padding[i] = padding_codeword
		}
	}

	return padding
}

func renderBarcode(codes [][]int) *utils.BitList {
	bl := new(utils.BitList)
	for _, row := range codes {
		lastIdx := len(row) - 1
		for i, col := range row {
			if i == lastIdx {
				bl.AddBits(col, 18)
			} else {
				bl.AddBits(col, 17)
			}
		}
	}
	return bl
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	_ "github.com/lib/pq"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	DATA_HOST = "localhost"
	DATA_PORT = 3306
	PORT      = 8080
)

type Config struct {
	DataHost     string
	DataPort     int
	DataName     string
	DataUsername string
	DataPassword string
	Port         int
}

type RowResponse map[string]string

func AssignConfigDefaultValues(config Config) Config {
	if config.DataHost == "" {
		config.DataHost = DATA_HOST
	}
	if config.DataPort == 0 {
		config.DataPort = DATA_PORT
	}
	if config.Port == 0 {
		config.Port = PORT
	}
	return config
}

func GetConfig(filename string) (Config, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return Config{}, err
	}
	var config Config
	err = json.Unmarshal(data, &config)
	if err != nil {
		return Config{}, err
	}
	return AssignConfigDefaultValues(config), nil
}

func GetQueries(filename string) (map[string]string, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	var queries map[string]string
	err = json.Unmarshal(data, &queries)
	if err != nil {
		return nil, err
	}
	return queries, nil
}

func GetFilenames() (string, string, error) {
	var configFile string
	var queriesFile string
	flag.StringVar(&configFile, "c", "", "config.json file")
	flag.StringVar(&queriesFile, "q", "", "queries.json file")
	flag.Parse()
	if configFile == "" || queriesFile == "" {
		return configFile, queriesFile, errors.New("You must specify a config.json and a queries.json file using -c and -q")
	}
	return configFile, queriesFile, nil
}

func GetDBConnectionAndQueries() (*sql.DB, Config, map[string]string, error) {
	configFile, queriesFile, err := GetFilenames()
	if err != nil {
		return nil, Config{}, nil, err
	}

	config, err := GetConfig(configFile)
	if err != nil {
		return nil, Config{}, nil, err
	}

	connectionString := fmt.Sprintf("postgres://%v:%v@%v/%v", config.DataUsername, config.DataPassword, config.DataHost, config.DataName)
	db, err := sql.Open("postgres", connectionString)
	if err != nil {
		return nil, Config{}, nil, err
	}

	queries, err := GetQueries(queriesFile)
	if err != nil {
		return nil, Config{}, nil, err
	}

	return db, config, queries, nil

}

var (
	db, config, queries, startupError = GetDBConnectionAndQueries()
)

func GetQueryAndParams(r *http.Request) (string, []string, error) {
	queryStringMap := r.URL.Query()
	queries := queryStringMap["q"]
	if len(queries) == 0 {
		return "", nil, errors.New("You must provide a query (q=)")
	}
	query := queries[0]
	params := queryStringMap["p"]
	return query, params, nil
}

type ErrorJson struct {
	ErrorMessage string
}

func WriteErrorMessage(w http.ResponseWriter, errorString string) {
	w.WriteHeader(http.StatusBadRequest)
	errorJson := ErrorJson{errorString}
	json, err := json.Marshal(errorJson)
	if err != nil {
		fmt.Fprintf(w, "{\"ErrorMessage\":\"Something went wrong\"")
		return
	}
	w.Write(json)
}

func Handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")

	query, params, err := GetQueryAndParams(r)
	if err != nil {
		WriteErrorMessage(w, err.Error())
		return
	}

	storedQuery, queryIsPresent := queries[query]
	if !queryIsPresent {
		WriteErrorMessage(w, "Passed query is not present in queries.json")
		return
	}

	parameterCount := strings.Count(storedQuery, "$")
	if parameterCount != len(params) {
		WriteErrorMessage(w, "Count of passed parameters are unequal to expected parameters")
		return
	}

	paramsInterfaced := make([]interface{}, len(params))
	for i, v := range params {
		paramsInterfaced[i] = v
	}

	rows, err := db.Query(storedQuery, paramsInterfaced...)
	if err != nil {
		WriteErrorMessage(w, err.Error())
		return
	}

	columns, err := rows.Columns()
	if err != nil {
		WriteErrorMessage(w, err.Error())
		return
	}

	rawResult := make([][]byte, len(columns))
	result := make([]string, len(columns))

	destination := make([]interface{}, len(columns))
	for i, _ := range rawResult {
		destination[i] = &rawResult[i]
	}

	response := []map[string]string{}

	defer rows.Close()
	for rows.Next() {
		err = rows.Scan(destination...)
		if err != nil {
			WriteErrorMessage(w, err.Error())
			return
		}

		for i, raw := range rawResult {
			if raw == nil {
				result[i] = ""
			} else {
				result[i] = string(raw)
			}
		}
		row := make(map[string]string)
		for i, v := range result {
			row[columns[i]] = v
		}
		response = append(response, row)
	}

	js, err := json.Marshal(response)
	if err != nil {
		WriteErrorMessage(w, err.Error())
	}

	w.Write(js)
}

func main() {
	if startupError != nil {
		fmt.Println(startupError)
		return
	}
	listenPort := fmt.Sprintf(":%d", config.Port)
	http.HandleFunc("/", Handler)
	http.ListenAndServe(listenPort, nil)
}
<commit_msg>Added handling for select vs other queries<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	_ "github.com/lib/pq"
	"io/ioutil"
	"net/http"
	"strings"
)

const (
	DATA_HOST = "localhost"
	DATA_PORT = 3306
	PORT      = 8080
)

type Config struct {
	DataHost     string
	DataPort     int
	DataName     string
	DataUsername string
	DataPassword string
	Port         int
}

type RowResponse map[string]string

func AssignConfigDefaultValues(config Config) Config {
	if config.DataHost == "" {
		config.DataHost = DATA_HOST
	}
	if config.DataPort == 0 {
		config.DataPort = DATA_PORT
	}
	if config.Port == 0 {
		config.Port = PORT
	}
	return config
}

func GetConfig(filename string) (Config, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return Config{}, err
	}
	var config Config
	err = json.Unmarshal(data, &config)
	if err != nil {
		return Config{}, err
	}
	return AssignConfigDefaultValues(config), nil
}

func GetQueries(filename string) (map[string]string, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	var queries map[string]string
	err = json.Unmarshal(data, &queries)
	if err != nil {
		return nil, err
	}
	return queries, nil
}

func GetFilenames() (string, string, error) {
	var configFile string
	var queriesFile string
	flag.StringVar(&configFile, "c", "", "config.json file")
	flag.StringVar(&queriesFile, "q", "", "queries.json file")
	flag.Parse()
	if configFile == "" || queriesFile == "" {
		return configFile, queriesFile, errors.New("You must specify a config.json and a queries.json file using -c and -q")
	}
	return configFile, queriesFile, nil
}

func GetDBConnectionAndQueries() (*sql.DB, Config, map[string]string, error) {
	configFile, queriesFile, err := GetFilenames()
	if err != nil {
		return nil, Config{}, nil, err
	}

	config, err := GetConfig(configFile)
	if err != nil {
		return nil, Config{}, nil, err
	}

	connectionString := fmt.Sprintf("postgres://%v:%v@%v/%v", config.DataUsername, config.DataPassword, config.DataHost, config.DataName)
	db, err := sql.Open("postgres", connectionString)
	if err != nil {
		return nil, Config{}, nil, err
	}

	queries, err := GetQueries(queriesFile)
	if err != nil {
		return nil, Config{}, nil, err
	}

	return db, config, queries, nil

}

var (
	db, config, queries, startupError = GetDBConnectionAndQueries()
)

func GetQueryAndParams(r *http.Request) (string, []string, error) {
	queryStringMap := r.URL.Query()
	queries := queryStringMap["q"]
	if len(queries) == 0 {
		return "", nil, errors.New("You must provide a query (q=)")
	}
	query := queries[0]
	params := queryStringMap["p"]
	return query, params, nil
}

type ErrorJson struct {
	Error string
}

func WriteErrorMessage(w http.ResponseWriter, errorString string) {
	w.WriteHeader(http.StatusBadRequest)
	errorJson := ErrorJson{errorString}
	json, err := json.Marshal(errorJson)
	if err != nil {
		fmt.Fprintf(w, "{\"Error\":\"Something went wrong\"")
		return
	}
	w.Write(json)
}

func IsSelectQuery(query string) bool {
	return strings.ToLower(query[0:6]) == "select"
}

func Handler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")

	query, params, err := GetQueryAndParams(r)
	if err != nil {
		WriteErrorMessage(w, err.Error())
		return
	}

	storedQuery, queryIsPresent := queries[query]
	if !queryIsPresent {
		WriteErrorMessage(w, "Passed query is not present in queries.json")
		return
	}

	parameterCount := strings.Count(storedQuery, "$")
	if parameterCount != len(params) {
		WriteErrorMessage(w, "Count of passed parameters are unequal to expected parameters")
		return
	}

	paramsInterfaced := make([]interface{}, len(params))
	for i, v := range params {
		paramsInterfaced[i] = v
	}

	if IsSelectQuery(storedQuery) {
		rows, err := db.Query(storedQuery, paramsInterfaced...)
		if err != nil {
			WriteErrorMessage(w, err.Error())
			return
		}

		columns, err := rows.Columns()
		if err != nil {
			WriteErrorMessage(w, err.Error())
			return
		}

		rawResult := make([][]byte, len(columns))
		result := make([]string, len(columns))

		destination := make([]interface{}, len(columns))
		for i, _ := range rawResult {
			destination[i] = &rawResult[i]
		}

		response := []map[string]string{}

		defer rows.Close()
		for rows.Next() {
			err = rows.Scan(destination...)
			if err != nil {
				WriteErrorMessage(w, err.Error())
				return
			}

			for i, raw := range rawResult {
				if raw == nil {
					result[i] = ""
				} else {
					result[i] = string(raw)
				}
			}
			row := make(map[string]string)
			for i, v := range result {
				row[columns[i]] = v
			}
			response = append(response, row)
		}

		js, err := json.Marshal(response)
		if err != nil {
			WriteErrorMessage(w, err.Error())
			return
		}

		w.Write(js)
	} else {
		_, err := db.Exec(storedQuery, paramsInterfaced...)
		if err != nil {
			WriteErrorMessage(w, err.Error())
			return
		}

		fmt.Fprintf(w, "{\"Success\":\"Query executed without errors\"}")
	}
}

func main() {
	if startupError != nil {
		fmt.Println(startupError)
		return
	}
	listenPort := fmt.Sprintf(":%d", config.Port)
	http.HandleFunc("/", Handler)
	http.ListenAndServe(listenPort, nil)
}
<|endoftext|>


<commit_before>package lib

import (
	"gopkg.in/gographics/imagick.v3/imagick"
	"math"
)

const (
	SHAPE_MASK_CIRCLE    string = "circle"
	SHAPE_MASK_ROUNDRECT string = "rounded"
	SHAPE_DIAMOND        string = "diamond"
)

type MagickCropper struct {
	*imagick.MagickWand
}

func (mc MagickCropper) GetAspect() float32 {
	return float32(mc.GetImageWidth()) / float32(mc.GetImageHeight())
}

func (mc MagickCropper) SmartCrop(w, h uint) error {
	var err error

	aspect := mc.GetAspect()

	if w > h {
		err = mc.ResizeImage(w, uint(float32(w)/aspect), imagick.FILTER_LANCZOS2_SHARP)
	} else {
		err = mc.ResizeImage(uint(float32(h)*aspect), h, imagick.FILTER_LANCZOS2_SHARP)
	}

	nw := int(mc.GetImageWidth())
	nh := int(mc.GetImageHeight())

	mc.CropImage(w, h, int(math.Abs(float64(nw-int(w)))/2), int(math.Abs(float64(nh-int(h)))/2))

	return err
}

func (mc MagickCropper) ShapeImage(t string, param float64) error {
	w, h := mc.GetImageWidth(), mc.GetImageHeight()
	result := imagick.NewMagickWand()
	canvas := imagick.NewDrawingWand()
	pw := imagick.NewPixelWand()

	pw.SetColor("none")
	result.NewImage(w, h, pw)

	pw.SetColor("white")
	canvas.SetFillColor(pw)

	switch t {
	case SHAPE_MASK_CIRCLE:
		if w > h {
			canvas.Circle(float64(w)/2, float64(h)/2, float64(w)/2, float64(h-1))
		} else {
			canvas.Circle(float64(w)/2, float64(h)/2, float64(w-1), float64(h)/2)
		}

	case SHAPE_MASK_ROUNDRECT:
		canvas.RoundRectangle(0, 0, float64(w), float64(h), param, param)

	case SHAPE_DIAMOND:
		canvas.Polygon([]imagick.PointInfo{
			{float64(w) / 2, 0},
			{float64(w), float64(h) / 2},
			{float64(w) / 2, float64(h)},
			{0, float64(h) / 2},
		})
	}

	result.DrawImage(canvas)
	result.CompositeImage(mc.MagickWand, imagick.COMPOSITE_OP_SRC_IN, true, 0, 0)

	mc.MagickWand.Clear()
	mc.MagickWand.AddImage(result)

	return nil
}
<commit_msg>+ default rectangle mask for no-filter<commit_after>package lib

import (
	"gopkg.in/gographics/imagick.v3/imagick"
	"math"
)

const (
	SHAPE_MASK_CIRCLE    string = "circle"
	SHAPE_MASK_ROUNDRECT string = "rounded"
	SHAPE_DIAMOND        string = "diamond"
)

type MagickCropper struct {
	*imagick.MagickWand
}

func (mc MagickCropper) GetAspect() float32 {
	return float32(mc.GetImageWidth()) / float32(mc.GetImageHeight())
}

func (mc MagickCropper) SmartCrop(w, h uint) error {
	var err error

	aspect := mc.GetAspect()

	if w > h {
		err = mc.ResizeImage(w, uint(float32(w)/aspect), imagick.FILTER_LANCZOS2_SHARP)
	} else {
		err = mc.ResizeImage(uint(float32(h)*aspect), h, imagick.FILTER_LANCZOS2_SHARP)
	}

	nw := int(mc.GetImageWidth())
	nh := int(mc.GetImageHeight())

	mc.CropImage(w, h, int(math.Abs(float64(nw-int(w)))/2), int(math.Abs(float64(nh-int(h)))/2))

	return err
}

func (mc MagickCropper) ShapeImage(t string, param float64) error {
	w, h := mc.GetImageWidth(), mc.GetImageHeight()
	result := imagick.NewMagickWand()
	canvas := imagick.NewDrawingWand()
	pw := imagick.NewPixelWand()

	pw.SetColor("none")
	result.NewImage(w, h, pw)

	pw.SetColor("white")
	canvas.SetFillColor(pw)

	switch t {
	case SHAPE_MASK_CIRCLE:
		if w > h {
			canvas.Circle(float64(w)/2, float64(h)/2, float64(w)/2, float64(h-1))
		} else {
			canvas.Circle(float64(w)/2, float64(h)/2, float64(w-1), float64(h)/2)
		}

	case SHAPE_MASK_ROUNDRECT:
		canvas.RoundRectangle(0, 0, float64(w), float64(h), param, param)

	case SHAPE_DIAMOND:
		canvas.Polygon([]imagick.PointInfo{
			{float64(w) / 2, 0},
			{float64(w), float64(h) / 2},
			{float64(w) / 2, float64(h)},
			{0, float64(h) / 2},
		})

	default:
		canvas.Rectangle(0, 0, float64(w), float64(h))
	}

	result.DrawImage(canvas)
	result.CompositeImage(mc.MagickWand, imagick.COMPOSITE_OP_SRC_IN, true, 0, 0)

	mc.MagickWand.Clear()
	mc.MagickWand.AddImage(result)

	return nil
}
<|endoftext|>