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

package pilot

import (
	"flag"
	"os"
	"strconv"
	"testing"

	"github.com/davecgh/go-spew/spew"

	"istio.io/istio/pkg/log"
	tutil "istio.io/istio/tests/e2e/tests/pilot/util"
)

var (
	defaultConfig = tutil.NewInfra()

	verbose bool
)

func init() {
	flag.StringVar(&defaultConfig.Hub, "hub", defaultConfig.Hub, "Docker hub")
	flag.StringVar(&defaultConfig.Tag, "tag", defaultConfig.Tag, "Docker tag")
	flag.StringVar(&defaultConfig.IstioNamespace, "ns", defaultConfig.IstioNamespace,
		"Namespace in which to install Istio components (empty to create/delete temporary one)")
	flag.StringVar(&defaultConfig.Namespace, "n", defaultConfig.Namespace,
		"Namespace in which to install the applications (empty to create/delete temporary one)")
	flag.StringVar(&defaultConfig.Registry, "registry", defaultConfig.Registry, "Pilot registry")
	flag.BoolVar(&verbose, "verbose", false, "Debug level noise from proxies")
	flag.BoolVar(&defaultConfig.CheckLogs, "logs", defaultConfig.CheckLogs,
		"Validate pod logs (expensive in long-running tests)")

	flag.StringVar(&defaultConfig.KubeConfig, "kubeconfig", defaultConfig.KubeConfig,
		"kube config file (missing or empty file makes the test use in-cluster kube config instead)")
	flag.IntVar(&defaultConfig.TestCount, "count", defaultConfig.TestCount, "Number of times to run each test")
	flag.BoolVar(&defaultConfig.Mixer, "mixer", defaultConfig.Mixer, "Enable / disable mixer.")
	flag.BoolVar(&defaultConfig.V1alpha1, "v1alpha1", defaultConfig.V1alpha1, "Enable / disable v1alpha1 routing rules.")
	flag.BoolVar(&defaultConfig.V1alpha2, "v1alpha2", defaultConfig.V1alpha2, "Enable / disable v1alpha2 routing rules.")
	flag.StringVar(&defaultConfig.ErrorLogsDir, "errorlogsdir", defaultConfig.ErrorLogsDir,
		"Store per pod logs as individual files in specific directory instead of writing to stderr.")
	flag.StringVar(&defaultConfig.CoreFilesDir, "core-files-dir", defaultConfig.CoreFilesDir,
		"Copy core files to this directory on the Kubernetes node machine.")

	// If specified, only run one test
	flag.StringVar(&defaultConfig.SelectedTest, "testtype", defaultConfig.SelectedTest,
		"Select test to run (default is all tests)")

	flag.BoolVar(&defaultConfig.UseAutomaticInjection, "use-sidecar-injector", defaultConfig.UseAutomaticInjection,
		"Use automatic sidecar injector")
	flag.BoolVar(&defaultConfig.UseAdmissionWebhook, "use-admission-webhook", defaultConfig.UseAdmissionWebhook,
		"Use k8s external admission webhook for config validation")

	flag.StringVar(&defaultConfig.AdmissionServiceName, "admission-service-name", defaultConfig.AdmissionServiceName,
		"Name of admission webhook service name")

	flag.IntVar(&defaultConfig.DebugPort, "debugport", defaultConfig.DebugPort, "Debugging port")

	flag.BoolVar(&defaultConfig.DebugImagesAndMode, "debug", defaultConfig.DebugImagesAndMode,
		"Use debug images and mode (false for prod)")
	flag.BoolVar(&defaultConfig.SkipCleanup, "skip-cleanup", defaultConfig.SkipCleanup,
		"Debug, skip clean up")
	flag.BoolVar(&defaultConfig.SkipCleanupOnFailure, "skip-cleanup-on-failure", defaultConfig.SkipCleanupOnFailure,
		"Debug, skip clean up on failure")
}

func setup(config *tutil.Infra, t *testing.T) {
	// Only run the tests if the user has defined the KUBECONFIG environment variable.
	if config.KubeConfig == "" {
		t.Skip("Env variable KUBECONFIG not set. Skipping integration tests")
	}

	if config.Hub == "" {
		t.Skip("HUB not specified. Skipping integration tests")
	}

	if config.Tag == "" {
		t.Skip("TAG not specified. Skipping integration tests")
	}

	tutil.Tlog("Deploying infrastructure", spew.Sdump(config))
	if config.Err = config.Setup(); config.Err != nil {
		t.Fatal(config.Err)
	}
}

func teardown(config *tutil.Infra) {
	config.Teardown()
}

func TestNoAuth(t *testing.T) {
	doTest(false, t)
}

// TODO(nmittler): Investigate why mTLS tests are failing.
/*
func TestMTls(t *testing.T) {
	doTest(true, t)
}*/

func doTest(useAuth bool, t *testing.T) {
	var config *tutil.Infra
	if useAuth {
		config = defaultConfig.CopyWithDefaultAuth()
	} else {
		config = &(*defaultConfig)
	}

	if verbose {
		config.Verbosity = 3
	}

	defer teardown(config)
	setup(config, t)

	tests := []tutil.Test{
		&http{Infra: config},
		&grpc{Infra: config},
		&tcp{Infra: config},
		&headless{Infra: config},
		&ingress{Infra: config},
		&egressRules{Infra: config},
		&routing{Infra: config},
		&routingToEgress{Infra: config},
		&zipkin{Infra: config},
		&authExclusion{Infra: config},
		&kubernetesExternalNameServices{Infra: config},
	}

	for _, test := range tests {
		// If the user has specified a test, skip all other tests
		if len(config.SelectedTest) > 0 && config.SelectedTest != test.String() {
			continue
		}

		// Run the test the configured number of times.
		for i := 0; i < config.TestCount; i++ {
			testName := test.String()
			if config.TestCount > 1 {
				testName = testName + "_attempt_" + strconv.Itoa(i+1)
			}
			t.Run(testName, func(t *testing.T) {
				if config.Err = test.Setup(); config.Err != nil {
					t.Fatal(config.Err)
				}
				defer test.Teardown()

				if config.Err = test.Run(); config.Err != nil {
					t.Error(config.Err)
				}
			})
		}
	}
}

// TODO(nmittler): convert individual tests over to pure golang tests
func TestMain(m *testing.M) {
	flag.Parse()
	_ = log.Configure(log.NewOptions())

	// Run all tests.
	os.Exit(m.Run())
}
<commit_msg>Workaround to fix prow. (#3502)<commit_after>// Copyright 2018 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pilot

import (
	"flag"
	"os"
	"strconv"
	"testing"

	"istio.io/istio/pkg/log"
	tutil "istio.io/istio/tests/e2e/tests/pilot/util"
)

var (
	defaultConfig = tutil.NewInfra()

	verbose bool
)

func init() {
	flag.StringVar(&defaultConfig.Hub, "hub", defaultConfig.Hub, "Docker hub")
	flag.StringVar(&defaultConfig.Tag, "tag", defaultConfig.Tag, "Docker tag")
	flag.StringVar(&defaultConfig.IstioNamespace, "ns", defaultConfig.IstioNamespace,
		"Namespace in which to install Istio components (empty to create/delete temporary one)")
	flag.StringVar(&defaultConfig.Namespace, "n", defaultConfig.Namespace,
		"Namespace in which to install the applications (empty to create/delete temporary one)")
	flag.StringVar(&defaultConfig.Registry, "registry", defaultConfig.Registry, "Pilot registry")
	flag.BoolVar(&verbose, "verbose", false, "Debug level noise from proxies")
	flag.BoolVar(&defaultConfig.CheckLogs, "logs", defaultConfig.CheckLogs,
		"Validate pod logs (expensive in long-running tests)")

	flag.StringVar(&defaultConfig.KubeConfig, "kubeconfig", defaultConfig.KubeConfig,
		"kube config file (missing or empty file makes the test use in-cluster kube config instead)")
	flag.IntVar(&defaultConfig.TestCount, "count", defaultConfig.TestCount, "Number of times to run each test")
	flag.BoolVar(&defaultConfig.Mixer, "mixer", defaultConfig.Mixer, "Enable / disable mixer.")
	flag.BoolVar(&defaultConfig.V1alpha1, "v1alpha1", defaultConfig.V1alpha1, "Enable / disable v1alpha1 routing rules.")
	flag.BoolVar(&defaultConfig.V1alpha2, "v1alpha2", defaultConfig.V1alpha2, "Enable / disable v1alpha2 routing rules.")
	flag.StringVar(&defaultConfig.ErrorLogsDir, "errorlogsdir", defaultConfig.ErrorLogsDir,
		"Store per pod logs as individual files in specific directory instead of writing to stderr.")
	flag.StringVar(&defaultConfig.CoreFilesDir, "core-files-dir", defaultConfig.CoreFilesDir,
		"Copy core files to this directory on the Kubernetes node machine.")

	// If specified, only run one test
	flag.StringVar(&defaultConfig.SelectedTest, "testtype", defaultConfig.SelectedTest,
		"Select test to run (default is all tests)")

	flag.BoolVar(&defaultConfig.UseAutomaticInjection, "use-sidecar-injector", defaultConfig.UseAutomaticInjection,
		"Use automatic sidecar injector")
	flag.BoolVar(&defaultConfig.UseAdmissionWebhook, "use-admission-webhook", defaultConfig.UseAdmissionWebhook,
		"Use k8s external admission webhook for config validation")

	flag.StringVar(&defaultConfig.AdmissionServiceName, "admission-service-name", defaultConfig.AdmissionServiceName,
		"Name of admission webhook service name")

	flag.IntVar(&defaultConfig.DebugPort, "debugport", defaultConfig.DebugPort, "Debugging port")

	flag.BoolVar(&defaultConfig.DebugImagesAndMode, "debug", defaultConfig.DebugImagesAndMode,
		"Use debug images and mode (false for prod)")
	flag.BoolVar(&defaultConfig.SkipCleanup, "skip-cleanup", defaultConfig.SkipCleanup,
		"Debug, skip clean up")
	flag.BoolVar(&defaultConfig.SkipCleanupOnFailure, "skip-cleanup-on-failure", defaultConfig.SkipCleanupOnFailure,
		"Debug, skip clean up on failure")
}

func setup(config *tutil.Infra, t *testing.T) {
	// Only run the tests if the user has defined the KUBECONFIG environment variable.
	if config.KubeConfig == "" {
		t.Skip("Env variable KUBECONFIG not set. Skipping integration tests")
	}

	if config.Hub == "" {
		t.Skip("HUB not specified. Skipping integration tests")
	}

	if config.Tag == "" {
		t.Skip("TAG not specified. Skipping integration tests")
	}

	// TODO(nmittler): Restore this tutil.Tlog("Deploying infrastructure", spew.Sdump(config))
	if config.Err = config.Setup(); config.Err != nil {
		t.Fatal(config.Err)
	}
}

func teardown(config *tutil.Infra) {
	config.Teardown()
}

func TestNoAuth(t *testing.T) {
	doTest(false, t)
}

// TODO(nmittler): Investigate why mTLS tests are failing.
/*
func TestMTls(t *testing.T) {
	doTest(true, t)
}*/

func doTest(useAuth bool, t *testing.T) {
	var config *tutil.Infra
	if useAuth {
		config = defaultConfig.CopyWithDefaultAuth()
	} else {
		config = &(*defaultConfig)
	}

	if verbose {
		config.Verbosity = 3
	}

	defer teardown(config)
	setup(config, t)

	tests := []tutil.Test{
		&http{Infra: config},
		&grpc{Infra: config},
		&tcp{Infra: config},
		&headless{Infra: config},
		&ingress{Infra: config},
		&egressRules{Infra: config},
		&routing{Infra: config},
		&routingToEgress{Infra: config},
		&zipkin{Infra: config},
		&authExclusion{Infra: config},
		&kubernetesExternalNameServices{Infra: config},
	}

	for _, test := range tests {
		// If the user has specified a test, skip all other tests
		if len(config.SelectedTest) > 0 && config.SelectedTest != test.String() {
			continue
		}

		// Run the test the configured number of times.
		for i := 0; i < config.TestCount; i++ {
			testName := test.String()
			if config.TestCount > 1 {
				testName = testName + "_attempt_" + strconv.Itoa(i+1)
			}
			t.Run(testName, func(t *testing.T) {
				if config.Err = test.Setup(); config.Err != nil {
					t.Fatal(config.Err)
				}
				defer test.Teardown()

				if config.Err = test.Run(); config.Err != nil {
					t.Error(config.Err)
				}
			})
		}
	}
}

// TODO(nmittler): convert individual tests over to pure golang tests
func TestMain(m *testing.M) {
	flag.Parse()
	_ = log.Configure(log.NewOptions())

	// Run all tests.
	os.Exit(m.Run())
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"os"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/daemon/graphdriver"
	// register the windows graph driver
	_ "github.com/docker/docker/daemon/graphdriver/windows"
	"github.com/docker/docker/pkg/parsers"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libnetwork"
)

const (
	defaultVirtualSwitch = "Virtual Switch"
	platformSupported    = true
	windowsMinCPUShares  = 1
	windowsMaxCPUShares  = 9
)

func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
	return nil
}

