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

// Package flags defines command-line flags to make them consistent between binaries.
// Not all flags make sense for all binaries.
package flags

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"upspin.io/log"
)

var (
	// Config is a list of configuration options (key=value); used by servers only.
	Config []string

	// Context names the Upspin context file to use.
	Context = filepath.Join(os.Getenv("HOME"), "/upspin/rc")

	// Endpoint specifies the endpoint of remote service (applies to forwarding servers only).
	Endpoint = "inprocess"

	// HTTPSAddr is the network address on which to listen for incoming network connections.
	HTTPSAddr = "localhost:443"

	// Log sets the level of logging (implements flag.Value).
	Log logFlag

	// Project is the project name on GCP; used by servers only.
	Project = ""
)

// flags is a map of flag registration functions keyed by flag name,
// used by Parse to register specific (or all) flags.
var flags = map[string]func(){
	"config": func() {
		flag.Var(configFlag{&Config}, "config", "comma-separated list of configuration options (key=value) for this server")
	},
	"context": func() {
		flag.StringVar(&Context, "context", Context, "context `file`")
	},
	"endpoint": func() {
		flag.StringVar(&Endpoint, "endpoint", Endpoint, "`endpoint` of remote service for forwarding servers")
	},
	"https": func() {
		flag.StringVar(&HTTPSAddr, "https", HTTPSAddr, "`address` for incoming network connections")
	},
	"project": func() {
		flag.StringVar(&Project, "project", Project, "GCP `project` name")
	},
	"log": func() {
		Log.Set("info")
		flag.Var(&Log, "log", "`level` of logging: debug, info, error, disabled")
	},
}

// Parse registers the command-line flags for the given flag names
// and calls flag.Parse. Passing zero names registers all flags.
// Passing an unknown name triggers a panic.
//
// For example:
// 	flags.Parse("config", "endpoint") // Register Config and Endpoint.
// or
// 	flags.Parse() // Register all flags.
func Parse(names ...string) {
	if len(names) == 0 {
		// Register all flags if no names provided.
		for _, fn := range flags {
			fn()
		}
	} else {
		for _, n := range names {
			fn, ok := flags[n]
			if !ok {
				panic(fmt.Sprintf("unknown flag %q", n))
			}
			fn()
		}
	}
	flag.Parse()
}

type logFlag string

// String implements flag.Value.
func (f logFlag) String() string {
	return string(f)
}

// Set implements flag.Value.
func (f *logFlag) Set(level string) error {
	err := log.SetLevel(level)
	if err != nil {
		return err
	}
	*f = logFlag(log.Level())
	return nil
}

// Get implements flag.Getter.
func (logFlag) Get() interface{} {
	return log.Level()
}

type configFlag struct {
	s *[]string
}

// String implements flag.Value.
func (f configFlag) String() string {
	return strings.Join(*f.s, ",")
}

// Set implements flag.Value.
func (f configFlag) Set(s string) error {
	*f.s = strings.Split(strings.TrimSpace(s), ",")
	return nil
}

// Get implements flag.Getter.
func (f configFlag) Get() interface{} {
	return *f.s
}
<commit_msg>flags: fix nil-pointer crash if configflag is empty<commit_after>// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package flags defines command-line flags to make them consistent between binaries.
// Not all flags make sense for all binaries.
package flags

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"upspin.io/log"
)

var (
	// Config is a list of configuration options (key=value); used by servers only.
	Config []string

	// Context names the Upspin context file to use.
	Context = filepath.Join(os.Getenv("HOME"), "/upspin/rc")

	// Endpoint specifies the endpoint of remote service (applies to forwarding servers only).
	Endpoint = "inprocess"

	// HTTPSAddr is the network address on which to listen for incoming network connections.
	HTTPSAddr = "localhost:443"

	// Log sets the level of logging (implements flag.Value).
	Log logFlag

	// Project is the project name on GCP; used by servers only.
	Project = ""
)

// flags is a map of flag registration functions keyed by flag name,
// used by Parse to register specific (or all) flags.
var flags = map[string]func(){
	"config": func() {
		flag.Var(configFlag{&Config}, "config", "comma-separated list of configuration options (key=value) for this server")
	},
	"context": func() {
		flag.StringVar(&Context, "context", Context, "context `file`")
	},
	"endpoint": func() {
		flag.StringVar(&Endpoint, "endpoint", Endpoint, "`endpoint` of remote service for forwarding servers")
	},
	"https": func() {
		flag.StringVar(&HTTPSAddr, "https", HTTPSAddr, "`address` for incoming network connections")
	},
	"project": func() {
		flag.StringVar(&Project, "project", Project, "GCP `project` name")
	},
	"log": func() {
		Log.Set("info")
		flag.Var(&Log, "log", "`level` of logging: debug, info, error, disabled")
	},
}

// Parse registers the command-line flags for the given flag names
// and calls flag.Parse. Passing zero names registers all flags.
// Passing an unknown name triggers a panic.
//
// For example:
// 	flags.Parse("config", "endpoint") // Register Config and Endpoint.
// or
// 	flags.Parse() // Register all flags.
func Parse(names ...string) {
	if len(names) == 0 {
		// Register all flags if no names provided.
		for _, fn := range flags {
			fn()
		}
	} else {
		for _, n := range names {
			fn, ok := flags[n]
			if !ok {
				panic(fmt.Sprintf("unknown flag %q", n))
			}
			fn()
		}
	}
	flag.Parse()
}

type logFlag string

// String implements flag.Value.
func (f logFlag) String() string {
	return string(f)
}

// Set implements flag.Value.
func (f *logFlag) Set(level string) error {
	err := log.SetLevel(level)
	if err != nil {
		return err
	}
	*f = logFlag(log.Level())
	return nil
}

// Get implements flag.Getter.
func (logFlag) Get() interface{} {
	return log.Level()
}

type configFlag struct {
	s *[]string
}

// String implements flag.Value.
func (f configFlag) String() string {
	if f.s == nil {
		return ""
	}
	return strings.Join(*f.s, ",")
}

// Set implements flag.Value.
func (f configFlag) Set(s string) error {
	*f.s = strings.Split(strings.TrimSpace(s), ",")
	return nil
}

// Get implements flag.Getter.
func (f configFlag) Get() interface{} {
	if f.s == nil {
		return ""
	}
	return *f.s
}
<|endoftext|>


<commit_before>package signal

import (
	"context"
)

func executeAndFulfill(f func() error, done chan<- error) {
	err := f()
	if err != nil {
		done <- err
	}
	close(done)
}

// ExecuteAsync executes a function asychrously and return its result.
func ExecuteAsync(f func() error) <-chan error {
	done := make(chan error, 1)
	go executeAndFulfill(f, done)
	return done
}

func ErrorOrFinish1(ctx context.Context, c <-chan error) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-c:
		return err
	}
}

func ErrorOrFinish2(ctx context.Context, c1, c2 <-chan error) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err, failed := <-c1:
		if failed {
			return err
		}
		return ErrorOrFinish1(ctx, c2)
	case err, failed := <-c2:
		if failed {
			return err
		}
		return ErrorOrFinish1(ctx, c1)
	}
}
<commit_msg>simplify error propagation<commit_after>package signal

import (
	"context"
)

func executeAndFulfill(f func() error, done chan<- error) {
	err := f()
	if err != nil {
		done <- err
	}
	close(done)
}

// ExecuteAsync executes a function asychrously and return its result.
func ExecuteAsync(f func() error) <-chan error {
	done := make(chan error, 1)
	go executeAndFulfill(f, done)
	return done
}

func ErrorOrFinish1(ctx context.Context, c <-chan error) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-c:
		return err
	}
}

