<commit_before>package action

import (
	"context"
	"fmt"

	"github.com/gopasspw/gopass/pkg/backend/rcs/noop"
	"github.com/gopasspw/gopass/pkg/notify"
	"github.com/gopasspw/gopass/pkg/out"
	"github.com/gopasspw/gopass/pkg/store"

	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

// Sync all stores with their remotes
func (s *Action) Sync(ctx context.Context, c *cli.Context) error {
	store := c.String("store")
	return s.sync(ctx, c, store)
}

func (s *Action) sync(ctx context.Context, c *cli.Context, store string) error {
	out.Green(ctx, "Sync starting ...")

	numEntries := 0
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0))
	}
	numMPs := 0

	mps := s.Store.MountPoints()
	mps = append([]string{""}, mps...)

	// sync all stores (root and all mounted sub stores)
	for _, mp := range mps {
		if store != "" {
			if store != "root" && mp != store {
				continue
			}
			if store == "root" && mp != "" {
				continue
			}
		}

		numMPs++
		_ = s.syncMount(ctx, mp)
	}
	out.Green(ctx, "All done")

	// calculate number of changes entries
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0)) - numEntries
	}
	diff := ""
	if numEntries > 0 {
		diff = fmt.Sprintf(" Added %d entries", numEntries)
	} else if numEntries < 0 {
		diff = fmt.Sprintf(" Removed %d entries", -1*numEntries)
	}
	_ = notify.Notify(ctx, "gopass - sync", fmt.Sprintf("Finished. Synced %d remotes.%s", numMPs, diff))

	return nil
}

// syncMount syncs a single mount
func (s *Action) syncMount(ctx context.Context, mp string) error {
	ctxno := out.WithNewline(ctx, false)
	name := mp
	if mp == "" {
		name = "<root>"
	}
	out.Print(ctxno, color.GreenString("[%s] ", name))

	sub, err := s.Store.GetSubStore(mp)
	if err != nil {
		out.Red(ctx, "Failed to get sub store '%s': %s", name, err)
		return fmt.Errorf("failed to get sub stores (%s)", err)
	}

	if sub == nil {
		out.Red(ctx, "Failed to get sub stores '%s: nil'", name)
		return fmt.Errorf("failed to get sub stores (nil)")
	}

	numMP := 0
	if l, err := sub.List(ctx, ""); err == nil {
		numMP = len(l)
	}

	if sub.RCS().Name() == noop.New().Name() {
		out.Red(ctxno, "\n   WARNING: Mount uses noop RCS backend. Not syncing!")
	}

	out.Print(ctxno, "\n   "+color.GreenString("git pull and push ... "))
	if err := sub.RCS().Push(ctx, "", ""); err != nil {
		if errors.Cause(err) == store.ErrGitNoRemote {
			out.Yellow(ctx, "Skipped (no remote)")
			out.Debug(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}

		out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	if l, err := sub.List(ctx, ""); err == nil {
		diff := len(l) - numMP
		if diff > 0 {
			out.Print(ctxno, color.GreenString(" (Added %d entries)", diff))
		} else if diff < 0 {
			out.Print(ctxno, color.GreenString(" (Removed %d entries)", -1*diff))
		} else {
			out.Print(ctxno, color.GreenString(" (no changes)"))
		}
	}

	// import keys
	out.Print(ctxno, "\n   "+color.GreenString("importing missing keys ... "))
	if err := sub.ImportMissingPublicKeys(ctx); err != nil {
		out.Red(ctx, "Failed to import missing public keys for '%s': %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	// export keys
	out.Print(ctxno, "\n   "+color.GreenString("exporting missing keys ... "))
	rs, err := sub.GetRecipients(ctx, "")
	if err != nil {
		out.Red(ctx, "Failed to load recipients for '%s': %s", name, err)
		return err
	}
	exported, err := sub.ExportMissingPublicKeys(ctx, rs)
	if err != nil {
		out.Red(ctx, "Failed to export missing public keys for '%s': %s", name, err)
		return err
	}

	// only run second push if we did export any keys
	if exported {
		if err := sub.RCS().Push(ctx, "", ""); err != nil {
			out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}
		out.Print(ctxno, color.GreenString("OK"))
	} else {
		out.Print(ctxno, color.GreenString("nothing to do"))
	}
	out.Print(ctx, "\n   "+color.GreenString("done"))
	return nil
}
<commit_msg>Abort syncMount when using noop backend<commit_after>package action

import (
	"context"
	"fmt"

	"github.com/gopasspw/gopass/pkg/backend/rcs/noop"
	"github.com/gopasspw/gopass/pkg/notify"
	"github.com/gopasspw/gopass/pkg/out"
	"github.com/gopasspw/gopass/pkg/store"

	"github.com/fatih/color"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

// Sync all stores with their remotes
func (s *Action) Sync(ctx context.Context, c *cli.Context) error {
	store := c.String("store")
	return s.sync(ctx, c, store)
}

func (s *Action) sync(ctx context.Context, c *cli.Context, store string) error {
	out.Green(ctx, "Sync starting ...")

	numEntries := 0
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0))
	}
	numMPs := 0

	mps := s.Store.MountPoints()
	mps = append([]string{""}, mps...)

	// sync all stores (root and all mounted sub stores)
	for _, mp := range mps {
		if store != "" {
			if store != "root" && mp != store {
				continue
			}
			if store == "root" && mp != "" {
				continue
			}
		}

		numMPs++
		_ = s.syncMount(ctx, mp)
	}
	out.Green(ctx, "All done")

	// calculate number of changes entries
	if l, err := s.Store.Tree(ctx); err == nil {
		numEntries = len(l.List(0)) - numEntries
	}
	diff := ""
	if numEntries > 0 {
		diff = fmt.Sprintf(" Added %d entries", numEntries)
	} else if numEntries < 0 {
		diff = fmt.Sprintf(" Removed %d entries", -1*numEntries)
	}
	_ = notify.Notify(ctx, "gopass - sync", fmt.Sprintf("Finished. Synced %d remotes.%s", numMPs, diff))

	return nil
}

// syncMount syncs a single mount
func (s *Action) syncMount(ctx context.Context, mp string) error {
	ctxno := out.WithNewline(ctx, false)
	name := mp
	if mp == "" {
		name = "<root>"
	}
	out.Print(ctxno, color.GreenString("[%s] ", name))

	sub, err := s.Store.GetSubStore(mp)
	if err != nil {
		out.Red(ctx, "Failed to get sub store '%s': %s", name, err)
		return fmt.Errorf("failed to get sub stores (%s)", err)
	}

	if sub == nil {
		out.Red(ctx, "Failed to get sub stores '%s: nil'", name)
		return fmt.Errorf("failed to get sub stores (nil)")
	}

	numMP := 0
	if l, err := sub.List(ctx, ""); err == nil {
		numMP = len(l)
	}

	if sub.RCS().Name() == noop.New().Name() {
		out.Red(ctxno, "\n   WARNING: Mount uses RCS backend 'noop'. Not syncing!\n")
		return nil
	}

	out.Print(ctxno, "\n   "+color.GreenString("git pull and push ... "))
	if err := sub.RCS().Push(ctx, "", ""); err != nil {
		if errors.Cause(err) == store.ErrGitNoRemote {
			out.Yellow(ctx, "Skipped (no remote)")
			out.Debug(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}

		out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	if l, err := sub.List(ctx, ""); err == nil {
		diff := len(l) - numMP
		if diff > 0 {
			out.Print(ctxno, color.GreenString(" (Added %d entries)", diff))
		} else if diff < 0 {
			out.Print(ctxno, color.GreenString(" (Removed %d entries)", -1*diff))
		} else {
			out.Print(ctxno, color.GreenString(" (no changes)"))
		}
	}

	// import keys
	out.Print(ctxno, "\n   "+color.GreenString("importing missing keys ... "))
	if err := sub.ImportMissingPublicKeys(ctx); err != nil {
		out.Red(ctx, "Failed to import missing public keys for '%s': %s", name, err)
		return err
	}
	out.Print(ctxno, color.GreenString("OK"))

	// export keys
	out.Print(ctxno, "\n   "+color.GreenString("exporting missing keys ... "))
	rs, err := sub.GetRecipients(ctx, "")
	if err != nil {
		out.Red(ctx, "Failed to load recipients for '%s': %s", name, err)
		return err
	}
	exported, err := sub.ExportMissingPublicKeys(ctx, rs)
	if err != nil {
		out.Red(ctx, "Failed to export missing public keys for '%s': %s", name, err)
		return err
	}

	// only run second push if we did export any keys
	if exported {
		if err := sub.RCS().Push(ctx, "", ""); err != nil {
			out.Red(ctx, "Failed to push '%s' to it's remote: %s", name, err)
			return err
		}
		out.Print(ctxno, color.GreenString("OK"))
	} else {
		out.Print(ctxno, color.GreenString("nothing to do"))
	}
	out.Print(ctx, "\n   "+color.GreenString("done"))
	return nil
}
<|endoftext|>


<commit_before>package cli

import (
	"fmt"
	"os"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
	kubecmd "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"github.com/openshift/origin/pkg/cmd/cli/cmd"
	"github.com/openshift/origin/pkg/cmd/templates"
)

const longDesc = `
OpenShift Client

The OpenShift client exposes commands for managing your applications, as well as lower level
tools to interact with each component of your system.

At the present time, the CLI wraps many of the upstream Kubernetes commands and works generically
on all resources.  To create a new application, try:

    $ %[1]s new-app openshift/ruby-20-centos~git@github.com/mfojtik/sinatra-app-example

This will create an application based on the Docker image 'openshift/ruby-20-centos' that builds
the source code at 'github.com/mfojtik/sinatra-app-example'. To start the build, run

    $ %[1]s start-build sinatra-app-example

and watch the build logs and build status with:

    $ %[1]s get builds
    $ %[1]s build-logs <name_of_build>

You'll be able to view the deployed application on the IP and port of the service that new-app
created for you.

Note: This is an alpha release of OpenShift and will change significantly.  See
    https://github.com/openshift/origin for the latest information on OpenShift.
`
const defaultClusterURL = "https://localhost:8443"

func NewCommandCLI(name, fullName string) *cobra.Command {
	// Main command
	cmds := &cobra.Command{
		Use:     name,
		Aliases: []string{"kubectl"},
		Short:   "Client tools for OpenShift",
		Long:    fmt.Sprintf(longDesc, fullName),
		Run: func(c *cobra.Command, args []string) {
			c.SetOutput(os.Stdout)
			c.Help()
		},
	}

	// Override global default to https and port 8443
	clientcmd.DefaultCluster.Server = defaultClusterURL

	// TODO: there should be two client configs, one for OpenShift, and one for Kubernetes
	clientConfig := DefaultClientConfig(cmds.PersistentFlags())
	f := cmd.NewFactory(clientConfig)
	f.BindFlags(cmds.PersistentFlags())
	out := os.Stdout

	cmds.SetUsageTemplate(templates.CliUsageTemplate())
	cmds.SetHelpTemplate(templates.CliHelpTemplate())

	cmds.AddCommand(cmd.NewCmdNewApplication(f, out))
	cmds.AddCommand(cmd.NewCmdStartBuild(f, out))
	cmds.AddCommand(cmd.NewCmdCancelBuild(f, out))
	cmds.AddCommand(cmd.NewCmdBuildLogs(f, out))
	cmds.AddCommand(cmd.NewCmdRollback(name, "rollback", f, out))

	cmds.AddCommand(f.NewCmdGet(out))
	cmds.AddCommand(f.NewCmdDescribe(out))
	// Deprecate 'osc apply' with 'osc create' command.
	cmds.AddCommand(applyToCreate(f.NewCmdCreate(out)))
	cmds.AddCommand(cmd.NewCmdProcess(f, out))
	cmds.AddCommand(f.NewCmdUpdate(out))
	cmds.AddCommand(f.NewCmdDelete(out))

	cmds.AddCommand(f.NewCmdLog(out))
	cmds.AddCommand(f.NewCmdProxy(out))

	cmds.AddCommand(kubecmd.NewCmdNamespace(out))

	// Origin build commands

	cmds.AddCommand(cmd.NewCmdOptions(f, out))

	return cmds
}

// NewCmdKubectl provides exactly the functionality from Kubernetes,
// but with support for OpenShift resources
func NewCmdKubectl(name string) *cobra.Command {
	flags := pflag.NewFlagSet("", pflag.ContinueOnError)
	clientcmd.DefaultCluster.Server = defaultClusterURL
	clientConfig := DefaultClientConfig(flags)
	f := cmd.NewFactory(clientConfig)
	cmd := f.NewKubectlCommand(os.Stdout)
	cmd.Use = name
	cmd.Short = "Kubernetes cluster management via kubectl"
	cmd.Long = cmd.Long + "\n\nThis command is provided for direct management of the Kubernetes cluster OpenShift runs on."
	flags.VisitAll(func(flag *pflag.Flag) {
		cmd.PersistentFlags().AddFlag(flag)
	})
	return cmd
}

// applyToCreate injects the deprecation notice about for 'apply' command into
// 'create' command.
// TODO: Remove this once we get rid of 'apply' in all documentation/etc.
func applyToCreate(dst *cobra.Command) *cobra.Command {
	dst.Aliases = append(dst.Aliases, "apply")
	oldRun := dst.Run
	dst.Run = func(c *cobra.Command, args []string) {
		if len(os.Args) >= 2 && os.Args[2] == "apply" {
			glog.Errorf("DEPRECATED: The 'apply' command is now deprecated, use 'create' instead.")
		}
		oldRun(c, args)
	}
	return dst
}

// Copy of kubectl/cmd/DefaultClientConfig, using NewNonInteractiveDeferredLoadingClientConfig
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
	// TODO find and merge duplicates, this is also in other places
	loadingRules := clientcmd.NewClientConfigLoadingRules()
	loadingRules.EnvVarPath = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
	flags.StringVar(&loadingRules.CommandLinePath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")

	overrides := &clientcmd.ConfigOverrides{}
	overrideFlags := clientcmd.RecommendedConfigOverrideFlags("")
	overrideFlags.ContextOverrideFlags.NamespaceShort = "n"
	clientcmd.BindOverrideFlags(overrides, flags, overrideFlags)
	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)

	return clientConfig
}
<commit_msg>Fix off-by-1 error<commit_after>package cli

import (
	"fmt"
	"os"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
	kubecmd "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
	"github.com/golang/glog"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"

	"github.com/openshift/origin/pkg/cmd/cli/cmd"
	"github.com/openshift/origin/pkg/cmd/templates"
)

const longDesc = `
OpenShift Client

The OpenShift client exposes commands for managing your applications, as well as lower level
tools to interact with each component of your system.

At the present time, the CLI wraps many of the upstream Kubernetes commands and works generically
on all resources.  To create a new application, try:

    $ %[1]s new-app openshift/ruby-20-centos~git@github.com/mfojtik/sinatra-app-example

This will create an application based on the Docker image 'openshift/ruby-20-centos' that builds
the source code at 'github.com/mfojtik/sinatra-app-example'. To start the build, run

    $ %[1]s start-build sinatra-app-example

and watch the build logs and build status with:

    $ %[1]s get builds
    $ %[1]s build-logs <name_of_build>

You'll be able to view the deployed application on the IP and port of the service that new-app
created for you.

Note: This is an alpha release of OpenShift and will change significantly.  See
    https://github.com/openshift/origin for the latest information on OpenShift.
`
const defaultClusterURL = "https://localhost:8443"

func NewCommandCLI(name, fullName string) *cobra.Command {
	// Main command
	cmds := &cobra.Command{
		Use:     name,
		Aliases: []string{"kubectl"},
		Short:   "Client tools for OpenShift",
		Long:    fmt.Sprintf(longDesc, fullName),
		Run: func(c *cobra.Command, args []string) {
			c.SetOutput(os.Stdout)
			c.Help()
		},
	}

	// Override global default to https and port 8443
	clientcmd.DefaultCluster.Server = defaultClusterURL

	// TODO: there should be two client configs, one for OpenShift, and one for Kubernetes
	clientConfig := DefaultClientConfig(cmds.PersistentFlags())
	f := cmd.NewFactory(clientConfig)
	f.BindFlags(cmds.PersistentFlags())
	out := os.Stdout

	cmds.SetUsageTemplate(templates.CliUsageTemplate())
	cmds.SetHelpTemplate(templates.CliHelpTemplate())

	cmds.AddCommand(cmd.NewCmdNewApplication(f, out))
	cmds.AddCommand(cmd.NewCmdStartBuild(f, out))
	cmds.AddCommand(cmd.NewCmdCancelBuild(f, out))
	cmds.AddCommand(cmd.NewCmdBuildLogs(f, out))
	cmds.AddCommand(cmd.NewCmdRollback(name, "rollback", f, out))

	cmds.AddCommand(f.NewCmdGet(out))
	cmds.AddCommand(f.NewCmdDescribe(out))
	// Deprecate 'osc apply' with 'osc create' command.
	cmds.AddCommand(applyToCreate(f.NewCmdCreate(out)))
	cmds.AddCommand(cmd.NewCmdProcess(f, out))
	cmds.AddCommand(f.NewCmdUpdate(out))
	cmds.AddCommand(f.NewCmdDelete(out))

	cmds.AddCommand(f.NewCmdLog(out))
	cmds.AddCommand(f.NewCmdProxy(out))

	cmds.AddCommand(kubecmd.NewCmdNamespace(out))

	// Origin build commands

	cmds.AddCommand(cmd.NewCmdOptions(f, out))

	return cmds
}

// NewCmdKubectl provides exactly the functionality from Kubernetes,
// but with support for OpenShift resources
func NewCmdKubectl(name string) *cobra.Command {
	flags := pflag.NewFlagSet("", pflag.ContinueOnError)
	clientcmd.DefaultCluster.Server = defaultClusterURL
	clientConfig := DefaultClientConfig(flags)
	f := cmd.NewFactory(clientConfig)
	cmd := f.NewKubectlCommand(os.Stdout)
	cmd.Use = name
	cmd.Short = "Kubernetes cluster management via kubectl"
	cmd.Long = cmd.Long + "\n\nThis command is provided for direct management of the Kubernetes cluster OpenShift runs on."
	flags.VisitAll(func(flag *pflag.Flag) {
		cmd.PersistentFlags().AddFlag(flag)
	})
	return cmd
}

// applyToCreate injects the deprecation notice about for 'apply' command into
// 'create' command.
// TODO: Remove this once we get rid of 'apply' in all documentation/etc.
func applyToCreate(dst *cobra.Command) *cobra.Command {
	dst.Aliases = append(dst.Aliases, "apply")
	oldRun := dst.Run
	dst.Run = func(c *cobra.Command, args []string) {
		calledApply := false
		calledApply = calledApply || len(os.Args) >= 2 && os.Args[1] == "apply" // `osc apply`
		calledApply = calledApply || len(os.Args) >= 3 && os.Args[2] == "apply" // `openshift cli apply`
		if calledApply {
			glog.Errorf("DEPRECATED: The 'apply' command is now deprecated, use 'create' instead.")
		}
		oldRun(c, args)
	}
	return dst
}

// Copy of kubectl/cmd/DefaultClientConfig, using NewNonInteractiveDeferredLoadingClientConfig
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
	// TODO find and merge duplicates, this is also in other places
	loadingRules := clientcmd.NewClientConfigLoadingRules()
	loadingRules.EnvVarPath = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
	flags.StringVar(&loadingRules.CommandLinePath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")

	overrides := &clientcmd.ConfigOverrides{}
	overrideFlags := clientcmd.RecommendedConfigOverrideFlags("")
	overrideFlags.ContextOverrideFlags.NamespaceShort = "n"
	clientcmd.BindOverrideFlags(overrides, flags, overrideFlags)
	clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)

	return clientConfig
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 kube

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"

	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/portforward"
	"k8s.io/client-go/transport/spdy"
)

// Tunnel describes a ssh-like tunnel to a kubernetes pod
type Tunnel struct {
	Local     int
	Remote    int
	Namespace string
	PodName   string
	Out       io.Writer
	stopChan  chan struct{}
	readyChan chan struct{}
	config    *rest.Config
	client    rest.Interface
}

// NewTunnel creates a new tunnel
func NewTunnel(client rest.Interface, config *rest.Config, namespace, podName string, remote int) *Tunnel {
	return &Tunnel{
		config:    config,
		client:    client,
		Namespace: namespace,
		PodName:   podName,
		Remote:    remote,
		stopChan:  make(chan struct{}, 1),
		readyChan: make(chan struct{}, 1),
		Out:       ioutil.Discard,
	}
}

// Close disconnects a tunnel connection
func (t *Tunnel) Close() {
	close(t.stopChan)
	close(t.readyChan)
}

// ForwardPort opens a tunnel to a kubernetes pod
func (t *Tunnel) ForwardPort() error {
	// Build a url to the portforward endpoint
	// example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward
	u := t.client.Post().
		Resource("pods").
		Namespace(t.Namespace).
		Name(t.PodName).
		SubResource("portforward").URL()

	transport, upgrader, err := spdy.RoundTripperFor(t.config)
	if err != nil {
		return err
	}
	dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", u)

	local, err := getAvailablePort()
	if err != nil {
		return fmt.Errorf("could not find an available port: %s", err)
	}
	t.Local = local

	ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)}

	pf, err := portforward.New(dialer, ports, t.stopChan, t.readyChan, t.Out, t.Out)
	if err != nil {
		return err
	}

	errChan := make(chan error)
	go func() {
		errChan <- pf.ForwardPorts()
	}()

	select {
	case err = <-errChan:
		return fmt.Errorf("forwarding ports: %v", err)
	case <-pf.Ready:
		return nil
	}
}