func setupInitLayer(initLayer string) error {
	return nil
}

func checkKernel() error {
	return nil
}

// adaptContainerSettings is called during container creation to modify any
// settings necessary in the HostConfig structure.
func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) {
	if hostConfig.CPUShares < 0 {
		logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares)
		hostConfig.CPUShares = windowsMinCPUShares
	} else if hostConfig.CPUShares > windowsMaxCPUShares {
		logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares)
		hostConfig.CPUShares = windowsMaxCPUShares
	}
}

// verifyPlatformContainerSettings performs platform-specific validation of the
// hostconfig and config structures.
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
	return nil, nil
}

// checkConfigOptions checks for mutually incompatible config options
func checkConfigOptions(config *Config) error {
	return nil
}

// checkSystem validates platform-specific requirements
func checkSystem() error {
	var dwVersion uint32

	// TODO Windows. May need at some point to ensure have elevation and
	// possibly LocalSystem.

	// Validate the OS version. Note that docker.exe must be manifested for this
	// call to return the correct version.
	dwVersion, err := syscall.GetVersion()
	if err != nil {
		return fmt.Errorf("Failed to call GetVersion()")
	}
	if int(dwVersion&0xFF) < 10 {
		return fmt.Errorf("This version of Windows does not support the docker daemon")
	}

	return nil
}

// configureKernelSecuritySupport configures and validate security support for the kernel
func configureKernelSecuritySupport(config *Config, driverName string) error {
	return nil
}

func migrateIfDownlevel(driver graphdriver.Driver, root string) error {
	return nil
}

func configureSysInit(config *Config) (string, error) {
	// TODO Windows.
	return os.Getenv("TEMP"), nil
}

func isBridgeNetworkDisabled(config *Config) bool {
	return false
}

func initNetworkController(config *Config) (libnetwork.NetworkController, error) {
	// Set the name of the virtual switch if not specified by -b on daemon start
	if config.Bridge.VirtualSwitchName == "" {
		config.Bridge.VirtualSwitchName = defaultVirtualSwitch
	}
	return nil, nil
}

// registerLinks sets up links between containers and writes the
// configuration out for persistence.
func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error {
	// TODO Windows. Factored out for network modes. There may be more
	// refactoring required here.

	if hostConfig == nil || hostConfig.Links == nil {
		return nil
	}

	for _, l := range hostConfig.Links {
		name, alias, err := parsers.ParseLink(l)
		if err != nil {
			return err
		}
		child, err := daemon.Get(name)
		if err != nil {
			//An error from daemon.Get() means this name could not be found
			return fmt.Errorf("Could not get container for %s", name)
		}
		if err := daemon.registerLink(container, child, alias); err != nil {
			return err
		}
	}

	// After we load all the links into the daemon
	// set them to nil on the hostconfig
	hostConfig.Links = nil
	if err := container.writeHostConfig(); err != nil {
		return err
	}
	return nil
}

func (daemon *Daemon) newBaseContainer(id string) Container {
	return Container{
		CommonContainer: CommonContainer{
			ID:           id,
			State:        NewState(),
			execCommands: newExecStore(),
			root:         daemon.containerRoot(id),
		},
	}
}
<commit_msg>Windows: Fix ADD from URL in dockerfile<commit_after>package daemon

import (
	"fmt"
	"os"
	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/daemon/graphdriver"
	// register the windows graph driver
	_ "github.com/docker/docker/daemon/graphdriver/windows"
	"github.com/docker/docker/pkg/parsers"
	"github.com/docker/docker/runconfig"
	"github.com/docker/libnetwork"
)

const (
	defaultVirtualSwitch = "Virtual Switch"
	platformSupported    = true
	windowsMinCPUShares  = 1
	windowsMaxCPUShares  = 9
)

func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
	return nil
}

func setupInitLayer(initLayer string) error {
	return nil
}

func checkKernel() error {
	return nil
}

// adaptContainerSettings is called during container creation to modify any
// settings necessary in the HostConfig structure.
func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, adjustCPUShares bool) {
	if hostConfig == nil {
		return
	}

	if hostConfig.CPUShares < 0 {
		logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, windowsMinCPUShares)
		hostConfig.CPUShares = windowsMinCPUShares
	} else if hostConfig.CPUShares > windowsMaxCPUShares {
		logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, windowsMaxCPUShares)
		hostConfig.CPUShares = windowsMaxCPUShares
	}
}

// verifyPlatformContainerSettings performs platform-specific validation of the
// hostconfig and config structures.
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
	return nil, nil
}

// checkConfigOptions checks for mutually incompatible config options
func checkConfigOptions(config *Config) error {
	return nil
}

// checkSystem validates platform-specific requirements
func checkSystem() error {
	var dwVersion uint32

	// TODO Windows. May need at some point to ensure have elevation and
	// possibly LocalSystem.

	// Validate the OS version. Note that docker.exe must be manifested for this
	// call to return the correct version.
	dwVersion, err := syscall.GetVersion()
	if err != nil {
		return fmt.Errorf("Failed to call GetVersion()")
	}
	if int(dwVersion&0xFF) < 10 {
		return fmt.Errorf("This version of Windows does not support the docker daemon")
	}

	return nil
}

// configureKernelSecuritySupport configures and validate security support for the kernel
func configureKernelSecuritySupport(config *Config, driverName string) error {
	return nil
}

func migrateIfDownlevel(driver graphdriver.Driver, root string) error {
	return nil
}

func configureSysInit(config *Config) (string, error) {
	// TODO Windows.
	return os.Getenv("TEMP"), nil
}

func isBridgeNetworkDisabled(config *Config) bool {
	return false
}

func initNetworkController(config *Config) (libnetwork.NetworkController, error) {
	// Set the name of the virtual switch if not specified by -b on daemon start
	if config.Bridge.VirtualSwitchName == "" {
		config.Bridge.VirtualSwitchName = defaultVirtualSwitch
	}
	return nil, nil
}

// registerLinks sets up links between containers and writes the
// configuration out for persistence.
func (daemon *Daemon) registerLinks(container *Container, hostConfig *runconfig.HostConfig) error {
	// TODO Windows. Factored out for network modes. There may be more
	// refactoring required here.

	if hostConfig == nil || hostConfig.Links == nil {
		return nil
	}

	for _, l := range hostConfig.Links {
		name, alias, err := parsers.ParseLink(l)
		if err != nil {
			return err
		}
		child, err := daemon.Get(name)
		if err != nil {
			//An error from daemon.Get() means this name could not be found
			return fmt.Errorf("Could not get container for %s", name)
		}
		if err := daemon.registerLink(container, child, alias); err != nil {
			return err
		}
	}

	// After we load all the links into the daemon
	// set them to nil on the hostconfig
	hostConfig.Links = nil
	if err := container.writeHostConfig(); err != nil {
		return err
	}
	return nil
}

func (daemon *Daemon) newBaseContainer(id string) Container {
	return Container{
		CommonContainer: CommonContainer{
			ID:           id,
			State:        NewState(),
			execCommands: newExecStore(),
			root:         daemon.containerRoot(id),
		},
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go 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 main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"

	"code.google.com/p/go.tools/go/vcs"
)

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
		switch b.goos {
		case "android", "nacl":
			// Cross compile.
		default:
			// If we are building, for example, linux/386 on a linux/amd64 machine we want to
			// make sure that the whole build is done as a if this were compiled on a real
			// linux/386 machine. In other words, we want to not do a cross compilation build.
			// To do this we set GOHOSTOS and GOHOSTARCH to override the detection in make.bash.
			//
			// The exception to this rule is when we are doing nacl/android builds. These are by
			// definition always cross compilation, and we have support built into cmd/go to be
			// able to handle this case.
			e = append(e, "GOHOSTOS="+b.goos, "GOHOSTARCH="+b.goarch)
		}
	}

	for _, k := range extraEnv() {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv() {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOPATH":  true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if err := repo.Export(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error exporting repository: %s", err)
	}
	if err := ioutil.WriteFile(filepath.Join(goworkpath, "VERSION"), []byte(hash), 0644); err != nil {
		return "", fmt.Errorf("error writing VERSION file: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gccpath := filepath.Join(repo.Path, "gcc")

	// get a handle to Git vcs.Cmd for pulling down GCC from the mirror.
	git := vcs.ByCmd("git")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return git.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	}

	if err := git.Download(gccpath); err != nil {
		return "", err
	}

	// get the modified files for this commit.

	var buf bytes.Buffer
	if err := run(exec.Command("hg", "status", "--no-status", "--change", hash),
		allOutput(&buf), runDir(repo.Path), runEnv(envv)); err != nil {
		return "", fmt.Errorf("Failed to find the modified files for %s: %s", hash, err)
	}
	modifiedFiles := strings.Split(buf.String(), "\n")
	var isMirrored bool
	for _, f := range modifiedFiles {
		if strings.HasPrefix(f, "go/") || strings.HasPrefix(f, "libgo/") {
			isMirrored = true
			break
		}
	}

	// use git log to find the corresponding commit to sync to in the gcc mirror.
	// If the files modified in the gofrontend are mirrored to gcc, we expect a
	// commit with a similar description in the gcc mirror. If the files modified are
	// not mirrored, e.g. in support/, we can sync to the most recent gcc commit that
	// occurred before those files were modified to verify gccgo's status at that point.
	logCmd := []string{
		"git",
		"log",
		"-1",
		"--format=%H",
	}
	var errMsg string
	if isMirrored {
		commitDesc, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{desc|firstline|escape}")
		if err != nil {
			return "", err
		}

		quotedDesc := regexp.QuoteMeta(string(commitDesc))
		logCmd = append(logCmd, "--grep", quotedDesc, "--regexp-ignore-case", "--extended-regexp")
		errMsg = fmt.Sprintf("Failed to find a commit with a similar description to '%s'", string(commitDesc))
	} else {
		commitDate, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{date|rfc3339date}")
		if err != nil {
			return "", err
		}

		logCmd = append(logCmd, "--before", string(commitDate))
		errMsg = fmt.Sprintf("Failed to find a commit before '%s'", string(commitDate))
	}

	buf.Reset()
	if err := run(exec.Command(gccpath, logCmd...), runEnv(envv), allOutput(&buf), runDir(gccpath)); err != nil {
		return "", fmt.Errorf("%s: %s", errMsg, err)
	}
	gccRev := buf.String()
	if gccRev == "" {
		return "", fmt.Errorf(errMsg)
	}

	// checkout gccRev
	// TODO(cmang): Fix this to work in parallel mode.
	if err := run(exec.Command("git", "reset", "--hard", strings.TrimSpace(gccRev)), runEnv(envv), runDir(gccpath)); err != nil {
		return "", fmt.Errorf("Failed to checkout commit at revision %s: %s", gccRev, err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	if err := run(exec.Command(filepath.Join(gccpath, "configure"),
		"--enable-languages=c,c++,go",
		"--disable-bootstrap",
		"--disable-multilib",
	), runEnv(envv), runDir(gccobjdir)); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %v", err)
	}

	// build gcc
	if err := run(exec.Command("make"), runTimeout(*buildTimeout), runEnv(envv), runDir(gccobjdir)); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}

// extraEnv returns environment variables that need to be copied from
// the gobuilder's environment to the envv of its subprocesses.
func extraEnv() []string {
	extra := []string{
		"GOARM",
		"GO386",
		"CGO_ENABLED",
		"CC",
		"CC_FOR_TARGET",
		"PATH",
		"TMPDIR",
		"USER",
	}
	if runtime.GOOS == "plan9" {
		extra = append(extra, "objtype", "cputype", "path")
	}
	return extra
}
<commit_msg>dashboard/builder: set correct path to gcc<commit_after>// Copyright 2013 The Go 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 main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"

	"code.google.com/p/go.tools/go/vcs"
)