func ErrorOrFinish2(ctx context.Context, c1, c2 <-chan error) error {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case err := <-c1:
		if err != nil {
			return err
		}
		return ErrorOrFinish1(ctx, c2)
	case err := <-c2:
		if err != nil {
			return err
		}
		return ErrorOrFinish1(ctx, c1)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main contains a script that is run in CI when a new version tag is pushed to master.
// This script archives compiled executables of the gapic-generator-go plugin tool and creates
// a GitHub release with for the given tag and commitish using the given GitHub token.
//
// This script must be run from the root directory of the gapic-generator-go repository.
//
// Usage: go run ./util/cmd/release -version=v1.2.3 -token=$GITHUB_TOKEN -commitish=abc123
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var version, token, commitish string

func init() {
	flag.StringVar(&commitish, "commitish", "", "the target commitish to use [required]")
	flag.StringVar(&token, "token", "", "the GitHub token to use [optional]")
	flag.StringVar(&version, "version", "", "the version tag [required]")
}

func main() {
	flag.Parse()
	if commitish == "" {
		log.Fatalln("Missing required flag: -commitish")
	}
	if token == "" {
		log.Fatalln("Missing required flag: -token")
	}
	if version == "" {
		log.Fatalln("Missing required flag: -version")
	}
	if !strings.HasPrefix(version, "v") {
		log.Fatalln("Invalid version, should be in form vX.X.X")
	}

	outDir, err := ioutil.TempDir(os.TempDir(), "gapic-generator-go-")
	if err != nil {
		log.Fatalf("Error: unable to create temporary directory %+v\n", err)
	}
	defer os.RemoveAll(outDir)

	// Get cross compiler & GitHub release helper
	// Mousetrap is a windows dependency that is not implicitly got since
	// we only get the linux dependencies.
	execute(
		"go",
		"get",
		"github.com/mitchellh/gox",
		"github.com/inconshreveable/mousetrap",
		"github.com/tcnksm/ghr")

	// Compile plugin binaries.
	stagingDir := filepath.Join(outDir, "binaries")
	osArchs := []string{
		"windows/amd64",
		"linux/amd64",
		"darwin/amd64",
		"linux/arm",
	}
	for _, osArch := range osArchs {
		execute(
			"gox",
			fmt.Sprintf("-osarch=%s", osArch),
			"-output",
			filepath.Join(stagingDir, fmt.Sprintf("protoc-gen-go_gapic-%s-{{.OS}}-{{.Arch}}", version), "protoc-gen-go_gapic"),
			"github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_gapic")
	}

	dirs, _ := filepath.Glob(filepath.Join(stagingDir, "*"))
	for _, dir := range dirs {
		// The windows binaries are suffixed with '.exe'. This allows us to create
		// tarballs of the executables whether or not they contain a suffix.
		files, _ := filepath.Glob(filepath.Join(dir, "protoc-gen-go_gapic*"))
		execute(
			"tar",
			"-zcf",
			dir+".tar.gz",
			"-C",
			filepath.Dir(files[0]),
			filepath.Base(files[0]))
		// Remove the individual binary directory.
		execute("rm", "-r", dir)
	}

	// Execute GitHub release of artifacts.
	execute(
		"ghr",
		"-t="+token,
		"-n="+version,
		"-b='"+notes(version)+"'",
		"-u=googleapis",
		"-r=gapic-generator-go",
		"-c="+commitish,
		version,
		stagingDir)
}

// execute runs the given strings as a command.
func execute(cmd string, args ...string) {
	if output, err := exec.Command(cmd, args...).CombinedOutput(); err != nil {
		log.Fatalf("%s", output)
	}
}

// executeWithOutput runs the given strings as a command and returns the output.
func executeWithOutput(cmd string, args ...string) string {
	out, err := exec.Command(cmd, args...).Output()
	if err != nil {
		log.Fatalf("%s", err)
	}
	return string(out)
}

// notes collects the commit messages since the previous tag, aggregates
// dependency updates into one message, and returns formatted release notes.
func notes(version string) string {
	previous := executeWithOutput(
		"git",
		"describe",
		"--abbrev=0",
		"--tags",
		version+"^",
	)
	previous = strings.TrimSpace(previous)

	output := executeWithOutput(
		"git",
		"log",
		previous+"..HEAD",
		"--oneline",
		"--pretty=format:%s",
	)
	commits := strings.Split(output, "\n")

	return format(commits)
}

// format parses the given commits messages and formats them into release notes
// organized by component.
func format(commits []string) string {
	var hasDeps bool
	var gapic, bazel, gencli, chore, samples, other []string

	for _, msg := range commits {
		sep := strings.Index(msg, ":")
		if sep == -1 {
			other = append(other, "* "+msg)
			continue
		}

		comp := msg[:sep]
		content := strings.TrimSpace(msg[sep+1:])

		switch comp {
		case "gapic":
			gapic = append(gapic, "* "+content)
		case "bazel":
			bazel = append(bazel, "* "+content)
		case "gencli":
			gencli = append(gencli, "* "+content)
		case "chore(deps)":
			hasDeps = true
		case "chore":
			chore = append(chore, "* "+content)
		case "samples":
			samples = append(samples, "* "+content)
		default:
			other = append(other, "* "+msg)
		}
	}

	if hasDeps {
		chore = append(chore, "* update dependencies (see history)")
	}

	var notes strings.Builder
	if len(gapic) > 0 {
		notes.WriteString("# gapic\n\n")
		notes.WriteString(strings.Join(gapic, "\n"))
		notes.WriteString("\n\n")
	}

	if len(bazel) > 0 {
		notes.WriteString("# bazel\n\n")
		notes.WriteString(strings.Join(bazel, "\n"))
		notes.WriteString("\n\n")
	}

	if len(gencli) > 0 {
		notes.WriteString("# gencli\n\n")
		notes.WriteString(strings.Join(gencli, "\n"))
		notes.WriteString("\n\n")
	}

	if len(samples) > 0 {
		notes.WriteString("# samples\n\n")
		notes.WriteString(strings.Join(samples, "\n"))
		notes.WriteString("\n\n")
	}

	if len(chore) > 0 {
		notes.WriteString("# chores\n\n")
		notes.WriteString(strings.Join(chore, "\n"))
		notes.WriteString("\n\n")
	}

	if len(other) > 0 {
		notes.WriteString("# other\n\n")
		notes.WriteString(strings.Join(other, "\n"))
	}

	return notes.String()
}
<commit_msg>chore: remove extraneous quotes on release notes (#355)<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package main contains a script that is run in CI when a new version tag is pushed to master.
// This script archives compiled executables of the gapic-generator-go plugin tool and creates
// a GitHub release with for the given tag and commitish using the given GitHub token.
//
// This script must be run from the root directory of the gapic-generator-go repository.
//
// Usage: go run ./util/cmd/release -version=v1.2.3 -token=$GITHUB_TOKEN -commitish=abc123
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var version, token, commitish string

func init() {
	flag.StringVar(&commitish, "commitish", "", "the target commitish to use [required]")
	flag.StringVar(&token, "token", "", "the GitHub token to use [optional]")
	flag.StringVar(&version, "version", "", "the version tag [required]")
}

func main() {
	flag.Parse()
	if commitish == "" {
		log.Fatalln("Missing required flag: -commitish")
	}
	if token == "" {
		log.Fatalln("Missing required flag: -token")
	}
	if version == "" {
		log.Fatalln("Missing required flag: -version")
	}
	if !strings.HasPrefix(version, "v") {
		log.Fatalln("Invalid version, should be in form vX.X.X")
	}

	outDir, err := ioutil.TempDir(os.TempDir(), "gapic-generator-go-")
	if err != nil {
		log.Fatalf("Error: unable to create temporary directory %+v\n", err)
	}
	defer os.RemoveAll(outDir)

	// Get cross compiler & GitHub release helper
	// Mousetrap is a windows dependency that is not implicitly got since
	// we only get the linux dependencies.
	execute(
		"go",
		"get",
		"github.com/mitchellh/gox",
		"github.com/inconshreveable/mousetrap",
		"github.com/tcnksm/ghr")

	// Compile plugin binaries.
	stagingDir := filepath.Join(outDir, "binaries")
	osArchs := []string{
		"windows/amd64",
		"linux/amd64",
		"darwin/amd64",
		"linux/arm",
	}
	for _, osArch := range osArchs {
		execute(
			"gox",
			fmt.Sprintf("-osarch=%s", osArch),
			"-output",
			filepath.Join(stagingDir, fmt.Sprintf("protoc-gen-go_gapic-%s-{{.OS}}-{{.Arch}}", version), "protoc-gen-go_gapic"),
			"github.com/googleapis/gapic-generator-go/cmd/protoc-gen-go_gapic")
	}

	dirs, _ := filepath.Glob(filepath.Join(stagingDir, "*"))
	for _, dir := range dirs {
		// The windows binaries are suffixed with '.exe'. This allows us to create
		// tarballs of the executables whether or not they contain a suffix.
		files, _ := filepath.Glob(filepath.Join(dir, "protoc-gen-go_gapic*"))
		execute(
			"tar",
			"-zcf",
			dir+".tar.gz",
			"-C",
			filepath.Dir(files[0]),
			filepath.Base(files[0]))
		// Remove the individual binary directory.
		execute("rm", "-r", dir)
	}

	// Execute GitHub release of artifacts.
	execute(
		"ghr",
		"-t="+token,
		"-n="+version,
		"-b="+notes(version),
		"-u=googleapis",
		"-r=gapic-generator-go",
		"-c="+commitish,
		version,
		stagingDir)
}

// execute runs the given strings as a command.
func execute(cmd string, args ...string) {
	if output, err := exec.Command(cmd, args...).CombinedOutput(); err != nil {
		log.Fatalf("%s", output)
	}
}

// executeWithOutput runs the given strings as a command and returns the output.
func executeWithOutput(cmd string, args ...string) string {
	out, err := exec.Command(cmd, args...).Output()
	if err != nil {
		log.Fatalf("%s", err)
	}
	return string(out)
}

// notes collects the commit messages since the previous tag, aggregates
// dependency updates into one message, and returns formatted release notes.
func notes(version string) string {
	previous := executeWithOutput(
		"git",
		"describe",
		"--abbrev=0",
		"--tags",
		version+"^",
	)
	previous = strings.TrimSpace(previous)

	output := executeWithOutput(
		"git",
		"log",
		previous+"..HEAD",
		"--oneline",
		"--pretty=format:%s",
	)
	commits := strings.Split(output, "\n")

	return format(commits)
}

// format parses the given commits messages and formats them into release notes
// organized by component.
func format(commits []string) string {
	var hasDeps bool
	var gapic, bazel, gencli, chore, samples, other []string

	for _, msg := range commits {
		sep := strings.Index(msg, ":")
		if sep == -1 {
			other = append(other, "* "+msg)
			continue
		}

		comp := msg[:sep]
		content := strings.TrimSpace(msg[sep+1:])

		switch comp {
		case "gapic":
			gapic = append(gapic, "* "+content)
		case "bazel":
			bazel = append(bazel, "* "+content)
		case "gencli":
			gencli = append(gencli, "* "+content)
		case "chore(deps)":
			hasDeps = true
		case "chore":
			chore = append(chore, "* "+content)
		case "samples":
			samples = append(samples, "* "+content)
		default:
			other = append(other, "* "+msg)
		}
	}

	if hasDeps {
		chore = append(chore, "* update dependencies (see history)")
	}

	var notes strings.Builder
	if len(gapic) > 0 {
		notes.WriteString("# gapic\n\n")
		notes.WriteString(strings.Join(gapic, "\n"))
		notes.WriteString("\n\n")
	}

	if len(bazel) > 0 {
		notes.WriteString("# bazel\n\n")
		notes.WriteString(strings.Join(bazel, "\n"))
		notes.WriteString("\n\n")
	}

	if len(gencli) > 0 {
		notes.WriteString("# gencli\n\n")
		notes.WriteString(strings.Join(gencli, "\n"))
		notes.WriteString("\n\n")
	}

	if len(samples) > 0 {
		notes.WriteString("# samples\n\n")
		notes.WriteString(strings.Join(samples, "\n"))
		notes.WriteString("\n\n")
	}

	if len(chore) > 0 {
		notes.WriteString("# chores\n\n")
		notes.WriteString(strings.Join(chore, "\n"))
		notes.WriteString("\n\n")
	}

	if len(other) > 0 {
		notes.WriteString("# other\n\n")
		notes.WriteString(strings.Join(other, "\n"))
	}

	return notes.String()
}
<|endoftext|>


<commit_before>package imageutil

import (
	"context"
	"encoding/json"
	"sync"
	"time"

	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/leases"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/reference"
	"github.com/containerd/containerd/remotes"
	"github.com/moby/buildkit/util/leaseutil"
	digest "github.com/opencontainers/go-digest"
	specs "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
)

type ContentCache interface {
	content.Ingester
	content.Provider
}

var leasesMu sync.Mutex
var leasesF []func(context.Context) error

func CancelCacheLeases() {
	leasesMu.Lock()
	for _, f := range leasesF {
		f(context.TODO())
	}
	leasesF = nil
	leasesMu.Unlock()
}

func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *specs.Platform) (digest.Digest, []byte, error) {
	// TODO: fix buildkit to take interface instead of struct
	var platform platforms.MatchComparer
	if p != nil {
		platform = platforms.Only(*p)
	} else {
		platform = platforms.Default()
	}
	ref, err := reference.Parse(str)
	if err != nil {
		return "", nil, errors.WithStack(err)
	}

	if leaseManager != nil {
		ctx2, done, err := leaseutil.WithLease(ctx, leaseManager, leases.WithExpiration(5*time.Minute), leaseutil.MakeTemporary)
		if err != nil {
			return "", nil, errors.WithStack(err)
		}
		ctx = ctx2
		defer func() {
			// this lease is not deleted to allow other components to access manifest/config from cache. It will be deleted after 5 min deadline or on pruning inactive builder
			leasesMu.Lock()
			leasesF = append(leasesF, done)
			leasesMu.Unlock()
		}()
	}

	desc := specs.Descriptor{
		Digest: ref.Digest(),
	}
	if desc.Digest != "" {
		ra, err := cache.ReaderAt(ctx, desc)
		if err == nil {
			desc.Size = ra.Size()
			mt, err := DetectManifestMediaType(ra)
			if err == nil {
				desc.MediaType = mt
			}
		}
	}
	// use resolver if desc is incomplete
	if desc.MediaType == "" {
		_, desc, err = resolver.Resolve(ctx, ref.String())
		if err != nil {
			return "", nil, err
		}
	}

	fetcher, err := resolver.Fetcher(ctx, ref.String())
	if err != nil {
		return "", nil, err
	}

	if desc.MediaType == images.MediaTypeDockerSchema1Manifest {
		return readSchema1Config(ctx, ref.String(), desc, fetcher, cache)
	}

	children := childrenConfigHandler(cache, platform)

	handlers := []images.Handler{
		remotes.FetchHandler(cache, fetcher),
		children,
	}
	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
		return "", nil, err
	}
	config, err := images.Config(ctx, cache, desc, platform)
	if err != nil {
		return "", nil, err
	}

	dt, err := content.ReadBlob(ctx, cache, config)
	if err != nil {
		return "", nil, err
	}

	return desc.Digest, dt, nil
}