func getAvailablePort() (int, error) {
	l, err := net.Listen("tcp", ":0")
	if err != nil {
		return 0, err
	}
	defer l.Close()

	_, p, err := net.SplitHostPort(l.Addr().String())
	if err != nil {
		return 0, err
	}
	port, err := strconv.Atoi(p)
	if err != nil {
		return 0, err
	}
	return port, err
}
<commit_msg>fix(helm): Tunnel closing already closed channel (#3157)<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 kube

import (
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"

	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/portforward"
	"k8s.io/client-go/transport/spdy"
)

// Tunnel describes a ssh-like tunnel to a kubernetes pod
type Tunnel struct {
	Local     int
	Remote    int
	Namespace string
	PodName   string
	Out       io.Writer
	stopChan  chan struct{}
	readyChan chan struct{}
	config    *rest.Config
	client    rest.Interface
}

// NewTunnel creates a new tunnel
func NewTunnel(client rest.Interface, config *rest.Config, namespace, podName string, remote int) *Tunnel {
	return &Tunnel{
		config:    config,
		client:    client,
		Namespace: namespace,
		PodName:   podName,
		Remote:    remote,
		stopChan:  make(chan struct{}, 1),
		readyChan: make(chan struct{}, 1),
		Out:       ioutil.Discard,
	}
}

// Close disconnects a tunnel connection
func (t *Tunnel) Close() {
	close(t.stopChan)
}

// ForwardPort opens a tunnel to a kubernetes pod
func (t *Tunnel) ForwardPort() error {
	// Build a url to the portforward endpoint
	// example: http://localhost:8080/api/v1/namespaces/helm/pods/tiller-deploy-9itlq/portforward
	u := t.client.Post().
		Resource("pods").
		Namespace(t.Namespace).
		Name(t.PodName).
		SubResource("portforward").URL()

	transport, upgrader, err := spdy.RoundTripperFor(t.config)
	if err != nil {
		return err
	}
	dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", u)

	local, err := getAvailablePort()
	if err != nil {
		return fmt.Errorf("could not find an available port: %s", err)
	}
	t.Local = local

	ports := []string{fmt.Sprintf("%d:%d", t.Local, t.Remote)}

	pf, err := portforward.New(dialer, ports, t.stopChan, t.readyChan, t.Out, t.Out)
	if err != nil {
		return err
	}

	errChan := make(chan error)
	go func() {
		errChan <- pf.ForwardPorts()
	}()

	select {
	case err = <-errChan:
		return fmt.Errorf("forwarding ports: %v", err)
	case <-pf.Ready:
		return nil
	}
}

func getAvailablePort() (int, error) {
	l, err := net.Listen("tcp", ":0")
	if err != nil {
		return 0, err
	}
	defer l.Close()

	_, p, err := net.SplitHostPort(l.Addr().String())
	if err != nil {
		return 0, err
	}
	port, err := strconv.Atoi(p)
	if err != nil {
		return 0, err
	}
	return port, err
}
<|endoftext|>


<commit_before>package mount

import (
	"time"
)

// GetMounts retrieves a list of mounts for the current running process.
func GetMounts() ([]*Info, error) {
	return parseMountTable()
}

// Mounted determines if a specified mountpoint has been mounted.
// On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab.
func Mounted(mountpoint string) (bool, error) {
	entries, err := parseMountTable()
	if err != nil {
		return false, err
	}

	// Search the table for the mountpoint
	for _, e := range entries {
		if e.Mountpoint == mountpoint {
			return true, nil
		}
	}
	return false, nil
}

// Mount will mount filesystem according to the specified configuration, on the
// condition that the target path is *not* already mounted. Options must be
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
// flags.go for supported option flags.
func Mount(device, target, mType, options string) error {
	flag, _ := parseOptions(options)
	if flag&REMOUNT != REMOUNT {
		if mounted, err := Mounted(target); err != nil || mounted {
			return err
		}
	}
	return ForceMount(device, target, mType, options)
}

// ForceMount will mount a filesystem according to the specified configuration,
// *regardless* if the target path is not already mounted. Options must be
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
// flags.go for supported option flags.
func ForceMount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	if err := mount(device, target, mType, uintptr(flag), data); err != nil {
		return err
	}
	return nil
}