// builderEnv represents the environment that a Builder will run tests in.
type builderEnv interface {
	// setup sets up the builder environment and returns the directory to run the buildCmd in.
	setup(repo *Repo, workpath, hash string, envv []string) (string, error)
}

// goEnv represents the builderEnv for the main Go repo.
type goEnv struct {
	goos, goarch string
}

func (b *Builder) envv() []string {
	if runtime.GOOS == "windows" {
		return b.envvWindows()
	}

	var e []string
	if *buildTool == "go" {
		e = []string{
			"GOOS=" + b.goos,
			"GOARCH=" + b.goarch,
			"GOROOT_FINAL=/usr/local/go",
		}
		switch b.goos {
		case "android", "nacl":
			// Cross compile.
		default:
			// If we are building, for example, linux/386 on a linux/amd64 machine we want to
			// make sure that the whole build is done as a if this were compiled on a real
			// linux/386 machine. In other words, we want to not do a cross compilation build.
			// To do this we set GOHOSTOS and GOHOSTARCH to override the detection in make.bash.
			//
			// The exception to this rule is when we are doing nacl/android builds. These are by
			// definition always cross compilation, and we have support built into cmd/go to be
			// able to handle this case.
			e = append(e, "GOHOSTOS="+b.goos, "GOHOSTARCH="+b.goarch)
		}
	}

	for _, k := range extraEnv() {
		if s, ok := getenvOk(k); ok {
			e = append(e, k+"="+s)
		}
	}
	return e
}

func (b *Builder) envvWindows() []string {
	var start map[string]string
	if *buildTool == "go" {
		start = map[string]string{
			"GOOS":         b.goos,
			"GOHOSTOS":     b.goos,
			"GOARCH":       b.goarch,
			"GOHOSTARCH":   b.goarch,
			"GOROOT_FINAL": `c:\go`,
			"GOBUILDEXIT":  "1", // exit all.bat with completion status.
		}
	}

	for _, name := range extraEnv() {
		if s, ok := getenvOk(name); ok {
			start[name] = s
		}
	}
	if b.goos == "windows" {
		switch b.goarch {
		case "amd64":
			start["PATH"] = `c:\TDM-GCC-64\bin;` + start["PATH"]
		case "386":
			start["PATH"] = `c:\TDM-GCC-32\bin;` + start["PATH"]
		}
	}
	skip := map[string]bool{
		"GOBIN":   true,
		"GOPATH":  true,
		"GOROOT":  true,
		"INCLUDE": true,
		"LIB":     true,
	}
	var e []string
	for name, v := range start {
		e = append(e, name+"="+v)
		skip[name] = true
	}
	for _, kv := range os.Environ() {
		s := strings.SplitN(kv, "=", 2)
		name := strings.ToUpper(s[0])
		switch {
		case name == "":
			// variables, like "=C:=C:\", just copy them
			e = append(e, kv)
		case !skip[name]:
			e = append(e, kv)
			skip[name] = true
		}
	}
	return e
}

// setup for a goEnv clones the main go repo to workpath/go at the provided hash
// and returns the path workpath/go/src, the location of all go build scripts.
func (env *goEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	goworkpath := filepath.Join(workpath, "go")
	if err := repo.Export(goworkpath, hash); err != nil {
		return "", fmt.Errorf("error exporting repository: %s", err)
	}
	if err := ioutil.WriteFile(filepath.Join(goworkpath, "VERSION"), []byte(hash), 0644); err != nil {
		return "", fmt.Errorf("error writing VERSION file: %s", err)
	}
	return filepath.Join(goworkpath, "src"), nil
}

// gccgoEnv represents the builderEnv for the gccgo compiler.
type gccgoEnv struct{}

// setup for a gccgoEnv clones the gofrontend repo to workpath/go at the hash
// and clones the latest GCC branch to repo.Path/gcc. The gccgo sources are
// replaced with the updated sources in the gofrontend repo and gcc gets
// gets configured and built in workpath/gcc-objdir. The path to
// workpath/gcc-objdir is returned.
func (env *gccgoEnv) setup(repo *Repo, workpath, hash string, envv []string) (string, error) {
	gccpath := filepath.Join(repo.Path, "gcc")

	// get a handle to Git vcs.Cmd for pulling down GCC from the mirror.
	git := vcs.ByCmd("git")

	// only pull down gcc if we don't have a local copy.
	if _, err := os.Stat(gccpath); err != nil {
		if err := timeout(*cmdTimeout, func() error {
			// pull down a working copy of GCC.
			return git.Create(gccpath, *gccPath)
		}); err != nil {
			return "", err
		}
	}

	if err := git.Download(gccpath); err != nil {
		return "", err
	}

	// get the modified files for this commit.

	var buf bytes.Buffer
	if err := run(exec.Command("hg", "status", "--no-status", "--change", hash),
		allOutput(&buf), runDir(repo.Path), runEnv(envv)); err != nil {
		return "", fmt.Errorf("Failed to find the modified files for %s: %s", hash, err)
	}
	modifiedFiles := strings.Split(buf.String(), "\n")
	var isMirrored bool
	for _, f := range modifiedFiles {
		if strings.HasPrefix(f, "go/") || strings.HasPrefix(f, "libgo/") {
			isMirrored = true
			break
		}
	}

	// use git log to find the corresponding commit to sync to in the gcc mirror.
	// If the files modified in the gofrontend are mirrored to gcc, we expect a
	// commit with a similar description in the gcc mirror. If the files modified are
	// not mirrored, e.g. in support/, we can sync to the most recent gcc commit that
	// occurred before those files were modified to verify gccgo's status at that point.
	logCmd := []string{
		"git",
		"log",
		"-1",
		"--format=%H",
	}
	var errMsg string
	if isMirrored {
		commitDesc, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{desc|firstline|escape}")
		if err != nil {
			return "", err
		}

		quotedDesc := regexp.QuoteMeta(string(commitDesc))
		logCmd = append(logCmd, "--grep", quotedDesc, "--regexp-ignore-case", "--extended-regexp")
		errMsg = fmt.Sprintf("Failed to find a commit with a similar description to '%s'", string(commitDesc))
	} else {
		commitDate, err := repo.Master.VCS.LogAtRev(repo.Path, hash, "{date|rfc3339date}")
		if err != nil {
			return "", err
		}

		logCmd = append(logCmd, "--before", string(commitDate))
		errMsg = fmt.Sprintf("Failed to find a commit before '%s'", string(commitDate))
	}

	buf.Reset()
	if err := run(exec.Command(gccpath, logCmd...), runEnv(envv), allOutput(&buf), runDir(gccpath)); err != nil {
		return "", fmt.Errorf("%s: %s", errMsg, err)
	}
	gccRev := buf.String()
	if gccRev == "" {
		return "", fmt.Errorf(errMsg)
	}

	// checkout gccRev
	// TODO(cmang): Fix this to work in parallel mode.
	if err := run(exec.Command("git", "reset", "--hard", strings.TrimSpace(gccRev)), runEnv(envv), runDir(gccpath)); err != nil {
		return "", fmt.Errorf("Failed to checkout commit at revision %s: %s", gccRev, err)
	}

	// make objdir to work in
	gccobjdir := filepath.Join(workpath, "gcc-objdir")
	if err := os.Mkdir(gccobjdir, mkdirPerm); err != nil {
		return "", err
	}

	// configure GCC with substituted gofrontend and libgo
	if err := run(exec.Command(filepath.Join(gccpath, "configure"),
		"--enable-languages=c,c++,go",
		"--disable-bootstrap",
		"--disable-multilib",
	), runEnv(envv), runDir(gccobjdir)); err != nil {
		return "", fmt.Errorf("Failed to configure GCC: %v", err)
	}

	// build gcc
	if err := run(exec.Command("make"), runTimeout(*buildTimeout), runEnv(envv), runDir(gccobjdir)); err != nil {
		return "", fmt.Errorf("Failed to build GCC: %s", err)
	}

	return gccobjdir, nil
}

func getenvOk(k string) (v string, ok bool) {
	v = os.Getenv(k)
	if v != "" {
		return v, true
	}
	keq := k + "="
	for _, kv := range os.Environ() {
		if kv == keq {
			return "", true
		}
	}
	return "", false
}

// extraEnv returns environment variables that need to be copied from
// the gobuilder's environment to the envv of its subprocesses.
func extraEnv() []string {
	extra := []string{
		"GOARM",
		"GO386",
		"CGO_ENABLED",
		"CC",
		"CC_FOR_TARGET",
		"PATH",
		"TMPDIR",
		"USER",
	}
	if runtime.GOOS == "plan9" {
		extra = append(extra, "objtype", "cputype", "path")
	}
	return extra
}
<|endoftext|>


<commit_before>// Copyright 2013 The Go 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 main

import (
	"encoding/xml"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"code.google.com/p/go.tools/go/vcs"
)

// Repo represents a mercurial repository.
type Repo struct {
	Path   string
	Master *vcs.RepoRoot
	sync.Mutex
}

// RemoteRepo constructs a *Repo representing a remote repository.
func RemoteRepo(url, path string) (*Repo, error) {
	rr, err := vcs.RepoRootForImportPath(url, *verbose)
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: rr,
	}, nil
}

// Clone clones the current Repo to a new destination
// returning a new *Repo if successful.
func (r *Repo) Clone(path, rev string) (*Repo, error) {
	r.Lock()
	defer r.Unlock()

	err := timeout(*cmdTimeout, func() error {
		downloadPath := r.Path
		if !r.Exists() {
			downloadPath = r.Master.Repo
		}

		err := r.Master.VCS.CreateAtRev(path, downloadPath, rev)
		if err != nil {
			return err
		}
		return r.Master.VCS.TagSync(path, "")
	})
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: r.Master,
	}, nil
}

// Export exports the current Repo at revision rev to a new destination.
func (r *Repo) Export(path, rev string) error {
	r.Lock()
	defer r.Unlock()

	downloadPath := r.Path
	if !r.Exists() {
		_, err := r.Clone(path, rev)
		return err
	}

	args := []string{r.Master.VCS.Cmd, "archive", "-t", "files", "-r", rev, path}
	if err := run(*cmdTimeout, nil, downloadPath, args...); err != nil {
		return fmt.Errorf("executing %s: %v", strings.Join(args, " "), err)
	}
	return nil
}

// UpdateTo updates the working copy of this Repo to the
// supplied revision.
func (r *Repo) UpdateTo(hash string) error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.TagSync(r.Path, hash)
	})
}

// Exists reports whether this Repo represents a valid Mecurial repository.
func (r *Repo) Exists() bool {
	fi, err := os.Stat(filepath.Join(r.Path, "."+r.Master.VCS.Cmd))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Pull pulls changes from the default path, that is, the path
// this Repo was cloned from.
func (r *Repo) Pull() error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.Download(r.Path)
	})
}