func childrenConfigHandler(provider content.Provider, platform platforms.MatchComparer) images.HandlerFunc {
	return func(ctx context.Context, desc specs.Descriptor) ([]specs.Descriptor, error) {
		var descs []specs.Descriptor
		switch desc.MediaType {
		case images.MediaTypeDockerSchema2Manifest, specs.MediaTypeImageManifest:
			p, err := content.ReadBlob(ctx, provider, desc)
			if err != nil {
				return nil, err
			}

			// TODO(stevvooe): We just assume oci manifest, for now. There may be
			// subtle differences from the docker version.
			var manifest specs.Manifest
			if err := json.Unmarshal(p, &manifest); err != nil {
				return nil, err
			}

			descs = append(descs, manifest.Config)
		case images.MediaTypeDockerSchema2ManifestList, specs.MediaTypeImageIndex:
			p, err := content.ReadBlob(ctx, provider, desc)
			if err != nil {
				return nil, err
			}

			var index specs.Index
			if err := json.Unmarshal(p, &index); err != nil {
				return nil, err
			}

			if platform != nil {
				for _, d := range index.Manifests {
					if d.Platform == nil || platform.Match(*d.Platform) {
						descs = append(descs, d)
					}
				}
			} else {
				descs = append(descs, index.Manifests...)
			}
		case images.MediaTypeDockerSchema2Config, specs.MediaTypeImageConfig:
			// childless data types.
			return nil, nil
		default:
			return nil, errors.Errorf("encountered unknown type %v; children may not be fetched", desc.MediaType)
		}

		return descs, nil
	}
}

// specs.MediaTypeImageManifest, // TODO: detect schema1/manifest-list
func DetectManifestMediaType(ra content.ReaderAt) (string, error) {
	// TODO: schema1

	dt := make([]byte, ra.Size())
	if _, err := ra.ReadAt(dt, 0); err != nil {
		return "", err
	}

	return DetectManifestBlobMediaType(dt)
}

func DetectManifestBlobMediaType(dt []byte) (string, error) {
	var mfst struct {
		MediaType string          `json:"mediaType"`
		Config    json.RawMessage `json:"config"`
	}

	if err := json.Unmarshal(dt, &mfst); err != nil {
		return "", err
	}

	if mfst.MediaType != "" {
		return mfst.MediaType, nil
	}
	if mfst.Config != nil {
		return images.MediaTypeDockerSchema2Manifest, nil
	}
	return images.MediaTypeDockerSchema2ManifestList, nil
}
<commit_msg>fix legacy config media type application/octet-stream<commit_after>package imageutil

import (
	"context"
	"encoding/json"
	"sync"
	"time"

	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/leases"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/reference"
	"github.com/containerd/containerd/remotes"
	"github.com/containerd/containerd/remotes/docker"
	"github.com/moby/buildkit/util/leaseutil"
	digest "github.com/opencontainers/go-digest"
	specs "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
)

type ContentCache interface {
	content.Ingester
	content.Provider
}

var leasesMu sync.Mutex
var leasesF []func(context.Context) error

func CancelCacheLeases() {
	leasesMu.Lock()
	for _, f := range leasesF {
		f(context.TODO())
	}
	leasesF = nil
	leasesMu.Unlock()
}

func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *specs.Platform) (digest.Digest, []byte, error) {
	// TODO: fix buildkit to take interface instead of struct
	var platform platforms.MatchComparer
	if p != nil {
		platform = platforms.Only(*p)
	} else {
		platform = platforms.Default()
	}
	ref, err := reference.Parse(str)
	if err != nil {
		return "", nil, errors.WithStack(err)
	}

	if leaseManager != nil {
		ctx2, done, err := leaseutil.WithLease(ctx, leaseManager, leases.WithExpiration(5*time.Minute), leaseutil.MakeTemporary)
		if err != nil {
			return "", nil, errors.WithStack(err)
		}
		ctx = ctx2
		defer func() {
			// this lease is not deleted to allow other components to access manifest/config from cache. It will be deleted after 5 min deadline or on pruning inactive builder
			leasesMu.Lock()
			leasesF = append(leasesF, done)
			leasesMu.Unlock()
		}()
	}

	desc := specs.Descriptor{
		Digest: ref.Digest(),
	}
	if desc.Digest != "" {
		ra, err := cache.ReaderAt(ctx, desc)
		if err == nil {
			desc.Size = ra.Size()
			mt, err := DetectManifestMediaType(ra)
			if err == nil {
				desc.MediaType = mt
			}
		}
	}
	// use resolver if desc is incomplete
	if desc.MediaType == "" {
		_, desc, err = resolver.Resolve(ctx, ref.String())
		if err != nil {
			return "", nil, err
		}
	}

	fetcher, err := resolver.Fetcher(ctx, ref.String())
	if err != nil {
		return "", nil, err
	}

	if desc.MediaType == images.MediaTypeDockerSchema1Manifest {
		return readSchema1Config(ctx, ref.String(), desc, fetcher, cache)
	}

	children := childrenConfigHandler(cache, platform)

	handlers := []images.Handler{
		remotes.FetchHandler(cache, fetcher),
		children,
	}
	if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
		return "", nil, err
	}
	config, err := images.Config(ctx, cache, desc, platform)
	if err != nil {
		return "", nil, err
	}

	dt, err := content.ReadBlob(ctx, cache, config)
	if err != nil {
		return "", nil, err
	}

	return desc.Digest, dt, nil
}

func childrenConfigHandler(provider content.Provider, platform platforms.MatchComparer) images.HandlerFunc {
	return func(ctx context.Context, desc specs.Descriptor) ([]specs.Descriptor, error) {
		var descs []specs.Descriptor
		switch desc.MediaType {
		case images.MediaTypeDockerSchema2Manifest, specs.MediaTypeImageManifest:
			p, err := content.ReadBlob(ctx, provider, desc)
			if err != nil {
				return nil, err
			}

			// TODO(stevvooe): We just assume oci manifest, for now. There may be
			// subtle differences from the docker version.
			var manifest specs.Manifest
			if err := json.Unmarshal(p, &manifest); err != nil {
				return nil, err
			}

			descs = append(descs, manifest.Config)
		case images.MediaTypeDockerSchema2ManifestList, specs.MediaTypeImageIndex:
			p, err := content.ReadBlob(ctx, provider, desc)
			if err != nil {
				return nil, err
			}

			var index specs.Index
			if err := json.Unmarshal(p, &index); err != nil {
				return nil, err
			}

			if platform != nil {
				for _, d := range index.Manifests {
					if d.Platform == nil || platform.Match(*d.Platform) {
						descs = append(descs, d)
					}
				}
			} else {
				descs = append(descs, index.Manifests...)
			}
		case images.MediaTypeDockerSchema2Config, specs.MediaTypeImageConfig, docker.LegacyConfigMediaType:
			// childless data types.
			return nil, nil
		default:
			return nil, errors.Errorf("encountered unknown type %v; children may not be fetched", desc.MediaType)
		}

		return descs, nil
	}
}

// specs.MediaTypeImageManifest, // TODO: detect schema1/manifest-list
func DetectManifestMediaType(ra content.ReaderAt) (string, error) {
	// TODO: schema1

	dt := make([]byte, ra.Size())
	if _, err := ra.ReadAt(dt, 0); err != nil {
		return "", err
	}

	return DetectManifestBlobMediaType(dt)
}

func DetectManifestBlobMediaType(dt []byte) (string, error) {
	var mfst struct {
		MediaType string          `json:"mediaType"`
		Config    json.RawMessage `json:"config"`
	}

	if err := json.Unmarshal(dt, &mfst); err != nil {
		return "", err
	}

	if mfst.MediaType != "" {
		return mfst.MediaType, nil
	}
	if mfst.Config != nil {
		return images.MediaTypeDockerSchema2Manifest, nil
	}
	return images.MediaTypeDockerSchema2ManifestList, nil
}
<|endoftext|>


<commit_before>package duo

import (
	"context"
	"fmt"
	"net/url"

	"github.com/duosecurity/duo_api_golang"
	"github.com/duosecurity/duo_api_golang/authapi"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

type AuthClient interface {
	Preauth(options ...func(*url.Values)) (*authapi.PreauthResult, error)
	Auth(factor string, options ...func(*url.Values)) (*authapi.AuthResult, error)
}

func pathDuoAccess() *framework.Path {
	return &framework.Path{
		Pattern: `duo/access`,
		Fields: map[string]*framework.FieldSchema{
			"skey": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo secret key",
			},
			"ikey": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo integration key",
			},
			"host": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo api host",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: pathDuoAccessWrite,
		},

		HelpSynopsis:    pathDuoAccessHelpSyn,
		HelpDescription: pathDuoAccessHelpDesc,
	}
}

func GetDuoAuthClient(ctx context.Context, req *logical.Request, config *DuoConfig) (AuthClient, error) {
	entry, err := req.Storage.Get(ctx, "duo/access")
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, fmt.Errorf(
			"Duo access credentials haven't been configured. Please configure\n" +
				"them at the 'duo/access' endpoint")
	}
	var access DuoAccess
	if err := entry.DecodeJSON(&access); err != nil {
		return nil, err
	}

	duoClient := duoapi.NewDuoApi(
		access.IKey,
		access.SKey,
		access.Host,
		config.UserAgent,
	)
	duoAuthClient := authapi.NewAuthApi(*duoClient)
	check, err := duoAuthClient.Check()
	if err != nil {
		return nil, err
	}
	if check == nil || check.StatResult.Message == nil || check.StatResult.Message_Detail == nil {
		return nil, fmt.Errorf("Could not connect to Duo; got nil result back from API check call")
	}
	if check.StatResult.Stat != "OK" {
		return nil, fmt.Errorf("Could not connect to Duo: %s (%s)", *check.StatResult.Message, *check.StatResult.Message_Detail)
	}
	return duoAuthClient, nil
}

func pathDuoAccessWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	entry, err := logical.StorageEntryJSON("duo/access", DuoAccess{
		SKey: d.Get("skey").(string),
		IKey: d.Get("ikey").(string),
		Host: d.Get("host").(string),
	})
	if err != nil {
		return nil, err
	}

	if err := req.Storage.Put(ctx, entry); err != nil {
		return nil, err
	}

	return nil, nil
}

type DuoAccess struct {
	SKey string `json:"skey"`
	IKey string `json:"ikey"`
	Host string `json:"host"`
}

const pathDuoAccessHelpSyn = `
Configure the access keys and host for Duo API connections.
`

const pathDuoAccessHelpDesc = `
To authenticate users with Duo, the backend needs to know what host to connect to
and must authenticate with an integration key and secret key. This endpoint is used
to configure that information.
`
<commit_msg>Better duo status message handling (#3834)<commit_after>package duo

import (
	"context"
	"fmt"
	"net/url"

	"github.com/duosecurity/duo_api_golang"
	"github.com/duosecurity/duo_api_golang/authapi"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

type AuthClient interface {
	Preauth(options ...func(*url.Values)) (*authapi.PreauthResult, error)
	Auth(factor string, options ...func(*url.Values)) (*authapi.AuthResult, error)
}

func pathDuoAccess() *framework.Path {
	return &framework.Path{
		Pattern: `duo/access`,
		Fields: map[string]*framework.FieldSchema{
			"skey": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo secret key",
			},
			"ikey": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo integration key",
			},
			"host": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "Duo api host",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: pathDuoAccessWrite,
		},

		HelpSynopsis:    pathDuoAccessHelpSyn,
		HelpDescription: pathDuoAccessHelpDesc,
	}
}