// Unmount will unmount the target filesystem, so long as it is mounted.
func Unmount(target string) error {
	if mounted, err := Mounted(target); err != nil || !mounted {
		return err
	}
	return ForceUnmount(target)
}

// ForceUnmount will force an unmount of the target filesystem, regardless if
// it is mounted or not.
func ForceUnmount(target string) (err error) {
	// Simple retry logic for unmount
	for i := 0; i < 10; i++ {
		if err = unmount(target, 0); err == nil {
			return nil
		}
		time.Sleep(100 * time.Millisecond)
	}
	return
}
<commit_msg>Make sure you get the realpath when checking Mounted<commit_after>package mount

import (
	"time"

	"github.com/containers/storage/pkg/fileutils"
)

// GetMounts retrieves a list of mounts for the current running process.
func GetMounts() ([]*Info, error) {
	return parseMountTable()
}

// Mounted determines if a specified mountpoint has been mounted.
// On Linux it looks at /proc/self/mountinfo and on Solaris at mnttab.
func Mounted(mountpoint string) (bool, error) {
	entries, err := parseMountTable()
	if err != nil {
		return false, err
	}

	mountpoint, err = fileutils.ReadSymlinkedDirectory(mountpoint)
	if err != nil {
		return false, err
	}
	// Search the table for the mountpoint
	for _, e := range entries {
		if e.Mountpoint == mountpoint {
			return true, nil
		}
	}
	return false, nil
}

// Mount will mount filesystem according to the specified configuration, on the
// condition that the target path is *not* already mounted. Options must be
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
// flags.go for supported option flags.
func Mount(device, target, mType, options string) error {
	flag, _ := parseOptions(options)
	if flag&REMOUNT != REMOUNT {
		if mounted, err := Mounted(target); err != nil || mounted {
			return err
		}
	}
	return ForceMount(device, target, mType, options)
}

// ForceMount will mount a filesystem according to the specified configuration,
// *regardless* if the target path is not already mounted. Options must be
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
// flags.go for supported option flags.
func ForceMount(device, target, mType, options string) error {
	flag, data := parseOptions(options)
	if err := mount(device, target, mType, uintptr(flag), data); err != nil {
		return err
	}
	return nil
}

// Unmount will unmount the target filesystem, so long as it is mounted.
func Unmount(target string) error {
	if mounted, err := Mounted(target); err != nil || !mounted {
		return err
	}
	return ForceUnmount(target)
}

// ForceUnmount will force an unmount of the target filesystem, regardless if
// it is mounted or not.
func ForceUnmount(target string) (err error) {
	// Simple retry logic for unmount
	for i := 0; i < 10; i++ {
		if err = unmount(target, 0); err == nil {
			return nil
		}
		time.Sleep(100 * time.Millisecond)
	}
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"sync"
	"time"

	"camlistore.org/pkg/auth"
	"camlistore.org/pkg/blob"
	"camlistore.org/pkg/blobserver"
	"camlistore.org/pkg/buildinfo"
	"camlistore.org/pkg/env"
	"camlistore.org/pkg/images"
	"camlistore.org/pkg/jsonconfig"
	"camlistore.org/pkg/osutil"
	"camlistore.org/pkg/search"
)

// RootHandler handles serving the about/splash page.
type RootHandler struct {
	// Stealth determines whether we hide from non-authenticated
	// clients.
	Stealth bool

	OwnerName string // for display purposes only.
	Username  string // default user for mobile setup.

	// URL prefixes (path or full URL) to the primary blob and
	// search root.
	BlobRoot     string
	SearchRoot   string
	importerRoot string
	statusRoot   string
	Prefix       string // root handler's prefix

	Storage blobserver.Storage // of BlobRoot, or nil

	searchInitOnce sync.Once // runs searchInit, which populates searchHandler
	searchInit     func()
	searchHandler  *search.Handler // of SearchRoot, or nil

	ui   *UIHandler     // or nil, if none configured
	sync []*SyncHandler // list of configured sync handlers, for discovery.
}

func (rh *RootHandler) SearchHandler() (h *search.Handler, ok bool) {
	rh.searchInitOnce.Do(rh.searchInit)
	return rh.searchHandler, rh.searchHandler != nil
}

func init() {
	blobserver.RegisterHandlerConstructor("root", newRootFromConfig)
}

func newRootFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err error) {
	username, _ := getUserName()
	root := &RootHandler{
		BlobRoot:   conf.OptionalString("blobRoot", ""),
		SearchRoot: conf.OptionalString("searchRoot", ""),
		OwnerName:  conf.OptionalString("ownerName", username),
		Username:   osutil.Username(),
		Prefix:     ld.MyPrefix(),
	}
	root.Stealth = conf.OptionalBool("stealth", false)
	root.statusRoot = conf.OptionalString("statusRoot", "")
	if err = conf.Validate(); err != nil {
		return
	}

	if root.BlobRoot != "" {
		bs, err := ld.GetStorage(root.BlobRoot)
		if err != nil {
			return nil, fmt.Errorf("Root handler's blobRoot of %q error: %v", root.BlobRoot, err)
		}
		root.Storage = bs
	}

	root.searchInit = func() {}
	if root.SearchRoot != "" {
		prefix := root.SearchRoot
		if t := ld.GetHandlerType(prefix); t != "search" {
			if t == "" {
				return nil, fmt.Errorf("root handler's searchRoot of %q is invalid and doesn't refer to a declared handler", prefix)
			}
			return nil, fmt.Errorf("root handler's searchRoot of %q is of type %q, not %q", prefix, t, "search")
		}
		root.searchInit = func() {
			h, err := ld.GetHandler(prefix)
			if err != nil {
				log.Fatalf("Error fetching SearchRoot at %q: %v", prefix, err)
			}
			root.searchHandler = h.(*search.Handler)
			root.searchInit = nil
		}
	}

	if pfx, _, _ := ld.FindHandlerByType("importer"); err == nil {
		root.importerRoot = pfx
	}

	return root, nil
}

func (rh *RootHandler) registerUIHandler(h *UIHandler) {
	rh.ui = h
}

func (rh *RootHandler) registerSyncHandler(h *SyncHandler) {
	rh.sync = append(rh.sync, h)
	sort.Sort(byFromTo(rh.sync))
}