// Log returns the changelog for this repository.
func (r *Repo) Log() ([]HgLog, error) {
	if err := r.Pull(); err != nil {
		return nil, err
	}
	r.Lock()
	defer r.Unlock()

	var logStruct struct {
		Log []HgLog
	}
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.Log(r.Path, xmlLogTemplate)
		if err != nil {
			return err
		}

		err = xml.Unmarshal([]byte("<Top>"+string(data)+"</Top>"), &logStruct)
		if err != nil {
			return fmt.Errorf("unmarshal %s log: %v", r.Master.VCS, err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	for i, log := range logStruct.Log {
		// Let's pretend there can be only one parent.
		if log.Parent != "" && strings.Contains(log.Parent, " ") {
			logStruct.Log[i].Parent = strings.Split(log.Parent, " ")[0]
		}
	}
	return logStruct.Log, nil
}

// FullHash returns the full hash for the given Mercurial revision.
func (r *Repo) FullHash(rev string) (string, error) {
	r.Lock()
	defer r.Unlock()

	var hash string
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.LogAtRev(r.Path, rev, "{node}")
		if err != nil {
			return err
		}

		s := strings.TrimSpace(string(data))
		if s == "" {
			return fmt.Errorf("cannot find revision")
		}
		if len(s) != 40 {
			return fmt.Errorf("%s returned invalid hash: %s", r.Master.VCS, s)
		}
		hash = s
		return nil
	})
	if err != nil {
		return "", err
	}
	return hash, nil
}

// HgLog represents a single Mercurial revision.
type HgLog struct {
	Hash   string
	Author string
	Date   string
	Desc   string
	Parent string
	Branch string
	Files  string

	// Internal metadata
	added bool
	bench bool // needs to be benchmarked?
}

// xmlLogTemplate is a template to pass to Mercurial to make
// hg log print the log in valid XML for parsing with xml.Unmarshal.
// Can not escape branches and files, because it crashes python with:
// AttributeError: 'NoneType' object has no attribute 'replace'
const xmlLogTemplate = `
        <Log>
        <Hash>{node|escape}</Hash>
        <Parent>{parents}</Parent>
        <Author>{author|escape}</Author>
        <Date>{date|rfc3339date}</Date>
        <Desc>{desc|escape}</Desc>
        <Branch>{branches}</Branch>
        <Files>{files}</Files>
        </Log>
`
<commit_msg>dashboard/builder: fix crash on commits that contain ESC symbol Currently performance builders crash with: hg log: unmarshal Mercurial log: XML syntax error on line 4991: illegal character code U+001B<commit_after>// Copyright 2013 The Go 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 main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"code.google.com/p/go.tools/go/vcs"
)

// Repo represents a mercurial repository.
type Repo struct {
	Path   string
	Master *vcs.RepoRoot
	sync.Mutex
}

// RemoteRepo constructs a *Repo representing a remote repository.
func RemoteRepo(url, path string) (*Repo, error) {
	rr, err := vcs.RepoRootForImportPath(url, *verbose)
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: rr,
	}, nil
}

// Clone clones the current Repo to a new destination
// returning a new *Repo if successful.
func (r *Repo) Clone(path, rev string) (*Repo, error) {
	r.Lock()
	defer r.Unlock()

	err := timeout(*cmdTimeout, func() error {
		downloadPath := r.Path
		if !r.Exists() {
			downloadPath = r.Master.Repo
		}

		err := r.Master.VCS.CreateAtRev(path, downloadPath, rev)
		if err != nil {
			return err
		}
		return r.Master.VCS.TagSync(path, "")
	})
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: r.Master,
	}, nil
}

// Export exports the current Repo at revision rev to a new destination.
func (r *Repo) Export(path, rev string) error {
	r.Lock()
	defer r.Unlock()

	downloadPath := r.Path
	if !r.Exists() {
		_, err := r.Clone(path, rev)
		return err
	}

	args := []string{r.Master.VCS.Cmd, "archive", "-t", "files", "-r", rev, path}
	if err := run(*cmdTimeout, nil, downloadPath, args...); err != nil {
		return fmt.Errorf("executing %s: %v", strings.Join(args, " "), err)
	}
	return nil
}

// UpdateTo updates the working copy of this Repo to the
// supplied revision.
func (r *Repo) UpdateTo(hash string) error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.TagSync(r.Path, hash)
	})
}

// Exists reports whether this Repo represents a valid Mecurial repository.
func (r *Repo) Exists() bool {
	fi, err := os.Stat(filepath.Join(r.Path, "."+r.Master.VCS.Cmd))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Pull pulls changes from the default path, that is, the path
// this Repo was cloned from.
func (r *Repo) Pull() error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.Download(r.Path)
	})
}

// Log returns the changelog for this repository.
func (r *Repo) Log() ([]HgLog, error) {
	if err := r.Pull(); err != nil {
		return nil, err
	}
	r.Lock()
	defer r.Unlock()

	var logStruct struct {
		Log []HgLog
	}
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.Log(r.Path, xmlLogTemplate)
		if err != nil {
			return err
		}

		// We have a commit with description that contains 0x1b byte.
		// Mercurial does not escape it, but xml.Unmarshal does not accept it.
		data = bytes.Replace(data, []byte{0x1b}, []byte{'?'}, -1)

		err = xml.Unmarshal([]byte("<Top>"+string(data)+"</Top>"), &logStruct)
		if err != nil {
			return fmt.Errorf("unmarshal %s log: %v", r.Master.VCS, err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	for i, log := range logStruct.Log {
		// Let's pretend there can be only one parent.
		if log.Parent != "" && strings.Contains(log.Parent, " ") {
			logStruct.Log[i].Parent = strings.Split(log.Parent, " ")[0]
		}
	}
	return logStruct.Log, nil
}

// FullHash returns the full hash for the given Mercurial revision.
func (r *Repo) FullHash(rev string) (string, error) {
	r.Lock()
	defer r.Unlock()

	var hash string
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.LogAtRev(r.Path, rev, "{node}")
		if err != nil {
			return err
		}

		s := strings.TrimSpace(string(data))
		if s == "" {
			return fmt.Errorf("cannot find revision")
		}
		if len(s) != 40 {
			return fmt.Errorf("%s returned invalid hash: %s", r.Master.VCS, s)
		}
		hash = s
		return nil
	})
	if err != nil {
		return "", err
	}
	return hash, nil
}

// HgLog represents a single Mercurial revision.
type HgLog struct {
	Hash   string
	Author string
	Date   string
	Desc   string
	Parent string
	Branch string
	Files  string

	// Internal metadata
	added bool
	bench bool // needs to be benchmarked?
}

// xmlLogTemplate is a template to pass to Mercurial to make
// hg log print the log in valid XML for parsing with xml.Unmarshal.
// Can not escape branches and files, because it crashes python with:
// AttributeError: 'NoneType' object has no attribute 'replace'
const xmlLogTemplate = `
        <Log>
        <Hash>{node|escape}</Hash>
        <Parent>{parents}</Parent>
        <Author>{author|escape}</Author>
        <Date>{date|rfc3339date}</Date>
        <Desc>{desc|escape}</Desc>
        <Branch>{branches}</Branch>
        <Files>{files}</Files>
        </Log>
`
<|endoftext|>


<commit_before>// Copyright 2013 The Go 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 main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	"golang.org/x/tools/go/vcs"
)

// Repo represents a mercurial repository.
type Repo struct {
	Path   string
	Master *vcs.RepoRoot
	sync.Mutex
}

// RemoteRepo constructs a *Repo representing a remote repository.
func RemoteRepo(url, path string) (*Repo, error) {
	rr, err := vcs.RepoRootForImportPath(url, *verbose)
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: rr,
	}, nil
}

// Clone clones the current Repo to a new destination
// returning a new *Repo if successful.
func (r *Repo) Clone(path, rev string) (*Repo, error) {
	r.Lock()
	defer r.Unlock()

	err := timeout(*cmdTimeout, func() error {
		downloadPath := r.Path
		if !r.Exists() {
			downloadPath = r.Master.Repo
		}
		if rev == "" {
			return r.Master.VCS.Create(path, downloadPath)
		}
		return r.Master.VCS.CreateAtRev(path, downloadPath, rev)
	})
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: r.Master,
	}, nil
}

// Export exports the current Repo at revision rev to a new destination.
func (r *Repo) Export(path, rev string) error {
	r.Lock()

	downloadPath := r.Path
	if !r.Exists() {
		r.Unlock()
		_, err := r.Clone(path, rev)
		return err
	}

	switch r.Master.VCS.Cmd {
	default:
		r.Unlock()
		// TODO(adg,cmang): implement Export in go/vcs
		_, err := r.Clone(path, rev)
		return err
	case "hg":
		defer r.Unlock()
		cmd := exec.Command(r.Master.VCS.Cmd, "archive", "-t", "files", "-r", rev, path)
		cmd.Dir = downloadPath
		if err := run(cmd); err != nil {
			return fmt.Errorf("executing %v: %v", cmd.Args, err)
		}
	}
	return nil
}

// UpdateTo updates the working copy of this Repo to the
// supplied revision.
func (r *Repo) UpdateTo(hash string) error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.TagSync(r.Path, hash)
	})
}

// Exists reports whether this Repo represents a valid Mecurial repository.
func (r *Repo) Exists() bool {
	fi, err := os.Stat(filepath.Join(r.Path, "."+r.Master.VCS.Cmd))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Pull pulls changes from the default path, that is, the path
// this Repo was cloned from.
func (r *Repo) Pull() error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.Download(r.Path)
	})
}

// Log returns the changelog for this repository.
func (r *Repo) Log() ([]HgLog, error) {
	if err := r.Pull(); err != nil {
		return nil, err
	}
	r.Lock()
	defer r.Unlock()

	var logStruct struct {
		Log []HgLog
	}
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.Log(r.Path, xmlLogTemplate)
		if err != nil {
			return err
		}

		// We have a commit with description that contains 0x1b byte.
		// Mercurial does not escape it, but xml.Unmarshal does not accept it.
		data = bytes.Replace(data, []byte{0x1b}, []byte{'?'}, -1)

		err = xml.Unmarshal([]byte("<Top>"+string(data)+"</Top>"), &logStruct)
		if err != nil {
			return fmt.Errorf("unmarshal %s log: %v", r.Master.VCS, err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	for i, log := range logStruct.Log {
		// Let's pretend there can be only one parent.
		if log.Parent != "" && strings.Contains(log.Parent, " ") {
			logStruct.Log[i].Parent = strings.Split(log.Parent, " ")[0]
		}
	}
	return logStruct.Log, nil
}

// FullHash returns the full hash for the given Mercurial revision.
func (r *Repo) FullHash(rev string) (string, error) {
	r.Lock()
	defer r.Unlock()

	var hash string
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.LogAtRev(r.Path, rev, "{node}")
		if err != nil {
			return err
		}

		s := strings.TrimSpace(string(data))
		if s == "" {
			return fmt.Errorf("cannot find revision")
		}
		if len(s) != 40 {
			return fmt.Errorf("%s returned invalid hash: %s", r.Master.VCS, s)
		}
		hash = s
		return nil
	})
	if err != nil {
		return "", err
	}
	return hash, nil
}

// HgLog represents a single Mercurial revision.
type HgLog struct {
	Hash   string
	Author string
	Date   string
	Desc   string
	Parent string
	Branch string
	Files  string

	// Internal metadata
	added bool
	bench bool // needs to be benchmarked?
}

// xmlLogTemplate is a template to pass to Mercurial to make
// hg log print the log in valid XML for parsing with xml.Unmarshal.
// Can not escape branches and files, because it crashes python with:
// AttributeError: 'NoneType' object has no attribute 'replace'
const xmlLogTemplate = `
        <Log>
        <Hash>{node|escape}</Hash>
        <Parent>{p1node}</Parent>
        <Author>{author|escape}</Author>
        <Date>{date|rfc3339date}</Date>
        <Desc>{desc|escape}</Desc>
        <Branch>{branches}</Branch>
        <Files>{files}</Files>
        </Log>
`
<commit_msg>dashboard/builder: don't use vcs TagSync to update a path to a hash<commit_after>// Copyright 2013 The Go 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 main

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"

	"golang.org/x/tools/go/vcs"
)

// Repo represents a mercurial repository.
type Repo struct {
	Path   string
	Master *vcs.RepoRoot
	sync.Mutex
}

// RemoteRepo constructs a *Repo representing a remote repository.
func RemoteRepo(url, path string) (*Repo, error) {
	rr, err := vcs.RepoRootForImportPath(url, *verbose)
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: rr,
	}, nil
}