func GetDuoAuthClient(ctx context.Context, req *logical.Request, config *DuoConfig) (AuthClient, error) {
	entry, err := req.Storage.Get(ctx, "duo/access")
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return nil, fmt.Errorf(
			"Duo access credentials haven't been configured. Please configure\n" +
				"them at the 'duo/access' endpoint")
	}
	var access DuoAccess
	if err := entry.DecodeJSON(&access); err != nil {
		return nil, err
	}

	duoClient := duoapi.NewDuoApi(
		access.IKey,
		access.SKey,
		access.Host,
		config.UserAgent,
	)
	duoAuthClient := authapi.NewAuthApi(*duoClient)
	check, err := duoAuthClient.Check()
	if err != nil {
		return nil, err
	}
	if check == nil {
		return nil, fmt.Errorf("Could not connect to Duo; got nil result back from API check call")
	}
	var msg, detail string
	if check.StatResult.Message != nil {
		msg = *check.StatResult.Message
	}
	if check.StatResult.Message_Detail != nil {
		detail = *check.StatResult.Message_Detail
	}
	if check.StatResult.Stat != "OK" {
		return nil, fmt.Errorf("Could not connect to Duo: %s (%s)", msg, detail)
	}
	return duoAuthClient, nil
}

func pathDuoAccessWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	entry, err := logical.StorageEntryJSON("duo/access", DuoAccess{
		SKey: d.Get("skey").(string),
		IKey: d.Get("ikey").(string),
		Host: d.Get("host").(string),
	})
	if err != nil {
		return nil, err
	}

	if err := req.Storage.Put(ctx, entry); err != nil {
		return nil, err
	}

	return nil, nil
}

type DuoAccess struct {
	SKey string `json:"skey"`
	IKey string `json:"ikey"`
	Host string `json:"host"`
}

const pathDuoAccessHelpSyn = `
Configure the access keys and host for Duo API connections.
`

const pathDuoAccessHelpDesc = `
To authenticate users with Duo, the backend needs to know what host to connect to
and must authenticate with an integration key and secret key. This endpoint is used
to configure that information.
`
<|endoftext|>


<commit_before>package handler

import (
	"fmt"
	"net/http"

	"code.uber.internal/infra/kraken/utils/log"
)

// Error defines an HTTP handler error which encapsulates status and headers
// to be set in the HTTP response.
type Error struct {
	status int
	header http.Header
	msg    string
}

// Errorf creates a new Error with Printf-style formatting. Defaults to 500 error.
func Errorf(format string, args ...interface{}) *Error {
	return &Error{
		status: http.StatusInternalServerError,
		header: http.Header{},
		msg:    fmt.Sprintf(format, args...),
	}
}

// ErrorStatus creates an empty message error with status s.
func ErrorStatus(s int) *Error {
	return Errorf("").Status(s)
}

// Status sets a custom status on e.
func (e *Error) Status(s int) *Error {
	e.status = s
	return e
}

// Header adds a custom header to e.
func (e *Error) Header(k, v string) *Error {
	e.header.Add(k, v)
	return e
}

// GetStatus returns the error status.
func (e *Error) GetStatus() int {
	return e.status
}

func (e *Error) Error() string {
	if e.msg == "" {
		return fmt.Sprintf("server error %d", e.status)
	}
	return fmt.Sprintf("server error %d: %s", e.status, e.msg)
}

// ErrHandler defines an HTTP handler which returns an error.
type ErrHandler func(http.ResponseWriter, *http.Request) error

// Wrap converts an ErrHandler into an http.HandlerFunc by handling the error
// returned by h.
func Wrap(h ErrHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var status int
		var errMsg string
		if err := h(w, r); err != nil {
			switch e := err.(type) {
			case *Error:
				for k, vs := range e.header {
					for _, v := range vs {
						w.Header().Add(k, v)
					}
				}
				status = e.status
				errMsg = e.msg
			default:
				status = http.StatusInternalServerError
				errMsg = e.Error()
			}
			w.WriteHeader(status)
			w.Write([]byte(errMsg))
		} else {
			status = http.StatusOK
		}
		if status >= 400 {
			log.Infof("%d %s %s %s", status, r.Method, r.URL.Path, errMsg)
		}
	}
}
<commit_msg>Don't log 404s<commit_after>package handler

import (
	"fmt"
	"net/http"

	"code.uber.internal/infra/kraken/utils/log"
)

// Error defines an HTTP handler error which encapsulates status and headers
// to be set in the HTTP response.
type Error struct {
	status int
	header http.Header
	msg    string
}

// Errorf creates a new Error with Printf-style formatting. Defaults to 500 error.
func Errorf(format string, args ...interface{}) *Error {
	return &Error{
		status: http.StatusInternalServerError,
		header: http.Header{},
		msg:    fmt.Sprintf(format, args...),
	}
}

// ErrorStatus creates an empty message error with status s.
func ErrorStatus(s int) *Error {
	return Errorf("").Status(s)
}

// Status sets a custom status on e.
func (e *Error) Status(s int) *Error {
	e.status = s
	return e
}

// Header adds a custom header to e.
func (e *Error) Header(k, v string) *Error {
	e.header.Add(k, v)
	return e
}

// GetStatus returns the error status.
func (e *Error) GetStatus() int {
	return e.status
}

func (e *Error) Error() string {
	if e.msg == "" {
		return fmt.Sprintf("server error %d", e.status)
	}
	return fmt.Sprintf("server error %d: %s", e.status, e.msg)
}

// ErrHandler defines an HTTP handler which returns an error.
type ErrHandler func(http.ResponseWriter, *http.Request) error

// Wrap converts an ErrHandler into an http.HandlerFunc by handling the error
// returned by h.
func Wrap(h ErrHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var status int
		var errMsg string
		if err := h(w, r); err != nil {
			switch e := err.(type) {
			case *Error:
				for k, vs := range e.header {
					for _, v := range vs {
						w.Header().Add(k, v)
					}
				}
				status = e.status
				errMsg = e.msg
			default:
				status = http.StatusInternalServerError
				errMsg = e.Error()
			}
			w.WriteHeader(status)
			w.Write([]byte(errMsg))
		} else {
			status = http.StatusOK
		}
		if status >= 400 && status != 404 {
			log.Infof("%d %s %s %s", status, r.Method, r.URL.Path, errMsg)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Remove ' = 0' for 'var x int' to remove golint warnings.<commit_after><|endoftext|>


<commit_before>package testflight_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Flying", func() {
	var tmpdir string

	BeforeEach(func() {
		var err error

		tmpdir, err = ioutil.TempDir("", "fly-test")
		Ω(err).ShouldNot(HaveOccurred())

		err = ioutil.WriteFile(filepath.Join(tmpdir, "build.yml"), []byte(fmt.Sprintf(`---
---
image: %s

params:
  FOO: 1

run:
  path: bash
  args:
    - -c
    - |
      echo some output
      echo FOO is $FOO
      exit 0
`, helperRootfs)), 0644)
		Ω(err).ShouldNot(HaveOccurred())
	})

	AfterEach(func() {
		os.RemoveAll(tmpdir)
	})

	It("works", func() {
		fly := exec.Command(builtComponents["fly"])
		fly.Dir = tmpdir

		session, err := gexec.Start(fly, GinkgoWriter, GinkgoWriter)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

		Ω(session).Should(gbytes.Say("some output"))
		Ω(session).Should(gbytes.Say("FOO is 1"))
	})
})
<commit_msg>fix typo<commit_after>package testflight_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

var _ = Describe("Flying", func() {
	var tmpdir string

	BeforeEach(func() {
		var err error

		tmpdir, err = ioutil.TempDir("", "fly-test")
		Ω(err).ShouldNot(HaveOccurred())

		err = ioutil.WriteFile(filepath.Join(tmpdir, "build.yml"), []byte(fmt.Sprintf(`---
image: %s

params:
  FOO: 1

run:
  path: bash
  args:
    - -c
    - |
      echo some output
      echo FOO is $FOO
      exit 0
`, helperRootfs)), 0644)
		Ω(err).ShouldNot(HaveOccurred())
	})

	AfterEach(func() {
		os.RemoveAll(tmpdir)
	})

	It("works", func() {
		fly := exec.Command(builtComponents["fly"])
		fly.Dir = tmpdir

		session, err := gexec.Start(fly, GinkgoWriter, GinkgoWriter)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

		Ω(session).Should(gbytes.Say("some output"))
		Ω(session).Should(gbytes.Say("FOO is 1"))
	})
})
<|endoftext|>


<commit_before><commit_msg>Set glExperimental to true in Init<commit_after><|endoftext|>


<commit_before>//Command to run test version:
//goapp serve app.yaml
//Command to deploy/update application:
//goapp deploy -application golangnode0 -version 0

package main

import (
	"fmt"
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}

func startPage(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, test application started.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
}

func showInfo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Inforamtion page for test project.\nLanguage - Go\nPlatform - Google Application Engine")
}

func init() {

	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	//Wrong code for App Enine - server cant understand what it need to show
	//http.ListenAndServe(":80", nil)
}

/*
func main() {
	fmt.Println("Hello, test server started on 80 port.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	http.ListenAndServe(":80", nil)
}
*/
<commit_msg>Correct version for deploy to GAE<commit_after>//Command to run test version:
//goapp serve app.yaml
//Command to deploy/update application:
//goapp deploy -application golangnode0 -version 0

package main

import (
	"fmt"
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!")
}

func startPage(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, test application started.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
}

func showInfo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Inforamtion page for test project.\nLanguage - Go\nPlatform - Google Application Engine")
}

func init() {

	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	//Wrong code for App Enine - server cant understand what it need to show
	//http.ListenAndServe(":80", nil)
}

/*
func main() {
	fmt.Println("Hello, test server started on 80 port.\n - /helloworld - show title page\n - /showinfo - show information about this thing")
	http.HandleFunc("/", startPage)
	http.HandleFunc("/helloworld", helloWorld)
	http.HandleFunc("/showinfo", showInfo)
	http.ListenAndServe(":8080", nil)
}
*/
<|endoftext|>


<commit_before><commit_msg>goroutine test<commit_after><|endoftext|>


<commit_before>package config

import (
	"reflect"
	"testing"
)

func TestLoadConfiguration(t *testing.T) {
	var config Config
	err := LoadConfiguration("../config.json", &config)
	if err != nil {
		t.Error(err)
	}
	defaultConfig := Config{
		TelegramToken:          "write-your-telegram-token-here",
		TelegramBotName:        "golosovalochka_bot",
		Account:                "golosovalochka",
		PostingKey:             "5...",
		ActiveKey:              "5...",
		ReferralFee:            5.0,
		RequiredVotes:          1,
		InitialUserRating:      10,
		MaximumOpenedVotes:     3,
		MaximumUserVotesPerDay: 4,
		Developer:              "@babin",
		GroupID:                -1001143551951,
		GroupLink:              "https://t.me/joinchat/AlKeQUQpN8-9oShtaTcY7Q",
		DatabasePath:           "./db/database.db",
		Domains:                []string{"golos.io", "golos.blog", "goldvoice.club"},
		Chain:                  "golos",
		Rpc:                    []string{"wss://ws.golos.io", "wss://api.golos.cf"},
	}
	if !reflect.DeepEqual(defaultConfig, config) {
		t.Error("Конфиги не совпадают")
	}
}
<commit_msg>Forget about tests. Again<commit_after>package config

import (
	"reflect"
	"testing"
)