func (rh *RootHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if wantsDiscovery(req) {
		if auth.Allowed(req, auth.OpDiscovery) {
			rh.serveDiscovery(rw, req)
			return
		}
		if !rh.Stealth {
			http.Error(rw, "Unauthorized", http.StatusUnauthorized)
		}
		return
	}

	if rh.Stealth {
		return
	}
	if req.URL.Path == "/favicon.ico" {
		ServeStaticFile(rw, req, Files, "favicon.ico")
		return
	}
	f := func(p string, a ...interface{}) {
		fmt.Fprintf(rw, p, a...)
	}
	f("
This is camlistored (%s), a "+
		"Camlistore server.
", buildinfo.Version())
	if auth.IsLocalhost(req) && !env.IsDev() {
		f("
If you're coming from localhost, configure your Camlistore server at /setup.
")
	}
	if rh.ui != nil {
		f("
To manage your content, access the %s.
", rh.ui.prefix, rh.ui.prefix)
	}
	if rh.statusRoot != "" {
		f("
To view status, see %s", rh.statusRoot, rh.statusRoot)
	}
	fmt.Fprintf(rw, "")
}

type byFromTo []*SyncHandler

func (b byFromTo) Len() int      { return len(b) }
func (b byFromTo) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b byFromTo) Less(i, j int) bool {
	if b[i].fromName < b[j].fromName {
		return true
	}
	return b[i].fromName == b[j].fromName && b[i].toName < b[j].toName
}

func (rh *RootHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
	m := map[string]interface{}{
		"blobRoot":      rh.BlobRoot,
		"importerRoot":  rh.importerRoot,
		"searchRoot":    rh.SearchRoot,
		"ownerName":     rh.OwnerName,
		"username":      rh.Username,
		"statusRoot":    rh.statusRoot,
		"wsAuthToken":   auth.ProcessRandom(),
		"thumbVersion":  images.ThumbnailVersion(),
		"blobHashFuncs": blob.HashFuncs(),
	}
	if gener, ok := rh.Storage.(blobserver.Generationer); ok {
		initTime, gen, err := gener.StorageGeneration()
		if err != nil {
			m["storageGenerationError"] = err.Error()
		} else {
			m["storageInitTime"] = initTime.UTC().Format(time.RFC3339)
			m["storageGeneration"] = gen
		}
	} else {
		log.Printf("Storage type %T is not a blobserver.Generationer; not sending storageGeneration", rh.Storage)
	}
	if rh.ui != nil {
		rh.ui.populateDiscoveryMap(m)
	}
	if len(rh.sync) > 0 {
		var syncHandlers []map[string]interface{}
		for _, sh := range rh.sync {
			syncHandlers = append(syncHandlers, sh.discoveryMap())
		}
		m["syncHandlers"] = syncHandlers
	}
	discoveryHelper(rw, req, m)
}

func discoveryHelper(rw http.ResponseWriter, req *http.Request, m map[string]interface{}) {
	rw.Header().Set("Content-Type", "text/javascript")
	if cb := req.FormValue("cb"); identOrDotPattern.MatchString(cb) {
		fmt.Fprintf(rw, "%s(", cb)
		defer rw.Write([]byte(");\n"))
	} else if v := req.FormValue("var"); identOrDotPattern.MatchString(v) {
		fmt.Fprintf(rw, "%s = ", v)
		defer rw.Write([]byte(";\n"))
	}
	bytes, _ := json.MarshalIndent(m, "", "  ")
	rw.Write(bytes)
}
<commit_msg>pkg/server: redirect "/" to "/ui/"<commit_after>/*
Copyright 2011 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package server

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"sort"
	"sync"
	"time"

	"camlistore.org/pkg/auth"
	"camlistore.org/pkg/blob"
	"camlistore.org/pkg/blobserver"
	"camlistore.org/pkg/buildinfo"
	"camlistore.org/pkg/env"
	"camlistore.org/pkg/images"
	"camlistore.org/pkg/jsonconfig"
	"camlistore.org/pkg/osutil"
	"camlistore.org/pkg/search"
)

// RootHandler handles serving the about/splash page.
type RootHandler struct {
	// Stealth determines whether we hide from non-authenticated
	// clients.
	Stealth bool

	OwnerName string // for display purposes only.
	Username  string // default user for mobile setup.

	// URL prefixes (path or full URL) to the primary blob and
	// search root.
	BlobRoot     string
	SearchRoot   string
	importerRoot string
	statusRoot   string
	Prefix       string // root handler's prefix

	Storage blobserver.Storage // of BlobRoot, or nil

	searchInitOnce sync.Once // runs searchInit, which populates searchHandler
	searchInit     func()
	searchHandler  *search.Handler // of SearchRoot, or nil

	ui   *UIHandler     // or nil, if none configured
	sync []*SyncHandler // list of configured sync handlers, for discovery.
}

func (rh *RootHandler) SearchHandler() (h *search.Handler, ok bool) {
	rh.searchInitOnce.Do(rh.searchInit)
	return rh.searchHandler, rh.searchHandler != nil
}

func init() {
	blobserver.RegisterHandlerConstructor("root", newRootFromConfig)
}

func newRootFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, err error) {
	username, _ := getUserName()
	root := &RootHandler{
		BlobRoot:   conf.OptionalString("blobRoot", ""),
		SearchRoot: conf.OptionalString("searchRoot", ""),
		OwnerName:  conf.OptionalString("ownerName", username),
		Username:   osutil.Username(),
		Prefix:     ld.MyPrefix(),
	}
	root.Stealth = conf.OptionalBool("stealth", false)
	root.statusRoot = conf.OptionalString("statusRoot", "")
	if err = conf.Validate(); err != nil {
		return
	}

	if root.BlobRoot != "" {
		bs, err := ld.GetStorage(root.BlobRoot)
		if err != nil {
			return nil, fmt.Errorf("Root handler's blobRoot of %q error: %v", root.BlobRoot, err)
		}
		root.Storage = bs
	}

	root.searchInit = func() {}
	if root.SearchRoot != "" {
		prefix := root.SearchRoot
		if t := ld.GetHandlerType(prefix); t != "search" {
			if t == "" {
				return nil, fmt.Errorf("root handler's searchRoot of %q is invalid and doesn't refer to a declared handler", prefix)
			}
			return nil, fmt.Errorf("root handler's searchRoot of %q is of type %q, not %q", prefix, t, "search")
		}
		root.searchInit = func() {
			h, err := ld.GetHandler(prefix)
			if err != nil {
				log.Fatalf("Error fetching SearchRoot at %q: %v", prefix, err)
			}
			root.searchHandler = h.(*search.Handler)
			root.searchInit = nil
		}
	}

	if pfx, _, _ := ld.FindHandlerByType("importer"); err == nil {
		root.importerRoot = pfx
	}

	return root, nil
}

func (rh *RootHandler) registerUIHandler(h *UIHandler) {
	rh.ui = h
}

func (rh *RootHandler) registerSyncHandler(h *SyncHandler) {
	rh.sync = append(rh.sync, h)
	sort.Sort(byFromTo(rh.sync))
}

func (rh *RootHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	if wantsDiscovery(req) {
		if auth.Allowed(req, auth.OpDiscovery) {
			rh.serveDiscovery(rw, req)
			return
		}
		if !rh.Stealth {
			http.Error(rw, "Unauthorized", http.StatusUnauthorized)
		}
		return
	}

	if rh.Stealth {
		return
	}
	if req.RequestURI == "/" && rh.ui != nil {
		http.Redirect(rw, req, "/ui/", http.StatusMovedPermanently)
		return
	}
	if req.URL.Path == "/favicon.ico" {
		ServeStaticFile(rw, req, Files, "favicon.ico")
		return
	}
	f := func(p string, a ...interface{}) {
		fmt.Fprintf(rw, p, a...)
	}
	f("
This is camlistored (%s), a "+
		"Camlistore server.
", buildinfo.Version())
	if auth.IsLocalhost(req) && !env.IsDev() {
		f("
If you're coming from localhost, configure your Camlistore server at /setup.
")
	}
	if rh.ui != nil {
		f("
To manage your content, access the %s.
", rh.ui.prefix, rh.ui.prefix)
	}
	if rh.statusRoot != "" {
		f("
To view status, see %s", rh.statusRoot, rh.statusRoot)
	}
	fmt.Fprintf(rw, "")
}

type byFromTo []*SyncHandler

func (b byFromTo) Len() int      { return len(b) }
func (b byFromTo) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b byFromTo) Less(i, j int) bool {
	if b[i].fromName < b[j].fromName {
		return true
	}
	return b[i].fromName == b[j].fromName && b[i].toName < b[j].toName
}

func (rh *RootHandler) serveDiscovery(rw http.ResponseWriter, req *http.Request) {
	m := map[string]interface{}{
		"blobRoot":      rh.BlobRoot,
		"importerRoot":  rh.importerRoot,
		"searchRoot":    rh.SearchRoot,
		"ownerName":     rh.OwnerName,
		"username":      rh.Username,
		"statusRoot":    rh.statusRoot,
		"wsAuthToken":   auth.ProcessRandom(),
		"thumbVersion":  images.ThumbnailVersion(),
		"blobHashFuncs": blob.HashFuncs(),
	}
	if gener, ok := rh.Storage.(blobserver.Generationer); ok {
		initTime, gen, err := gener.StorageGeneration()
		if err != nil {
			m["storageGenerationError"] = err.Error()
		} else {
			m["storageInitTime"] = initTime.UTC().Format(time.RFC3339)
			m["storageGeneration"] = gen
		}
	} else {
		log.Printf("Storage type %T is not a blobserver.Generationer; not sending storageGeneration", rh.Storage)
	}
	if rh.ui != nil {
		rh.ui.populateDiscoveryMap(m)
	}
	if len(rh.sync) > 0 {
		var syncHandlers []map[string]interface{}
		for _, sh := range rh.sync {
			syncHandlers = append(syncHandlers, sh.discoveryMap())
		}
		m["syncHandlers"] = syncHandlers
	}
	discoveryHelper(rw, req, m)
}

func discoveryHelper(rw http.ResponseWriter, req *http.Request, m map[string]interface{}) {
	rw.Header().Set("Content-Type", "text/javascript")
	if cb := req.FormValue("cb"); identOrDotPattern.MatchString(cb) {
		fmt.Fprintf(rw, "%s(", cb)
		defer rw.Write([]byte(");\n"))
	} else if v := req.FormValue("var"); identOrDotPattern.MatchString(v) {
		fmt.Fprintf(rw, "%s = ", v)
		defer rw.Write([]byte(";\n"))
	}
	bytes, _ := json.MarshalIndent(m, "", "  ")
	rw.Write(bytes)
}
<|endoftext|>


<commit_before>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.21.18 Zinc 2018-04-06"
<commit_msg>Bump version: v0.22.0 Aluminium 2018-04-07<commit_after>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.22.0 Aluminium 2018-04-07"
<|endoftext|>


<commit_before>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.21.8 Zinc 2018-02-09"
<commit_msg>Bump version: v0.21.9 Zinc 2018-02-13<commit_after>package program

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.21.9 Zinc 2018-02-13"
<|endoftext|>


<commit_before>package libbusyna

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

// Create a Makefile file with db data read form the provided channel.
func DeployMake(c <-chan CmdData, outputfile string) {
	fd, err := ioutil.TempFile(filepath.Dir(outputfile), "Makefile-")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(fd.Name())

	// Header:
	fd.WriteString(fmt.Sprintf("# Automatically generated by busyna\n\n"))
	fd.WriteString(".PHONY: all clean\n\n")
	fd.WriteString("all:\n\n")

	// Rules:
	targets := map[string][]CmdData{}
	for cmddata := range c {
		for target0 := range cmddata.Targets {
			target := filepath.Join(cmddata.Cmd.Dir, target0)
			if tcmds, ok := targets[target]; ok {
				targets[target] = append(tcmds, cmddata)
			} else {
				targets[target] = []CmdData{cmddata}
			}
		}
	}
	for target, cmddatas := range targets {
		fd.WriteString(fmt.Sprintf("%s:", target))
		for _, cmddata := range cmddatas {
			for dep0 := range cmddata.Deps {
				dep := filepath.Join(cmddata.Cmd.Dir, dep0)
				if dep != target {
					fd.WriteString(fmt.Sprintf(" %s", dep))
				}
			}
		}
		for _, cmddata := range cmddatas {
			fd.WriteString("\n\t")
			if cmddata.Cmd.Dir != "." && cmddata.Cmd.Dir != "" {
				fd.WriteString(fmt.Sprintf("mkdir -p \"%s\"; cd \"%s\"; ", cmddata.Cmd.Dir, cmddata.Cmd.Dir))
			}
			fd.WriteString(cmddata.Cmd.Line)
		}
		fd.WriteString("\n\n")
	}

	// Fix "all" target, to depend on all targets:
	fd.WriteString("all:")
	for target := range targets {
		fd.WriteString(fmt.Sprintf(" %s", target))
	}
	fd.WriteString("\n\n")

	// Create the "clean" target:
	fd.WriteString("clean:\n\trm -f")
	for target := range targets {
		fd.WriteString(fmt.Sprintf(" '%s'", target))
	}
	fd.WriteString("\n\tfind . -depth -type d -exec rmdir {} \\; 2>/dev/null || true")
	fd.WriteString("\n\n")

	fd.Close()

	if err = os.Rename(fd.Name(), outputfile); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Force directory creation in deploymake<commit_after>package libbusyna

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

// Create a Makefile file with db data read form the provided channel.
func DeployMake(c <-chan CmdData, outputfile string) {
	fd, err := ioutil.TempFile(filepath.Dir(outputfile), "Makefile-")
	if err != nil {
		log.Fatal(err)
	}
	defer os.Remove(fd.Name())

	// Header:
	fd.WriteString(fmt.Sprintf("# Automatically generated by busyna\n\n"))
	fd.WriteString(".PHONY: all clean\n\n")
	fd.WriteString("all:\n\n")

	// Rules:
	targets := map[string][]CmdData{}
	for cmddata := range c {
		for target0 := range cmddata.Targets {
			target := filepath.Join(cmddata.Cmd.Dir, target0)
			if tcmds, ok := targets[target]; ok {
				targets[target] = append(tcmds, cmddata)
			} else {
				targets[target] = []CmdData{cmddata}
			}
		}
	}
	for target, cmddatas := range targets {
		fd.WriteString(fmt.Sprintf("%s:", target))
		for _, cmddata := range cmddatas {
			for dep0 := range cmddata.Deps {
				dep := filepath.Join(cmddata.Cmd.Dir, dep0)
				if dep != target {
					fd.WriteString(fmt.Sprintf(" %s", dep))
				}
			}
		}
		for _, cmddata := range cmddatas {
			fd.WriteString("\n\t")
			if cmddata.Cmd.Dir != "." && cmddata.Cmd.Dir != "" {
				fd.WriteString(fmt.Sprintf("mkdir -p \"%s\"; mkdir -p \"%s\"; cd \"%s\"; ", cmddata.Cmd.Dir, filepath.Dir(target), cmddata.Cmd.Dir))
			}
			fd.WriteString(cmddata.Cmd.Line)
		}
		fd.WriteString("\n\n")
	}

	// Fix "all" target, to depend on all targets:
	fd.WriteString("all:")
	for target := range targets {
		fd.WriteString(fmt.Sprintf(" %s", target))
	}
	fd.WriteString("\n\n")

	// Create the "clean" target:
	fd.WriteString("clean:\n\trm -f")
	for target := range targets {
		fd.WriteString(fmt.Sprintf(" '%s'", target))
	}
	fd.WriteString("\n\tfind . -depth -type d -exec rmdir {} \\; 2>/dev/null || true")
	fd.WriteString("\n\n")

	fd.Close()

	if err = os.Rename(fd.Name(), outputfile); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// +build ignore

// Copyright 2014 Andreas Koch. 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"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
)

// The main project namespace
const ProjectNamespace = "allmark.io"

// GOPATH environment variable name
const GOPATH = "GOPATH"

// GOBIN environment variable name
const GOBIN = "GOBIN"

var (

	// command line flags
	verboseFlagIsSet      = flag.Bool("v", false, "Verbose mode")
	fmtFlagIsSet          = flag.Bool("fmt", false, "Format the source files")
	testFlagIsSet         = flag.Bool("test", false, "Execute all tests (go test")
	installFlagIsSet      = flag.Bool("install", false, "Force rebuild of everything (go install -a)")
	crossCompileFlagIsSet = flag.Bool("crosscompile", false, "Cross-compile everything using docker (Won't work if you don't have docker installed)")
	dependenciesFlagIsSet = flag.Bool("dependencies", false, "List all third-party dependencies")
	versionFlagIsSet      = flag.Bool("version", false, "Get the current version number of the repository")

	// working directory
	root = getWorkingDirectory()

	// packages to build
	buildPackages = []string{
		fmt.Sprintf("%s/cmd/allmark", ProjectNamespace),
	}

	// a regular expression matching all non-standard go library packages (e.g. github.com/..., allmark.io/... )
	nonStandardPackagePattern = regexp.MustCompile(`^\w+[\.-].+/`)

	// The git version pattern.
	gitVersionPattern = regexp.MustCompile(`\b\d\d\d\d-\d\d-\d\d-[0-9a-f]{7,7}\b`)

	// A list of all supported compilation targets (e.g. "windows/386")
	compilationTargets = []compilationTarget{
		compilationTarget{"darwin", "386"},
		compilationTarget{"darwin", "amd64"},
		compilationTarget{"dragonfly", "386"},
		compilationTarget{"dragonfly", "amd64"},
		compilationTarget{"freebsd", "386"},
		compilationTarget{"freebsd", "amd64"},
		compilationTarget{"freebsd", "arm"},
		compilationTarget{"linux", "386"},
		compilationTarget{"linux", "amd64"},
		compilationTarget{"linux", "arm"},
		compilationTarget{"nacl", "386"},
		compilationTarget{"nacl", "amd64p32"},
		compilationTarget{"nacl", "arm"},
		compilationTarget{"netbsd", "386"},
		compilationTarget{"netbsd", "amd64"},
		compilationTarget{"netbsd", "arm"},
		compilationTarget{"openbsd", "386"},
		compilationTarget{"openbsd", "amd64"},
		compilationTarget{"solaris", "amd64"},
		compilationTarget{"windows", "386"},
		compilationTarget{"windows", "amd64"},
	}
)

// Compilation Target Definition
type compilationTarget struct {
	OperatingSystem string
	Architecture    string
}

func (target *compilationTarget) String() string {
	return fmt.Sprintf("%s/%s", target.OperatingSystem, target.Architecture)
}

func main() {
	log.SetFlags(0)
	flag.Parse()

	if *fmtFlagIsSet {
		format()
		return
	}

	if *testFlagIsSet {
		executeTests()
		return
	}

	if *installFlagIsSet {
		install()
		return
	}

	if *crossCompileFlagIsSet {
		crossCompile()
		return
	}

	if *dependenciesFlagIsSet {
		listDependencies()
		return
	}

	if *versionFlagIsSet {
		printProjectVersionNumber()
		return
	}

	flag.PrintDefaults()
}

// Install all parts of allmark using go install.
func install() {

	for _, buildPackagage := range buildPackages {
		runCommand(os.Stdout, os.Stderr, root, "go", "install", buildPackagage)
	}

}

// Cross-compile all parts of allmark for all supported platforms.
func crossCompile() {

	// iterate over all supported compilation targets
	for _, target := range compilationTargets {

		// iterate over all build packages
		for _, buildPackagage := range buildPackages {

			// assemble the build command
			command, args := getCrossCompilationCommand(buildPackagage, target.OperatingSystem, target.Architecture)

			// build the package for the specified os and arch
			fmt.Printf("Compiling %s for %s\n", buildPackagage, target.String())
			runCommand(os.Stdout, os.Stderr, root, command, args...)
		}
	}

}

// Execute all test in the current project.
func executeTests() {
	packages := getPackagesWithTests()

	for index, packageName := range packages {

		fmt.Printf("Testing package %02d of %v: %s\n", index+1, len(packages), packageName)
		runCommand(os.Stdout, os.Stderr, root, "go", "test", packageName)
	}
}

// Format all packages of allmark using go fmt.
func format() {
	packages := getInternalPackages()

	for index, packageName := range packages {

		fmt.Printf("Formatting package %02d of %v: %s\n", index+1, len(packages), packageName)
		runCommand(os.Stdout, os.Stderr, root, "go", "fmt", packageName)

	}
}

// List all third-party packages that allmark depends on.
func listDependencies() {
	thirdPartyPackages := getThirdPartyPackages()

	for _, dependency := range thirdPartyPackages {
		fmt.Println(dependency)
	}
}

// Print the current version number of the project.
func printProjectVersionNumber() {
	fmt.Println(gitVersion())
}

// Get all packages which tests in them.
func getPackagesWithTests() []string {
	isInternalPackageWithTests := func(packageName string) bool {
		isInternalPackage := strings.HasPrefix(packageName, ProjectNamespace)
		if !isInternalPackage {
			return false
		}

		return packageHasTests(packageName)
	}

	internalPackagesWithTests := getAllNonStandardLibraryPackages(isInternalPackageWithTests)
	return internalPackagesWithTests
}

// Get all internal packages used in this project.
func getInternalPackages() []string {

	isInternalPackage := func(packageName string) bool {
		return strings.HasPrefix(packageName, ProjectNamespace)
	}

	internalPackages := getAllNonStandardLibraryPackages(isInternalPackage)
	return internalPackages
}

// Get all third party packages used in this project.
func getThirdPartyPackages() []string {

	isThirdPartyPackage := func(packageName string) bool {
		return !strings.HasPrefix(packageName, ProjectNamespace)
	}

	thirdPartyPackages := getAllNonStandardLibraryPackages(isThirdPartyPackage)
	return thirdPartyPackages
}

// Get a sorted and unique list of all non-standard library packages used in this project that meet the supplied expression.
func getAllNonStandardLibraryPackages(inclusionExpression func(packageName string) bool) []string {

	// get all dependent packages (will include duplicates and standard library packages)
	allDependentPackages := make([]string, 0)
	for _, buildPackage := range buildPackages {
		output := new(bytes.Buffer)
		errors := new(bytes.Buffer)
		runCommand(output, errors, root, "go", "list", "- f", `'{{ join .Deps ","}}'`, buildPackage)

		allDependentPackages = append(allDependentPackages, strings.Split(output.String(), ",")...)
	}

	// sort the list
	sort.Strings(allDependentPackages)

	// unique
	packages := make([]string, 0)
	uniquePackages := make(map[string]int)

	for _, dep := range allDependentPackages {

		// skip packages we have already seen
		if _, exists := uniquePackages[dep]; exists {

			// increment
			uniquePackages[dep] = uniquePackages[dep] + 1
			continue
		}

		// skip standard library packages
		if isStandardLibraryPackage(dep) {
			continue
		}

		// skip all packages that don't meet the expression
		if !inclusionExpression(dep) {
			continue
		}

		packages = append(packages, dep)
		uniquePackages[dep] = uniquePackages[dep] + 1
	}

	return packages

}

// Check if the supplied package name is a standard library package.
func isStandardLibraryPackage(packageName string) bool {
	return nonStandardPackagePattern.MatchString(packageName) == false
}

// Check whether the package with the supplied name has tests or not.
func packageHasTests(packageName string) bool {
	packagePath := getPackagePathByName(packageName)
	testFilePattern := filepath.Join(packagePath, "*_test.go")
	matches, err := filepath.Glob(testFilePattern)
	if err != nil {
		log.Fatalf("Unable to find test files in %q. Error: %s", testFilePattern, err.Error())
	}

	packageContainsTestFiles := len(matches) > 0
	return packageContainsTestFiles
}

// Get the path of package from its name.
func getPackagePathByName(packageName string) string {
	packagePath := strings.Join(strings.Split(packageName, "/"), string(os.PathSeparator))
	return filepath.Join(root, "src", packagePath)
}

// getWorkingDirectory returns the current working directory path or fails.
func getWorkingDirectory() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get current directory: %v", err)
	}

	return root
}

// Execute go in the specified go path with the supplied command arguments.
func runCommand(stdout, stderr io.Writer, workingDirectory string, command string, args ...string) {

	commandName := command
	cmdName := fmt.Sprintf("%s %s", commandName, strings.Join(args, " "))

	// set the go path
	cmd := exec.Command(commandName, args...)
	cmd.Dir = workingDirectory

	cmd.Env = cleanGoEnv()
	cmd.Env = setEnv(cmd.Env, GOPATH, root)
	cmd.Env = setEnv(cmd.Env, GOBIN, filepath.Join(root, "bin"))

	// execute the command
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	if *verboseFlagIsSet {
		log.Printf("Running %s", cmdName)
	}

	err := cmd.Run()
	if err != nil {
		log.Fatalf("Error running %s: %v", cmdName, err)
	}
}

// cleanGoEnv returns a copy of the current environment with GOPATH and GOBIN removed.
func cleanGoEnv() (clean []string) {
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, GOPATH+"=") || strings.HasPrefix(env, GOBIN+"=") {
			continue
		}

		clean = append(clean, env)
	}

	return
}

// setEnv sets the given key & value in the provided environment.
// Each value in the env list should be of the form key=value.
func setEnv(env []string, key, value string) []string {
	for i, s := range env {
		if strings.HasPrefix(s, fmt.Sprintf("%s=", key)) {
			env[i] = envPair(key, value)
			return env
		}
	}
	env = append(env, envPair(key, value))
	return env
}

// Create an environment variable of the form key=value.
func envPair(key, value string) string {
	return fmt.Sprintf("%s=%s", key, value)
}

// gitVersion returns the git version of the git repo at root as a
// string of the form "yyyy-mm-dd-xxxxxxx", with an optional trailing
// '+' if there are any local uncomitted modifications to the tree.
func gitVersion() string {
	cmd := exec.Command("git", "rev-list", "--max-count=1", "--pretty=format:'%ad-%h'", "--date=short", "HEAD")
	cmd.Dir = root

	commandOutput, err := cmd.Output()
	if err != nil {
		log.Fatalf("Error running git rev-list in %s: %v", root, err)
	}

	versionNumber := strings.TrimSpace(string(commandOutput))
	if m := gitVersionPattern.FindStringSubmatch(versionNumber); m != nil {
		versionNumber = m[0]
	} else {
		log.Fatalf("Failed to find git version in string %q", versionNumber)
	}

	cmd = exec.Command("git", "diff", "--exit-code")
	cmd.Dir = root
	if err := cmd.Run(); err != nil {
		versionNumber += "+"
	}

	return versionNumber
}

// Get the command for cross-compiling the specified package for the desired operating system and architecture.
func getCrossCompilationCommand(packageName, os, arch string) (command string, args []string) {
	dockerImageName := "golang:1.4-cross"
	projectPathInDocker := "/usr/src/allmark"
	binPath := filepath.Join(projectPathInDocker, "bin")

	command = `docker`
	args = []string{
		"run",
		"--rm",
		"-v=" + fmt.Sprintf(`%s:%s`, root, projectPathInDocker),
		`-w=` + projectPathInDocker,
		"-e=" + "GOOS=" + os,
		"-e=" + "GOARCH=" + arch,
		"-e=" + fmt.Sprintf(`GOPATH=%s`, projectPathInDocker),
		"-e=" + fmt.Sprintf(`GOBIN=%s`, binPath),
		dockerImageName,
		"go",
		"install",
		packageName,
	}

	return command, args
}
<commit_msg>Make: Implemented a command for updating all dependencies<commit_after>// +build ignore

// Copyright 2014 Andreas Koch. 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"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
)

// The main project namespace
const ProjectNamespace = "allmark.io"

// GOPATH environment variable name
const GOPATH = "GOPATH"

// GOBIN environment variable name
const GOBIN = "GOBIN"

var (

	// command line flags
	verboseFlagIsSet            = flag.Bool("v", false, "Verbose mode")
	fmtFlagIsSet                = flag.Bool("fmt", false, "Format the source files")
	testFlagIsSet               = flag.Bool("test", false, "Execute all tests (go test")
	installFlagIsSet            = flag.Bool("install", false, "Force rebuild of everything (go install -a)")
	crossCompileFlagIsSet       = flag.Bool("crosscompile", false, "Cross-compile everything using docker (Won't work if you don't have docker installed)")
	listDependenciesFlagIsSet   = flag.Bool("list-dependencies", false, "List all third-party dependencies")
	updateDependenciesFlagIsSet = flag.Bool("update-dependencies", false, "Update all third-party dependencies")
	versionFlagIsSet            = flag.Bool("version", false, "Get the current version number of the repository")

	// working directory
	root = getWorkingDirectory()

	// packages to build
	buildPackages = []string{
		fmt.Sprintf("%s/cmd/allmark", ProjectNamespace),
	}

	// a regular expression matching all non-standard go library packages (e.g. github.com/..., allmark.io/... )
	nonStandardPackagePattern = regexp.MustCompile(`^\w+[\.-].+/`)

	// The git version pattern.
	gitVersionPattern = regexp.MustCompile(`\b\d\d\d\d-\d\d-\d\d-[0-9a-f]{7,7}\b`)

	// A list of all supported compilation targets (e.g. "windows/386")
	compilationTargets = []compilationTarget{
		compilationTarget{"darwin", "386"},
		compilationTarget{"darwin", "amd64"},
		compilationTarget{"dragonfly", "386"},
		compilationTarget{"dragonfly", "amd64"},
		compilationTarget{"freebsd", "386"},
		compilationTarget{"freebsd", "amd64"},
		compilationTarget{"freebsd", "arm"},
		compilationTarget{"linux", "386"},
		compilationTarget{"linux", "amd64"},
		compilationTarget{"linux", "arm"},
		compilationTarget{"nacl", "386"},
		compilationTarget{"nacl", "amd64p32"},
		compilationTarget{"nacl", "arm"},
		compilationTarget{"netbsd", "386"},
		compilationTarget{"netbsd", "amd64"},
		compilationTarget{"netbsd", "arm"},
		compilationTarget{"openbsd", "386"},
		compilationTarget{"openbsd", "amd64"},
		compilationTarget{"solaris", "amd64"},
		compilationTarget{"windows", "386"},
		compilationTarget{"windows", "amd64"},
	}
)

// Compilation Target Definition
type compilationTarget struct {
	OperatingSystem string
	Architecture    string
}

func (target *compilationTarget) String() string {
	return fmt.Sprintf("%s/%s", target.OperatingSystem, target.Architecture)
}

func main() {
	log.SetFlags(0)
	flag.Parse()

	if *fmtFlagIsSet {
		format()
		return
	}

	if *testFlagIsSet {
		executeTests()
		return
	}

	if *installFlagIsSet {
		install()
		return
	}

	if *crossCompileFlagIsSet {
		crossCompile()
		return
	}

	if *listDependenciesFlagIsSet {
		listDependencies()
		return
	}

	if *updateDependenciesFlagIsSet {
		updateDependencies()
		return
	}

	if *versionFlagIsSet {
		printProjectVersionNumber()
		return
	}

	flag.PrintDefaults()
}

// Install all parts of allmark using go install.
func install() {

	for _, buildPackagage := range buildPackages {
		runCommand(os.Stdout, os.Stderr, root, "go", "install", buildPackagage)
	}

}

// Cross-compile all parts of allmark for all supported platforms.
func crossCompile() {

	// iterate over all supported compilation targets
	for _, target := range compilationTargets {

		// iterate over all build packages
		for _, buildPackagage := range buildPackages {

			// assemble the build command
			command, args := getCrossCompilationCommand(buildPackagage, target.OperatingSystem, target.Architecture)

			// build the package for the specified os and arch
			fmt.Printf("Compiling %s for %s\n", buildPackagage, target.String())
			runCommand(os.Stdout, os.Stderr, root, command, args...)
		}
	}

}

// Execute all test in the current project.
func executeTests() {
	packages := getPackagesWithTests()

	for index, packageName := range packages {

		fmt.Printf("Testing package %02d of %v: %s\n", index+1, len(packages), packageName)
		runCommand(os.Stdout, os.Stderr, root, "go", "test", packageName)
	}
}

// Format all packages of allmark using go fmt.
func format() {
	packages := getInternalPackages()

	for index, packageName := range packages {

		fmt.Printf("Formatting package %02d of %v: %s\n", index+1, len(packages), packageName)
		runCommand(os.Stdout, os.Stderr, root, "go", "fmt", packageName)

	}
}

// List all third-party packages that allmark depends on.
func listDependencies() {
	thirdPartyPackages := getThirdPartyPackages()

	for _, dependency := range thirdPartyPackages {
		fmt.Println(dependency)
	}
}

// Update all third-party packages that allmark depends on.
func updateDependencies() {
	thirdPartyPackages := getThirdPartyPackages()

	for index, dependency := range thirdPartyPackages {

		fmt.Printf("Updating package %02d of %v: %s\n", index+1, len(thirdPartyPackages), dependency)
		runCommand(os.Stdout, os.Stderr, root, "go", "get", dependency)

	}
}

// Print the current version number of the project.
func printProjectVersionNumber() {
	fmt.Println(gitVersion())
}

// Get all packages which tests in them.
func getPackagesWithTests() []string {
	isInternalPackageWithTests := func(packageName string) bool {
		isInternalPackage := strings.HasPrefix(packageName, ProjectNamespace)
		if !isInternalPackage {
			return false
		}

		return packageHasTests(packageName)
	}

	internalPackagesWithTests := getAllNonStandardLibraryPackages(isInternalPackageWithTests)
	return internalPackagesWithTests
}

// Get all internal packages used in this project.
func getInternalPackages() []string {

	isInternalPackage := func(packageName string) bool {
		return strings.HasPrefix(packageName, ProjectNamespace)
	}

	internalPackages := getAllNonStandardLibraryPackages(isInternalPackage)
	return internalPackages
}

// Get all third party packages used in this project.
func getThirdPartyPackages() []string {

	isThirdPartyPackage := func(packageName string) bool {
		return !strings.HasPrefix(packageName, ProjectNamespace)
	}

	thirdPartyPackages := getAllNonStandardLibraryPackages(isThirdPartyPackage)
	return thirdPartyPackages
}

// Get a sorted and unique list of all non-standard library packages used in this project that meet the supplied expression.
func getAllNonStandardLibraryPackages(inclusionExpression func(packageName string) bool) []string {

	// get all dependent packages (will include duplicates and standard library packages)
	allDependentPackages := make([]string, 0)
	for _, buildPackage := range buildPackages {
		output := new(bytes.Buffer)
		errors := new(bytes.Buffer)
		runCommand(output, errors, root, "go", "list", "-f", `'{{ join .Deps ","}}'`, buildPackage)

		allDependentPackages = append(allDependentPackages, strings.Split(output.String(), ",")...)
	}

	// sort the list
	sort.Strings(allDependentPackages)

	// unique
	packages := make([]string, 0)
	uniquePackages := make(map[string]int)

	for _, dep := range allDependentPackages {

		// skip packages we have already seen
		if _, exists := uniquePackages[dep]; exists {

			// increment
			uniquePackages[dep] = uniquePackages[dep] + 1
			continue
		}

		// skip standard library packages
		if isStandardLibraryPackage(dep) {
			continue
		}

		// skip all packages that don't meet the expression
		if !inclusionExpression(dep) {
			continue
		}

		packages = append(packages, dep)
		uniquePackages[dep] = uniquePackages[dep] + 1
	}

	return packages

}

// Check if the supplied package name is a standard library package.
func isStandardLibraryPackage(packageName string) bool {
	return nonStandardPackagePattern.MatchString(packageName) == false
}

// Check whether the package with the supplied name has tests or not.
func packageHasTests(packageName string) bool {
	packagePath := getPackagePathByName(packageName)
	testFilePattern := filepath.Join(packagePath, "*_test.go")
	matches, err := filepath.Glob(testFilePattern)
	if err != nil {
		log.Fatalf("Unable to find test files in %q. Error: %s", testFilePattern, err.Error())
	}

	packageContainsTestFiles := len(matches) > 0
	return packageContainsTestFiles
}

// Get the path of package from its name.
func getPackagePathByName(packageName string) string {
	packagePath := strings.Join(strings.Split(packageName, "/"), string(os.PathSeparator))
	return filepath.Join(root, "src", packagePath)
}

// getWorkingDirectory returns the current working directory path or fails.
func getWorkingDirectory() string {
	root, err := os.Getwd()
	if err != nil {
		log.Fatalf("Failed to get current directory: %v", err)
	}

	return root
}

// Execute go in the specified go path with the supplied command arguments.
func runCommand(stdout, stderr io.Writer, workingDirectory string, command string, args ...string) {

	commandName := command
	cmdName := fmt.Sprintf("%s %s", commandName, strings.Join(args, " "))

	// set the go path
	cmd := exec.Command(commandName, args...)
	cmd.Dir = workingDirectory

	cmd.Env = cleanGoEnv()
	cmd.Env = setEnv(cmd.Env, GOPATH, root)
	cmd.Env = setEnv(cmd.Env, GOBIN, filepath.Join(root, "bin"))

	// execute the command
	cmd.Stdout = stdout
	cmd.Stderr = stderr

	if *verboseFlagIsSet {
		log.Printf("Running %s", cmdName)
	}

	err := cmd.Run()
	if err != nil {
		log.Fatalf("Error running %s: %v", cmdName, err)
	}
}

// cleanGoEnv returns a copy of the current environment with GOPATH and GOBIN removed.
func cleanGoEnv() (clean []string) {
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, GOPATH+"=") || strings.HasPrefix(env, GOBIN+"=") {
			continue
		}

		clean = append(clean, env)
	}

	return
}

// setEnv sets the given key & value in the provided environment.
// Each value in the env list should be of the form key=value.
func setEnv(env []string, key, value string) []string {
	for i, s := range env {
		if strings.HasPrefix(s, fmt.Sprintf("%s=", key)) {
			env[i] = envPair(key, value)
			return env
		}
	}
	env = append(env, envPair(key, value))
	return env
}

// Create an environment variable of the form key=value.
func envPair(key, value string) string {
	return fmt.Sprintf("%s=%s", key, value)
}

// gitVersion returns the git version of the git repo at root as a
// string of the form "yyyy-mm-dd-xxxxxxx", with an optional trailing
// '+' if there are any local uncomitted modifications to the tree.
func gitVersion() string {
	cmd := exec.Command("git", "rev-list", "--max-count=1", "--pretty=format:'%ad-%h'", "--date=short", "HEAD")
	cmd.Dir = root

	commandOutput, err := cmd.Output()
	if err != nil {
		log.Fatalf("Error running git rev-list in %s: %v", root, err)
	}

	versionNumber := strings.TrimSpace(string(commandOutput))
	if m := gitVersionPattern.FindStringSubmatch(versionNumber); m != nil {
		versionNumber = m[0]
	} else {
		log.Fatalf("Failed to find git version in string %q", versionNumber)
	}

	cmd = exec.Command("git", "diff", "--exit-code")
	cmd.Dir = root
	if err := cmd.Run(); err != nil {
		versionNumber += "+"
	}

	return versionNumber
}

// Get the command for cross-compiling the specified package for the desired operating system and architecture.
func getCrossCompilationCommand(packageName, os, arch string) (command string, args []string) {
	dockerImageName := "golang:1.4-cross"
	projectPathInDocker := "/usr/src/allmark"
	binPath := filepath.Join(projectPathInDocker, "bin")

	command = `docker`
	args = []string{
		"run",
		"--rm",
		"-v=" + fmt.Sprintf(`%s:%s`, root, projectPathInDocker),
		`-w=` + projectPathInDocker,
		"-e=" + "GOOS=" + os,
		"-e=" + "GOARCH=" + arch,
		"-e=" + fmt.Sprintf(`GOPATH=%s`, projectPathInDocker),
		"-e=" + fmt.Sprintf(`GOBIN=%s`, binPath),
		dockerImageName,
		"go",
		"install",
		packageName,
	}

	return command, args
}
<|endoftext|>


<commit_before>package vix

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"github.com/c4milo/unzipit"
	"github.com/dustin/go-humanize"
	govix "github.com/hooklift/govix"
)

// Virtual machine configuration
type VM struct {
	// Which VMware VIX service provider to use. ie: fusion, workstation, server, etc
	Provider string
	// Whether to verify SSL or not for remote connections in ESXi
	VerifySSL bool
	// Name of the virtual machine
	Name string
	// Description for the virtual machine, it is created as an annotation in
	// VMware.
	Description string
	// Image to use during the creation of this virtual machine
	Image Image
	// Number of virtual cpus
	CPUs uint
	// Memory size in megabytes.
	Memory string
	// Switches to where this machine is going to be attach to
	VSwitches []string
	// Whether to upgrade the VM virtual hardware
	UpgradeVHardware bool
	// The timeout to wait for VMware Tools to be initialized inside the VM
	ToolsInitTimeout time.Duration
	// Whether to launch the VM with graphical environment
	LaunchGUI bool
	// Whether to enable or disable shared folders for this VM
	SharedFolders bool
	// Network adapters
	VNetworkAdapters []*govix.NetworkAdapter
	// CD/DVD drives
	CDDVDDrives []*govix.CDDVDDrive
	// VM IP address as reported by VIX
	IPAddress string
}

// Creates VIX instance with VMware
func (v *VM) client() (*govix.Host, error) {
	var p govix.Provider

	switch strings.ToLower(v.Provider) {
	case "fusion", "workstation":
		p = govix.VMWARE_WORKSTATION
	case "serverv1":
		p = govix.VMWARE_SERVER
	case "serverv2":
		p = govix.VMWARE_VI_SERVER
	case "player":
		p = govix.VMWARE_PLAYER
	case "workstation_shared":
		p = govix.VMWARE_WORKSTATION_SHARED
	default:
		p = govix.VMWARE_WORKSTATION
	}

	var options govix.HostOption
	if v.VerifySSL {
		options = govix.VERIFY_SSL_CERT
	}

	host, err := govix.Connect(govix.ConnectConfig{
		Provider: p,
		Options:  options,
	})

	if err != nil {
		return nil, err
	}

	log.Printf("[INFO] VIX client configured for product: VMware %s. SSL: %t", v.Provider, v.VerifySSL)

	return host, nil
}

// Sets default values for VM attributes
func (v *VM) SetDefaults() {
	if v.CPUs <= 0 {
		v.CPUs = 2
	}

	if v.Memory == "" {
		v.Memory = "512mib"
	}

	if v.Description == "" {
		v.Description = "Machine was created using Terraform VIX provider"
	}

	if v.ToolsInitTimeout.Seconds() <= 0 {
		v.ToolsInitTimeout = time.Duration(30) * time.Second
	}
}

// Downloads, extracts and opens Gold virtual machine, then it creates a clone
// out of it.
func (v *VM) Create() (string, error) {
	log.Printf("[DEBUG] Creating VM resource...")

	usr, err := user.Current()
	if err != nil {
		return "", err
	}

	image := v.Image
	goldPath := filepath.Join(usr.HomeDir, filepath.Join(".terraform/vix/gold", image.Checksum))
	_, err = os.Stat(goldPath)
	finfo, _ := ioutil.ReadDir(goldPath)
	goldPathEmpty := len(finfo) == 0

	if os.IsNotExist(err) || goldPathEmpty {
		log.Println("[DEBUG] Gold virtual machine does not exist or is empty")

		imgPath := filepath.Join(usr.HomeDir, ".terraform/vix/images", image.Checksum)
		if err = image.Download(imgPath); err != nil {
			return "", err
		}
		defer image.file.Close()

		log.Printf("[DEBUG] Unpacking Gold virtual machine into %s\n", goldPath)
		_, err = unzipit.Unpack(image.file, goldPath)
		if err != nil {
			return "", err
		}
	}

	pattern := filepath.Join(goldPath, "**.vmx")

	log.Printf("[DEBUG] Finding Gold virtual machine vmx file in %s", pattern)
	files, _ := filepath.Glob(pattern)

	if len(files) == 0 {
		return "", fmt.Errorf("[ERROR] vmx file was not found: %s", pattern)
	}

	vmxFile := files[0]
	log.Printf("[DEBUG] Gold virtual machine vmx file found %v", vmxFile)

	// Gets VIX instance
	client, err := v.client()
	if err != nil {
		return "", err
	}
	defer client.Disconnect()

	log.Printf("[INFO] Opening Gold virtual machine from %s", vmxFile)

	vm, err := client.OpenVm(vmxFile, v.Image.Password)

	if err != nil {
		return "", err
	}

	baseVMDir := filepath.Join(usr.HomeDir, ".terraform", "vix", "vms",
		image.Checksum, v.Name)

	newvmx := filepath.Join(baseVMDir, v.Name+".vmx")

	if _, err = os.Stat(newvmx); os.IsNotExist(err) {
		log.Printf("[INFO] Virtual machine clone not found: %s, err: %+v", newvmx, err)
		// If there is not a VMX file, make sure nothing else is in there either.
		// We were seeing VIX 13004 errors when only a nvram file existed.
		os.RemoveAll(baseVMDir)

		log.Printf("[INFO] Cloning Gold virtual machine into %s...", newvmx)
		_, err := vm.Clone(govix.CLONETYPE_FULL, newvmx)

		// If there is an error and the error is other than "The snapshot already exists"
		// then return the error
		if err != nil && err.(*govix.VixError).Code != 13004 {
			return "", err
		}
	} else {
		log.Printf("[INFO] Virtual Machine clone %s already exist, moving on.", newvmx)
	}

	if err = v.Update(newvmx); err != nil {
		return "", err
	}

	return newvmx, nil
}

// Opens and updates virtual machine resource
func (v *VM) Update(vmxFile string) error {
	// Sets default values if some attributes were not set or have
	// invalid values
	v.SetDefaults()

	// Gets VIX instance
	client, err := v.client()
	if err != nil {
		return err
	}
	defer client.Disconnect()

	if client.Provider == govix.VMWARE_VI_SERVER ||
		client.Provider == govix.VMWARE_SERVER {
		log.Printf("[INFO] Registering VM in host's inventory...")
		err = client.RegisterVm(vmxFile)
		if err != nil {
			return err
		}
	}

	log.Printf("[INFO] Opening virtual machine from %s", vmxFile)

	vm, err := client.OpenVm(vmxFile, v.Image.Password)
	if err != nil {
		return err
	}

	running, err := vm.IsRunning()
	if err != nil {
		return err
	}

	if running {
		log.Printf("[INFO] Virtual machine seems to be running, we need to " +
			"power it off in order to make changes.")
		err = v.powerOff(vm)
		if err != nil {
			return err
		}
	}

	memoryInMb, err := humanize.ParseBytes(v.Memory)
	if err != nil {
		log.Printf("[WARN] Unable to set memory size, defaulting to 512mib: %s", err)
		memoryInMb = 512
	} else {
		memoryInMb = (memoryInMb / 1024) / 1024
	}

	log.Printf("[DEBUG] Setting memory size to %d megabytes", memoryInMb)
	vm.SetMemorySize(uint(memoryInMb))

	log.Printf("[DEBUG] Setting vcpus to %d", v.CPUs)
	vm.SetNumberVcpus(v.CPUs)

	log.Printf("[DEBUG] Setting name to %s", v.Name)
	vm.SetDisplayName(v.Name)

	log.Printf("[DEBUG] Setting description to %s", v.Description)
	vm.SetAnnotation(v.Description)

	if v.UpgradeVHardware &&
		client.Provider != govix.VMWARE_PLAYER {

		log.Println("[INFO] Upgrading virtual hardware...")
		err = vm.UpgradeVHardware()
		if err != nil {
			return err
		}
	}

	log.Printf("[DEBUG] Removing all network adapters from vmx file...")
	err = vm.RemoveAllNetworkAdapters()
	if err != nil {
		return err
	}

	log.Println("[INFO] Attaching virtual network adapters...")
	for _, adapter := range v.VNetworkAdapters {
		adapter.StartConnected = true
		if adapter.ConnType == govix.NETWORK_BRIDGED {
			adapter.LinkStatePropagation = true
		}

		log.Printf("[DEBUG] Adapter: %+v", adapter)
		err := vm.AddNetworkAdapter(adapter)
		if err != nil {
			return err
		}
	}

	log.Printf("[DEBUG] Removing all CD/DVD drives from vmx file...")
	err = vm.RemoveAllCDDVDDrives()
	if err != nil {
		return err
	}

	log.Println("[INFO] Attaching CD/DVD drives... ")
	for _, cdrom := range v.CDDVDDrives {
		err := vm.AttachCDDVD(cdrom)
		if err != nil {
			return err
		}
	}

	log.Println("[INFO] Powering virtual machine on...")
	var options govix.VMPowerOption

	if v.LaunchGUI {
		log.Println("[INFO] Preparing to launch GUI...")
		options |= govix.VMPOWEROP_LAUNCH_GUI
	}

	options |= govix.VMPOWEROP_NORMAL

	err = vm.PowerOn(options)
	if err != nil {
		return err
	}

	log.Println("[INFO] Waiting for VMware Tools to initialize...")
	err = vm.WaitForToolsInGuest(v.ToolsInitTimeout)
	if err != nil {
		log.Println("[WARN] VMware Tools took too long to initialize or is not " +
			"installed.")

		if v.SharedFolders {
			log.Println("[WARN] Enabling shared folders is not possible.")
		}
		return nil
	}

	if v.SharedFolders {
		log.Println("[DEBUG] Enabling shared folders...")

		err = vm.EnableSharedFolders(v.SharedFolders)
		if err != nil {
			return err
		}
	}
	return nil
}

// Powers off a virtual machine attempting a graceful shutdown.
func (v *VM) powerOff(vm *govix.VM) error {
	tstate, err := vm.ToolsState()
	if err != nil {
		return err
	}

	var powerOpts govix.VMPowerOption
	log.Printf("Tools state %d", tstate)

	if (tstate & govix.TOOLSSTATE_RUNNING) != 0 {
		log.Printf("[INFO] VMware Tools is running, attempting a graceful shutdown...")
		// if VMware Tools is running, attempt a graceful shutdown.
		powerOpts |= govix.VMPOWEROP_FROM_GUEST
	} else {
		log.Printf("[INFO] VMware Tools is NOT running, shutting down the " +
			"machine abruptly...")
		powerOpts |= govix.VMPOWEROP_NORMAL
	}

	err = vm.PowerOff(powerOpts)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Virtual machine is off.")

	return nil
}

// Destroys a virtual machine resource
func (v *VM) Destroy(vmxFile string) error {
	log.Printf("[DEBUG] Destroying VM resource %s...", vmxFile)

	client, err := v.client()
	if err != nil {
		return err
	}
	defer client.Disconnect()

	vm, err := client.OpenVm(vmxFile, v.Image.Password)
	if err != nil {
		return err
	}

	running, err := vm.IsRunning()
	if err != nil {
		return err
	}

	if running {
		if err = v.powerOff(vm); err != nil {
			return err
		}
	}

	if client.Provider == govix.VMWARE_VI_SERVER ||
		client.Provider == govix.VMWARE_SERVER {
		log.Printf("[INFO] Unregistering VM from host's inventory...")

		err := client.UnregisterVm(vmxFile)
		if err != nil {
			return err
		}
	}

	return vm.Delete(govix.VMDELETE_KEEP_FILES | govix.VMDELETE_FORCE)
}

// Refreshes state with VMware
func (v *VM) Refresh(vmxFile string) (bool, error) {
	log.Printf("[DEBUG] Syncing VM resource %s...", vmxFile)

	client, err := v.client()
	if err != nil {
		return false, err
	}
	defer client.Disconnect()

	vm, err := client.OpenVm(vmxFile, v.Image.Password)
	if err != nil {
		return false, err
	}

	running, err := vm.IsRunning()
	if !running {
		return running, err
	}

	vcpus, err := vm.Vcpus()
	if err != nil {
		return running, err
	}

	memory, err := vm.MemorySize()
	if err != nil {
		return running, err
	}

	// We need to convert memory value to megabytes so humanize can interpret it
	// properly.
	memory = (memory * 1024) * 1024
	v.Memory = strings.ToLower(humanize.IBytes(uint64(memory)))
	v.CPUs = uint(vcpus)
	v.Name, err = vm.DisplayName()
	v.Description, err = vm.Annotation()
	v.VNetworkAdapters, err = vm.NetworkAdapters()
	v.IPAddress, err = vm.IPAddress()

	return running, err
}
<commit_msg>Gets code up to date wth GoVIX<commit_after>package vix

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"time"

	"github.com/c4milo/unzipit"
	"github.com/dustin/go-humanize"
	govix "github.com/hooklift/govix"
)

// Virtual machine configuration
type VM struct {
	// Which VMware VIX service provider to use. ie: fusion, workstation, server, etc
	Provider string
	// Whether to verify SSL or not for remote connections in ESXi
	VerifySSL bool
	// Name of the virtual machine
	Name string
	// Description for the virtual machine, it is created as an annotation in
	// VMware.
	Description string
	// Image to use during the creation of this virtual machine
	Image Image
	// Number of virtual cpus
	CPUs uint
	// Memory size in megabytes.
	Memory string
	// Switches to where this machine is going to be attach to
	VSwitches []string
	// Whether to upgrade the VM virtual hardware
	UpgradeVHardware bool
	// The timeout to wait for VMware Tools to be initialized inside the VM
	ToolsInitTimeout time.Duration
	// Whether to launch the VM with graphical environment
	LaunchGUI bool
	// Whether to enable or disable shared folders for this VM
	SharedFolders bool
	// Network adapters
	VNetworkAdapters []*govix.NetworkAdapter
	// CD/DVD drives
	CDDVDDrives []*govix.CDDVDDrive
	// VM IP address as reported by VIX
	IPAddress string
}

// Creates VIX instance with VMware
func (v *VM) client() (*govix.Host, error) {
	var p govix.Provider

	switch strings.ToLower(v.Provider) {
	case "fusion", "workstation":
		p = govix.VMWARE_WORKSTATION
	case "serverv1":
		p = govix.VMWARE_SERVER
	case "serverv2":
		p = govix.VMWARE_VI_SERVER
	case "player":
		p = govix.VMWARE_PLAYER
	case "workstation_shared":
		p = govix.VMWARE_WORKSTATION_SHARED
	default:
		p = govix.VMWARE_WORKSTATION
	}

	var options govix.HostOption
	if v.VerifySSL {
		options = govix.VERIFY_SSL_CERT
	}

	host, err := govix.Connect(govix.ConnectConfig{
		Provider: p,
		Options:  options,
	})

	if err != nil {
		return nil, err
	}

	log.Printf("[INFO] VIX client configured for product: VMware %s. SSL: %t", v.Provider, v.VerifySSL)

	return host, nil
}

// Sets default values for VM attributes
func (v *VM) SetDefaults() {
	if v.CPUs <= 0 {
		v.CPUs = 2
	}

	if v.Memory == "" {
		v.Memory = "512mib"
	}

	if v.Description == "" {
		v.Description = "Machine was created using Terraform VIX provider"
	}

	if v.ToolsInitTimeout.Seconds() <= 0 {
		v.ToolsInitTimeout = time.Duration(30) * time.Second
	}
}

// Downloads, extracts and opens Gold virtual machine, then it creates a clone
// out of it.
func (v *VM) Create() (string, error) {
	log.Printf("[DEBUG] Creating VM resource...")

	usr, err := user.Current()
	if err != nil {
		return "", err
	}

	image := v.Image
	goldPath := filepath.Join(usr.HomeDir, filepath.Join(".terraform/vix/gold", image.Checksum))
	_, err = os.Stat(goldPath)
	finfo, _ := ioutil.ReadDir(goldPath)
	goldPathEmpty := len(finfo) == 0

	if os.IsNotExist(err) || goldPathEmpty {
		log.Println("[DEBUG] Gold virtual machine does not exist or is empty")

		imgPath := filepath.Join(usr.HomeDir, ".terraform/vix/images", image.Checksum)
		if err = image.Download(imgPath); err != nil {
			return "", err
		}
		defer image.file.Close()

		log.Printf("[DEBUG] Unpacking Gold virtual machine into %s\n", goldPath)
		_, err = unzipit.Unpack(image.file, goldPath)
		if err != nil {
			return "", err
		}
	}

	pattern := filepath.Join(goldPath, "**.vmx")

	log.Printf("[DEBUG] Finding Gold virtual machine vmx file in %s", pattern)
	files, _ := filepath.Glob(pattern)

	if len(files) == 0 {
		return "", fmt.Errorf("[ERROR] vmx file was not found: %s", pattern)
	}

	vmxFile := files[0]
	log.Printf("[DEBUG] Gold virtual machine vmx file found %v", vmxFile)

	// Gets VIX instance
	client, err := v.client()
	if err != nil {
		return "", err
	}
	defer client.Disconnect()

	log.Printf("[INFO] Opening Gold virtual machine from %s", vmxFile)

	vm, err := client.OpenVM(vmxFile, v.Image.Password)

	if err != nil {
		return "", err
	}

	baseVMDir := filepath.Join(usr.HomeDir, ".terraform", "vix", "vms",
		image.Checksum, v.Name)

	newvmx := filepath.Join(baseVMDir, v.Name+".vmx")

	if _, err = os.Stat(newvmx); os.IsNotExist(err) {
		log.Printf("[INFO] Virtual machine clone not found: %s, err: %+v", newvmx, err)
		// If there is not a VMX file, make sure nothing else is in there either.
		// We were seeing VIX 13004 errors when only a nvram file existed.
		os.RemoveAll(baseVMDir)

		log.Printf("[INFO] Cloning Gold virtual machine into %s...", newvmx)
		_, err := vm.Clone(govix.CLONETYPE_FULL, newvmx)

		// If there is an error and the error is other than "The snapshot already exists"
		// then return the error
		if err != nil && err.(*govix.Error).Code != 13004 {
			return "", err
		}
	} else {
		log.Printf("[INFO] Virtual Machine clone %s already exist, moving on.", newvmx)
	}

	if err = v.Update(newvmx); err != nil {
		return "", err
	}

	return newvmx, nil
}

// Opens and updates virtual machine resource
func (v *VM) Update(vmxFile string) error {
	// Sets default values if some attributes were not set or have
	// invalid values
	v.SetDefaults()

	// Gets VIX instance
	client, err := v.client()
	if err != nil {
		return err
	}
	defer client.Disconnect()

	if client.Provider == govix.VMWARE_VI_SERVER ||
		client.Provider == govix.VMWARE_SERVER {
		log.Printf("[INFO] Registering VM in host's inventory...")
		err = client.RegisterVM(vmxFile)
		if err != nil {
			return err
		}
	}

	log.Printf("[INFO] Opening virtual machine from %s", vmxFile)

	vm, err := client.OpenVM(vmxFile, v.Image.Password)
	if err != nil {
		return err
	}

	running, err := vm.IsRunning()
	if err != nil {
		return err
	}

	if running {
		log.Printf("[INFO] Virtual machine seems to be running, we need to " +
			"power it off in order to make changes.")
		err = v.powerOff(vm)
		if err != nil {
			return err
		}
	}

	memoryInMb, err := humanize.ParseBytes(v.Memory)
	if err != nil {
		log.Printf("[WARN] Unable to set memory size, defaulting to 512mib: %s", err)
		memoryInMb = 512
	} else {
		memoryInMb = (memoryInMb / 1024) / 1024
	}

	log.Printf("[DEBUG] Setting memory size to %d megabytes", memoryInMb)
	vm.SetMemorySize(uint(memoryInMb))

	log.Printf("[DEBUG] Setting vcpus to %d", v.CPUs)
	vm.SetNumberVcpus(v.CPUs)

	log.Printf("[DEBUG] Setting name to %s", v.Name)
	vm.SetDisplayName(v.Name)

	log.Printf("[DEBUG] Setting description to %s", v.Description)
	vm.SetAnnotation(v.Description)

	if v.UpgradeVHardware &&
		client.Provider != govix.VMWARE_PLAYER {

		log.Println("[INFO] Upgrading virtual hardware...")
		err = vm.UpgradeVHardware()
		if err != nil {
			return err
		}
	}

	log.Printf("[DEBUG] Removing all network adapters from vmx file...")
	err = vm.RemoveAllNetworkAdapters()
	if err != nil {
		return err
	}

	log.Println("[INFO] Attaching virtual network adapters...")
	for _, adapter := range v.VNetworkAdapters {
		adapter.StartConnected = true
		if adapter.ConnType == govix.NETWORK_BRIDGED {
			adapter.LinkStatePropagation = true
		}

		log.Printf("[DEBUG] Adapter: %+v", adapter)
		err := vm.AddNetworkAdapter(adapter)
		if err != nil {
			return err
		}
	}

	log.Printf("[DEBUG] Removing all CD/DVD drives from vmx file...")
	err = vm.RemoveAllCDDVDDrives()
	if err != nil {
		return err
	}

	log.Println("[INFO] Attaching CD/DVD drives... ")
	for _, cdrom := range v.CDDVDDrives {
		err := vm.AttachCDDVD(cdrom)
		if err != nil {
			return err
		}
	}

	log.Println("[INFO] Powering virtual machine on...")
	var options govix.VMPowerOption

	if v.LaunchGUI {
		log.Println("[INFO] Preparing to launch GUI...")
		options |= govix.VMPOWEROP_LAUNCH_GUI
	}

	options |= govix.VMPOWEROP_NORMAL

	err = vm.PowerOn(options)
	if err != nil {
		return err
	}

	log.Println("[INFO] Waiting for VMware Tools to initialize...")
	err = vm.WaitForToolsInGuest(v.ToolsInitTimeout)
	if err != nil {
		log.Println("[WARN] VMware Tools took too long to initialize or is not " +
			"installed.")

		if v.SharedFolders {
			log.Println("[WARN] Enabling shared folders is not possible.")
		}
		return nil
	}

	if v.SharedFolders {
		log.Println("[DEBUG] Enabling shared folders...")

		err = vm.EnableSharedFolders(v.SharedFolders)
		if err != nil {
			return err
		}
	}
	return nil
}

// Powers off a virtual machine attempting a graceful shutdown.
func (v *VM) powerOff(vm *govix.VM) error {
	tstate, err := vm.ToolsState()
	if err != nil {
		return err
	}

	var powerOpts govix.VMPowerOption
	log.Printf("Tools state %d", tstate)

	if (tstate & govix.TOOLSSTATE_RUNNING) != 0 {
		log.Printf("[INFO] VMware Tools is running, attempting a graceful shutdown...")
		// if VMware Tools is running, attempt a graceful shutdown.
		powerOpts |= govix.VMPOWEROP_FROM_GUEST
	} else {
		log.Printf("[INFO] VMware Tools is NOT running, shutting down the " +
			"machine abruptly...")
		powerOpts |= govix.VMPOWEROP_NORMAL
	}

	err = vm.PowerOff(powerOpts)
	if err != nil {
		return err
	}
	log.Printf("[DEBUG] Virtual machine is off.")

	return nil
}

// Destroys a virtual machine resource
func (v *VM) Destroy(vmxFile string) error {
	log.Printf("[DEBUG] Destroying VM resource %s...", vmxFile)

	client, err := v.client()
	if err != nil {
		return err
	}
	defer client.Disconnect()

	vm, err := client.OpenVM(vmxFile, v.Image.Password)
	if err != nil {
		return err
	}

	running, err := vm.IsRunning()
	if err != nil {
		return err
	}

	if running {
		if err = v.powerOff(vm); err != nil {
			return err
		}
	}

	if client.Provider == govix.VMWARE_VI_SERVER ||
		client.Provider == govix.VMWARE_SERVER {
		log.Printf("[INFO] Unregistering VM from host's inventory...")

		err := client.UnregisterVM(vmxFile)
		if err != nil {
			return err
		}
	}

	return vm.Delete(govix.VMDELETE_KEEP_FILES | govix.VMDELETE_FORCE)
}

// Refreshes state with VMware
func (v *VM) Refresh(vmxFile string) (bool, error) {
	log.Printf("[DEBUG] Syncing VM resource %s...", vmxFile)

	client, err := v.client()
	if err != nil {
		return false, err
	}
	defer client.Disconnect()

	vm, err := client.OpenVM(vmxFile, v.Image.Password)
	if err != nil {
		return false, err
	}

	running, err := vm.IsRunning()
	if !running {
		return running, err
	}

	vcpus, err := vm.Vcpus()
	if err != nil {
		return running, err
	}

	memory, err := vm.MemorySize()
	if err != nil {
		return running, err
	}

	// We need to convert memory value to megabytes so humanize can interpret it
	// properly.
	memory = (memory * 1024) * 1024
	v.Memory = strings.ToLower(humanize.IBytes(uint64(memory)))
	v.CPUs = uint(vcpus)
	v.Name, err = vm.DisplayName()
	v.Description, err = vm.Annotation()
	v.VNetworkAdapters, err = vm.NetworkAdapters()
	v.IPAddress, err = vm.IPAddress()

	return running, err
}
<|endoftext|>


<commit_before>package socks

import (
	"net"

	"github.com/v2ray/v2ray-core/common/alloc"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy/socks/protocol"
)

var udpAddress v2net.Address

func (server *SocksServer) ListenUDP(port uint16) error {
	addr := &net.UDPAddr{
		IP:   net.IP{0, 0, 0, 0},
		Port: int(port),
		Zone: "",
	}
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Error("Socks failed to listen UDP on port %d: %v", port, err)
		return err
	}
	udpAddress = v2net.IPAddress(server.config.IP(), port)

	go server.AcceptPackets(conn)
	return nil
}

func (server *SocksServer) getUDPAddr() v2net.Address {
	return udpAddress
}

func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error {
	for {
		buffer := alloc.NewBuffer()
		nBytes, addr, err := conn.ReadFromUDP(buffer.Value)
		if err != nil {
			log.Error("Socks failed to read UDP packets: %v", err)
			buffer.Release()
			continue
		}
		log.Info("Client UDP connection from %v", addr)
		request, err := protocol.ReadUDPRequest(buffer.Value[:nBytes])
		buffer.Release()
		if err != nil {
			log.Error("Socks failed to parse UDP request: %v", err)
			request.Data.Release()
			continue
		}
		if request.Fragment != 0 {
			log.Warning("Dropping fragmented UDP packets.")
			// TODO handle fragments
			request.Data.Release()
			continue
		}

		udpPacket := v2net.NewPacket(request.Destination(), request.Data, false)
		log.Info("Send packet to %s with %d bytes", udpPacket.Destination().String(), request.Data.Len())
		go server.handlePacket(conn, udpPacket, addr, request.Address)
	}
}

func (server *SocksServer) handlePacket(conn *net.UDPConn, packet v2net.Packet, clientAddr *net.UDPAddr, targetAddr v2net.Address) {
	ray := server.vPoint.DispatchToOutbound(packet)
	close(ray.InboundInput())

	if data, ok := <-ray.InboundOutput(); ok {
		response := &protocol.Socks5UDPRequest{
			Fragment: 0,
			Address:  targetAddr,
			Data:     data,
		}
		log.Info("Writing back UDP response with %d bytes from %s to %s", data.Len(), targetAddr.String(), clientAddr.String())

		udpMessage := alloc.NewSmallBuffer().Clear()
		response.Write(udpMessage)

		nBytes, err := conn.WriteToUDP(udpMessage.Value, clientAddr)
		udpMessage.Release()
		response.Data.Release()
		if err != nil {
			log.Error("Socks failed to write UDP message (%d bytes) to %s: %v", nBytes, clientAddr.String(), err)
		}
	}
}
<commit_msg>Handle multiple UDP packets in socks.<commit_after>package socks

import (
	"net"

	"github.com/v2ray/v2ray-core/common/alloc"
	"github.com/v2ray/v2ray-core/common/log"
	v2net "github.com/v2ray/v2ray-core/common/net"
	"github.com/v2ray/v2ray-core/proxy/socks/protocol"
)

var udpAddress v2net.Address

func (server *SocksServer) ListenUDP(port uint16) error {
	addr := &net.UDPAddr{
		IP:   net.IP{0, 0, 0, 0},
		Port: int(port),
		Zone: "",
	}
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Error("Socks failed to listen UDP on port %d: %v", port, err)
		return err
	}
	udpAddress = v2net.IPAddress(server.config.IP(), port)

	go server.AcceptPackets(conn)
	return nil
}

func (server *SocksServer) getUDPAddr() v2net.Address {
	return udpAddress
}

func (server *SocksServer) AcceptPackets(conn *net.UDPConn) error {
	for {
		buffer := alloc.NewBuffer()
		nBytes, addr, err := conn.ReadFromUDP(buffer.Value)
		if err != nil {
			log.Error("Socks failed to read UDP packets: %v", err)
			buffer.Release()
			continue
		}
		log.Info("Client UDP connection from %v", addr)
		request, err := protocol.ReadUDPRequest(buffer.Value[:nBytes])
		buffer.Release()
		if err != nil {
			log.Error("Socks failed to parse UDP request: %v", err)
			request.Data.Release()
			continue
		}
		if request.Fragment != 0 {
			log.Warning("Dropping fragmented UDP packets.")
			// TODO handle fragments
			request.Data.Release()
			continue
		}

		udpPacket := v2net.NewPacket(request.Destination(), request.Data, false)
		log.Info("Send packet to %s with %d bytes", udpPacket.Destination().String(), request.Data.Len())
		go server.handlePacket(conn, udpPacket, addr, request.Address)
	}
}

func (server *SocksServer) handlePacket(conn *net.UDPConn, packet v2net.Packet, clientAddr *net.UDPAddr, targetAddr v2net.Address) {
	ray := server.vPoint.DispatchToOutbound(packet)
	close(ray.InboundInput())

	for data := range ray.InboundOutput() {
		response := &protocol.Socks5UDPRequest{
			Fragment: 0,
			Address:  targetAddr,
			Data:     data,
		}
		log.Info("Writing back UDP response with %d bytes from %s to %s", data.Len(), targetAddr.String(), clientAddr.String())

		udpMessage := alloc.NewSmallBuffer().Clear()
		response.Write(udpMessage)

		nBytes, err := conn.WriteToUDP(udpMessage.Value, clientAddr)
		udpMessage.Release()
		response.Data.Release()
		if err != nil {
			log.Error("Socks failed to write UDP message (%d bytes) to %s: %v", nBytes, clientAddr.String(), err)
		}
	}
}
<|endoftext|>