// Clone clones the current Repo to a new destination
// returning a new *Repo if successful.
func (r *Repo) Clone(path, rev string) (*Repo, error) {
	r.Lock()
	defer r.Unlock()

	err := timeout(*cmdTimeout, func() error {
		downloadPath := r.Path
		if !r.Exists() {
			downloadPath = r.Master.Repo
		}
		if rev == "" {
			return r.Master.VCS.Create(path, downloadPath)
		}
		return r.Master.VCS.CreateAtRev(path, downloadPath, rev)
	})
	if err != nil {
		return nil, err
	}
	return &Repo{
		Path:   path,
		Master: r.Master,
	}, nil
}

// Export exports the current Repo at revision rev to a new destination.
func (r *Repo) Export(path, rev string) error {
	r.Lock()

	downloadPath := r.Path
	if !r.Exists() {
		r.Unlock()
		_, err := r.Clone(path, rev)
		return err
	}

	switch r.Master.VCS.Cmd {
	default:
		r.Unlock()
		// TODO(adg,cmang): implement Export in go/vcs
		_, err := r.Clone(path, rev)
		return err
	case "hg":
		defer r.Unlock()
		cmd := exec.Command(r.Master.VCS.Cmd, "archive", "-t", "files", "-r", rev, path)
		cmd.Dir = downloadPath
		if err := run(cmd); err != nil {
			return fmt.Errorf("executing %v: %v", cmd.Args, err)
		}
	}
	return nil
}

// UpdateTo updates the working copy of this Repo to the
// supplied revision.
func (r *Repo) UpdateTo(hash string) error {
	r.Lock()
	defer r.Unlock()

	if r.Master.VCS.Cmd == "git" {
		cmd := exec.Command("git", "reset", "--hard", hash)
		var log bytes.Buffer
		err := run(cmd, runTimeout(*cmdTimeout), runDir(r.Path), allOutput(&log))
		if err != nil {
			return fmt.Errorf("Error running git update -C %v: %v ; output=%s", hash, err, log.Bytes())
		}
		return nil
	}

	// Else go down three more levels of abstractions, at
	// least two of which are broken for git.
	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.TagSync(r.Path, hash)
	})
}

// Exists reports whether this Repo represents a valid Mecurial repository.
func (r *Repo) Exists() bool {
	fi, err := os.Stat(filepath.Join(r.Path, "."+r.Master.VCS.Cmd))
	if err != nil {
		return false
	}
	return fi.IsDir()
}

// Pull pulls changes from the default path, that is, the path
// this Repo was cloned from.
func (r *Repo) Pull() error {
	r.Lock()
	defer r.Unlock()

	return timeout(*cmdTimeout, func() error {
		return r.Master.VCS.Download(r.Path)
	})
}