func TestLoadConfiguration(t *testing.T) {
	var config Config
	err := LoadConfiguration("../config.json", &config)
	if err != nil {
		t.Error(err)
	}
	defaultConfig := Config{
		TelegramToken:          "write-your-telegram-token-here",
		TelegramBotName:        "golosovalochka_bot",
		Account:                "golosovalochka",
		PostingKey:             "5...",
		ActiveKey:              "5...",
		ReferralFee:            5.0,
		RequiredVotes:          2,
		InitialUserRating:      10,
		MaximumOpenedVotes:     3,
		MaximumUserVotesPerDay: 4,
		Developer:              "@babin",
		GroupID:                -1001143551951,
		GroupLink:              "https://t.me/joinchat/AlKeQUQpN8-9oShtaTcY7Q",
		DatabasePath:           "./db/database.db",
		Domains:                []string{"golos.io", "golos.blog", "goldvoice.club"},
		Chain:                  "golos",
		Rpc:                    []string{"wss://ws.golos.io", "wss://api.golos.cf"},
	}
	if !reflect.DeepEqual(defaultConfig, config) {
		t.Error("Конфиги не совпадают")
	}
}
<|endoftext|>


<commit_before>package runtime_test

import (
	"bytes"
	"fmt"
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"testing"
)

func checkGdbEnvironment(t *testing.T) {
	testenv.MustHaveGoBuild(t)
	if runtime.GOOS == "darwin" {
		t.Skip("gdb does not work on darwin")
	}
	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
		t.Skip("gdb test can fail with GOROOT_FINAL pending")
	}
}

func checkGdbVersion(t *testing.T) {
	// Issue 11214 reports various failures with older versions of gdb.
	out, err := exec.Command("gdb", "--version").CombinedOutput()
	if err != nil {
		t.Skipf("skipping: error executing gdb: %v", err)
	}
	re := regexp.MustCompile(`([0-9]+)\.([0-9]+)`)
	matches := re.FindSubmatch(out)
	if len(matches) < 3 {
		t.Skipf("skipping: can't determine gdb version from\n%s\n", out)
	}
	major, err1 := strconv.Atoi(string(matches[1]))
	minor, err2 := strconv.Atoi(string(matches[2]))
	if err1 != nil || err2 != nil {
		t.Skipf("skipping: can't determine gdb version: %v, %v", err1, err2)
	}
	if major < 7 || (major == 7 && minor < 7) {
		t.Skipf("skipping: gdb version %d.%d too old", major, minor)
	}
	t.Logf("gdb version %d.%d", major, minor)
}

func checkGdbPython(t *testing.T) {
	cmd := exec.Command("gdb", "-nx", "-q", "--batch", "-iex", "python import sys; print('go gdb python support')")
	out, err := cmd.CombinedOutput()

	if err != nil {
		t.Skipf("skipping due to issue running gdb: %v", err)
	}
	if string(out) != "go gdb python support\n" {
		t.Skipf("skipping due to lack of python gdb support: %s", out)
	}
}

const helloSource = `
package main
import "fmt"
func main() {
	mapvar := make(map[string]string,5)
	mapvar["abc"] = "def"
	mapvar["ghi"] = "jkl"
	strvar := "abc"
	ptrvar := &strvar
	fmt.Println("hi") // line 10
	_ = ptrvar
}
`

func TestGdbPython(t *testing.T) {
	checkGdbEnvironment(t)
	checkGdbVersion(t)
	checkGdbPython(t)

	dir, err := ioutil.TempDir("", "go-build")
	if err != nil {
		t.Fatalf("failed to create temp directory: %v", err)
	}
	defer os.RemoveAll(dir)

	src := filepath.Join(dir, "main.go")
	err = ioutil.WriteFile(src, []byte(helloSource), 0644)
	if err != nil {
		t.Fatalf("failed to create file: %v", err)
	}

	cmd := exec.Command("go", "build", "-o", "a.exe")
	cmd.Dir = dir
	out, err := testEnv(cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("building source %v\n%s", err, out)
	}

	args := []string{"-nx", "-q", "--batch", "-iex",
		fmt.Sprintf("add-auto-load-safe-path %s/src/runtime", runtime.GOROOT()),
		"-ex", "info auto-load python-scripts",
		"-ex", "br main.go:10",
		"-ex", "run",
		"-ex", "echo BEGIN info goroutines\n",
		"-ex", "info goroutines",
		"-ex", "echo END\n",
		"-ex", "echo BEGIN print mapvar\n",
		"-ex", "print mapvar",
		"-ex", "echo END\n",
		"-ex", "echo BEGIN print strvar\n",
		"-ex", "print strvar",
		"-ex", "echo END\n"}

	// without framepointer, gdb cannot backtrace our non-standard
	// stack frames on RISC architectures.
	canBackTrace := false
	switch runtime.GOARCH {
	case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64", "mips64", "mips64le", "s390x":
		canBackTrace = true
		args = append(args,
			"-ex", "echo BEGIN goroutine 2 bt\n",
			"-ex", "goroutine 2 bt",
			"-ex", "echo END\n")
	}

	args = append(args, filepath.Join(dir, "a.exe"))
	got, _ := exec.Command("gdb", args...).CombinedOutput()

	firstLine := bytes.SplitN(got, []byte("\n"), 2)[0]
	if string(firstLine) != "Loading Go Runtime support." {
		// This can happen when using all.bash with
		// GOROOT_FINAL set, because the tests are run before
		// the final installation of the files.
		cmd := exec.Command("go", "env", "GOROOT")
		cmd.Env = []string{}
		out, err := cmd.CombinedOutput()
		if err != nil && bytes.Contains(out, []byte("cannot find GOROOT")) {
			t.Skipf("skipping because GOROOT=%s does not exist", runtime.GOROOT())
		}

		_, file, _, _ := runtime.Caller(1)

		t.Logf("package testing source file: %s", file)
		t.Fatalf("failed to load Go runtime support: %s\n%s", firstLine, got)
	}

	// Extract named BEGIN...END blocks from output
	partRe := regexp.MustCompile(`(?ms)^BEGIN ([^\n]*)\n(.*?)\nEND`)
	blocks := map[string]string{}
	for _, subs := range partRe.FindAllSubmatch(got, -1) {
		blocks[string(subs[1])] = string(subs[2])
	}

	infoGoroutinesRe := regexp.MustCompile(`\*\s+\d+\s+running\s+`)
	if bl := blocks["info goroutines"]; !infoGoroutinesRe.MatchString(bl) {
		t.Fatalf("info goroutines failed: %s", bl)
	}

	printMapvarRe := regexp.MustCompile(`\Q = map[string]string = {["abc"] = "def", ["ghi"] = "jkl"}\E$`)
	if bl := blocks["print mapvar"]; !printMapvarRe.MatchString(bl) {
		t.Fatalf("print mapvar failed: %s", bl)
	}

	strVarRe := regexp.MustCompile(`\Q = "abc"\E$`)
	if bl := blocks["print strvar"]; !strVarRe.MatchString(bl) {
		t.Fatalf("print strvar failed: %s", bl)
	}

	btGoroutineRe := regexp.MustCompile(`^#0\s+runtime.+at`)
	if bl := blocks["goroutine 2 bt"]; canBackTrace && !btGoroutineRe.MatchString(bl) {
		t.Fatalf("goroutine 2 bt failed: %s", bl)
	} else if !canBackTrace {
		t.Logf("gdb cannot backtrace for GOARCH=%s, skipped goroutine backtrace test", runtime.GOARCH)
	}
}

const backtraceSource = `
package main

//go:noinline
func aaa() bool { return bbb() }

//go:noinline
func bbb() bool { return ccc() }

//go:noinline
func ccc() bool { return ddd() }

//go:noinline
func ddd() bool { return f() }

//go:noinline
func eee() bool { return true }

var f = eee

func main() {
	_ = aaa()
}
`

// TestGdbBacktrace tests that gdb can unwind the stack correctly
// using only the DWARF debug info.
func TestGdbBacktrace(t *testing.T) {
	checkGdbEnvironment(t)
	checkGdbVersion(t)

	dir, err := ioutil.TempDir("", "go-build")
	if err != nil {
		t.Fatalf("failed to create temp directory: %v", err)
	}
	defer os.RemoveAll(dir)

	// Build the source code.
	src := filepath.Join(dir, "main.go")
	err = ioutil.WriteFile(src, []byte(backtraceSource), 0644)
	if err != nil {
		t.Fatalf("failed to create file: %v", err)
	}
	cmd := exec.Command("go", "build", "-o", "a.exe")
	cmd.Dir = dir
	out, err := testEnv(cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("building source %v\n%s", err, out)
	}

	// Execute gdb commands.
	args := []string{"-nx", "-batch",
		"-ex", "break main.eee",
		"-ex", "run",
		"-ex", "backtrace",
		"-ex", "continue",
		filepath.Join(dir, "a.exe"),
	}
	got, _ := exec.Command("gdb", args...).CombinedOutput()

	// Check that the backtrace matches the source code.
	bt := []string{
		"eee",
		"ddd",
		"ccc",
		"bbb",
		"aaa",
		"main",
	}
	for i, name := range bt {
		s := fmt.Sprintf("#%v.*main\\.%v", i, name)
		re := regexp.MustCompile(s)
		if found := re.Find(got) != nil; !found {
			t.Errorf("could not find '%v' in backtrace", s)
			t.Fatalf("gdb output:\n%v", string(got))
		}
	}
}
<commit_msg>runtime: in tests, make sure gdb does not start with a shell<commit_after>package runtime_test

import (
	"bytes"
	"fmt"
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"testing"
)

func checkGdbEnvironment(t *testing.T) {
	testenv.MustHaveGoBuild(t)
	if runtime.GOOS == "darwin" {
		t.Skip("gdb does not work on darwin")
	}
	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
		t.Skip("gdb test can fail with GOROOT_FINAL pending")
	}
}

func checkGdbVersion(t *testing.T) {
	// Issue 11214 reports various failures with older versions of gdb.
	out, err := exec.Command("gdb", "--version").CombinedOutput()
	if err != nil {
		t.Skipf("skipping: error executing gdb: %v", err)
	}
	re := regexp.MustCompile(`([0-9]+)\.([0-9]+)`)
	matches := re.FindSubmatch(out)
	if len(matches) < 3 {
		t.Skipf("skipping: can't determine gdb version from\n%s\n", out)
	}
	major, err1 := strconv.Atoi(string(matches[1]))
	minor, err2 := strconv.Atoi(string(matches[2]))
	if err1 != nil || err2 != nil {
		t.Skipf("skipping: can't determine gdb version: %v, %v", err1, err2)
	}
	if major < 7 || (major == 7 && minor < 7) {
		t.Skipf("skipping: gdb version %d.%d too old", major, minor)
	}
	t.Logf("gdb version %d.%d", major, minor)
}

func checkGdbPython(t *testing.T) {
	cmd := exec.Command("gdb", "-nx", "-q", "--batch", "-iex", "python import sys; print('go gdb python support')")
	out, err := cmd.CombinedOutput()

	if err != nil {
		t.Skipf("skipping due to issue running gdb: %v", err)
	}
	if string(out) != "go gdb python support\n" {
		t.Skipf("skipping due to lack of python gdb support: %s", out)
	}
}

const helloSource = `
package main
import "fmt"
func main() {
	mapvar := make(map[string]string,5)
	mapvar["abc"] = "def"
	mapvar["ghi"] = "jkl"
	strvar := "abc"
	ptrvar := &strvar
	fmt.Println("hi") // line 10
	_ = ptrvar
}
`