// Log returns the changelog for this repository.
func (r *Repo) Log() ([]HgLog, error) {
	if err := r.Pull(); err != nil {
		return nil, err
	}
	r.Lock()
	defer r.Unlock()

	var logStruct struct {
		Log []HgLog
	}
	err := timeout(*cmdTimeout, func() error {
		data, err := r.Master.VCS.Log(r.Path, xmlLogTemplate)
		if err != nil {
			return err
		}

		// We have a commit with description that contains 0x1b byte.
		// Mercurial does not escape it, but xml.Unmarshal does not accept it.
		data = bytes.Replace(data, []byte{0x1b}, []byte{'?'}, -1)

		err = xml.Unmarshal([]byte("<Top>"+string(data)+"</Top>"), &logStruct)
		if err != nil {
			return fmt.Errorf("unmarshal %s log: %v", r.Master.VCS, err)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	for i, log := range logStruct.Log {
		// Let's pretend there can be only one parent.
		if log.Parent != "" && strings.Contains(log.Parent, " ") {
			logStruct.Log[i].Parent = strings.Split(log.Parent, " ")[0]
		}
	}
	return logStruct.Log, nil
}

// FullHash returns the full hash for the given Git or Mercurial revision.
func (r *Repo) FullHash(rev string) (string, error) {
	r.Lock()
	defer r.Unlock()

	var hash string
	err := timeout(*cmdTimeout, func() error {
		var data []byte
		// Avoid the vcs package for git, since it's broken
		// for git, and and we're trying to remove levels of
		// abstraction which are increasingly getting
		// difficult to navigate.
		if r.Master.VCS.Cmd == "git" {
			cmd := exec.Command("git", "rev-parse", rev)
			var out bytes.Buffer
			err := run(cmd, runTimeout(*cmdTimeout), runDir(r.Path), allOutput(&out))
			data = out.Bytes()
			if err != nil {
				return fmt.Errorf("Failed to find FullHash of %q; git rev-parse: %v, %s", rev, err, data)
			}
		} else {
			var err error
			data, err = r.Master.VCS.LogAtRev(r.Path, rev, "{node}")
			if err != nil {
				return err
			}
		}
		s := strings.TrimSpace(string(data))
		if s == "" {
			return fmt.Errorf("cannot find revision")
		}
		if len(s) != 40 { // correct for both hg and git
			return fmt.Errorf("%s returned invalid hash: %s", r.Master.VCS, s)
		}
		hash = s
		return nil
	})
	if err != nil {
		return "", err
	}
	return hash, nil
}

// HgLog represents a single Mercurial revision.
type HgLog struct {
	Hash   string
	Author string
	Date   string
	Desc   string
	Parent string
	Branch string
	Files  string

	// Internal metadata
	added bool
	bench bool // needs to be benchmarked?
}

// xmlLogTemplate is a template to pass to Mercurial to make
// hg log print the log in valid XML for parsing with xml.Unmarshal.
// Can not escape branches and files, because it crashes python with:
// AttributeError: 'NoneType' object has no attribute 'replace'
const xmlLogTemplate = `
        <Log>
        <Hash>{node|escape}</Hash>
        <Parent>{p1node}</Parent>
        <Author>{author|escape}</Author>
        <Date>{date|rfc3339date}</Date>
        <Desc>{desc|escape}</Desc>
        <Branch>{branches}</Branch>
        <Files>{files}</Files>
        </Log>
`
<|endoftext|>


<commit_before>package game

import (
	"kmud/database"
	"kmud/utils"
)

type mapBuilder struct {
	width    int
	height   int
	depth    int
	data     [][][]mapTile
	userRoom database.Room
}

type mapTile struct {
	char  rune
	color utils.Color
}

func (self *mapTile) toString(cm utils.ColorMode) string {
	if self.char == ' ' {
		return string(self.char)
	}

	return utils.Colorize(cm, self.color, string(self.char))
}

func newMapBuilder(width int, height int, depth int) mapBuilder {
	var builder mapBuilder

	// Double the X/Y axis to account for extra space to draw exits
	width *= 2
	height *= 2

	builder.data = make([][][]mapTile, depth)

	for z := 0; z < depth; z++ {
		builder.data[z] = make([][]mapTile, height)
		for y := 0; y < height; y++ {
			builder.data[z][y] = make([]mapTile, width)
		}
	}

	builder.width = width
	builder.height = height
	builder.depth = depth

	for z := 0; z < depth; z++ {
		for y := 0; y < height; y++ {
			for x := 0; x < width; x++ {
				builder.data[z][y][x].char = ' '
			}
		}
	}

	return builder
}

func (self *mapBuilder) setUserRoom(room database.Room) {
	self.userRoom = room
}

func (self *mapBuilder) addRoom(room database.Room, x int, y int, z int) {
	addIfExists := func(dir database.ExitDirection, x int, y int) {
		if x < 0 || y < 0 {
			return
		}

		if room.HasExit(dir) {
			self.data[z][y][x].addExit(dir)
		}
	}

	if self.userRoom.Id == room.Id {
		self.data[z][y][x].char = 'O'
		self.data[z][y][x].color = utils.ColorRed
	} else {
		self.data[z][y][x].color = utils.ColorMagenta
		if room.HasExit(database.DirectionUp) && room.HasExit(database.DirectionDown) {
			self.data[z][y][x].char = '+'
		} else if room.HasExit(database.DirectionUp) {
			self.data[z][y][x].char = 'U'
		} else if room.HasExit(database.DirectionDown) {
			self.data[z][y][x].char = 'D'
		} else {
			self.data[z][y][x].char = '#'
			self.data[z][y][x].color = utils.ColorWhite
		}
	}

	addIfExists(database.DirectionNorth, x, y-1)
	addIfExists(database.DirectionNorthEast, x+1, y-1)
	addIfExists(database.DirectionEast, x+1, y)
	addIfExists(database.DirectionSouthEast, x+1, y+1)
	addIfExists(database.DirectionSouth, x, y+1)
	addIfExists(database.DirectionSouthWest, x-1, y+1)
	addIfExists(database.DirectionWest, x-1, y)
	addIfExists(database.DirectionNorthWest, x-1, y-1)
}

func (self *mapBuilder) toString(cm utils.ColorMode) string {
	str := ""

	for z := 0; z < self.depth; z++ {
		var rows []string
		for y := 0; y < self.height; y++ {
			row := ""
			for x := 0; x < self.width; x++ {
				tile := self.data[z][y][x].toString(cm)
				row = row + tile
			}
			rows = append(rows, row)
		}

		if self.depth > 1 {
			divider := "================================================================================\n"
			rows = append(rows, divider)
		}

		for _, row := range rows {
			str = str + row + "\n"
		}
	}

	return str
}

func (self *mapTile) addExit(dir database.ExitDirection) {
	combineChars := func(r1 rune, r2 rune, r3 rune) {
		if self.char == r1 {
			self.char = r2
		} else {
			self.char = r3
		}
	}

	self.color = utils.ColorBlue

	switch dir {
	case database.DirectionNorth:
		combineChars('v', '|', '^')
	case database.DirectionNorthEast:
		combineChars('\\', 'X', '/')
	case database.DirectionEast:
		combineChars('<', '-', '>')
	case database.DirectionSouthEast:
		combineChars('/', 'X', '\\')
	case database.DirectionSouth:
		combineChars('^', '|', 'v')
	case database.DirectionSouthWest:
		combineChars('\\', 'X', '/')
	case database.DirectionWest:
		combineChars('>', '-', '<')
	case database.DirectionNorthWest:
		combineChars('/', 'X', '\\')
	default:
		panic("Unexpected direction given to mapTile::addExit()")
	}
}

// vim: nocindent
<commit_msg>Don't bother drawing 1-way exits for now<commit_after>package game

import (
	"kmud/database"
	"kmud/utils"
)

type mapBuilder struct {
	width    int
	height   int
	depth    int
	data     [][][]mapTile
	userRoom database.Room
}

type mapTile struct {
	char  rune
	color utils.Color
}

func (self *mapTile) toString(cm utils.ColorMode) string {
	if self.char == ' ' {
		return string(self.char)
	}

	return utils.Colorize(cm, self.color, string(self.char))
}

func newMapBuilder(width int, height int, depth int) mapBuilder {
	var builder mapBuilder

	// Double the X/Y axis to account for extra space to draw exits
	width *= 2
	height *= 2

	builder.data = make([][][]mapTile, depth)

	for z := 0; z < depth; z++ {
		builder.data[z] = make([][]mapTile, height)
		for y := 0; y < height; y++ {
			builder.data[z][y] = make([]mapTile, width)
		}
	}

	builder.width = width
	builder.height = height
	builder.depth = depth

	for z := 0; z < depth; z++ {
		for y := 0; y < height; y++ {
			for x := 0; x < width; x++ {
				builder.data[z][y][x].char = ' '
			}
		}
	}

	return builder
}

func (self *mapBuilder) setUserRoom(room database.Room) {
	self.userRoom = room
}

func (self *mapBuilder) addRoom(room database.Room, x int, y int, z int) {
	addIfExists := func(dir database.ExitDirection, x int, y int) {
		if x < 0 || y < 0 {
			return
		}

		if room.HasExit(dir) {
			self.data[z][y][x].addExit(dir)
		}
	}

	if self.userRoom.Id == room.Id {
		self.data[z][y][x].char = 'O'
		self.data[z][y][x].color = utils.ColorRed
	} else {
		self.data[z][y][x].color = utils.ColorMagenta
		if room.HasExit(database.DirectionUp) && room.HasExit(database.DirectionDown) {
			self.data[z][y][x].char = '+'
		} else if room.HasExit(database.DirectionUp) {
			self.data[z][y][x].char = 'U'
		} else if room.HasExit(database.DirectionDown) {
			self.data[z][y][x].char = 'D'
		} else {
			self.data[z][y][x].char = '#'
			self.data[z][y][x].color = utils.ColorWhite
		}
	}

	addIfExists(database.DirectionNorth, x, y-1)
	addIfExists(database.DirectionNorthEast, x+1, y-1)
	addIfExists(database.DirectionEast, x+1, y)
	addIfExists(database.DirectionSouthEast, x+1, y+1)
	addIfExists(database.DirectionSouth, x, y+1)
	addIfExists(database.DirectionSouthWest, x-1, y+1)
	addIfExists(database.DirectionWest, x-1, y)
	addIfExists(database.DirectionNorthWest, x-1, y-1)
}

func (self *mapBuilder) toString(cm utils.ColorMode) string {
	str := ""

	for z := 0; z < self.depth; z++ {
		var rows []string
		for y := 0; y < self.height; y++ {
			row := ""
			for x := 0; x < self.width; x++ {
				tile := self.data[z][y][x].toString(cm)
				row = row + tile
			}
			rows = append(rows, row)
		}

		if self.depth > 1 {
			divider := "================================================================================\n"
			rows = append(rows, divider)
		}

		for _, row := range rows {
			str = str + row + "\n"
		}
	}

	return str
}

func (self *mapTile) addExit(dir database.ExitDirection) {
	combineChars := func(r1 rune, r2 rune, r3 rune) {
		if self.char == r1 {
			self.char = r2
		} else {
			self.char = r3
		}
	}

	self.color = utils.ColorBlue

	switch dir {
	case database.DirectionNorth:
		combineChars('|', '|', '|')
	case database.DirectionNorthEast:
		combineChars('\\', 'X', '/')
	case database.DirectionEast:
		combineChars('-', '-', '-')
	case database.DirectionSouthEast:
		combineChars('/', 'X', '\\')
	case database.DirectionSouth:
		combineChars('|', '|', '|')
	case database.DirectionSouthWest:
		combineChars('\\', 'X', '/')
	case database.DirectionWest:
		combineChars('-', '-', '-')
	case database.DirectionNorthWest:
		combineChars('/', 'X', '\\')
	default:
		panic("Unexpected direction given to mapTile::addExit()")
	}
}

// vim: nocindent
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"

	"github.com/go-zero-boilerplate/gensql/schema"

	"github.com/codemodus/kace"

	"strings"
)

type GeneratorSetup struct {
	Entities []*GeneratorEntity
}

type GeneratorEntity struct {
	Dialect      *GeneratorDialect
	EntityName   string
	StructName   string
	VariableName string
	SqlTable     string

	AllFields        []*GeneratorField
	PkFields         []*GeneratorField
	NonPkFields      []*GeneratorField
	InsertableFields []*GeneratorField
	EditableFields   []*GeneratorField
	TriggerFields    []*GeneratorField
}

type GeneratorField struct {
	IsAuto         bool
	IsPkField      bool
	IsTriggerField bool
	IsNullable     bool

	FieldName    string
	VariableName string
	GoType       string
	GoStructDef  string
	SqlColumn    string
	SchemaType   schema.FieldType
	SqlSize      int
	DefaultValue string
	ExtraArgs    []string
}

type GeneratorDialect struct {
	Name           string
	Dialect        schema.SchemaDialect
	GoVariablePart string
}

func splitStringRemoveEmpty(s, separator string) (strs []string) {
	for _, split := range strings.Split(s, separator) {
		trimmed := strings.TrimSpace(split)
		if trimmed != "" {
			strs = append(strs, trimmed)
		}
	}
	return
}

func schemaFieldTypeFromGoType(goType string, isCreatedField, isUpdatedField bool) schema.FieldType {
	if isCreatedField {
		return schema.DATETIME
	} else if isUpdatedField {
		return schema.TIMESTAMP
	}

	fieldType, err := schema.GoToFieldType(goType)
	if err != nil {
		panic(fmt.Errorf("Cannot append schema, unable to get field type for go type '%s', error: %s", goType, err.Error()))
	}
	return fieldType
}

func generatorFieldFromString(s string) *GeneratorField {
	splitted := splitStringRemoveEmpty(s, " ")
	if len(splitted) == 0 {
		panic("Cannot generate field from string '" + s + "'")
	}

	var (
		fieldName      string = splitted[0]
		fieldGoType    string
		fieldArgs      []string
		isTriggerField bool             = false
		isCreatedField bool             = false
		isUpdatedField bool             = false
		isAuto         bool             = false
		isPkField      bool             = false
		isNullable     bool             = false
		schemaType     schema.FieldType = schema.VARCHAR
		sqlSize        int              = 0
		defaultValue   string           = ""
	)

	if len(splitted) == 1 {
		fieldArgs = []string{}
		switch splitted[0] {
		case "created":
			fieldGoType = "time.Time"
			isTriggerField = true
			isCreatedField = true
		case "updated":
			fieldGoType = "time.Time"
			isTriggerField = true
			isUpdatedField = true
		default:
			panic("GoType not supported for 'trigger' field name: " + splitted[0])
		}
	} else {
		fieldGoType = splitted[1]
		fieldArgs = splitted[2:]
	}

	for _, arg := range fieldArgs {
		switch strings.ToLower(arg) {
		case "pk":
			isPkField = true
		case "auto":
			isAuto = true
		case "nullable":
			isNullable = true
		}

		if num, err := strconv.ParseInt(arg, 10, 32); err == nil {
			sqlSize = int(num)
		}

		if strings.HasPrefix(strings.ToLower(arg), "default:") {
			defaultValue = strings.Split(arg, ":")[1]
		}
	}

	schemaType = schemaFieldTypeFromGoType(fieldGoType, isCreatedField, isUpdatedField)

	return &GeneratorField{
		IsAuto:         isAuto,
		IsPkField:      isPkField,
		IsTriggerField: isTriggerField,
		IsNullable:     isNullable,
		FieldName:      kace.Camel(fieldName, true),
		VariableName:   kace.Camel(fieldName, false),
		GoType:         fieldGoType,
		GoStructDef:    kace.Camel(fieldName, true) + " " + fieldGoType,
		SqlColumn:      kace.Snake(fieldName),
		SchemaType:     schemaType,
		SqlSize:        sqlSize,
		DefaultValue:   defaultValue,
		ExtraArgs:      fieldArgs,
	}
}

func getSchemaGoVariablePart(dialectString string) string {
	switch strings.ToLower(dialectString) {
	case "mysql":
		return "database.MysqlDialect"
	case "sqlite":
		return "database.SqliteDialect"
	case "postgres":
		return "database.PostgresDialect"
	default:
		panic("Dialect '" + dialectString + "' not supported for the generation 'variable' part")
	}
}

func GeneratorSetupFromYamlSetup(orderedEntityNames []string, y *YamlSetup) (g *GeneratorSetup) {
	g = &GeneratorSetup{}

	for _, entityName := range orderedEntityNames {
		entitySetup := (*y)[entityName]

		allFields := []*GeneratorField{}
		pkFields := []*GeneratorField{}
		nonPkFields := []*GeneratorField{}
		editableFields := []*GeneratorField{}
		insertableFields := []*GeneratorField{}
		triggerFields := []*GeneratorField{}

		for _, fieldString := range entitySetup.Fields {
			field := generatorFieldFromString(fieldString)
			allFields = append(allFields, field)

			if field.IsPkField {
				pkFields = append(pkFields, field)
			} else {
				nonPkFields = append(nonPkFields, field)
			}

			if field.IsTriggerField {
				triggerFields = append(triggerFields, field)
			}

			if !field.IsPkField && !field.IsTriggerField {
				editableFields = append(editableFields, field)
				insertableFields = append(insertableFields, field)
			}
		}

		dialectName := kace.Camel(entitySetup.Dialect, true)
		generatorDialect := &GeneratorDialect{
			Name:           dialectName,
			GoVariablePart: getSchemaGoVariablePart(entitySetup.Dialect),
			Dialect:        schema.ParseSchemaDialectFromString(entitySetup.Dialect),
		}

		g.Entities = append(g.Entities, &GeneratorEntity{
			Dialect: generatorDialect,

			EntityName:   entityName,
			StructName:   kace.Camel(entityName, true),
			VariableName: kace.Camel(entityName, false),
			SqlTable:     kace.Snake(entityName),

			AllFields:        allFields,
			PkFields:         pkFields,
			NonPkFields:      nonPkFields,
			EditableFields:   editableFields,
			InsertableFields: insertableFields,
			TriggerFields:    triggerFields,
		})
	}

	return g
}
<commit_msg>Typo fixed.<commit_after>package main

import (
	"fmt"
	"strconv"

	"github.com/go-zero-boilerplate/gensql/schema"

	"github.com/codemodus/kace"

	"strings"
)

type GeneratorSetup struct {
	Entities []*GeneratorEntity
}

type GeneratorEntity struct {
	Dialect      *GeneratorDialect
	EntityName   string
	StructName   string
	VariableName string
	SqlTable     string

	AllFields        []*GeneratorField
	PkFields         []*GeneratorField
	NonPkFields      []*GeneratorField
	InsertableFields []*GeneratorField
	EditableFields   []*GeneratorField
	TriggerFields    []*GeneratorField
}

type GeneratorField struct {
	IsAuto         bool
	IsPkField      bool
	IsTriggerField bool
	IsNullable     bool

	FieldName    string
	VariableName string
	GoType       string
	GoStructDef  string
	SqlColumn    string
	SchemaType   schema.FieldType
	SqlSize      int
	DefaultValue string
	ExtraArgs    []string
}

type GeneratorDialect struct {
	Name           string
	Dialect        schema.SchemaDialect
	GoVariablePart string
}

func splitStringRemoveEmpty(s, separator string) (strs []string) {
	for _, split := range strings.Split(s, separator) {
		trimmed := strings.TrimSpace(split)
		if trimmed != "" {
			strs = append(strs, trimmed)
		}
	}
	return
}

func schemaFieldTypeFromGoType(goType string, isCreatedField, isUpdatedField bool) schema.FieldType {
	if isCreatedField {
		return schema.DATETIME
	} else if isUpdatedField {
		return schema.TIMESTAMP
	}

	fieldType, err := schema.GoToFieldType(goType)
	if err != nil {
		panic(fmt.Errorf("Cannot append schema, unable to get field type for go type '%s', error: %s", goType, err.Error()))
	}
	return fieldType
}

func generatorFieldFromString(s string) *GeneratorField {
	splitted := splitStringRemoveEmpty(s, " ")
	if len(splitted) == 0 {
		panic("Cannot generate field from string '" + s + "'")
	}

	var (
		fieldName      string = splitted[0]
		fieldGoType    string
		fieldArgs      []string
		isTriggerField bool             = false
		isCreatedField bool             = false
		isUpdatedField bool             = false
		isAuto         bool             = false
		isPkField      bool             = false
		isNullable     bool             = false
		schemaType     schema.FieldType = schema.VARCHAR
		sqlSize        int              = 0
		defaultValue   string           = ""
	)

	if len(splitted) == 1 {
		fieldArgs = []string{}
		switch splitted[0] {
		case "created":
			fieldGoType = "time.Time"
			isTriggerField = true
			isCreatedField = true
		case "updated":
			fieldGoType = "time.Time"
			isTriggerField = true
			isUpdatedField = true
		default:
			panic("GoType not supported for 'trigger' field name: " + splitted[0])
		}
	} else {
		fieldGoType = splitted[1]
		fieldArgs = splitted[2:]
	}

	for _, arg := range fieldArgs {
		switch strings.ToLower(arg) {
		case "pk":
			isPkField = true
		case "auto":
			isAuto = true
		case "nullable":
			isNullable = true
		}

		if num, err := strconv.ParseInt(arg, 10, 32); err == nil {
			sqlSize = int(num)
		}

		if strings.HasPrefix(strings.ToLower(arg), "default:") {
			defaultValue = strings.Split(arg, ":")[1]
		}
	}

	schemaType = schemaFieldTypeFromGoType(fieldGoType, isCreatedField, isUpdatedField)

	return &GeneratorField{
		IsAuto:         isAuto,
		IsPkField:      isPkField,
		IsTriggerField: isTriggerField,
		IsNullable:     isNullable,
		FieldName:      kace.Camel(fieldName, true),
		VariableName:   kace.Camel(fieldName, false),
		GoType:         fieldGoType,
		GoStructDef:    kace.Camel(fieldName, true) + " " + fieldGoType,
		SqlColumn:      kace.Snake(fieldName),
		SchemaType:     schemaType,
		SqlSize:        sqlSize,
		DefaultValue:   defaultValue,
		ExtraArgs:      fieldArgs,
	}
}

func getSchemaGoVariablePart(dialectString string) string {
	switch strings.ToLower(dialectString) {
	case "mysql":
		return "databases.MysqlDialect"
	case "sqlite":
		return "databases.SqliteDialect"
	case "postgres":
		return "databases.PostgresDialect"
	default:
		panic("Dialect '" + dialectString + "' not supported for the generation 'variable' part")
	}
}

func GeneratorSetupFromYamlSetup(orderedEntityNames []string, y *YamlSetup) (g *GeneratorSetup) {
	g = &GeneratorSetup{}

	for _, entityName := range orderedEntityNames {
		entitySetup := (*y)[entityName]

		allFields := []*GeneratorField{}
		pkFields := []*GeneratorField{}
		nonPkFields := []*GeneratorField{}
		editableFields := []*GeneratorField{}
		insertableFields := []*GeneratorField{}
		triggerFields := []*GeneratorField{}

		for _, fieldString := range entitySetup.Fields {
			field := generatorFieldFromString(fieldString)
			allFields = append(allFields, field)

			if field.IsPkField {
				pkFields = append(pkFields, field)
			} else {
				nonPkFields = append(nonPkFields, field)
			}

			if field.IsTriggerField {
				triggerFields = append(triggerFields, field)
			}

			if !field.IsPkField && !field.IsTriggerField {
				editableFields = append(editableFields, field)
				insertableFields = append(insertableFields, field)
			}
		}

		dialectName := kace.Camel(entitySetup.Dialect, true)
		generatorDialect := &GeneratorDialect{
			Name:           dialectName,
			GoVariablePart: getSchemaGoVariablePart(entitySetup.Dialect),
			Dialect:        schema.ParseSchemaDialectFromString(entitySetup.Dialect),
		}

		g.Entities = append(g.Entities, &GeneratorEntity{
			Dialect: generatorDialect,

			EntityName:   entityName,
			StructName:   kace.Camel(entityName, true),
			VariableName: kace.Camel(entityName, false),
			SqlTable:     kace.Snake(entityName),

			AllFields:        allFields,
			PkFields:         pkFields,
			NonPkFields:      nonPkFields,
			EditableFields:   editableFields,
			InsertableFields: insertableFields,
			TriggerFields:    triggerFields,
		})
	}

	return g
}
<|endoftext|>


<commit_before>/*
copyright 2019 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
    http://www.apache.org/licenses/license-2.0
unless required by applicable law or agreed to in writing, software
distributed under the license is distributed on an "as is" basis,
without warranties or conditions of any kind, either express or implied.
see the license for the specific language governing permissions and
limitations under the license.
*/

package generator

import (
	"bufio"
	"bytes"
	"fmt"
	//"io"
	k8sjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
	"log"
	"os"
	"path/filepath"
	"shifter/lib"
	"strconv"
)

func Yaml(path string, objects []lib.K8sobject, destination string) {
	if destination == "gcs" {

		for _, v := range objects {
			var b bytes.Buffer

			w := bufio.NewWriter(&b)
			e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
			err := e.Encode(v.Object, w)
			if err != nil {
				fmt.Println(err)
			}
			w.Flush()
			kind := fmt.Sprintf("%v", v.Kind)
			lib.GCSStreamFileUpload(b, "shifter-tmp", kind)
		}

	} else {
		// Create our output folder
		outPath := filepath.Clean(path)
		if filepath.Ext(outPath) == ".yaml" || filepath.Ext(outPath) == ".yml" {
			log.Println("Creating multidoc file", outPath)
			createFolder(filepath.Dir(outPath))
			_, err := os.Create(outPath)
			if err != nil {
				fmt.Println(err)
			}

			for _, v := range objects {
				f, err := os.OpenFile(outPath, os.O_RDWR|os.O_APPEND, 0666)
				if err != nil {
					log.Println(err)
				}
				w := bufio.NewWriter(f)
				defer f.Close()

				fmt.Fprintln(w, "---")
				e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
				err = e.Encode(v.Object, w)
				if err != nil {
					fmt.Println(err)
				}
				w.Flush()
			}

		} else {
			createFolder(outPath)
			// Iterate over our objects to write out
			for k, v := range objects {
				no := strconv.Itoa(k)
				kind := fmt.Sprintf("%v", v.Kind)

				f, err := os.Create(outPath + "/" + no + "-" + kind + ".yaml")
				if err != nil {
					fmt.Println(err)
				}
				defer f.Close()

				log.Println("Creating file", f.Name())
				w := bufio.NewWriter(f)
				e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
				err = e.Encode(v.Object, w)
				if err != nil {
					fmt.Println(err)
				}
				w.Flush()
			}
		}
	}
	log.Println("Conversion completed")
}
<commit_msg>Update yaml processing<commit_after>/*
copyright 2019 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
    http://www.apache.org/licenses/license-2.0
unless required by applicable law or agreed to in writing, software
distributed under the license is distributed on an "as is" basis,
without warranties or conditions of any kind, either express or implied.
see the license for the specific language governing permissions and
limitations under the license.
*/

package generator

import (
	"bufio"
	"bytes"
	"fmt"
	//"io"
	k8sjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
	"log"
	"os"
	"path/filepath"
	"shifter/lib"
	"strconv"
)

func Yaml(path string, objects []lib.K8sobject, destination string) {
	if destination == "gcs" {
		for _, v := range objects {
			var buf bytes.Buffer

			w := bufio.NewWriter(&b)
			e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
			err := e.Encode(v.Object, w)
			if err != nil {
				fmt.Println(err)
			}
			w.Flush()
			kind := fmt.Sprintf("%v", v.Kind)
			lib.GCSStreamFileUpload(buf, "shifter-tmp", kind)
		}

	} else {
		// Create our output folder
		outPath := filepath.Clean(path)
		if filepath.Ext(outPath) == ".yaml" || filepath.Ext(outPath) == ".yml" {
			log.Println("Creating multidoc file", outPath)
			createFolder(filepath.Dir(outPath))
			_, err := os.Create(outPath)
			if err != nil {
				fmt.Println(err)
			}

			for _, v := range objects {
				f, err := os.OpenFile(outPath, os.O_RDWR|os.O_APPEND, 0666)
				if err != nil {
					log.Println(err)
				}
				w := bufio.NewWriter(f)
				defer f.Close()

				fmt.Fprintln(w, "---")
				e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
				err = e.Encode(v.Object, w)
				if err != nil {
					fmt.Println(err)
				}
				w.Flush()
			}

		} else {
			createFolder(outPath)
			// Iterate over our objects to write out
			for k, v := range objects {
				no := strconv.Itoa(k)
				kind := fmt.Sprintf("%v", v.Kind)

				f, err := os.Create(outPath + "/" + no + "-" + kind + ".yaml")
				if err != nil {
					fmt.Println(err)
				}
				defer f.Close()

				log.Println("Creating file", f.Name())
				w := bufio.NewWriter(f)
				e := k8sjson.NewYAMLSerializer(k8sjson.DefaultMetaFactory, nil, nil)
				err = e.Encode(v.Object, w)
				if err != nil {
					fmt.Println(err)
				}
				w.Flush()
			}
		}
	}
	log.Println("Conversion completed")
}
<|endoftext|>


<commit_before>package concourse

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
)

type Config struct {
	Prefix                   string   `yaml:"prefix"`
	Region                   string   `yaml:"region"`
	KeyName                  string   `yaml:"key_name"`
	SubnetIds                []string `yaml:"subnet_ids"`
	VpcId                    string   `yaml:"vpc_id"`
	AvailabilityZones        []string `yaml:"availability_zones"`
	AccessibleCIDRS          string   `yaml:"accessible_cidrs"`
	DBInstanceClass          string   `yaml:"db_instance_class"`
	DBEngineVersion          string   `yaml:"db_engine_version"`
	// Deprecated: Use WebInstanceType and WorkerInstanceType instead.
	InstanceType             string   `yaml:"instance_type"`
	WebInstanceType          string   `yaml:"web_instance_type"`
	WorkerInstanceType       string   `yaml:"worker_instance_type"`
	WorkerInstanceProfile    string   `yaml:"worker_instance_profile"`
	AMI                      string   `yaml:"ami_id"`
	AsgMin                   string   `yaml:"asg_min"`
	AsgMax                   string   `yaml:"asg_max"`
	WebAsgDesired            string   `yaml:"web_asg_desired"`
	WorkerAsgDesired         string   `yaml:"worker_asg_desired"`
	ElbProtocol              string   `yaml:"elb_protocol"`
	ElbPort                  int      `yaml:"elb_port"`
	CustomExternalDomainName string   `yaml:"custom_external_domain_name"`
	SSLCertificateArn        string   `yaml:"ssl_certificate_arn"`
	BasicAuthUsername        string   `yaml:"basic_auth_username"`
	BasicAuthPassword        string   `yaml:"basic_auth_password"`
	GithubAuthClientId       string   `yaml:"github_auth_client_id"`
	GithubAuthClientSecret   string   `yaml:"github_auth_client_secret"`
	GithubAuthOrganizations  []string `yaml:"github_auth_organizations"`
	GithubAuthTeams          []string `yaml:"github_auth_teams"`
	GithubAuthUsers          []string `yaml:"github_auth_users"`
}

func ConfigFromFile(filename string) (*Config, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	c, err := ConfigFromBytes(data)
	if err != nil {
		return nil, fmt.Errorf("file %s: %v", filename, err)
	}

	return &c, nil
}

func ConfigFromString(data string) (Config, error) {
	return ConfigFromBytes([]byte(data))
}

func ConfigFromBytes(data []byte) (Config, error) {
	c := Config{}

	err := yaml.Unmarshal(data, &c)
	if err != nil {
		log.Fatalf("error: %v", err)
	}
	return c, err
}
<commit_msg>format code<commit_after>package concourse

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
)