func TestGdbPython(t *testing.T) {
	checkGdbEnvironment(t)
	checkGdbVersion(t)
	checkGdbPython(t)

	dir, err := ioutil.TempDir("", "go-build")
	if err != nil {
		t.Fatalf("failed to create temp directory: %v", err)
	}
	defer os.RemoveAll(dir)

	src := filepath.Join(dir, "main.go")
	err = ioutil.WriteFile(src, []byte(helloSource), 0644)
	if err != nil {
		t.Fatalf("failed to create file: %v", err)
	}

	cmd := exec.Command("go", "build", "-o", "a.exe")
	cmd.Dir = dir
	out, err := testEnv(cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("building source %v\n%s", err, out)
	}

	args := []string{"-nx", "-q", "--batch", "-iex",
		fmt.Sprintf("add-auto-load-safe-path %s/src/runtime", runtime.GOROOT()),
		"-ex", "set startup-with-shell off",
		"-ex", "info auto-load python-scripts",
		"-ex", "br main.go:10",
		"-ex", "run",
		"-ex", "echo BEGIN info goroutines\n",
		"-ex", "info goroutines",
		"-ex", "echo END\n",
		"-ex", "echo BEGIN print mapvar\n",
		"-ex", "print mapvar",
		"-ex", "echo END\n",
		"-ex", "echo BEGIN print strvar\n",
		"-ex", "print strvar",
		"-ex", "echo END\n"}

	// without framepointer, gdb cannot backtrace our non-standard
	// stack frames on RISC architectures.
	canBackTrace := false
	switch runtime.GOARCH {
	case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64", "mips64", "mips64le", "s390x":
		canBackTrace = true
		args = append(args,
			"-ex", "echo BEGIN goroutine 2 bt\n",
			"-ex", "goroutine 2 bt",
			"-ex", "echo END\n")
	}

	args = append(args, filepath.Join(dir, "a.exe"))
	got, _ := exec.Command("gdb", args...).CombinedOutput()

	firstLine := bytes.SplitN(got, []byte("\n"), 2)[0]
	if string(firstLine) != "Loading Go Runtime support." {
		// This can happen when using all.bash with
		// GOROOT_FINAL set, because the tests are run before
		// the final installation of the files.
		cmd := exec.Command("go", "env", "GOROOT")
		cmd.Env = []string{}
		out, err := cmd.CombinedOutput()
		if err != nil && bytes.Contains(out, []byte("cannot find GOROOT")) {
			t.Skipf("skipping because GOROOT=%s does not exist", runtime.GOROOT())
		}

		_, file, _, _ := runtime.Caller(1)

		t.Logf("package testing source file: %s", file)
		t.Fatalf("failed to load Go runtime support: %s\n%s", firstLine, got)
	}

	// Extract named BEGIN...END blocks from output
	partRe := regexp.MustCompile(`(?ms)^BEGIN ([^\n]*)\n(.*?)\nEND`)
	blocks := map[string]string{}
	for _, subs := range partRe.FindAllSubmatch(got, -1) {
		blocks[string(subs[1])] = string(subs[2])
	}

	infoGoroutinesRe := regexp.MustCompile(`\*\s+\d+\s+running\s+`)
	if bl := blocks["info goroutines"]; !infoGoroutinesRe.MatchString(bl) {
		t.Fatalf("info goroutines failed: %s", bl)
	}

	printMapvarRe := regexp.MustCompile(`\Q = map[string]string = {["abc"] = "def", ["ghi"] = "jkl"}\E$`)
	if bl := blocks["print mapvar"]; !printMapvarRe.MatchString(bl) {
		t.Fatalf("print mapvar failed: %s", bl)
	}

	strVarRe := regexp.MustCompile(`\Q = "abc"\E$`)
	if bl := blocks["print strvar"]; !strVarRe.MatchString(bl) {
		t.Fatalf("print strvar failed: %s", bl)
	}

	btGoroutineRe := regexp.MustCompile(`^#0\s+runtime.+at`)
	if bl := blocks["goroutine 2 bt"]; canBackTrace && !btGoroutineRe.MatchString(bl) {
		t.Fatalf("goroutine 2 bt failed: %s", bl)
	} else if !canBackTrace {
		t.Logf("gdb cannot backtrace for GOARCH=%s, skipped goroutine backtrace test", runtime.GOARCH)
	}
}

const backtraceSource = `
package main

//go:noinline
func aaa() bool { return bbb() }

//go:noinline
func bbb() bool { return ccc() }

//go:noinline
func ccc() bool { return ddd() }

//go:noinline
func ddd() bool { return f() }

//go:noinline
func eee() bool { return true }

var f = eee

func main() {
	_ = aaa()
}
`

// TestGdbBacktrace tests that gdb can unwind the stack correctly
// using only the DWARF debug info.
func TestGdbBacktrace(t *testing.T) {
	checkGdbEnvironment(t)
	checkGdbVersion(t)

	dir, err := ioutil.TempDir("", "go-build")
	if err != nil {
		t.Fatalf("failed to create temp directory: %v", err)
	}
	defer os.RemoveAll(dir)

	// Build the source code.
	src := filepath.Join(dir, "main.go")
	err = ioutil.WriteFile(src, []byte(backtraceSource), 0644)
	if err != nil {
		t.Fatalf("failed to create file: %v", err)
	}
	cmd := exec.Command("go", "build", "-o", "a.exe")
	cmd.Dir = dir
	out, err := testEnv(cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("building source %v\n%s", err, out)
	}

	// Execute gdb commands.
	args := []string{"-nx", "-batch",
		"-ex", "set startup-with-shell off",
		"-ex", "break main.eee",
		"-ex", "run",
		"-ex", "backtrace",
		"-ex", "continue",
		filepath.Join(dir, "a.exe"),
	}
	got, _ := exec.Command("gdb", args...).CombinedOutput()

	// Check that the backtrace matches the source code.
	bt := []string{
		"eee",
		"ddd",
		"ccc",
		"bbb",
		"aaa",
		"main",
	}
	for i, name := range bt {
		s := fmt.Sprintf("#%v.*main\\.%v", i, name)
		re := regexp.MustCompile(s)
		if found := re.Find(got) != nil; !found {
			t.Errorf("could not find '%v' in backtrace", s)
			t.Fatalf("gdb output:\n%v", string(got))
		}
	}
}
<|endoftext|>


<commit_before>package mlstate

import (
	"fmt"
	"pfi/sensorbee/pystate/py"
	"pfi/sensorbee/sensorbee/core"
	"pfi/sensorbee/sensorbee/data"
)

var (
	lossPath = data.MustCompilePath("loss")
	accPath  = data.MustCompilePath("accuracy")
)

// PyMLState is python instance specialized to multiple layer classification.
type PyMLState struct {
	ins py.ObjectInstance

	bucket    data.Array
	batchSize int
}

// NewPyMLState creates `core.SharedState` for multiple layer classification.
func NewPyMLState(modulePathName, moduleName, className string, batchSize int,
	modelPath string, gpuID int) (*PyMLState, error) {
	py.ImportSysAndAppendPath(modulePathName)

	mdl, err := py.LoadModule(moduleName)
	if err != nil {
		return nil, err
	}
	defer mdl.DecRef()

	ins, err := mdl.NewInstance(className, data.String(modelPath), data.Int(gpuID))
	if err != nil {
		return nil, err
	}

	return &PyMLState{
		ins:       ins,
		bucket:    make(data.Array, 0, batchSize),
		batchSize: batchSize,
	}, nil
}

// Terminate this state.
func (s *PyMLState) Terminate(ctx *core.Context) error {
	s.ins.DecRef()
	return nil
}

// Write and call "fit" function. Tuples is cached per train batch size.
func (s *PyMLState) Write(ctx *core.Context, t *core.Tuple) error {
	s.bucket = append(s.bucket, t.Data)

	var err error
	if len(s.bucket) >= s.batchSize {
		m, er := s.Fit(ctx, s.bucket)
		err = er
		s.bucket = s.bucket[:0] // clear slice but keep capacity

		// optional logging, return non-error even if the value does not have
		// accuracy and loss.
		if ret, er := data.AsMap(m); er == nil {
			var loss float64
			if l, e := ret.Get(lossPath); e != nil {
				return err
			} else if loss, e = data.ToFloat(l); e != nil {
				return err
			}
			var acc float64
			if a, e := ret.Get(accPath); e != nil {
				return err
			} else if acc, e = data.ToFloat(a); e != nil {
				return err
			}
			ctx.Log().Debugf("loss=%.3f acc=%.3f", loss/float64(s.batchSize),
				acc/float64(s.batchSize))
		}
	}

	return err
}

// Fit receives `data.Array` type but it assumes `[]data.Map` type
// for passing arguments to `fit` method.
func (s *PyMLState) Fit(ctx *core.Context, bucket data.Array) (data.Value, error) {
	return s.ins.Call("fit", bucket)
}

// FitMap receives `[]data.Map`, these maps are converted to `data.Array`
func (s *PyMLState) FitMap(ctx *core.Context, bucket []data.Map) (data.Value, error) {
	args := make(data.Array, len(bucket))
	for i, v := range bucket {
		args[i] = v
	}
	return s.ins.Call("fit", args)
}

// PyMLFit fits buckets. fit algorithm and return value is depends on Python
// implementation.
func PyMLFit(ctx *core.Context, stateName string, bucket []data.Map) (data.Value, error) {
	s, err := lookupPyMLState(ctx, stateName)
	if err != nil {
		return nil, err
	}

	return s.FitMap(ctx, bucket)
}

// PyMLPredict predicts data and return estimate value.
func PyMLPredict(ctx *core.Context, stateName string, dt data.Value) (data.Value, error) {
	s, err := lookupPyMLState(ctx, stateName)
	if err != nil {
		return nil, err
	}

	return s.ins.Call("predict", dt)
}

func lookupPyMLState(ctx *core.Context, stateName string) (*PyMLState, error) {
	st, err := ctx.SharedStates.Get(stateName)
	if err != nil {
		return nil, err
	}

	if s, ok := st.(*PyMLState); ok {
		return s, nil
	}

	return nil, fmt.Errorf("state '%v' isn't a PyMLState", stateName)
}
<commit_msg>Support save/load state<commit_after>package mlstate

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"pfi/sensorbee/pystate/py"
	"pfi/sensorbee/sensorbee/core"
	"pfi/sensorbee/sensorbee/data"
)

var (
	lossPath = data.MustCompilePath("loss")
	accPath  = data.MustCompilePath("accuracy")
)

// PyMLState is python instance specialized to multiple layer classification.
type PyMLState struct {
	ins py.ObjectInstance

	bucket    data.Array
	batchSize int
}

// NewPyMLState creates `core.SharedState` for multiple layer classification.
func NewPyMLState(modulePathName, moduleName, className string, batchSize int,
	modelPath string, gpuID int) (*PyMLState, error) {
	py.ImportSysAndAppendPath(modulePathName)

	mdl, err := py.LoadModule(moduleName)
	if err != nil {
		return nil, err
	}
	defer mdl.DecRef()

	ins, err := mdl.NewInstance(className, data.String(modelPath), data.Int(gpuID))
	if err != nil {
		return nil, err
	}

	return &PyMLState{
		ins:       ins,
		bucket:    make(data.Array, 0, batchSize),
		batchSize: batchSize,
	}, nil
}

// Terminate this state.
func (s *PyMLState) Terminate(ctx *core.Context) error {
	s.ins.DecRef()
	return nil
}

// Write and call "fit" function. Tuples is cached per train batch size.
func (s *PyMLState) Write(ctx *core.Context, t *core.Tuple) error {
	s.bucket = append(s.bucket, t.Data)

	var err error
	if len(s.bucket) >= s.batchSize {
		m, er := s.Fit(ctx, s.bucket)
		err = er
		s.bucket = s.bucket[:0] // clear slice but keep capacity

		// optional logging, return non-error even if the value does not have
		// accuracy and loss.
		if ret, er := data.AsMap(m); er == nil {
			var loss float64
			if l, e := ret.Get(lossPath); e != nil {
				return err
			} else if loss, e = data.ToFloat(l); e != nil {
				return err
			}
			var acc float64
			if a, e := ret.Get(accPath); e != nil {
				return err
			} else if acc, e = data.ToFloat(a); e != nil {
				return err
			}
			ctx.Log().Debugf("loss=%.3f acc=%.3f", loss/float64(s.batchSize),
				acc/float64(s.batchSize))
		}
	}

	return err
}

// Fit receives `data.Array` type but it assumes `[]data.Map` type
// for passing arguments to `fit` method.
func (s *PyMLState) Fit(ctx *core.Context, bucket data.Array) (data.Value, error) {
	return s.ins.Call("fit", bucket)
}

// FitMap receives `[]data.Map`, these maps are converted to `data.Array`
func (s *PyMLState) FitMap(ctx *core.Context, bucket []data.Map) (data.Value, error) {
	args := make(data.Array, len(bucket))
	for i, v := range bucket {
		args[i] = v
	}
	return s.ins.Call("fit", args)
}

// Save saves the model of the state. pystate calls `save` method and
// use its return value as dumped model.
func (s *PyMLState) Save(ctx *core.Context, w io.Writer, params data.Map) error {
	res, err := s.ins.Call("save")
	if err != nil {
		return err
	}

	b, err := data.AsBlob(res)
	if err != nil {
		return err
	}

	buf := bytes.NewBuffer(b)
	_, err = buf.WriteTo(w)
	return err
}

// Load loads the model of the state. pystate calls `load` method and
// pass to the model data by using method parameter.
func (s *PyMLState) Load(ctx *core.Context, r io.Reader, params data.Map) error {
	dat, err := ioutil.ReadAll(r)
	if err != nil {
		return err
	}

	_, err = s.ins.Call("load", data.Blob(dat))
	return err
}

// PyMLFit fits buckets. fit algorithm and return value is depends on Python
// implementation.
func PyMLFit(ctx *core.Context, stateName string, bucket []data.Map) (data.Value, error) {
	s, err := lookupPyMLState(ctx, stateName)
	if err != nil {
		return nil, err
	}

	return s.FitMap(ctx, bucket)
}

// PyMLPredict predicts data and return estimate value.
func PyMLPredict(ctx *core.Context, stateName string, dt data.Value) (data.Value, error) {
	s, err := lookupPyMLState(ctx, stateName)
	if err != nil {
		return nil, err
	}

	return s.ins.Call("predict", dt)
}

func lookupPyMLState(ctx *core.Context, stateName string) (*PyMLState, error) {
	st, err := ctx.SharedStates.Get(stateName)
	if err != nil {
		return nil, err
	}

	if s, ok := st.(*PyMLState); ok {
		return s, nil
	}

	return nil, fmt.Errorf("state '%v' isn't a PyMLState", stateName)
}
<|endoftext|>


<commit_before>package transports

import (
	"fmt"
	"net/http"
	"io/ioutil"
	"github.com/headzoo/surf"
	"github.com/headzoo/surf/browser"
	"errors"
)

type FacebookTransport struct {
	*Transport
	Login         string
	Password      string
	Friend				string
	Browser       *browser.Browser
	Serializer		DefaultSerializer
}

func (t *FacebookTransport) DoLogin() bool {
	fmt.Println("FacebookTransport, Login()")
	err := t.Browser.Open("https://mobile.facebook.com/")
	if err != nil {
		panic(err)
	}

	LoginForm := t.Browser.Forms()[1]
	LoginForm.Input("email", t.Login)
	LoginForm.Input("pass", t.Password)
	if LoginForm.Submit() != nil {
		panic(err)
	}

	err = t.Browser.Open("https://mobile.facebook.com/profile.php")

	if err != nil {
		panic(err)
	}

	fmt.Println("Logged in as", t.Browser.Title(), "?")

	FriendUrl := fmt.Sprintf("https://mobile.facebook.com/%s", t.Friend )
	err = t.Browser.Open( FriendUrl)

	if err != nil {
		panic(err)
	}

	t.Browser.Click("a[href*=\"/messages/thread/\"]")

	return true

}

func (t *FacebookTransport) Prepare() {
	fmt.Println("FacebookTransport, Prepare()")

	t.Serializer = DefaultSerializer{}

	t.Browser = surf.NewBrowser()

	if !t.DoLogin() {
		err := errors.New( "Authentication error!")
		panic(err)
	}

	return
}

func (t *FacebookTransport) Handler(w http.ResponseWriter, originalRequest *http.Request) {

	client := &http.Client{}

	request, _ := http.NewRequest(originalRequest.Method, originalRequest.URL.String(), nil)

	serializedRequest := t.Serializer.Serialize(request)

	fmt.Println("Got", originalRequest)
	fmt.Println("Serialized", string(serializedRequest))

	MessageForm, _ := t.Browser.Form("#composer_form")
	MessageForm.Input( "body", string(serializedRequest))
	MessageForm.Submit()

	resp, _ := client.Do(request)
	b, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	w.Write(b)

	return
}

func (t *FacebookTransport) Listen() {
	fmt.Println( "FacebookTransport, Listen()")
	t.Prepare()
	fmt.Println("Polling...")
	for {
	}
	return
}
<commit_msg>Persist the chat URL<commit_after>package transports

import (
	"fmt"
	"net/http"
	"io/ioutil"
	"github.com/headzoo/surf"
	"github.com/headzoo/surf/browser"
	"errors"
)

type FacebookTransport struct {
	*Transport
	Login         string
	Password      string
	Friend				string
	Browser       *browser.Browser
	Serializer		DefaultSerializer
	ChatUrl string
}

func (t *FacebookTransport) DoLogin() bool {
	fmt.Println("FacebookTransport, Login()")
	err := t.Browser.Open("https://mobile.facebook.com/")
	if err != nil {
		panic(err)
	}

	LoginForm := t.Browser.Forms()[1]
	LoginForm.Input("email", t.Login)
	LoginForm.Input("pass", t.Password)
	if LoginForm.Submit() != nil {
		panic(err)
	}

	err = t.Browser.Open("https://mobile.facebook.com/profile.php")

	if err != nil {
		panic(err)
	}

	fmt.Println("Logged in as", t.Browser.Title(), "?")

	FriendUrl := fmt.Sprintf("https://mobile.facebook.com/%s", t.Friend )
	err = t.Browser.Open( FriendUrl)

	if err != nil {
		panic(err)
	}

	t.Browser.Click("a[href*=\"/messages/thread/\"]")

	t.ChatUrl = t.Browser.Url().String()

	return true

}

func (t *FacebookTransport) Prepare() {
	fmt.Println("FacebookTransport, Prepare()")

	t.Serializer = DefaultSerializer{}

	t.Browser = surf.NewBrowser()

	if !t.DoLogin() {
		err := errors.New( "Authentication error!")
		panic(err)
	}

	return
}

func (t *FacebookTransport) Handler(w http.ResponseWriter, originalRequest *http.Request) {

	t.Browser.Open( t.ChatUrl )

	client := &http.Client{}

	request, _ := http.NewRequest(originalRequest.Method, originalRequest.URL.String(), nil)

	serializedRequest := t.Serializer.Serialize(request)

	fmt.Println("Got", originalRequest)
	fmt.Println("Serialized", string(serializedRequest))

	MessageForm, _ := t.Browser.Form("#composer_form")
	MessageForm.Input( "body", string(serializedRequest))
	MessageForm.Submit()

	resp, _ := client.Do(request)
	b, _ := ioutil.ReadAll(resp.Body)
	resp.Body.Close()

	w.Write(b)

	return
}

func (t *FacebookTransport) Listen() {
	fmt.Println( "FacebookTransport, Listen()")
	t.Prepare()
	fmt.Println("Polling...")
	for {
	}
	return
}
<|endoftext|>


<commit_before>// This file contains functions for transpiling common branching and control
// flow, such as "if", "while", "do" and "for". The more complicated control
// flows like "switch" will be put into their own file of the same or sensible
// name.

package transpiler

import (
	"fmt"
	"go/token"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/types"
	"github.com/elliotchance/c2go/util"

	goast "go/ast"
)

func transpileIfStmt(n *ast.IfStmt, p *program.Program) (
	*goast.IfStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}
	children := n.Children

	// There is always 4 or 5 children in an IfStmt. For example:
	//
	//     if (i == 0) {
	//         return 0;
	//     } else {
	//         return 1;
	//     }
	//
	// 1. Not sure what this is for. This gets removed.
	// 2. Not sure what this is for.
	// 3. conditional = BinaryOperator: i == 0
	// 4. body = CompoundStmt: { return 0; }
	// 5. elseBody = CompoundStmt: { return 1; }
	//
	// elseBody will be nil if there is no else clause.

	// On linux I have seen only 4 children for an IfStmt with the same
	// definitions above, but missing the first argument. Since we don't
	// know what the first argument is for anyway we will just remove it on
	// Mac if necessary.
	if len(children) == 5 && children[0] != nil {
		panic("non-nil child 0 in IfStmt")
	}
	if len(children) == 5 {
		children = children[1:]
	}

	// From here on there must be 4 children.
	if len(children) != 4 {
		panic(fmt.Sprintf("Expected 4 children in IfStmt, got %#v", children))
	}

	// Maybe we will discover what the nil value is?
	if children[0] != nil {
		panic("non-nil child 0 in IfStmt")
	}

	conditional, conditionalType, newPre, newPost, err := transpileToExpr(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	// The condition in Go must always be a bool.
	boolCondition, err := types.CastExpr(p, conditional, conditionalType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, boolCondition == nil))

	if boolCondition == nil {
		boolCondition = util.NewNil()
	}

	body, newPre, newPost, err := transpileToBlockStmt(children[2], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	r := &goast.IfStmt{
		Cond: boolCondition,
		Body: body,
	}

	if children[3] != nil {
		elseBody, newPre, newPost, err := transpileToBlockStmt(children[3], p)
		if err != nil {
			return nil, nil, nil, err
		}

		preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

		r.Else = elseBody
	}

	return r, newPre, newPost, nil
}