type Config struct {
	Prefix            string   `yaml:"prefix"`
	Region            string   `yaml:"region"`
	KeyName           string   `yaml:"key_name"`
	SubnetIds         []string `yaml:"subnet_ids"`
	VpcId             string   `yaml:"vpc_id"`
	AvailabilityZones []string `yaml:"availability_zones"`
	AccessibleCIDRS   string   `yaml:"accessible_cidrs"`
	DBInstanceClass   string   `yaml:"db_instance_class"`
	DBEngineVersion   string   `yaml:"db_engine_version"`
	// Deprecated: Use WebInstanceType and WorkerInstanceType instead.
	InstanceType             string   `yaml:"instance_type"`
	WebInstanceType          string   `yaml:"web_instance_type"`
	WorkerInstanceType       string   `yaml:"worker_instance_type"`
	WorkerInstanceProfile    string   `yaml:"worker_instance_profile"`
	AMI                      string   `yaml:"ami_id"`
	AsgMin                   string   `yaml:"asg_min"`
	AsgMax                   string   `yaml:"asg_max"`
	WebAsgDesired            string   `yaml:"web_asg_desired"`
	WorkerAsgDesired         string   `yaml:"worker_asg_desired"`
	ElbProtocol              string   `yaml:"elb_protocol"`
	ElbPort                  int      `yaml:"elb_port"`
	CustomExternalDomainName string   `yaml:"custom_external_domain_name"`
	SSLCertificateArn        string   `yaml:"ssl_certificate_arn"`
	BasicAuthUsername        string   `yaml:"basic_auth_username"`
	BasicAuthPassword        string   `yaml:"basic_auth_password"`
	GithubAuthClientId       string   `yaml:"github_auth_client_id"`
	GithubAuthClientSecret   string   `yaml:"github_auth_client_secret"`
	GithubAuthOrganizations  []string `yaml:"github_auth_organizations"`
	GithubAuthTeams          []string `yaml:"github_auth_teams"`
	GithubAuthUsers          []string `yaml:"github_auth_users"`
}