func transpileForStmt(n *ast.ForStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}

	children := n.Children

	// There are always 5 children in a ForStmt, for example:
	//
	//     for ( c = 0 ; c < n ; c++ ) {
	//         doSomething();
	//     }
	//
	// 1. initExpression = BinaryStmt: c = 0
	// 2. Not sure what this is for, but it's always nil. There is a panic
	//    below in case we discover what it is used for (pun intended).
	// 3. conditionalExpression = BinaryStmt: c < n
	// 4. stepExpression = BinaryStmt: c++
	// 5. body = CompoundStmt: { CallExpr }

	if len(children) != 5 {
		panic(fmt.Sprintf("Expected 5 children in ForStmt, got %#v", children))
	}

	// TODO: The second child of a ForStmt appears to always be null.
	// Are there any cases where it is used?
	if children[1] != nil {
		panic("non-nil child 1 in ForStmt")
	}

	// If we have 2 and more initializations like
	// in operator for
	// for( a = 0, b = 0, c = 0; a < 5; a ++)
	switch children[0].(type) {
	case *ast.BinaryOperator:
		c := children[0].(*ast.BinaryOperator)
		if c.Operator == "," {
			// recursive action to code like that:
			// a = 0;
			// b = 0;
			// for(c = 0 ; a < 5 ; a++)
			//
			before, newPre, newPost, err := transpileToStmt(c.Children[0], p)
			if err != nil {
				return nil, nil, nil, err
			}
			preStmts = append(preStmts, newPre...)
			preStmts = append(preStmts, before)
			preStmts = append(preStmts, newPost...)
			children[0] = c.Children[1]
		}
	}

	init, newPre, newPost, err := transpileToStmt(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// If we have 2 and more increments
	// in operator for
	// for( a = 0; a < 5; a ++, b++, c+=2)
	switch children[3].(type) {
	case *ast.BinaryOperator:
		c := children[3].(*ast.BinaryOperator)
		if c.Operator == "," {
			// recursive action to code like that:
			// a = 0;
			// b = 0;
			// for(a = 0 ; a < 5 ; c+=2){
			// body
			// a++;
			// b++
			// }
			//
			var compound ast.CompoundStmt
			compound.Children = append(compound.Children, children[4])
			compound.Children = append(compound.Children, c.Children[0:len(c.Children)-1]...)
			children[4] = &compound
			children[3] = c.Children[len(c.Children)-1]
		}
	}

	post, newPre, newPost, err := transpileToStmt(children[3], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// The condition can be nil. This means an infinite loop and will be
	// rendered in Go as "for {".
	var condition goast.Expr
	if children[2] != nil {
		// If we have 2 and more conditions
		// in operator for
		// for( a = 0; b = c, b++, a < 5; a ++)
		switch children[2].(type) {
		case *ast.BinaryOperator:
			c := children[2].(*ast.BinaryOperator)
			if c.Operator == "," {
				// recursive action to code like that:
				// a = 0;
				// b = 0;
				// for(a = 0 ; a < 5 ; c+=2){
				// body
				// b = c
				// b++
				// }
				//
				var compound ast.CompoundStmt
				compound.Children = append(compound.Children, c.Children[0:len(c.Children)-1]...)
				compound.Children = append(compound.Children, children[4])
				children[4] = &compound
				children[2] = c.Children[len(c.Children)-1]
			}
		}
		var conditionType string
		var newPre, newPost []goast.Stmt
		condition, conditionType, newPre, newPost, err = transpileToExpr(children[2], p)
		if err != nil {
			return nil, nil, nil, err
		}

		preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

		condition, err = types.CastExpr(p, condition, conditionType, "bool")
		p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, condition == nil))

		if condition == nil {
			condition = util.NewNil()
		}
	}

	body, newPre, newPost, err := transpileToBlockStmt(children[4], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	return &goast.ForStmt{
		Init: init,
		Cond: condition,
		Post: post,
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileWhileStmt(n *ast.WhileStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}

	// TODO: The first child of a WhileStmt appears to always be null.
	// Are there any cases where it is used?
	children := n.Children[1:]

	body, newPre, newPost, err := transpileToBlockStmt(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	condition, conditionType, newPre, newPost, err := transpileToExpr(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	cond, err := types.CastExpr(p, condition, conditionType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, cond == nil))

	if cond == nil {
		cond = util.NewNil()
	}

	return &goast.ForStmt{
		Cond: cond,
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileDoStmt(n *ast.DoStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}
	children := n.Children

	body, newPre, newPost, err := transpileToBlockStmt(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	condition, conditionType, newPre, newPost, err := transpileToExpr(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// Add IfStmt to the end of the loop to check the condition.
	x, err := types.CastExpr(p, condition, conditionType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, x == nil))

	if x == nil {
		x = util.NewNil()
	}

	body.List = append(body.List, &goast.IfStmt{
		Cond: &goast.UnaryExpr{
			Op: token.NOT,
			X:  x,
		},
		Body: &goast.BlockStmt{
			List: []goast.Stmt{&goast.BranchStmt{Tok: token.BREAK}},
		},
	})

	return &goast.ForStmt{
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileContinueStmt(n *ast.ContinueStmt, p *program.Program) (*goast.BranchStmt, error) {
	return &goast.BranchStmt{
		Tok: token.CONTINUE,
	}, nil
}
<commit_msg>Better view without addition compount elements<commit_after>// This file contains functions for transpiling common branching and control
// flow, such as "if", "while", "do" and "for". The more complicated control
// flows like "switch" will be put into their own file of the same or sensible
// name.

package transpiler

import (
	"fmt"
	"go/token"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/types"
	"github.com/elliotchance/c2go/util"

	goast "go/ast"
)

func transpileIfStmt(n *ast.IfStmt, p *program.Program) (
	*goast.IfStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}
	children := n.Children

	// There is always 4 or 5 children in an IfStmt. For example:
	//
	//     if (i == 0) {
	//         return 0;
	//     } else {
	//         return 1;
	//     }
	//
	// 1. Not sure what this is for. This gets removed.
	// 2. Not sure what this is for.
	// 3. conditional = BinaryOperator: i == 0
	// 4. body = CompoundStmt: { return 0; }
	// 5. elseBody = CompoundStmt: { return 1; }
	//
	// elseBody will be nil if there is no else clause.

	// On linux I have seen only 4 children for an IfStmt with the same
	// definitions above, but missing the first argument. Since we don't
	// know what the first argument is for anyway we will just remove it on
	// Mac if necessary.
	if len(children) == 5 && children[0] != nil {
		panic("non-nil child 0 in IfStmt")
	}
	if len(children) == 5 {
		children = children[1:]
	}

	// From here on there must be 4 children.
	if len(children) != 4 {
		panic(fmt.Sprintf("Expected 4 children in IfStmt, got %#v", children))
	}

	// Maybe we will discover what the nil value is?
	if children[0] != nil {
		panic("non-nil child 0 in IfStmt")
	}

	conditional, conditionalType, newPre, newPost, err := transpileToExpr(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	// The condition in Go must always be a bool.
	boolCondition, err := types.CastExpr(p, conditional, conditionalType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, boolCondition == nil))

	if boolCondition == nil {
		boolCondition = util.NewNil()
	}

	body, newPre, newPost, err := transpileToBlockStmt(children[2], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	r := &goast.IfStmt{
		Cond: boolCondition,
		Body: body,
	}

	if children[3] != nil {
		elseBody, newPre, newPost, err := transpileToBlockStmt(children[3], p)
		if err != nil {
			return nil, nil, nil, err
		}

		preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

		r.Else = elseBody
	}

	return r, newPre, newPost, nil
}

func transpileForStmt(n *ast.ForStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}

	children := n.Children

	// There are always 5 children in a ForStmt, for example:
	//
	//     for ( c = 0 ; c < n ; c++ ) {
	//         doSomething();
	//     }
	//
	// 1. initExpression = BinaryStmt: c = 0
	// 2. Not sure what this is for, but it's always nil. There is a panic
	//    below in case we discover what it is used for (pun intended).
	// 3. conditionalExpression = BinaryStmt: c < n
	// 4. stepExpression = BinaryStmt: c++
	// 5. body = CompoundStmt: { CallExpr }

	if len(children) != 5 {
		panic(fmt.Sprintf("Expected 5 children in ForStmt, got %#v", children))
	}

	// TODO: The second child of a ForStmt appears to always be null.
	// Are there any cases where it is used?
	if children[1] != nil {
		panic("non-nil child 1 in ForStmt")
	}

	// If we have 2 and more initializations like
	// in operator for
	// for( a = 0, b = 0, c = 0; a < 5; a ++)
	switch children[0].(type) {
	case *ast.BinaryOperator:
		c := children[0].(*ast.BinaryOperator)
		if c.Operator == "," {
			// recursive action to code like that:
			// a = 0;
			// b = 0;
			// for(c = 0 ; a < 5 ; a++)
			//
			before, newPre, newPost, err := transpileToStmt(c.Children[0], p)
			if err != nil {
				return nil, nil, nil, err
			}
			preStmts = append(preStmts, newPre...)
			preStmts = append(preStmts, before)
			preStmts = append(preStmts, newPost...)
			children[0] = c.Children[1]
		}
	}

	init, newPre, newPost, err := transpileToStmt(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// If we have 2 and more increments
	// in operator for
	// for( a = 0; a < 5; a ++, b++, c+=2)
	switch children[3].(type) {
	case *ast.BinaryOperator:
		c := children[3].(*ast.BinaryOperator)
		if c.Operator == "," {
			// recursive action to code like that:
			// a = 0;
			// b = 0;
			// for(a = 0 ; a < 5 ; c+=2){
			// body
			// a++;
			// b++
			// }
			//
			compound := children[4].(*ast.CompoundStmt)
			compound.Children = append(compound.Children, c.Children[0:len(c.Children)-1]...)
			children[4] = compound
			children[3] = c.Children[len(c.Children)-1]
		}
	}

	post, newPre, newPost, err := transpileToStmt(children[3], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// The condition can be nil. This means an infinite loop and will be
	// rendered in Go as "for {".
	var condition goast.Expr
	if children[2] != nil {
		// If we have 2 and more conditions
		// in operator for
		// for( a = 0; b = c, b++, a < 5; a ++)
		switch children[2].(type) {
		case *ast.BinaryOperator:
			c := children[2].(*ast.BinaryOperator)
			if c.Operator == "," {
				// recursive action to code like that:
				// a = 0;
				// b = 0;
				// for(a = 0 ; a < 5 ; c+=2){
				// body
				// b = c
				// b++
				// }
				//

				compound := children[4].(*ast.CompoundStmt)
				compound.Children = append(c.Children[0:len(c.Children)-1], compound.Children...)
				children[4] = compound
				children[2] = c.Children[len(c.Children)-1]
			}
		}
		var conditionType string
		var newPre, newPost []goast.Stmt
		condition, conditionType, newPre, newPost, err = transpileToExpr(children[2], p)
		if err != nil {
			return nil, nil, nil, err
		}

		preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

		condition, err = types.CastExpr(p, condition, conditionType, "bool")
		p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, condition == nil))

		if condition == nil {
			condition = util.NewNil()
		}
	}

	body, newPre, newPost, err := transpileToBlockStmt(children[4], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	return &goast.ForStmt{
		Init: init,
		Cond: condition,
		Post: post,
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileWhileStmt(n *ast.WhileStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}

	// TODO: The first child of a WhileStmt appears to always be null.
	// Are there any cases where it is used?
	children := n.Children[1:]

	body, newPre, newPost, err := transpileToBlockStmt(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	condition, conditionType, newPre, newPost, err := transpileToExpr(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	cond, err := types.CastExpr(p, condition, conditionType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, cond == nil))

	if cond == nil {
		cond = util.NewNil()
	}

	return &goast.ForStmt{
		Cond: cond,
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileDoStmt(n *ast.DoStmt, p *program.Program) (
	*goast.ForStmt, []goast.Stmt, []goast.Stmt, error) {
	preStmts := []goast.Stmt{}
	postStmts := []goast.Stmt{}
	children := n.Children

	body, newPre, newPost, err := transpileToBlockStmt(children[0], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	condition, conditionType, newPre, newPost, err := transpileToExpr(children[1], p)
	if err != nil {
		return nil, nil, nil, err
	}

	preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost)

	// Add IfStmt to the end of the loop to check the condition.
	x, err := types.CastExpr(p, condition, conditionType, "bool")
	p.AddMessage(ast.GenerateWarningOrErrorMessage(err, n, x == nil))

	if x == nil {
		x = util.NewNil()
	}

	body.List = append(body.List, &goast.IfStmt{
		Cond: &goast.UnaryExpr{
			Op: token.NOT,
			X:  x,
		},
		Body: &goast.BlockStmt{
			List: []goast.Stmt{&goast.BranchStmt{Tok: token.BREAK}},
		},
	})

	return &goast.ForStmt{
		Body: body,
	}, preStmts, postStmts, nil
}

func transpileContinueStmt(n *ast.ContinueStmt, p *program.Program) (*goast.BranchStmt, error) {
	return &goast.BranchStmt{
		Tok: token.CONTINUE,
	}, nil
}
<|endoftext|>