func ConfigFromFile(filename string) (*Config, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	c, err := ConfigFromBytes(data)
	if err != nil {
		return nil, fmt.Errorf("file %s: %v", filename, err)
	}

	return &c, nil
}

func ConfigFromString(data string) (Config, error) {
	return ConfigFromBytes([]byte(data))
}

func ConfigFromBytes(data []byte) (Config, error) {
	c := Config{}

	err := yaml.Unmarshal(data, &c)
	if err != nil {
		log.Fatalf("error: %v", err)
	}
	return c, err
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go 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 main

import (
	"io/ioutil"
	"os"
	"path/filepath"
)

var hookFile = filepath.FromSlash(".git/hooks/commit-msg")

func installHook() {
	filename := filepath.Join(repoRoot(), hookFile)
	_, err := os.Stat(filename)
	if err == nil {
		return
	}
	if !os.IsNotExist(err) {
		dief("error checking for hook file: %v", err)
	}
	verbosef("Presubmit hook to add Change-Id to commit messages is missing.")
	verbosef("Automatically creating it at %v.", filename)
	hookContent := []byte(commitMsgHook)
	if err := ioutil.WriteFile(filename, hookContent, 0700); err != nil {
		dief("error writing hook file: %v", err)
	}
}

func repoRoot() string {
	dir, err := os.Getwd()
	if err != nil {
		dief("could not get current directory: %v", err)
	}
	for {
		if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
			return dir
		}
		if len(dir) == 1 && dir[0] == filepath.Separator {
			dief("git root not found. Rerun from within the Git tree.")
		}
		dir = filepath.Dir(dir)
	}
}

var commitMsgHook = `#!/bin/sh
# From Gerrit Code Review 2.2.1
#
# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

CHANGE_ID_AFTER="Bug|Issue"
MSG="$1"

# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
	clean_message=` + "`" + `sed -e '
		/^diff --git a\/.*/{
			s///
			q
		}
		/^Signed-off-by:/d
		/^#/d
	' "$MSG" | git stripspace` + "`" + `
	if test -z "$clean_message"
	then
		return
	fi

	if grep -i '^Change-Id:' "$MSG" >/dev/null
	then
		return
	fi

	id=` + "`" + `_gen_ChangeId` + "`" + `
	perl -e '
		$MSG = shift;
		$id = shift;
		$CHANGE_ID_AFTER = shift;

		undef $/;
		open(I, $MSG); $_ = <I>; close I;
		s|^diff --git a/.*||ms;
		s|^#.*$||mg;
		exit unless $_;

		@message = split /\n/;
		$haveFooter = 0;
		$startFooter = @message;
		for($line = @message - 1; $line >= 0; $line--) {
			$_ = $message[$line];

			if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
				$haveFooter++;
				next;
			}
			next if /^[ []/;
			$startFooter = $line if ($haveFooter && /^\r?$/);
			last;
		}

		@footer = @message[$startFooter+1..@message];
		@message = @message[0..$startFooter];
		push(@footer, "") unless @footer;

		for ($line = 0; $line < @footer; $line++) {
			$_ = $footer[$line];
			next if /^($CHANGE_ID_AFTER):/i;
			last;
		}
		splice(@footer, $line, 0, "Change-Id: I$id");

		$_ = join("\n", @message, @footer);
		open(O, ">$MSG"); print O; close O;
	' "$MSG" "$id" "$CHANGE_ID_AFTER"
}
_gen_ChangeIdInput() {
	echo "tree ` + "`" + `git write-tree` + "`" + `"
	if parent=` + "`" + `git rev-parse HEAD^0 2>/dev/null` + "`" + `
	then
		echo "parent $parent"
	fi
	echo "author ` + "`" + `git var GIT_AUTHOR_IDENT` + "`" + `"
	echo "committer ` + "`" + `git var GIT_COMMITTER_IDENT` + "`" + `"
	echo
	printf '%s' "$clean_message"
}
_gen_ChangeId() {
	_gen_ChangeIdInput |
	git hash-object -t commit --stdin
}

add_ChangeId
`
<commit_msg>review: Handle windows paths<commit_after>// Copyright 2014 The Go 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 main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
)

var hookFile = filepath.FromSlash(".git/hooks/commit-msg")

func installHook() {
	filename := filepath.Join(repoRoot(), hookFile)
	_, err := os.Stat(filename)
	if err == nil {
		return
	}
	if !os.IsNotExist(err) {
		dief("error checking for hook file: %v", err)
	}
	verbosef("Presubmit hook to add Change-Id to commit messages is missing.")
	verbosef("Automatically creating it at %v.", filename)
	hookContent := []byte(commitMsgHook)
	if err := ioutil.WriteFile(filename, hookContent, 0700); err != nil {
		dief("error writing hook file: %v", err)
	}
}

func repoRoot() string {
	dir, err := os.Getwd()
	if err != nil {
		dief("could not get current directory: %v", err)
	}
	rootlen := 1
	if runtime.GOOS == "windows" {
		rootlen += len(filepath.VolumeName(dir))
	}
	for {
		if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
			return dir
		}
		if len(dir) == rootlen && dir[rootlen-1] == filepath.Separator {
			dief("git root not found. Rerun from within the Git tree.")
		}
		dir = filepath.Dir(dir)
	}
}

var commitMsgHook = `#!/bin/sh
# From Gerrit Code Review 2.2.1
#
# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

CHANGE_ID_AFTER="Bug|Issue"
MSG="$1"

# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
	clean_message=` + "`" + `sed -e '
		/^diff --git a\/.*/{
			s///
			q
		}
		/^Signed-off-by:/d
		/^#/d
	' "$MSG" | git stripspace` + "`" + `
	if test -z "$clean_message"
	then
		return
	fi

	if grep -i '^Change-Id:' "$MSG" >/dev/null
	then
		return
	fi

	id=` + "`" + `_gen_ChangeId` + "`" + `
	perl -e '
		$MSG = shift;
		$id = shift;
		$CHANGE_ID_AFTER = shift;

		undef $/;
		open(I, $MSG); $_ = <I>; close I;
		s|^diff --git a/.*||ms;
		s|^#.*$||mg;
		exit unless $_;

		@message = split /\n/;
		$haveFooter = 0;
		$startFooter = @message;
		for($line = @message - 1; $line >= 0; $line--) {
			$_ = $message[$line];

			if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
				$haveFooter++;
				next;
			}
			next if /^[ []/;
			$startFooter = $line if ($haveFooter && /^\r?$/);
			last;
		}

		@footer = @message[$startFooter+1..@message];
		@message = @message[0..$startFooter];
		push(@footer, "") unless @footer;

		for ($line = 0; $line < @footer; $line++) {
			$_ = $footer[$line];
			next if /^($CHANGE_ID_AFTER):/i;
			last;
		}
		splice(@footer, $line, 0, "Change-Id: I$id");

		$_ = join("\n", @message, @footer);
		open(O, ">$MSG"); print O; close O;
	' "$MSG" "$id" "$CHANGE_ID_AFTER"
}
_gen_ChangeIdInput() {
	echo "tree ` + "`" + `git write-tree` + "`" + `"
	if parent=` + "`" + `git rev-parse HEAD^0 2>/dev/null` + "`" + `
	then
		echo "parent $parent"
	fi
	echo "author ` + "`" + `git var GIT_AUTHOR_IDENT` + "`" + `"
	echo "committer ` + "`" + `git var GIT_COMMITTER_IDENT` + "`" + `"
	echo
	printf '%s' "$clean_message"
}
_gen_ChangeId() {
	_gen_ChangeIdInput |
	git hash-object -t commit --stdin
}

add_ChangeId
`
<|endoftext|>


<commit_before>package git

import (
	"fmt"
	"testing"
)

type newRemoteTest struct {
	url                 string
	willBeError         bool
	expectedServiceHost string
	expectedOwner       string
	expectedRepoName    string
}

func TestNewRemote(t *testing.T) {
	newRemoteTests := []*newRemoteTest{
		{
			url:                 "git@github.com:mpppk/hlb.git",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:         "git@github.com:mpppk.git",
			willBeError: true,
		},
		{
			url:         "git@github.com:/hlb.git",
			willBeError: true,
		},
		{
			url:         "git@github.commpppk/hlb.git",
			willBeError: true,
		},
		{
			url:         "github.com/mpppk/hlb.git",
			willBeError: true,
		},
		{
			url:                 "https://github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:                 "http://github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:                 "https://mpppk@github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:         "http://github.com/mpppk",
			willBeError: true,
		},
	}

	for i, nr := range newRemoteTests {
		remote, err := NewRemote(nr.url)

		if err != nil {
			if !nr.willBeError {
				t.Errorf("%v: Unexpected error ocured: %v, params: %v",
					i, err, nr)
			} else {
				continue
			}
		} else if nr.willBeError {
			t.Errorf("%v: Error expected, params: %v",
				i, nr)
		}

		if remote.ServiceHost != nr.expectedServiceHost {
			t.Errorf("ServiceHost field must be host name "+
				"that extracted from provided URL "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedServiceHost, nr.url, remote.ServiceHost)
		}

		if remote.Owner != nr.expectedOwner {
			t.Errorf("Owner field must be owner name that extracted from provided URL, "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedOwner, nr.url, remote.Owner)
		}

		if remote.RepoName != nr.expectedRepoName {
			t.Errorf("RepoName field must be repository name that extracted from provided URL, "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedRepoName, nr.url, remote.RepoName)
		}
	}
}
<commit_msg>Remove unused import<commit_after>package git

import (
	"testing"
)

type newRemoteTest struct {
	url                 string
	willBeError         bool
	expectedServiceHost string
	expectedOwner       string
	expectedRepoName    string
}

func TestNewRemote(t *testing.T) {
	newRemoteTests := []*newRemoteTest{
		{
			url:                 "git@github.com:mpppk/hlb.git",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:         "git@github.com:mpppk.git",
			willBeError: true,
		},
		{
			url:         "git@github.com:/hlb.git",
			willBeError: true,
		},
		{
			url:         "git@github.commpppk/hlb.git",
			willBeError: true,
		},
		{
			url:         "github.com/mpppk/hlb.git",
			willBeError: true,
		},
		{
			url:                 "https://github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:                 "http://github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:                 "https://mpppk@github.com/mpppk/hlb",
			willBeError:         false,
			expectedServiceHost: "github.com",
			expectedOwner:       "mpppk",
			expectedRepoName:    "hlb",
		},
		{
			url:         "http://github.com/mpppk",
			willBeError: true,
		},
	}

	for i, nr := range newRemoteTests {
		remote, err := NewRemote(nr.url)

		if err != nil {
			if !nr.willBeError {
				t.Errorf("%v: Unexpected error ocured: %v, params: %v",
					i, err, nr)
			} else {
				continue
			}
		} else if nr.willBeError {
			t.Errorf("%v: Error expected, params: %v",
				i, nr)
		}

		if remote.ServiceHost != nr.expectedServiceHost {
			t.Errorf("ServiceHost field must be host name "+
				"that extracted from provided URL "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedServiceHost, nr.url, remote.ServiceHost)
		}

		if remote.Owner != nr.expectedOwner {
			t.Errorf("Owner field must be owner name that extracted from provided URL, "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedOwner, nr.url, remote.Owner)
		}

		if remote.RepoName != nr.expectedRepoName {
			t.Errorf("RepoName field must be repository name that extracted from provided URL, "+
				"%v: expected: %v, actual(extract from %v): %v",
				i, nr.expectedRepoName, nr.url, remote.RepoName)
		}
	}
}
<|endoftext|>