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

// Package clientv3 implements the official Go etcd client for v3.
//
// Create client using `clientv3.New`:
//
//	// expect dial time-out on ipv4 blackhole
//	_, err := clientv3.New(clientv3.Config{
//		Endpoints:   []string{"http://254.0.0.1:12345"},
//		DialTimeout: 2 * time.Second,
//	})
//
//	// etcd clientv3 >= v3.2.10, grpc/grpc-go >= v1.7.3
//	if err == context.DeadlineExceeded {
//		// handle errors
//	}
//
//	// etcd clientv3 <= v3.2.9, grpc/grpc-go <= v1.2.1
//	if err == grpc.ErrClientConnTimeout {
//		// handle errors
//	}
//
//	cli, err := clientv3.New(clientv3.Config{
//		Endpoints:   []string{"localhost:2379", "localhost:22379", "localhost:32379"},
//		DialTimeout: 5 * time.Second,
//	})
//	if err != nil {
//		// handle error!
//	}
//	defer cli.Close()
//
// Make sure to close the client after using it. If the client is not closed, the
// connection will have leaky goroutines.
//
// To specify a client request timeout, wrap the context with context.WithTimeout:
//
//	ctx, cancel := context.WithTimeout(context.Background(), timeout)
//	resp, err := kvc.Put(ctx, "sample_key", "sample_value")
//	cancel()
//	if err != nil {
//	    // handle error!
//	}
//	// use the response
//
// The Client has internal state (watchers and leases), so Clients should be reused instead of created as needed.
// Clients are safe for concurrent use by multiple goroutines.
//
// etcd client returns 2 types of errors:
//
//  1. context error: canceled or deadline exceeded.
//  2. gRPC error: e.g. when clock drifts in server-side before client's context deadline exceeded.
//  See https://github.com/etcd-io/etcd/blob/main/api/v3rpc/rpctypes/error.go
//
// Here is the example code to handle client errors:
//
//	resp, err := kvc.Put(ctx, "", "")
//	if err != nil {
//		if err == context.Canceled {
//			// ctx is canceled by another routine
//		} else if err == context.DeadlineExceeded {
//			// ctx is attached with a deadline and it exceeded
//		} else if err == rpctypes.ErrEmptyKey {
//			// client-side error: key is not provided
//		} else if ev, ok := status.FromError(err); ok {
//			code := ev.Code()
//			if code == codes.DeadlineExceeded {
//				// server-side context might have timed-out first (due to clock skew)
//				// while original client-side context is not timed-out yet
//			}
//		} else {
//			// bad cluster endpoints, which are not etcd servers
//		}
//	}
//
//	go func() { cli.Close() }()
//	_, err := kvc.Get(ctx, "a")
//	if err != nil {
//		// with etcd clientv3 <= v3.3
//		if err == context.Canceled {
//			// grpc balancer calls 'Get' with an inflight client.Close
//		} else if err == grpc.ErrClientConnClosing { // <= gRCP v1.7.x
//			// grpc balancer calls 'Get' after client.Close.
//		}
//		// with etcd clientv3 >= v3.4
//		if clientv3.IsConnCanceled(err) {
//			// gRPC client connection is closed
//		}
//	}
//
// The grpc load balancer is registered statically and is shared across etcd clients.
// To enable detailed load balancer logging, set the ETCD_CLIENT_DEBUG environment
// variable.  E.g. "ETCD_CLIENT_DEBUG=1".
//
package clientv3
<commit_msg>Golang Client docs: defer cancel(), avoid erroring<commit_after>// Copyright 2016 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package clientv3 implements the official Go etcd client for v3.
//
// Create client using `clientv3.New`:
//
//	// expect dial time-out on ipv4 blackhole
//	_, err := clientv3.New(clientv3.Config{
//		Endpoints:   []string{"http://254.0.0.1:12345"},
//		DialTimeout: 2 * time.Second,
//	})
//
//	// etcd clientv3 >= v3.2.10, grpc/grpc-go >= v1.7.3
//	if err == context.DeadlineExceeded {
//		// handle errors
//	}
//
//	// etcd clientv3 <= v3.2.9, grpc/grpc-go <= v1.2.1
//	if err == grpc.ErrClientConnTimeout {
//		// handle errors
//	}
//
//	cli, err := clientv3.New(clientv3.Config{
//		Endpoints:   []string{"localhost:2379", "localhost:22379", "localhost:32379"},
//		DialTimeout: 5 * time.Second,
//	})
//	if err != nil {
//		// handle error!
//	}
//	defer cli.Close()
//
// Make sure to close the client after using it. If the client is not closed, the
// connection will have leaky goroutines.
//
// To specify a client request timeout, wrap the context with context.WithTimeout:
//
//	ctx, cancel := context.WithTimeout(context.Background(), timeout)
//	defer cancel()
//	resp, err := kvc.Put(ctx, "sample_key", "sample_value")
//	if err != nil {
//	    // handle error!
//	}
//	// use the response
//
// The Client has internal state (watchers and leases), so Clients should be reused instead of created as needed.
// Clients are safe for concurrent use by multiple goroutines.
//
// etcd client returns 2 types of errors:
//
//  1. context error: canceled or deadline exceeded.
//  2. gRPC error: e.g. when clock drifts in server-side before client's context deadline exceeded.
//  See https://github.com/etcd-io/etcd/blob/main/api/v3rpc/rpctypes/error.go
//
// Here is the example code to handle client errors:
//
//	resp, err := kvc.Put(ctx, "", "")
//	if err != nil {
//		if err == context.Canceled {
//			// ctx is canceled by another routine
//		} else if err == context.DeadlineExceeded {
//			// ctx is attached with a deadline and it exceeded
//		} else if err == rpctypes.ErrEmptyKey {
//			// client-side error: key is not provided
//		} else if ev, ok := status.FromError(err); ok {
//			code := ev.Code()
//			if code == codes.DeadlineExceeded {
//				// server-side context might have timed-out first (due to clock skew)
//				// while original client-side context is not timed-out yet
//			}
//		} else {
//			// bad cluster endpoints, which are not etcd servers
//		}
//	}
//
//	go func() { cli.Close() }()
//	_, err := kvc.Get(ctx, "a")
//	if err != nil {
//		// with etcd clientv3 <= v3.3
//		if err == context.Canceled {
//			// grpc balancer calls 'Get' with an inflight client.Close
//		} else if err == grpc.ErrClientConnClosing { // <= gRCP v1.7.x
//			// grpc balancer calls 'Get' after client.Close.
//		}
//		// with etcd clientv3 >= v3.4
//		if clientv3.IsConnCanceled(err) {
//			// gRPC client connection is closed
//		}
//	}
//
// The grpc load balancer is registered statically and is shared across etcd clients.
// To enable detailed load balancer logging, set the ETCD_CLIENT_DEBUG environment
// variable.  E.g. "ETCD_CLIENT_DEBUG=1".
//
package clientv3
<|endoftext|>


<commit_before>package aws

import (
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/autoscaling"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/sns"
)

type AwsManager struct {
	session *session.Session
}

func NewAwsManager(region string) *AwsManager {

	sess := session.New()
	cred := credentials.NewChainCredentials([]credentials.Provider{
		&credentials.EnvProvider{},
		&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
		&ec2rolecreds.EC2RoleProvider{
			Client:       ec2metadata.New(sess),
			ExpiryWindow: 5 * time.Minute,
		},
	})

	conf := aws.NewConfig().WithCredentials(cred).WithMaxRetries(aws.UseServiceDefaultRetries).WithRegion(region)

	return &AwsManager{
		session: session.New(conf),
	}
}

func (self *AwsManager) EcsApi() *EcsApi {
	return &EcsApi{
		service: ecs.New(self.session),
	}
}

func (self *AwsManager) ElbApi() *ElbApi {
	return &ElbApi{
		service: elb.New(self.session),
	}
}

func (self *AwsManager) AutoscalingApi() *AutoscalingApi {
	return &AutoscalingApi{
		service: autoscaling.New(self.session),
	}
}

func (self *AwsManager) SnsApi() *SnsApi {
	return &SnsApi{
		service: sns.New(self.session),
	}
}

func (self *AwsManager) S3Api() *S3Api {
	return &S3Api{
		service: s3.New(self.session),
	}
}
<commit_msg>Fix missing import<commit_after>package aws

import (
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/autoscaling"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/sns"
)

type AwsManager struct {
	session *session.Session
}

func NewAwsManager(region string) *AwsManager {

	sess := session.New()
	cred := credentials.NewChainCredentials([]credentials.Provider{
		&credentials.EnvProvider{},
		&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
		&ec2rolecreds.EC2RoleProvider{
			Client:       ec2metadata.New(sess),
			ExpiryWindow: 5 * time.Minute,
		},
	})

	conf := aws.NewConfig().WithCredentials(cred).WithMaxRetries(aws.UseServiceDefaultRetries).WithRegion(region)

	return &AwsManager{
		session: session.New(conf),
	}
}

func (self *AwsManager) EcsApi() *EcsApi {
	return &EcsApi{
		service: ecs.New(self.session),
	}
}

func (self *AwsManager) ElbApi() *ElbApi {
	return &ElbApi{
		service: elb.New(self.session),
	}
}

func (self *AwsManager) AutoscalingApi() *AutoscalingApi {
	return &AutoscalingApi{
		service: autoscaling.New(self.session),
	}
}

func (self *AwsManager) SnsApi() *SnsApi {
	return &SnsApi{
		service: sns.New(self.session),
	}
}

func (self *AwsManager) S3Api() *S3Api {
	return &S3Api{
		service: s3.New(self.session),
	}
}
<|endoftext|>


<commit_before>package acceptance_test

import (
	"encoding/json"
	"fmt"
	"net/http"

	spamAPI "example-apps/spammer/api"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

const (
	orgName   = "outbound-conn-limit-test-org"
	spaceName = "outbound-conn-limit-test-space"

	setEnvTimeoutInSec = 10
	burst              = 60
)

var (
	proxyName   string
	spammerName string
)

var _ = Describe("Outbound connection limit", func() {
	BeforeEach(func() {
		proxyName = testConfig.Prefix + "-proxy"
		spammerName = testConfig.Prefix + "-spammer"
		if testConfig.RunExperimentalOutboundConnLimitTest {
			Skip("Skipping outbound connection limit test")
		}

		AuthAsAdmin()

		Expect(cfCLI.CreateOrg(orgName)).To(Succeed())
		Expect(cfCLI.TargetOrg(orgName)).To(Succeed())

		Expect(cfCLI.CreateSpace(spaceName, orgName)).To(Succeed())
		Expect(cfCLI.TargetSpace(spaceName)).To(Succeed())
	})

	AfterEach(func() {
		Expect(cf.Cf("delete-org", orgName, "-f").Wait(Timeout_Push)).To(gexec.Exit(0))
	})

	Describe("when an app opens multiple connections to one host", func() {
		It("the connections get rate limited", func() {
			By("pushing proxy")
			pushProxy(proxyName)

			By("pushing spammer")
			pushSpammer()

			By("verifying the burst is available on start")
			spamResp := spam()
			Expect(spamResp.SuccessCount).Should(BeEquivalentTo(burst))

			By("verifying the burst is exhausted")
			spamResp = spam()
			Expect(spamResp.SuccessCount).Should(BeNumerically("<", burst))
		})
	})
})

func pushSpammer() {
	session := cf.Cf("push", spammerName, "-p", appDir(spammerName), "-f", defaultManifest(spammerName), "--no-start")
	Expect(session.Wait(Timeout_Push)).To(gexec.Exit(0))

	proxyBaseURL := getAppBaseURL(proxyName)
	session = cf.Cf("set-env", spammerName, spamAPI.ProxyBaseURLField, proxyBaseURL)
	Expect(session.Wait(setEnvTimeoutInSec)).To(gexec.Exit(0))

	session = cf.Cf("start", spammerName)
	Expect(session.Wait(Timeout_Push)).To(gexec.Exit(0))
}

func spam() *spamAPI.SpamResp {
	spammerBaseURL := spamEndpoint(burst)
	resp, err := http.Get(spammerBaseURL)

	Expect(err).Should(BeNil())
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	target := &spamAPI.SpamResp{}

	Expect(decoder.Decode(target)).Should(BeNil())

	return target
}

func spamEndpoint(callCount int) string {
	spammerBaseURL := getAppBaseURL(spammerName)
	return fmt.Sprintf("%s%s%d", spammerBaseURL, spamAPI.SpamPath, callCount)
}

func getAppBaseURL(appName string) string {
	return fmt.Sprintf("https://%s.%s", appName, testConfig.AppsDomain)
}
<commit_msg>Fix spammer app push path<commit_after>package acceptance_test

import (
	"encoding/json"
	"fmt"
	"net/http"

	spamAPI "example-apps/spammer/api"

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gexec"
)

const (
	orgName   = "outbound-conn-limit-test-org"
	spaceName = "outbound-conn-limit-test-space"

	setEnvTimeoutInSec = 10
	burst              = 60
)

var (
	proxyName   string
	spammerName string
)

var _ = Describe("Outbound connection limit", func() {
	BeforeEach(func() {
		proxyName = testConfig.Prefix + "-proxy"
		spammerName = testConfig.Prefix + "-spammer"
		if testConfig.RunExperimentalOutboundConnLimitTest {
			Skip("Skipping outbound connection limit test")
		}

		AuthAsAdmin()

		Expect(cfCLI.CreateOrg(orgName)).To(Succeed())
		Expect(cfCLI.TargetOrg(orgName)).To(Succeed())

		Expect(cfCLI.CreateSpace(spaceName, orgName)).To(Succeed())
		Expect(cfCLI.TargetSpace(spaceName)).To(Succeed())
	})

	AfterEach(func() {
		Expect(cf.Cf("delete-org", orgName, "-f").Wait(Timeout_Push)).To(gexec.Exit(0))
	})

	Describe("when an app opens multiple connections to one host", func() {
		It("the connections get rate limited", func() {
			By("pushing proxy")
			pushProxy(proxyName)

			By("pushing spammer")
			pushSpammer(spammerName)

			By("verifying the burst is available on start")
			spamResp := spam()
			Expect(spamResp.SuccessCount).Should(BeEquivalentTo(burst))

			By("verifying the burst is exhausted")
			spamResp = spam()
			Expect(spamResp.SuccessCount).Should(BeNumerically("<", burst))
		})
	})
})

func pushSpammer(spammerName string) {
	session := cf.Cf("push", spammerName, "-p", appDir("spammer"), "-f", defaultManifest(spammerName), "--no-start")
	Expect(session.Wait(Timeout_Push)).To(gexec.Exit(0))

	proxyBaseURL := getAppBaseURL(proxyName)
	session = cf.Cf("set-env", spammerName, spamAPI.ProxyBaseURLField, proxyBaseURL)
	Expect(session.Wait(setEnvTimeoutInSec)).To(gexec.Exit(0))

	session = cf.Cf("start", spammerName)
	Expect(session.Wait(Timeout_Push)).To(gexec.Exit(0))
}

func spam() *spamAPI.SpamResp {
	spammerBaseURL := spamEndpoint(burst)
	resp, err := http.Get(spammerBaseURL)

	Expect(err).Should(BeNil())
	defer resp.Body.Close()

	decoder := json.NewDecoder(resp.Body)
	target := &spamAPI.SpamResp{}

	Expect(decoder.Decode(target)).Should(BeNil())

	return target
}

func spamEndpoint(callCount int) string {
	spammerBaseURL := getAppBaseURL(spammerName)
	return fmt.Sprintf("%s%s%d", spammerBaseURL, spamAPI.SpamPath, callCount)
}

func getAppBaseURL(appName string) string {
	return fmt.Sprintf("https://%s.%s", appName, testConfig.AppsDomain)
}
<|endoftext|>


<commit_before>// errchk $G $D/$F.go

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

package main

type T struct {
	x, x int  // this should be a compile-time error
}

/*
Accessing obj.x for obj of type T will lead to an error so this cannot
be used in a program, but I would argue that this should be a compile-
tume error at the declaration point.
*/
<commit_msg>- added comment with various viewpoints so we have whole story once we close this<commit_after>// errchk $G $D/$F.go

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

package main

type T struct {
	x, x int  // this should be a compile-time error
}

/*
Accessing obj.x for obj of type T will lead to an error so this cannot
be used in a program, but I would argue that this should be a compile-
tume error at the declaration point.
*/

/* Condensed e-mail thread:

---------- Russ Cox
I don't think this is an error as long as you don't refer to x. I like the fact that you could name
multiple elements in the struct "pad".

---------- Rob 'Commander' Pike to Russ, me, go-dev, reviewlog2
the real question is whether this program matches the spec and if not, which is in error.

---------- Russ Cox to Rob, me, go-dev, reviewlog2
true enough.  the spec disagrees with 6g.
when we discussed the disambiguation
rules for anonymous structs i thought we'd
mentioned this issue too and decided the
opposite, but i'm happy to make 6g agree
with the spec.

---------- Robert Griesemer to Russ, Rob, go-dev, reviewlog2
I think the spec could perhaps be more definitive. Note that 6g also accepts:

type T struct {
	x int
}

func (p *T) x() {
}

func (p *T) x() {
}

The spec says that the scope of methods and fields is selectors of the form obj.selector. In a scope an identifier can be declared only once. I'd conclude that in the scope of fields and selectors of T, there are multiple x. But it's somewhat indirect. From a programmer's point of view making this an error seems less surprising, at least to me.

---------- Ken Thompson to me, Russ, Rob, go-dev, reviewlog2
obviously i dont think this is an error, or
i would have made it an error. it seems like
a small point if the error comes up at
declaration or use.

---------- Robert Griesemer to Ken, Russ, Rob, go-dev, reviewlog2
I don't really care too much, but I think it should be consistent. The following code:

type T struct {
	x int;
}

func (p *T) x() {
}

func (p *T) x(a, b, c int) {
}

does result in an error (method redeclared). I don't quite see why this should behave any different then if both x() had the same parameter list.

PS: I agree that the spec is saying two different things here - or at least should be more precise; the section on selectors (which arguably is the newer section), would allow such a declaration. I suspect that the case below leads to an early error possibly due to some interaction with code that checks for forward declaration of functions/methods (this not having looked at 6g).

I am happy to go either way. It's a small item and we can close it once we all agree.
*/
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/ec2"
)

func resource_aws_subnet_create(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff so that we have all the proper attributes
	s = s.MergeDiff(d)

	// Create the Subnet
	createOpts := &ec2.CreateSubnet{
		AvailabilityZone: s.Attributes["availability_zone"],
		CidrBlock:        s.Attributes["cidr_block"],
		VpcId:            s.Attributes["vpc_id"],
	}
	log.Printf("[DEBUG] Subnet create config: %#v", createOpts)
	resp, err := ec2conn.CreateSubnet(createOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating subnet: %s", err)
	}

	// Get the ID and store it
	subnet := &resp.Subnet
	s.ID = subnet.SubnetId
	log.Printf("[INFO] Subnet ID: %s", s.ID)

	// Wait for the Subnet to become available
	log.Printf(
		"[DEBUG] Waiting for subnet (%s) to become available",
		s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	subnetRaw, err := stateConf.WaitForState()
	if err != nil {
		return s, fmt.Errorf(
			"Error waiting for subnet (%s) to become available: %s",
			s.ID, err)
	}

	// Map public ip on launch must be set in another API call
	if attr := s.Attributes["map_public_ip_on_launch"]; attr == "true" {
		modifyOpts := &ec2.ModifySubnetAttribute{
			SubnetId:            s.ID,
			MapPublicIpOnLaunch: true,
		}
		log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
		_, err := ec2conn.ModifySubnetAttribute(modifyOpts)
		if err != nil {
			return nil, fmt.Errorf("Error modify subnet attributes: %s", err)
		}
	}

	// Update our attributes and return
	return resource_aws_subnet_update_state(s, subnetRaw.(*ec2.Subnet))
}

func resource_aws_subnet_update(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	// This should never be called because we have no update-able
	// attributes
	panic("Update for subnet is not supported")
}

func resource_aws_subnet_destroy(
	s *terraform.InstanceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	log.Printf("[INFO] Deleting Subnet: %s", s.ID)
	f := func() error {
		_, err := ec2conn.DeleteSubnet(s.ID)
		return err
	}
	if err := resource.Retry(10*time.Second, f); err != nil {
		ec2err, ok := err.(*ec2.Error)
		if ok && ec2err.Code == "InvalidSubnetID.NotFound" {
			return nil
		}

		return fmt.Errorf("Error deleting subnet: %s", err)
	}

	// Wait for the Subnet to actually delete
	log.Printf("[DEBUG] Waiting for subnet (%s) to delete", s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"available", "pending"},
		Target:  "",
		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for subnet (%s) to destroy: %s",
			s.ID, err)
	}

	return nil
}

func resource_aws_subnet_refresh(
	s *terraform.InstanceState,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	subnetRaw, _, err := SubnetStateRefreshFunc(ec2conn, s.ID)()
	if err != nil {
		return s, err
	}
	if subnetRaw == nil {
		return nil, nil
	}

	subnet := subnetRaw.(*ec2.Subnet)
	return resource_aws_subnet_update_state(s, subnet)
}

func resource_aws_subnet_diff(
	s *terraform.InstanceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.InstanceDiff, error) {
	b := &diff.ResourceBuilder{
		Attrs: map[string]diff.AttrType{
			"availability_zone":       diff.AttrTypeCreate,
			"cidr_block":              diff.AttrTypeCreate,
			"vpc_id":                  diff.AttrTypeCreate,
			"map_public_ip_on_launch": diff.AttrTypeCreate,
		},

		ComputedAttrs: []string{
			"availability_zone",
		},
	}

	return b.Diff(s, c)
}

func resource_aws_subnet_update_state(
	s *terraform.InstanceState,
	subnet *ec2.Subnet) (*terraform.InstanceState, error) {
	s.Attributes["availability_zone"] = subnet.AvailabilityZone
	s.Attributes["cidr_block"] = subnet.CidrBlock
	s.Attributes["vpc_id"] = subnet.VpcId
	if subnet.MapPublicIpOnLaunch {
		s.Attributes["map_public_ip_on_launch"] = "true"
	}

	return s, nil
}

// SubnetStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a Subnet.
func SubnetStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeSubnets([]string{id}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSubnetID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on SubnetStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		subnet := &resp.Subnets[0]
		return subnet, subnet.State, nil
	}
}
<commit_msg>providers/aws: retry destroying subnet for some time [GH-449]<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/hashicorp/terraform/helper/diff"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/goamz/ec2"
)

func resource_aws_subnet_create(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff so that we have all the proper attributes
	s = s.MergeDiff(d)

	// Create the Subnet
	createOpts := &ec2.CreateSubnet{
		AvailabilityZone: s.Attributes["availability_zone"],
		CidrBlock:        s.Attributes["cidr_block"],
		VpcId:            s.Attributes["vpc_id"],
	}
	log.Printf("[DEBUG] Subnet create config: %#v", createOpts)
	resp, err := ec2conn.CreateSubnet(createOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating subnet: %s", err)
	}

	// Get the ID and store it
	subnet := &resp.Subnet
	s.ID = subnet.SubnetId
	log.Printf("[INFO] Subnet ID: %s", s.ID)

	// Wait for the Subnet to become available
	log.Printf(
		"[DEBUG] Waiting for subnet (%s) to become available",
		s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	subnetRaw, err := stateConf.WaitForState()
	if err != nil {
		return s, fmt.Errorf(
			"Error waiting for subnet (%s) to become available: %s",
			s.ID, err)
	}

	// Map public ip on launch must be set in another API call
	if attr := s.Attributes["map_public_ip_on_launch"]; attr == "true" {
		modifyOpts := &ec2.ModifySubnetAttribute{
			SubnetId:            s.ID,
			MapPublicIpOnLaunch: true,
		}
		log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
		_, err := ec2conn.ModifySubnetAttribute(modifyOpts)
		if err != nil {
			return nil, fmt.Errorf("Error modify subnet attributes: %s", err)
		}
	}

	// Update our attributes and return
	return resource_aws_subnet_update_state(s, subnetRaw.(*ec2.Subnet))
}

func resource_aws_subnet_update(
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	// This should never be called because we have no update-able
	// attributes
	panic("Update for subnet is not supported")
}

func resource_aws_subnet_destroy(
	s *terraform.InstanceState,
	meta interface{}) error {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	log.Printf("[INFO] Deleting Subnet: %s", s.ID)
	return resource.Retry(5*time.Minute, func() error {
		_, err := ec2conn.DeleteSubnet(s.ID)
		if err != nil {
			ec2err, ok := err.(*ec2.Error)
			if !ok {
				return err
			}

			switch ec2err.Code {
			case "InvalidSubnetID.NotFound":
				return nil
			case "DependencyViolation":
				return err // retry
			default:
				return resource.RetryError{err}
			}
		}

		return fmt.Errorf("Error deleting subnet: %s", err)
	})

	// Wait for the Subnet to actually delete
	log.Printf("[DEBUG] Waiting for subnet (%s) to delete", s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"available", "pending"},
		Target:  "",
		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return fmt.Errorf(
			"Error waiting for subnet (%s) to destroy: %s",
			s.ID, err)
	}

	return nil
}

func resource_aws_subnet_refresh(
	s *terraform.InstanceState,
	meta interface{}) (*terraform.InstanceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	subnetRaw, _, err := SubnetStateRefreshFunc(ec2conn, s.ID)()
	if err != nil {
		return s, err
	}
	if subnetRaw == nil {
		return nil, nil
	}

	subnet := subnetRaw.(*ec2.Subnet)
	return resource_aws_subnet_update_state(s, subnet)
}

func resource_aws_subnet_diff(
	s *terraform.InstanceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.InstanceDiff, error) {
	b := &diff.ResourceBuilder{
		Attrs: map[string]diff.AttrType{
			"availability_zone":       diff.AttrTypeCreate,
			"cidr_block":              diff.AttrTypeCreate,
			"vpc_id":                  diff.AttrTypeCreate,
			"map_public_ip_on_launch": diff.AttrTypeCreate,
		},

		ComputedAttrs: []string{
			"availability_zone",
		},
	}

	return b.Diff(s, c)
}

func resource_aws_subnet_update_state(
	s *terraform.InstanceState,
	subnet *ec2.Subnet) (*terraform.InstanceState, error) {
	s.Attributes["availability_zone"] = subnet.AvailabilityZone
	s.Attributes["cidr_block"] = subnet.CidrBlock
	s.Attributes["vpc_id"] = subnet.VpcId
	if subnet.MapPublicIpOnLaunch {
		s.Attributes["map_public_ip_on_launch"] = "true"
	}

	return s, nil
}

// SubnetStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
// a Subnet.
func SubnetStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
	return func() (interface{}, string, error) {
		resp, err := conn.DescribeSubnets([]string{id}, ec2.NewFilter())
		if err != nil {
			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSubnetID.NotFound" {
				resp = nil
			} else {
				log.Printf("Error on SubnetStateRefresh: %s", err)
				return nil, "", err
			}
		}

		if resp == nil {
			// Sometimes AWS just has consistency issues and doesn't see
			// our instance yet. Return an empty state.
			return nil, "", nil
		}

		subnet := &resp.Subnets[0]
		return subnet, subnet.State, nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/theinternetftw/dmgo"
	"github.com/theinternetftw/dmgo/profiling"
	"github.com/theinternetftw/glimmer"

	"fmt"
	"io/ioutil"
	"os"
	"time"
)

func main() {

	defer profiling.Start().Stop()

	assert(len(os.Args) == 2, "usage: ./dmgo ROM_FILENAME")
	cartFilename := os.Args[1]

	cartBytes, err := ioutil.ReadFile(cartFilename)
	dieIf(err)

	assert(len(cartBytes) > 3, "cannot parse, file is too small")

	var emu dmgo.Emulator
	windowTitle := "dmgo"

	fileMagic := string(cartBytes[:3])
	if fileMagic == "GBS" {
		// nsf(e) file
		emu = dmgo.NewGbsPlayer(cartBytes)
	} else {
		// rom file

		cartInfo := dmgo.ParseCartInfo(cartBytes)
		fmt.Printf("%q\n", cartInfo.Title)
		fmt.Printf("Cart type: %d\n", cartInfo.CartridgeType)
		fmt.Printf("Cart RAM size: %d\n", cartInfo.GetRAMSize())
		fmt.Printf("Cart ROM size: %d\n", cartInfo.GetROMSize())

		emu = dmgo.NewEmulator(cartBytes)
		windowTitle = cartInfo.Title + " - dmgo"
	}

	glimmer.InitDisplayLoop(windowTitle, 160*4, 144*4, 160, 144, func(sharedState *glimmer.WindowState) {
		startEmu(cartFilename, sharedState, emu)
	})
}

func startHeadlessEmu(emu dmgo.Emulator) {
	// FIXME: settings are for debug right now
	ticker := time.NewTicker(17*time.Millisecond)

	for {
		emu.Step()
		if emu.FlipRequested() {
			<-ticker.C
		}
	}
}

func startEmu(filename string, window *glimmer.WindowState, emu dmgo.Emulator) {

	// FIXME: settings are for debug right now
	lastFlipTime := time.Now()
	lastSaveTime := time.Now()
	lastInputPollTime := time.Now()

	timer := time.NewTimer(0)
	<-timer.C

	snapshotPrefix := filename + ".snapshot"

	saveFilename := filename + ".sav"
	if saveFile, err := ioutil.ReadFile(saveFilename); err == nil {
		err = emu.SetCartRAM(saveFile)
		if err != nil {
			fmt.Println("error loading savefile,", err)
		} else {
			fmt.Println("loaded save!")
		}
	}

	audio, err := glimmer.OpenAudioBuffer(4, 4096, 44100, 16, 2)
	workingAudioBuffer := make([]byte, audio.BufferSize())
	dieIf(err)

	maxRDiff := time.Duration(0)
	maxFDiff := time.Duration(0)
	frameCount := 0

	frametimeGoal := 1.0/60.0

	snapshotMode := 'x'

	newInput := dmgo.Input{}

	for {

		now := time.Now()

		inputDiff := now.Sub(lastInputPollTime)

		if inputDiff > 8*time.Millisecond {
			window.Mutex.Lock()
			newInput = dmgo.Input {
				Joypad: dmgo.Joypad {
					Sel:  window.CharIsDown('t'), Start: window.CharIsDown('y'),
					Up:   window.CharIsDown('w'), Down:  window.CharIsDown('s'),
					Left: window.CharIsDown('a'), Right: window.CharIsDown('d'),
					A:    window.CharIsDown('k'), B:     window.CharIsDown('j'),
				},
			}
			numDown := 'x'
			for r := '0'; r <= '9'; r++ {
				if window.CharIsDown(r) {
					numDown = r
					break
				}
			}
			if window.CharIsDown('m') {
				snapshotMode = 'm'
			} else if window.CharIsDown('l') {
				snapshotMode = 'l'
			}
			window.Mutex.Unlock()

			if numDown > '0' && numDown <= '9' {
				snapFilename := snapshotPrefix+string(numDown)
				if snapshotMode == 'm' {
					snapshotMode = 'x'
					snapshot := emu.MakeSnapshot()
					ioutil.WriteFile(snapFilename, snapshot, os.FileMode(0644))
				} else if snapshotMode == 'l' {
					snapshotMode = 'x'
					snapBytes, err := ioutil.ReadFile(snapFilename)
					if err != nil {
						fmt.Println("failed to load snapshot:", err)
						continue
					}
					newEmu, err := emu.LoadSnapshot(snapBytes)
					if err != nil {
						fmt.Println("failed to load snapshot:", err)
						continue
					}
					emu = newEmu
				}
			}
			lastInputPollTime = time.Now()
		}

		emu.UpdateInput(newInput)
		emu.Step()

		bufferAvailable := audio.BufferAvailable()

		// TODO: set this up so it's useful, but doesn't spam
		// if bufferAvailable == audio.BufferSize() {
			// fmt.Println("Platform AudioBuffer empty!")
		// }

		audioBufSlice := workingAudioBuffer[:bufferAvailable]
		audio.Write(emu.ReadSoundBuffer(audioBufSlice))

		if emu.FlipRequested() {
			window.Mutex.Lock()
			copy(window.Pix, emu.Framebuffer())
			window.RequestDraw()
			window.Mutex.Unlock()

			rDiff := time.Now().Sub(lastFlipTime)

			// hack to get better accuracy, could do
			// a two stage wait with spin at the end,
			// but that really adds to the cycles
			fudge := 2*time.Millisecond

			toWait := 16600000*time.Nanosecond - rDiff - fudge
			if toWait > time.Duration(0) {
				<-time.NewTimer(toWait).C
			}

			frameStart := lastFlipTime
			lastFlipTime = time.Now()

			fDiff := time.Now().Sub(frameStart)
			if rDiff > maxRDiff {
				maxRDiff = rDiff
			}
			if fDiff > maxFDiff {
				maxFDiff = fDiff
			}

			frameCount++
			if frameCount & 0xff == 0 {
				fmt.Printf("maxRTime %.4f, maxFTime %.4f\n", maxRDiff.Seconds(), maxFDiff.Seconds())
				maxRDiff = 0
				maxFDiff = 0
				if frametimeGoal == 0 {
					frametimeGoal = 1
				}
			}

		}
		if time.Now().Sub(lastSaveTime) > 5*time.Second {
			ram := emu.GetCartRAM()
			if len(ram) > 0 {
				ioutil.WriteFile(saveFilename, ram, os.FileMode(0644))
				lastSaveTime = time.Now()
			}
		}
	}
}

func assert(test bool, msg string) {
	if !test {
		fmt.Println(msg)
		os.Exit(1)
	}
}

func dieIf(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>Cut down on time.now calls<commit_after>package main

import (
	"github.com/theinternetftw/dmgo"
	"github.com/theinternetftw/dmgo/profiling"
	"github.com/theinternetftw/glimmer"

	"fmt"
	"io/ioutil"
	"os"
	"time"
)

func main() {

	defer profiling.Start().Stop()

	assert(len(os.Args) == 2, "usage: ./dmgo ROM_FILENAME")
	cartFilename := os.Args[1]

	cartBytes, err := ioutil.ReadFile(cartFilename)
	dieIf(err)

	assert(len(cartBytes) > 3, "cannot parse, file is too small")

	var emu dmgo.Emulator
	windowTitle := "dmgo"

	fileMagic := string(cartBytes[:3])
	if fileMagic == "GBS" {
		// nsf(e) file
		emu = dmgo.NewGbsPlayer(cartBytes)
	} else {
		// rom file

		cartInfo := dmgo.ParseCartInfo(cartBytes)
		fmt.Printf("%q\n", cartInfo.Title)
		fmt.Printf("Cart type: %d\n", cartInfo.CartridgeType)
		fmt.Printf("Cart RAM size: %d\n", cartInfo.GetRAMSize())
		fmt.Printf("Cart ROM size: %d\n", cartInfo.GetROMSize())

		emu = dmgo.NewEmulator(cartBytes)
		windowTitle = cartInfo.Title + " - dmgo"
	}

	glimmer.InitDisplayLoop(windowTitle, 160*4, 144*4, 160, 144, func(sharedState *glimmer.WindowState) {
		startEmu(cartFilename, sharedState, emu)
	})
}

func startHeadlessEmu(emu dmgo.Emulator) {
	// FIXME: settings are for debug right now
	ticker := time.NewTicker(17 * time.Millisecond)

	for {
		emu.Step()
		if emu.FlipRequested() {
			<-ticker.C
		}
	}
}

func startEmu(filename string, window *glimmer.WindowState, emu dmgo.Emulator) {

	// FIXME: settings are for debug right now
	lastFlipTime := time.Now()
	lastSaveTime := time.Now()
	lastInputPollTime := time.Now()

	timer := time.NewTimer(0)
	<-timer.C

	snapshotPrefix := filename + ".snapshot"

	saveFilename := filename + ".sav"
	if saveFile, err := ioutil.ReadFile(saveFilename); err == nil {
		err = emu.SetCartRAM(saveFile)
		if err != nil {
			fmt.Println("error loading savefile,", err)
		} else {
			fmt.Println("loaded save!")
		}
	}

	audio, err := glimmer.OpenAudioBuffer(4, 4096, 44100, 16, 2)
	workingAudioBuffer := make([]byte, audio.BufferSize())
	dieIf(err)

	maxRDiff := time.Duration(0)
	maxFDiff := time.Duration(0)
	frameCount := 0

	frametimeGoal := 1.0 / 60.0

	snapshotMode := 'x'

	newInput := dmgo.Input{}

	count := 0

	for {

		count++
		if count == 100 {
			count = 0
			now := time.Now()

			inputDiff := now.Sub(lastInputPollTime)

			if inputDiff > 8*time.Millisecond {
				window.Mutex.Lock()
				newInput = dmgo.Input{
					Joypad: dmgo.Joypad{
						Sel: window.CharIsDown('t'), Start: window.CharIsDown('y'),
						Up: window.CharIsDown('w'), Down: window.CharIsDown('s'),
						Left: window.CharIsDown('a'), Right: window.CharIsDown('d'),
						A: window.CharIsDown('k'), B: window.CharIsDown('j'),
					},
				}
				numDown := 'x'
				for r := '0'; r <= '9'; r++ {
					if window.CharIsDown(r) {
						numDown = r
						break
					}
				}
				if window.CharIsDown('m') {
					snapshotMode = 'm'
				} else if window.CharIsDown('l') {
					snapshotMode = 'l'
				}
				window.Mutex.Unlock()

				if numDown > '0' && numDown <= '9' {
					snapFilename := snapshotPrefix + string(numDown)
					if snapshotMode == 'm' {
						snapshotMode = 'x'
						snapshot := emu.MakeSnapshot()
						ioutil.WriteFile(snapFilename, snapshot, os.FileMode(0644))
					} else if snapshotMode == 'l' {
						snapshotMode = 'x'
						snapBytes, err := ioutil.ReadFile(snapFilename)
						if err != nil {
							fmt.Println("failed to load snapshot:", err)
							continue
						}
						newEmu, err := emu.LoadSnapshot(snapBytes)
						if err != nil {
							fmt.Println("failed to load snapshot:", err)
							continue
						}
						emu = newEmu
					}
				}
				lastInputPollTime = time.Now()
			}
		}

		emu.UpdateInput(newInput)
		emu.Step()

		bufferAvailable := audio.BufferAvailable()

		// TODO: set this up so it's useful, but doesn't spam
		// if bufferAvailable == audio.BufferSize() {
		// fmt.Println("Platform AudioBuffer empty!")
		// }

		audioBufSlice := workingAudioBuffer[:bufferAvailable]
		audio.Write(emu.ReadSoundBuffer(audioBufSlice))

		if emu.FlipRequested() {
			window.Mutex.Lock()
			copy(window.Pix, emu.Framebuffer())
			window.RequestDraw()
			window.Mutex.Unlock()

			rDiff := time.Now().Sub(lastFlipTime)

			// hack to get better accuracy, could do
			// a two stage wait with spin at the end,
			// but that really adds to the cycles
			fudge := 2 * time.Millisecond

			toWait := 16600000*time.Nanosecond - rDiff - fudge
			if toWait > time.Duration(0) {
				<-time.NewTimer(toWait).C
			}

			frameStart := lastFlipTime
			lastFlipTime = time.Now()

			fDiff := time.Now().Sub(frameStart)
			if rDiff > maxRDiff {
				maxRDiff = rDiff
			}
			if fDiff > maxFDiff {
				maxFDiff = fDiff
			}

			frameCount++
			if frameCount&0xff == 0 {
				fmt.Printf("maxRTime %.4f, maxFTime %.4f\n", maxRDiff.Seconds(), maxFDiff.Seconds())
				maxRDiff = 0
				maxFDiff = 0
				if frametimeGoal == 0 {
					frametimeGoal = 1
				}
			}

			if time.Now().Sub(lastSaveTime) > 5*time.Second {
				ram := emu.GetCartRAM()
				if len(ram) > 0 {
					ioutil.WriteFile(saveFilename, ram, os.FileMode(0644))
					lastSaveTime = time.Now()
				}
			}
		}
	}
}

func assert(test bool, msg string) {
	if !test {
		fmt.Println(msg)
		os.Exit(1)
	}
}

func dieIf(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<|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 main

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
	"google.golang.org/grpc"

	"k8s.io/helm/pkg/helm"
)

const (
	homeEnvVar = "HELM_HOME"
	hostEnvVar = "HELM_HOST"
)

var (
	helmHome        string
	tillerHost      string
	tillerNamespace string
)

// flagDebug is a signal that the user wants additional output.
var flagDebug bool

var globalUsage = `The Kubernetes package manager

To begin working with Helm, run the 'helm init' command:

	$ helm init

This will install Tiller to your running Kubernetes cluster.
It will also set up any necessary local configuration.

Common actions from this point include:

- helm search:    search for charts
- helm fetch:     download a chart to your local directory to view
- helm install:   upload the chart to Kubernetes
- helm list:      list releases of charts

Environment:
  $HELM_HOME      Set an alternative location for Helm files. By default, these are stored in ~/.helm
  $HELM_HOST      Set an alternative Tiller host. The format is host:port (default ":44134").
`

// RootCommand is the top-level command for Helm.
var RootCommand = &cobra.Command{
	Use:               "helm",
	Short:             "The Helm package manager for Kubernetes.",
	Long:              globalUsage,
	PersistentPostRun: teardown,
	SilenceUsage:      true,
}

func init() {
	home := os.Getenv(homeEnvVar)
	if home == "" {
		home = "$HOME/.helm"
	}
	thost := os.Getenv(hostEnvVar)
	p := RootCommand.PersistentFlags()
	p.StringVar(&helmHome, "home", home, "location of your Helm config. Overrides $HELM_HOME.")
	p.StringVar(&tillerHost, "host", thost, "address of tiller. Overrides $HELM_HOST.")
	p.StringVarP(&tillerNamespace, "namespace", "", "", "kubernetes namespace")
	p.BoolVarP(&flagDebug, "debug", "", false, "enable verbose output")
}

func main() {
	if err := RootCommand.Execute(); err != nil {
		os.Exit(1)
	}
}

func setupConnection(c *cobra.Command, args []string) error {
	if tillerHost == "" {
		tunnel, err := newTillerPortForwarder(tillerNamespace)
		if err != nil {
			return err
		}

		tillerHost = fmt.Sprintf(":%d", tunnel.Local)
		if flagDebug {
			fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local)
		}
	}

	// Set up the gRPC config.
	helm.Config.ServAddr = tillerHost
	if flagDebug {
		fmt.Printf("Server: %q\n", helm.Config.ServAddr)
	}
	return nil
}

func teardown(c *cobra.Command, args []string) {
	if tunnel != nil {
		tunnel.Close()
	}
}

func checkArgsLength(expectedNum, actualNum int, requiredArgs ...string) error {
	if actualNum != expectedNum {
		arg := "arguments"
		if expectedNum == 1 {
			arg = "argument"
		}
		return fmt.Errorf("This command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", "))
	}
	return nil
}

// requireInit is a PreRunE implementation for validating that $HELM_HOME is configured.
func requireInit(cmd *cobra.Command, args []string) error {
	err := requireHome()
	if err != nil {
		return fmt.Errorf("%s (try running 'helm init')", err)
	}
	return nil
}

// prettyError unwraps or rewrites certain errors to make them more user-friendly.
func prettyError(err error) error {
	// This is ridiculous. Why is 'grpc.rpcError' not exported? The least they
	// could do is throw an interface on the lib that would let us get back
	// the desc. Instead, we have to pass ALL errors through this.
	return errors.New(grpc.ErrorDesc(err))
}
<commit_msg>ref(cmd): move flags out of init()<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 main

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
	"google.golang.org/grpc"

	"k8s.io/helm/pkg/helm"
)

const (
	homeEnvVar = "HELM_HOME"
	hostEnvVar = "HELM_HOST"
)

var (
	helmHome        string
	tillerHost      string
	tillerNamespace string
)

// flagDebug is a signal that the user wants additional output.
var flagDebug bool

var globalUsage = `The Kubernetes package manager

To begin working with Helm, run the 'helm init' command:

	$ helm init

This will install Tiller to your running Kubernetes cluster.
It will also set up any necessary local configuration.

Common actions from this point include:

- helm search:    search for charts
- helm fetch:     download a chart to your local directory to view
- helm install:   upload the chart to Kubernetes
- helm list:      list releases of charts

Environment:
  $HELM_HOME      Set an alternative location for Helm files. By default, these are stored in ~/.helm
  $HELM_HOST      Set an alternative Tiller host. The format is host:port (default ":44134").
`

func newRootCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:          "helm",
		Short:        "The Helm package manager for Kubernetes.",
		Long:         globalUsage,
		SilenceUsage: true,
		PersistentPostRun: func(cmd *cobra.Command, args []string) {
			teardown()
		},
	}
	home := os.Getenv(homeEnvVar)
	if home == "" {
		home = "$HOME/.helm"
	}
	thost := os.Getenv(hostEnvVar)
	p := cmd.PersistentFlags()
	p.StringVar(&helmHome, "home", home, "location of your Helm config. Overrides $HELM_HOME.")
	p.StringVar(&tillerHost, "host", thost, "address of tiller. Overrides $HELM_HOST.")
	p.StringVarP(&tillerNamespace, "namespace", "", "", "kubernetes namespace")
	p.BoolVarP(&flagDebug, "debug", "", false, "enable verbose output")
	return cmd
}

// RootCommand is the top-level command for Helm.
var RootCommand = newRootCmd()

func main() {
	cmd := RootCommand
	if err := cmd.Execute(); err != nil {
		os.Exit(1)
	}
}

func setupConnection(c *cobra.Command, args []string) error {
	if tillerHost == "" {
		tunnel, err := newTillerPortForwarder(tillerNamespace)
		if err != nil {
			return err
		}

		tillerHost = fmt.Sprintf(":%d", tunnel.Local)
		if flagDebug {
			fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local)
		}
	}

	// Set up the gRPC config.
	helm.Config.ServAddr = tillerHost
	if flagDebug {
		fmt.Printf("Server: %q\n", helm.Config.ServAddr)
	}
	return nil
}

func teardown() {
	if tunnel != nil {
		tunnel.Close()
	}
}

func checkArgsLength(expectedNum, actualNum int, requiredArgs ...string) error {
	if actualNum != expectedNum {
		arg := "arguments"
		if expectedNum == 1 {
			arg = "argument"
		}
		return fmt.Errorf("This command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", "))
	}
	return nil
}

// requireInit is a PreRunE implementation for validating that $HELM_HOME is configured.
func requireInit(cmd *cobra.Command, args []string) error {
	err := requireHome()
	if err != nil {
		return fmt.Errorf("%s (try running 'helm init')", err)
	}
	return nil
}

// prettyError unwraps or rewrites certain errors to make them more user-friendly.
func prettyError(err error) error {
	// This is ridiculous. Why is 'grpc.rpcError' not exported? The least they
	// could do is throw an interface on the lib that would let us get back
	// the desc. Instead, we have to pass ALL errors through this.
	return errors.New(grpc.ErrorDesc(err))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"
	"os"
	"runtime/pprof"

	cmds "github.com/jbenet/go-ipfs/commands"
	cmdsCli "github.com/jbenet/go-ipfs/commands/cli"
	cmdsHttp "github.com/jbenet/go-ipfs/commands/http"
	"github.com/jbenet/go-ipfs/core/commands"
	u "github.com/jbenet/go-ipfs/util"
)

// log is the command logger
var log = u.Logger("cmd/ipfs")

func main() {
	args := os.Args[1:]

	req, err := cmdsCli.Parse(args, Root)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if len(req.Path()) == 0 {
		req, err = cmdsCli.Parse(args, commands.Root)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	var local bool // TODO: option to force local
	var root *cmds.Command
	cmd, err := Root.Get(req.Path())
	if err == nil {
		local = true
		root = Root

	} else if local {
		fmt.Println(err)
		os.Exit(1)

	} else {
		cmd, err = commands.Root.Get(req.Path())
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		local = false
		root = commands.Root
	}

	// TODO: get converted options so we can use them here (e.g. --debug, --config)

	if debug, ok := req.Option("debug"); ok && debug.(bool) {
		u.Debug = true

		// if debugging, setup profiling.
		if u.Debug {
			ofi, err := os.Create("cpu.prof")
			if err != nil {
				fmt.Println(err)
				return
			}
			pprof.StartCPUProfile(ofi)
			defer ofi.Close()
			defer pprof.StopCPUProfile()
		}
	}

	var res cmds.Response
	if local {
		// TODO: spin up node
		res = root.Call(req)
	} else {
		res, err = cmdsHttp.Send(req)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	if res.Error() != nil {
		fmt.Println(res.Error().Error())

		if cmd.Help != "" && res.Error().Code == cmds.ErrClient {
			// TODO: convert from markdown to ANSI terminal format?
			fmt.Println(cmd.Help)
		}

		os.Exit(1)
	}

	_, err = io.Copy(os.Stdout, res)
	if err != nil {
		fmt.Println(err.Error())
	}
}
<commit_msg>cmd/ipfs: Do command option conversion in CLI entry point<commit_after>package main

import (
	"fmt"
	"io"
	"os"
	"runtime/pprof"

	cmds "github.com/jbenet/go-ipfs/commands"
	cmdsCli "github.com/jbenet/go-ipfs/commands/cli"
	cmdsHttp "github.com/jbenet/go-ipfs/commands/http"
	"github.com/jbenet/go-ipfs/core/commands"
	u "github.com/jbenet/go-ipfs/util"
)

// log is the command logger
var log = u.Logger("cmd/ipfs")

func main() {
	args := os.Args[1:]
	root := Root

	req, err := cmdsCli.Parse(args, root)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// if the CLI-specific root doesn't contain the command, use the general root
	if len(req.Path()) == 0 {
		root = commands.Root
		req, err = cmdsCli.Parse(args, root)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	cmd, err := root.Get(req.Path())
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	options, err := getOptions(req, root)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	if debug, ok := options["debug"]; ok && debug.(bool) {
		u.Debug = true

		// if debugging, setup profiling.
		if u.Debug {
			ofi, err := os.Create("cpu.prof")
			if err != nil {
				fmt.Println(err)
				return
			}
			pprof.StartCPUProfile(ofi)
			defer ofi.Close()
			defer pprof.StopCPUProfile()
		}
	}

	var res cmds.Response
	if root == Root {
		// TODO: spin up node
		res = root.Call(req)
	} else {
		res, err = cmdsHttp.Send(req)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	}

	if res.Error() != nil {
		fmt.Println(res.Error().Error())

		if cmd.Help != "" && res.Error().Code == cmds.ErrClient {
			// TODO: convert from markdown to ANSI terminal format?
			fmt.Println(cmd.Help)
		}

		os.Exit(1)
	}

	_, err = io.Copy(os.Stdout, res)
	if err != nil {
		fmt.Println(err.Error())
	}
}

func getOptions(req cmds.Request, root *cmds.Command) (map[string]interface{}, error) {
	tempReq := cmds.NewRequest(req.Path(), req.Options(), nil, nil)

	options, err := root.GetOptions(tempReq.Path())
	if err != nil {
		return nil, err
	}

	err = tempReq.ConvertOptions(options)
	if err != nil {
		return nil, err
	}

	return tempReq.Options(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/cyberdelia/lzo"
)

var (
	uncompress = flag.Bool("decompress", false, "Decompress.")
	level      = flag.Int("level", 3, "Compression level.")
)

func decompress(path string) error {
	input, err := os.Open(path)
	if err != nil {
		return err
	}
	decompressor, err := lzo.NewReader(input)
	if err != nil {
		return err
	}
	output, err := os.Create(decompressor.Name)
	if err != nil {
		return err
	}
	_, err = io.Copy(output, decompressor)
	if err != nil {
		return err
	}
	return nil
}

func compress(level int, path string) error {
	if level > lzo.BestCompression {
		level = lzo.BestCompression
	} else if level < lzo.BestSpeed {
		level = lzo.BestSpeed
	} else {
		level = lzo.DefaultCompression
	}
	input, err := os.Open(path)
	if err != nil {
		return err
	}
	output, err := os.Create(path + ".lzo")
	if err != nil {
		return err
	}
	compressor, err := lzo.NewWriterLevel(output, level)
	defer compressor.Close()
	compressor.Name = input.Name()
	if err != nil {
		return err
	}
	_, err = io.Copy(compressor, input)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	flag.Parse()
	path := flag.Arg(0)
	var err error
	if *uncompress == true {
		err = decompress(path)
	} else {
		err = compress(*level, path)
	}
	if err != nil {
		fmt.Println("lzop:", err)
	}
}
<commit_msg>output error on stderr<commit_after>package main

import (
	"flag"
	"io"
	"log"
	"os"

	"github.com/cyberdelia/lzo"
)

var (
	uncompress = flag.Bool("decompress", false, "Decompress.")
	level      = flag.Int("level", 3, "Compression level.")
)

func decompress(path string) error {
	input, err := os.Open(path)
	if err != nil {
		return err
	}
	decompressor, err := lzo.NewReader(input)
	if err != nil {
		return err
	}
	output, err := os.Create(decompressor.Name)
	if err != nil {
		return err
	}
	_, err = io.Copy(output, decompressor)
	if err != nil {
		return err
	}
	return nil
}

func compress(level int, path string) error {
	if level > lzo.BestCompression {
		level = lzo.BestCompression
	} else if level < lzo.BestSpeed {
		level = lzo.BestSpeed
	} else {
		level = lzo.DefaultCompression
	}
	input, err := os.Open(path)
	if err != nil {
		return err
	}
	output, err := os.Create(path + ".lzo")
	if err != nil {
		return err
	}
	compressor, err := lzo.NewWriterLevel(output, level)
	defer compressor.Close()
	compressor.Name = input.Name()
	if err != nil {
		return err
	}
	_, err = io.Copy(compressor, input)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	log.SetFlags(0)
	flag.Parse()
	path := flag.Arg(0)
	var err error
	if *uncompress == true {
		err = decompress(path)
	} else {
		err = compress(*level, path)
	}
	if err != nil {
		log.Println("lzop:", err)
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"text/template"

	"github.com/pkg/errors"
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	gitconfig "github.com/tcnksm/go-gitconfig"
	gitlab "github.com/xanzy/go-gitlab"
	"github.com/zaquestion/lab/internal/action"
	"github.com/zaquestion/lab/internal/git"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

// mrCmd represents the mr command
var mrCreateCmd = &cobra.Command{
	Use:              "create [remote [branch]]",
	Aliases:          []string{"new"},
	Short:            "Open a merge request on GitLab",
	Long:             `Creates a merge request (default: MR created on default branch of origin)`,
	Args:             cobra.MaximumNArgs(2),
	PersistentPreRun: LabPersistentPreRun,
	Run:              runMRCreate,
}

func init() {
	mrCreateCmd.Flags().StringArrayP("message", "m", []string{}, "use the given <msg>; multiple -m are concatenated as separate paragraphs")
	mrCreateCmd.Flags().StringSliceP("assignee", "a", []string{}, "set assignee by username; can be specified multiple times for multiple assignees")
	mrCreateCmd.Flags().StringSliceP("label", "l", []string{}, "add label <label>; can be specified multiple times for multiple labels")
	mrCreateCmd.Flags().BoolP("remove-source-branch", "d", false, "remove source branch from remote after merge")
	mrCreateCmd.Flags().BoolP("squash", "s", false, "squash commits when merging")
	mrCreateCmd.Flags().Bool("allow-collaboration", false, "allow commits from other members")
	mrCreateCmd.Flags().Int("milestone", -1, "set milestone by milestone ID")
	mrCreateCmd.Flags().StringP("file", "F", "", "use the given file as the Description")
	mrCreateCmd.Flags().Bool("force-linebreak", false, "append 2 spaces to the end of each line to force markdown linebreaks")
	mrCreateCmd.Flags().BoolP("cover-letter", "c", false, "do not comment changelog and diffstat")
	mergeRequestCmd.Flags().AddFlagSet(mrCreateCmd.Flags())

	mrCmd.AddCommand(mrCreateCmd)
	carapace.Gen(mrCreateCmd).PositionalCompletion(
		action.Remotes(),
		action.RemoteBranches(0),
	)
}

// getAssignee returns the assigneeID for use with other GitLab API calls.
// NOTE: It is also used by issue_create.go
func getAssigneeID(assignee string) *int {
	if assignee == "" {
		return nil
	}
	if assignee[0] == '@' {
		assignee = assignee[1:]
	}
	assigneeID, err := lab.UserIDFromUsername(assignee)
	if err != nil {
		return nil
	}
	if assigneeID == -1 {
		return nil
	}
	return gitlab.Int(assigneeID)
}

// getAssignees returns the assigneeIDs for use with other GitLab API calls.
func getAssigneeIDs(assignees []string) []int {
	var ids []int
	for _, a := range assignees {
		ids = append(ids, *getAssigneeID(a))
	}
	return ids
}

func runMRCreate(cmd *cobra.Command, args []string) {
	msgs, err := cmd.Flags().GetStringArray("message")
	if err != nil {
		log.Fatal(err)
	}
	assignees, err := cmd.Flags().GetStringSlice("assignee")
	if err != nil {
		log.Fatal(err)
	}
	filename, err := cmd.Flags().GetString("file")
	if err != nil {
		log.Fatal(err)
	}
	branch, err := git.CurrentBranch()
	if err != nil {
		log.Fatal(err)
	}

	sourceRemote := determineSourceRemote(branch)
	sourceProjectName, err := git.PathWithNameSpace(sourceRemote)
	if err != nil {
		log.Fatal(err)
	}

	remoteBranch, err := git.CurrentUpstreamBranch()
	if remoteBranch == "" {
		// Fall back to local branch
		remoteBranch, err = git.CurrentBranch()
	}

	if err != nil {
		log.Fatal(err)
	}

	p, err := lab.FindProject(sourceProjectName)
	if err != nil {
		log.Fatal(err)
	}
	if _, err := lab.GetCommit(p.ID, remoteBranch); err != nil {
		err = errors.Wrapf(
			err,
			"aborting MR, source branch %s not present on remote %s. did you forget to push?",
			remoteBranch, sourceRemote)
		log.Fatal(err)
	}

	targetRemote := forkedFromRemote
	if len(args) > 0 {
		targetRemote = args[0]
		ok, err := git.IsRemote(targetRemote)
		if err != nil || !ok {
			log.Fatal(errors.Wrapf(err, "%s is not a valid remote", targetRemote))
		}
	}
	targetProjectName, err := git.PathWithNameSpace(targetRemote)
	if err != nil {
		log.Fatal(err)
	}
	targetProject, err := lab.FindProject(targetProjectName)
	if err != nil {
		log.Fatal(err)
	}

	targetBranch := targetProject.DefaultBranch
	if len(args) > 1 && targetBranch != args[1] {
		targetBranch = args[1]
		if _, err := lab.GetCommit(targetProject.ID, targetBranch); err != nil {
			err = errors.Wrapf(
				err,
				"aborting MR, %s:%s is not a valid target. Did you forget to push %s to %s?",
				targetRemote, branch, branch, targetRemote)
			log.Fatal(err)
		}
	}

	var title, body string

	if filename != "" {
		file, err := os.Open(filename)
		if err != nil {
			log.Fatal(err)
		}

		fileScan := bufio.NewScanner(file)
		fileScan.Split(bufio.ScanLines)

		// The first line in the file is the title.
		fileScan.Scan()
		title = fileScan.Text()

		for fileScan.Scan() {
			body = body + fileScan.Text() + "\n"
		}

		file.Close()

	} else if len(msgs) > 0 {
		title, body = msgs[0], strings.Join(msgs[1:], "\n\n")
	} else {
		coverLetterFormat, _ := cmd.Flags().GetBool("cover-letter")
		msg, err := mrText(targetBranch, branch, sourceRemote, forkedFromRemote, coverLetterFormat)
		if err != nil {
			log.Fatal(err)
		}

		title, body, err = git.Edit("MERGEREQ", msg)
		if err != nil {
			_, f, l, _ := runtime.Caller(0)
			log.Fatal(f+":"+strconv.Itoa(l)+" ", err)
		}
	}

	linebreak, _ := cmd.Flags().GetBool("force-linebreak")
	if linebreak {
		body = textToMarkdown(body)
	}

	removeSourceBranch, _ := cmd.Flags().GetBool("remove-source-branch")
	squash, _ := cmd.Flags().GetBool("squash")
	allowCollaboration, _ := cmd.Flags().GetBool("allow-collaboration")

	labels, err := cmd.Flags().GetStringSlice("label")
	if err != nil {
		log.Fatal(err)
	}

	milestoneID, _ := cmd.Flags().GetInt("milestone")
	var milestone *int
	if milestoneID < 0 {
		milestone = nil
	} else {
		milestone = &milestoneID
	}

	if title == "" {
		log.Fatal("aborting MR due to empty MR msg")
	}

	mrURL, err := lab.MRCreate(sourceProjectName, &gitlab.CreateMergeRequestOptions{
		SourceBranch:       &branch,
		TargetBranch:       gitlab.String(targetBranch),
		TargetProjectID:    &targetProject.ID,
		Title:              &title,
		Description:        &body,
		AssigneeIDs:        getAssigneeIDs(assignees),
		RemoveSourceBranch: &removeSourceBranch,
		Squash:             &squash,
		AllowCollaboration: &allowCollaboration,
		Labels:             labels,
		MilestoneID:        milestone,
	})
	if err != nil {
		// FIXME: not exiting fatal here to allow code coverage to
		// generate during Test_mrCreate. In the meantime API failures
		// will exit 0
		fmt.Fprintln(os.Stderr, err)
	}
	fmt.Println(mrURL + "/diffs")
}

func determineSourceRemote(branch string) string {
	// There is a precendence of options that should be considered here:
	// branch.<name>.pushRemote > remote.pushDefault > branch.<name>.remote
	// This rule is placed in git-config(1) manpage
	r, err := gitconfig.Local("branch." + branch + ".pushRemote")
	if err == nil {
		return r
	}
	r, err = gitconfig.Local("remote.pushDefault")
	if err == nil {
		return r
	}
	r, err = gitconfig.Local("branch." + branch + ".remote")
	if err == nil {
		return r
	}

	return forkRemote
}

func mrText(base, head, sourceRemote, forkedFromRemote string, coverLetterFormat bool) (string, error) {
	var (
		commitMsg string
		err       error
	)
	remoteBase := fmt.Sprintf("%s/%s", forkedFromRemote, base)
	commitMsg = ""
	if git.NumberCommits(remoteBase, head) == 1 {
		commitMsg, err = git.LastCommitMessage()
		if err != nil {
			return "", err
		}
	}

	const tmpl = `{{if .InitMsg}}{{.InitMsg}}{{end}}

{{if .Tmpl}}{{.Tmpl}}{{end}}
{{.CommentChar}} Requesting a merge into {{.Base}} from {{.Head}}
{{.CommentChar}}
{{.CommentChar}} Write a message for this merge request. The first block
{{.CommentChar}} of text is the title and the rest is the description.{{if .CommitLogs}}
{{.CommentChar}}
{{.CommentChar}} Changes:
{{.CommentChar}}
{{.CommitLogs}}{{end}}`

	mrTmpl := lab.LoadGitLabTmpl(lab.TmplMR)

	commitLogs, err := git.Log(remoteBase, head)
	if err != nil {
		return "", err
	}
	commitLogs = strings.TrimSpace(commitLogs)
	commentChar := git.CommentChar()

	if !coverLetterFormat {
		startRegexp := regexp.MustCompilePOSIX("^")
		commitLogs = startRegexp.ReplaceAllString(commitLogs, fmt.Sprintf("%s ", commentChar))
	} else {
		commitLogs = "\n" + strings.TrimSpace(commitLogs)
	}

	t, err := template.New("tmpl").Parse(tmpl)
	if err != nil {
		return "", err
	}

	msg := &struct {
		InitMsg     string
		Tmpl        string
		CommentChar string
		Base        string
		Head        string
		CommitLogs  string
	}{
		InitMsg:     commitMsg,
		Tmpl:        mrTmpl,
		CommentChar: commentChar,
		Base:        forkedFromRemote + ":" + base,
		Head:        sourceRemote + ":" + head,
		CommitLogs:  commitLogs,
	}

	var b bytes.Buffer
	err = t.Execute(&b, msg)
	if err != nil {
		return "", err
	}

	return b.String(), nil
}
<commit_msg>mr_create: Allow creating draft merge request<commit_after>package cmd

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"os"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"text/template"

	"github.com/pkg/errors"
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	gitconfig "github.com/tcnksm/go-gitconfig"
	gitlab "github.com/xanzy/go-gitlab"
	"github.com/zaquestion/lab/internal/action"
	"github.com/zaquestion/lab/internal/git"
	lab "github.com/zaquestion/lab/internal/gitlab"
)

// mrCmd represents the mr command
var mrCreateCmd = &cobra.Command{
	Use:              "create [remote [branch]]",
	Aliases:          []string{"new"},
	Short:            "Open a merge request on GitLab",
	Long:             `Creates a merge request (default: MR created on default branch of origin)`,
	Args:             cobra.MaximumNArgs(2),
	PersistentPreRun: LabPersistentPreRun,
	Run:              runMRCreate,
}

func init() {
	mrCreateCmd.Flags().StringArrayP("message", "m", []string{}, "use the given <msg>; multiple -m are concatenated as separate paragraphs")
	mrCreateCmd.Flags().StringSliceP("assignee", "a", []string{}, "set assignee by username; can be specified multiple times for multiple assignees")
	mrCreateCmd.Flags().StringSliceP("label", "l", []string{}, "add label <label>; can be specified multiple times for multiple labels")
	mrCreateCmd.Flags().BoolP("remove-source-branch", "d", false, "remove source branch from remote after merge")
	mrCreateCmd.Flags().BoolP("squash", "s", false, "squash commits when merging")
	mrCreateCmd.Flags().Bool("allow-collaboration", false, "allow commits from other members")
	mrCreateCmd.Flags().Int("milestone", -1, "set milestone by milestone ID")
	mrCreateCmd.Flags().StringP("file", "F", "", "use the given file as the Description")
	mrCreateCmd.Flags().Bool("force-linebreak", false, "append 2 spaces to the end of each line to force markdown linebreaks")
	mrCreateCmd.Flags().BoolP("cover-letter", "c", false, "do not comment changelog and diffstat")
	mrCreateCmd.Flags().Bool("draft", false, "mark the merge request as draft")
	mergeRequestCmd.Flags().AddFlagSet(mrCreateCmd.Flags())

	mrCmd.AddCommand(mrCreateCmd)
	carapace.Gen(mrCreateCmd).PositionalCompletion(
		action.Remotes(),
		action.RemoteBranches(0),
	)
}

// getAssignee returns the assigneeID for use with other GitLab API calls.
// NOTE: It is also used by issue_create.go
func getAssigneeID(assignee string) *int {
	if assignee == "" {
		return nil
	}
	if assignee[0] == '@' {
		assignee = assignee[1:]
	}
	assigneeID, err := lab.UserIDFromUsername(assignee)
	if err != nil {
		return nil
	}
	if assigneeID == -1 {
		return nil
	}
	return gitlab.Int(assigneeID)
}

// getAssignees returns the assigneeIDs for use with other GitLab API calls.
func getAssigneeIDs(assignees []string) []int {
	var ids []int
	for _, a := range assignees {
		ids = append(ids, *getAssigneeID(a))
	}
	return ids
}

func runMRCreate(cmd *cobra.Command, args []string) {
	msgs, err := cmd.Flags().GetStringArray("message")
	if err != nil {
		log.Fatal(err)
	}
	assignees, err := cmd.Flags().GetStringSlice("assignee")
	if err != nil {
		log.Fatal(err)
	}
	filename, err := cmd.Flags().GetString("file")
	if err != nil {
		log.Fatal(err)
	}
	branch, err := git.CurrentBranch()
	if err != nil {
		log.Fatal(err)
	}

	sourceRemote := determineSourceRemote(branch)
	sourceProjectName, err := git.PathWithNameSpace(sourceRemote)
	if err != nil {
		log.Fatal(err)
	}

	remoteBranch, err := git.CurrentUpstreamBranch()
	if remoteBranch == "" {
		// Fall back to local branch
		remoteBranch, err = git.CurrentBranch()
	}

	if err != nil {
		log.Fatal(err)
	}

	p, err := lab.FindProject(sourceProjectName)
	if err != nil {
		log.Fatal(err)
	}
	if _, err := lab.GetCommit(p.ID, remoteBranch); err != nil {
		err = errors.Wrapf(
			err,
			"aborting MR, source branch %s not present on remote %s. did you forget to push?",
			remoteBranch, sourceRemote)
		log.Fatal(err)
	}

	targetRemote := forkedFromRemote
	if len(args) > 0 {
		targetRemote = args[0]
		ok, err := git.IsRemote(targetRemote)
		if err != nil || !ok {
			log.Fatal(errors.Wrapf(err, "%s is not a valid remote", targetRemote))
		}
	}
	targetProjectName, err := git.PathWithNameSpace(targetRemote)
	if err != nil {
		log.Fatal(err)
	}
	targetProject, err := lab.FindProject(targetProjectName)
	if err != nil {
		log.Fatal(err)
	}

	targetBranch := targetProject.DefaultBranch
	if len(args) > 1 && targetBranch != args[1] {
		targetBranch = args[1]
		if _, err := lab.GetCommit(targetProject.ID, targetBranch); err != nil {
			err = errors.Wrapf(
				err,
				"aborting MR, %s:%s is not a valid target. Did you forget to push %s to %s?",
				targetRemote, branch, branch, targetRemote)
			log.Fatal(err)
		}
	}

	var title, body string

	if filename != "" {
		file, err := os.Open(filename)
		if err != nil {
			log.Fatal(err)
		}

		fileScan := bufio.NewScanner(file)
		fileScan.Split(bufio.ScanLines)

		// The first line in the file is the title.
		fileScan.Scan()
		title = fileScan.Text()

		for fileScan.Scan() {
			body = body + fileScan.Text() + "\n"
		}

		file.Close()

	} else if len(msgs) > 0 {
		title, body = msgs[0], strings.Join(msgs[1:], "\n\n")
	} else {
		coverLetterFormat, _ := cmd.Flags().GetBool("cover-letter")
		msg, err := mrText(targetBranch, branch, sourceRemote, forkedFromRemote, coverLetterFormat)
		if err != nil {
			log.Fatal(err)
		}

		title, body, err = git.Edit("MERGEREQ", msg)
		if err != nil {
			_, f, l, _ := runtime.Caller(0)
			log.Fatal(f+":"+strconv.Itoa(l)+" ", err)
		}
	}

	linebreak, _ := cmd.Flags().GetBool("force-linebreak")
	if linebreak {
		body = textToMarkdown(body)
	}

	draft, _ := cmd.Flags().GetBool("draft")
	if draft {
		isWIP := strings.EqualFold(title[0:4], "wip:")
		isDraft := strings.EqualFold(title[0:6], "draft:") ||
			strings.EqualFold(title[0:7], "[draft]") ||
			strings.EqualFold(title[0:7], "(draft)")

		if !isWIP && !isDraft {
			title = "Draft: " + title
		}
	}

	removeSourceBranch, _ := cmd.Flags().GetBool("remove-source-branch")
	squash, _ := cmd.Flags().GetBool("squash")
	allowCollaboration, _ := cmd.Flags().GetBool("allow-collaboration")

	labels, err := cmd.Flags().GetStringSlice("label")
	if err != nil {
		log.Fatal(err)
	}

	milestoneID, _ := cmd.Flags().GetInt("milestone")
	var milestone *int
	if milestoneID < 0 {
		milestone = nil
	} else {
		milestone = &milestoneID
	}

	if title == "" {
		log.Fatal("aborting MR due to empty MR msg")
	}

	mrURL, err := lab.MRCreate(sourceProjectName, &gitlab.CreateMergeRequestOptions{
		SourceBranch:       &branch,
		TargetBranch:       gitlab.String(targetBranch),
		TargetProjectID:    &targetProject.ID,
		Title:              &title,
		Description:        &body,
		AssigneeIDs:        getAssigneeIDs(assignees),
		RemoveSourceBranch: &removeSourceBranch,
		Squash:             &squash,
		AllowCollaboration: &allowCollaboration,
		Labels:             labels,
		MilestoneID:        milestone,
	})
	if err != nil {
		// FIXME: not exiting fatal here to allow code coverage to
		// generate during Test_mrCreate. In the meantime API failures
		// will exit 0
		fmt.Fprintln(os.Stderr, err)
	}
	fmt.Println(mrURL + "/diffs")
}

func determineSourceRemote(branch string) string {
	// There is a precendence of options that should be considered here:
	// branch.<name>.pushRemote > remote.pushDefault > branch.<name>.remote
	// This rule is placed in git-config(1) manpage
	r, err := gitconfig.Local("branch." + branch + ".pushRemote")
	if err == nil {
		return r
	}
	r, err = gitconfig.Local("remote.pushDefault")
	if err == nil {
		return r
	}
	r, err = gitconfig.Local("branch." + branch + ".remote")
	if err == nil {
		return r
	}

	return forkRemote
}

func mrText(base, head, sourceRemote, forkedFromRemote string, coverLetterFormat bool) (string, error) {
	var (
		commitMsg string
		err       error
	)
	remoteBase := fmt.Sprintf("%s/%s", forkedFromRemote, base)
	commitMsg = ""
	if git.NumberCommits(remoteBase, head) == 1 {
		commitMsg, err = git.LastCommitMessage()
		if err != nil {
			return "", err
		}
	}

	const tmpl = `{{if .InitMsg}}{{.InitMsg}}{{end}}

{{if .Tmpl}}{{.Tmpl}}{{end}}
{{.CommentChar}} Requesting a merge into {{.Base}} from {{.Head}}
{{.CommentChar}}
{{.CommentChar}} Write a message for this merge request. The first block
{{.CommentChar}} of text is the title and the rest is the description.{{if .CommitLogs}}
{{.CommentChar}}
{{.CommentChar}} Changes:
{{.CommentChar}}
{{.CommitLogs}}{{end}}`

	mrTmpl := lab.LoadGitLabTmpl(lab.TmplMR)

	commitLogs, err := git.Log(remoteBase, head)
	if err != nil {
		return "", err
	}
	commitLogs = strings.TrimSpace(commitLogs)
	commentChar := git.CommentChar()

	if !coverLetterFormat {
		startRegexp := regexp.MustCompilePOSIX("^")
		commitLogs = startRegexp.ReplaceAllString(commitLogs, fmt.Sprintf("%s ", commentChar))
	} else {
		commitLogs = "\n" + strings.TrimSpace(commitLogs)
	}

	t, err := template.New("tmpl").Parse(tmpl)
	if err != nil {
		return "", err
	}

	msg := &struct {
		InitMsg     string
		Tmpl        string
		CommentChar string
		Base        string
		Head        string
		CommitLogs  string
	}{
		InitMsg:     commitMsg,
		Tmpl:        mrTmpl,
		CommentChar: commentChar,
		Base:        forkedFromRemote + ":" + base,
		Head:        sourceRemote + ":" + head,
		CommitLogs:  commitLogs,
	}

	var b bytes.Buffer
	err = t.Execute(&b, msg)
	if err != nil {
		return "", err
	}

	return b.String(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"http"
	"io"
	"fmt"
	"net"
	"strings"
	"log"
	"jra-go.googlecode.com/hg/linkio"
)

var gLink *linkio.Link

func init() {
	gLink = linkio.NewLink(56 /* kbps */ )
}

func loghit(r *http.Request, code int) {
	log.Printf("%v %v %v", r.Method, r.RawURL, code)
}

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

var doNotCopy = map[string]bool{
	"Connection":        true,
	"Transfer-Encoding": true,
	"Trailer":           true,
}

type Proxy struct{}

func NewProxy() *Proxy { return &Proxy{} }

func (p *Proxy) ServeHTTP(cwr http.ResponseWriter, creq *http.Request) {
	// c = things towards the client of the proxy
	// o = things towards origin server
	oreq := new(http.Request)
	oreq.ProtoMajor = 1
	oreq.ProtoMinor = 1
	oreq.Close = true
	oreq.Header = creq.Header
	oreq.Method = creq.Method

	ourl, err := http.ParseURL(creq.RawURL)
	if err != nil {
		http.Error(cwr, fmt.Sprint("Malformed request", err),
			http.StatusNotImplemented)
		loghit(creq, http.StatusNotImplemented)
		return
	}
	// don't set RawURL, or else the request will be written with only
	// it, instead of using the URL.Path as we want (see (* http.Request)Write)
	oreq.URL = ourl

	if oreq.URL.Scheme != "http" {
		http.Error(cwr, "I only proxy http", http.StatusNotImplemented)
		loghit(creq, http.StatusNotImplemented)
		return
	}

	if oreq.Method != "GET" && oreq.Method != "POST" {
		log.Print("Cannot handle method ", creq.Method)
		http.Error(cwr, "I only handle GET and POST", http.StatusNotImplemented)
		return
	}

	if oreq.Method == "POST" {
		oreq.Method = "POST"
		if _, ok := oreq.Header["Content-Type"]; !ok {
			oreq.Header.Set("Content-Type", "multipart/form-data")
		}
		oreq.ContentLength = creq.ContentLength
		oreq.Body = creq.Body
	}

	addr := oreq.URL.Host
	if !hasPort(addr) {
		addr += ":" + oreq.URL.Scheme
	}
	c, err := net.Dial("tcp", "", addr)
	if err != nil {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}
	c.SetReadTimeout(3 * 1e9)
	cc := http.NewClientConn(c, nil)

	// debug
	//dbg, err := http.DumpRequest(oreq, true)
	//log.Print("Dump request to origin server:\n", string(dbg))

	err = cc.Write(oreq)
	if err != nil {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}

	oresp, err := cc.Read(oreq)
	if err != nil && err != http.ErrPersistEOF {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}

	//dbg, err = http.DumpResponse(oresp, true)
	//log.Print("Dump response from origin server:\n", string(dbg))

	for hdr, val := range oresp.Header {
		if !doNotCopy[hdr] {
			for i := 0; i < len(val); i++ {
				cwr.SetHeader(hdr, val[i])
			}
		}
	}
	cwr.WriteHeader(oresp.StatusCode)

	// simulate it coming in over gLink, a shared rate-limited link
	io.Copy(cwr, gLink.NewLinkReader(oresp.Body))

	cc.Close()
	c.Close()
	loghit(creq, oresp.StatusCode)
}

func main() {
	proxy := NewProxy()
	err := http.ListenAndServe("[::]:12345", proxy)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.String())
	}
}

// ex: ts=2
<commit_msg>Make it build with r8171 (current tip).<commit_after>package main

import (
	"http"
	"io"
	"fmt"
	"net"
	"strings"
	"log"
	"jra-go.googlecode.com/hg/linkio"
)

var gLink *linkio.Link

func init() {
	gLink = linkio.NewLink(56 /* kbps */ )
}

func loghit(r *http.Request, code int) {
	log.Printf("%v %v %v", r.Method, r.RawURL, code)
}

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

var doNotCopy = map[string]bool{
	"Connection":        true,
	"Transfer-Encoding": true,
	"Trailer":           true,
}

type Proxy struct{}

func NewProxy() *Proxy { return &Proxy{} }

func (p *Proxy) ServeHTTP(cwr http.ResponseWriter, creq *http.Request) {
	// c = things towards the client of the proxy
	// o = things towards origin server
	oreq := new(http.Request)
	oreq.ProtoMajor = 1
	oreq.ProtoMinor = 1
	oreq.Close = true
	oreq.Header = creq.Header
	oreq.Method = creq.Method

	ourl, err := http.ParseURL(creq.RawURL)
	if err != nil {
		http.Error(cwr, fmt.Sprint("Malformed request", err),
			http.StatusNotImplemented)
		loghit(creq, http.StatusNotImplemented)
		return
	}
	// don't set RawURL, or else the request will be written with only
	// it, instead of using the URL.Path as we want (see (* http.Request)Write)
	oreq.URL = ourl

	if oreq.URL.Scheme != "http" {
		http.Error(cwr, "I only proxy http", http.StatusNotImplemented)
		loghit(creq, http.StatusNotImplemented)
		return
	}

	if oreq.Method != "GET" && oreq.Method != "POST" {
		log.Print("Cannot handle method ", creq.Method)
		http.Error(cwr, "I only handle GET and POST", http.StatusNotImplemented)
		return
	}

	if oreq.Method == "POST" {
		oreq.Method = "POST"
		if _, ok := oreq.Header["Content-Type"]; !ok {
			oreq.Header.Set("Content-Type", "multipart/form-data")
		}
		oreq.ContentLength = creq.ContentLength
		oreq.Body = creq.Body
	}

	addr := oreq.URL.Host
	if !hasPort(addr) {
		addr += ":" + oreq.URL.Scheme
	}
	c, err := net.Dial("tcp", addr)
	if err != nil {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}
	c.SetReadTimeout(3 * 1e9)
	cc := http.NewClientConn(c, nil)

	// debug
	//dbg, err := http.DumpRequest(oreq, true)
	//log.Print("Dump request to origin server:\n", string(dbg))

	err = cc.Write(oreq)
	if err != nil {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}

	oresp, err := cc.Read(oreq)
	if err != nil && err != http.ErrPersistEOF {
		http.Error(cwr, err.String(), http.StatusGatewayTimeout)
		loghit(creq, http.StatusGatewayTimeout)
		return
	}

	//dbg, err = http.DumpResponse(oresp, true)
	//log.Print("Dump response from origin server:\n", string(dbg))

	for hdr, val := range oresp.Header {
		if !doNotCopy[hdr] {
			h := cwr.Header()
			h[hdr] = val
		}
	}
	cwr.WriteHeader(oresp.StatusCode)

	// simulate it coming in over gLink, a shared rate-limited link
	io.Copy(cwr, gLink.NewLinkReader(oresp.Body))

	cc.Close()
	c.Close()
	loghit(creq, oresp.StatusCode)
}

func main() {
	proxy := NewProxy()
	err := http.ListenAndServe("[::]:12345", proxy)
	if err != nil {
		log.Fatal("ListenAndServe: ", err.String())
	}
}

// ex: ts=2
<|endoftext|>


<commit_before>// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// push cross compiles one or multiple executables and pushes them to a micro
// computer over ssh.
package main

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

// run is a shorthand for exec.Command().Run().
func run(name string, arg ...string) error {
	c := exec.Command(name, arg...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	return c.Run()
}

type tool int

const (
	none tool = iota
	rsync
	pscp
	scp
)
const toolName = "nonersyncpscpscp"

var toolIndex = [...]uint8{0, 4, 9, 13, 16}

func (i tool) String() string {
	if i < 0 || i >= tool(len(toolIndex)-1) {
		return fmt.Sprintf("tool(%d)", i)
	}
	return toolName[toolIndex[i]:toolIndex[i+1]]
}

func (t tool) push(verbose bool, src string, pkgs []string, host, rel string) error {
	dst := fmt.Sprintf("%s:%s", host, rel)
	var args []string
	switch t {
	case rsync:
		// Push all files via rsync. This is the fastest method.
		args = []string{"--archive", "--info=progress2", "--compress", src + "/", dst}
		if verbose {
			args = append([]string{"-v"}, args...)
		}
	case pscp, scp:
		// Push all files via pscp/scp, provided by PuTTY/OpenSSH.
		//
		// It is slower than rsync and will fail if one of the destination
		// executable is under use, but it is a reasonable fallback.
		// TODO(maruel): pscp/scp with an alternate name, then plink/ssh in to
		// rename the files.
		args = []string{"-C", "-p", "-r", filepath.Join(src, "."), dst}
		if verbose {
			args = append([]string{"-v"}, args...)
		}
	default:
		return errors.New("please make sure at least one of rsync, scp or pscp is in PATH")
	}
	if err := run(t.String(), args...); err != nil {
		return err
	}
	if runtime.GOOS == "windows" {
		// On Windows, the +x bit is lost, so we are required to ssh in to change
		// the file mode.
		args = []string{host, "chmod", "+x"}
		for _, pkg := range pkgs {
			args = append(args, filepath.Join(rel, filepath.Base(pkg)))
		}
		switch t {
		case rsync, scp:
			return run("ssh", args...)
		case pscp:
			return run("plink", args...)
		}
	}
	return nil

}

// detect returns which tool to use.
func detect() tool {
	if _, err := exec.Command("rsync", "--version").CombinedOutput(); err == nil {
		return rsync
	}
	if runtime.GOOS == "windows" {
		if _, err := exec.Command("pscp", "-V").CombinedOutput(); err == nil {
			return pscp
		}
	}
	_, err := exec.Command("scp", "-V").CombinedOutput()
	if err2, ok := err.(*exec.Error); ok && err2.Err == exec.ErrNotFound {
		return none
	}
	return scp
}

// toPkg returns one or multiple packages matching the relpath.
func toPkg(item string) ([]string, error) {
	out, err := exec.Command("go", "list", item).CombinedOutput()
	s := strings.TrimSpace(string(out))
	if err != nil {
		return nil, fmt.Errorf("failed to list package %q: %v\n%s", item, err, s)
	}
	return strings.Split(s, "\n"), nil
}

// pushInner does the actual work: build then push.
func pushInner(verbose bool, t tool, pkgs []string, host, rel, d string) error {
	// First build everything.
	for _, pkg := range pkgs {
		fmt.Printf("- Building %s\n", pkg)
		if err := run("go", "build", "-v", "-i", "-o", filepath.Join(d, filepath.Base(pkg)), pkg); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to build %s\n", pkg)
			return err
		}
	}

	// Then push it all as one swoop.
	fmt.Printf("- Pushing %d executables to %s in %s via %s\n", len(pkgs), rel, host, t)
	return t.push(verbose, d, pkgs, host, rel)
}

// push wraps pushInner with a temporary directory.
func push(verbose bool, t tool, items []string, host, rel string) error {
	// First convert the passed strings into real package names.
	var pkgs []string
	for _, item := range items {
		i, err := toPkg(item)
		if err != nil {
			return err
		}
		pkgs = append(pkgs, i...)
	}

	d, err := ioutil.TempDir("", "push")
	if err != nil {
		return err
	}
	err = pushInner(verbose, t, pkgs, host, rel, d)
	if err1 := os.RemoveAll(d); err == nil {
		err = err1
	}
	return err
}

func mainImpl() error {
	goarch := flag.String("goarch", "arm", "GOARCH value to use")
	goos := flag.String("goos", "linux", "GOOS value to use")
	rel := flag.String("rel", ".", "directory on remote host to push files into")
	host := flag.String("host", os.Getenv("PUSH_HOST"), "host to push to; defaults to content of environment variable PUSH_HOST")
	verbose := flag.Bool("v", false, "verbose output")
	flag.Parse()
	if flag.NArg() == 0 {
		return errors.New("expected argument, try -help")
	}
	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	t := detect()
	if t == none {
		return errors.New("Please make sure at least one of rsync, scp or pscp is in PATH")
	}

	// Simplify our life and just set it process wide.
	os.Setenv("GOARCH", *goarch)
	os.Setenv("GOOS", *goos)
	return push(*verbose, t, flag.Args(), *host, *rel)
}

func main() {
	if err := mainImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "push: %s\n\nVisit https://github.com/periph/bootstrap#troubleshooting-push for help.\n", err)
		os.Exit(1)
	}
}
<commit_msg>push: improvements<commit_after>// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// push cross compiles one or multiple executables and pushes them to a micro
// computer over ssh.
package main

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

// run is a shorthand for exec.Command().Run().
func run(name string, arg ...string) error {
	c := exec.Command(name, arg...)
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	return c.Run()
}

type tool int

const (
	none tool = iota
	rsync
	pscp
	scp
)
const toolName = "nonersyncpscpscp"

var toolIndex = [...]uint8{0, 4, 9, 13, 16}

func (i tool) String() string {
	if i < 0 || i >= tool(len(toolIndex)-1) {
		return fmt.Sprintf("tool(%d)", i)
	}
	return toolName[toolIndex[i]:toolIndex[i+1]]
}

func (t tool) push(verbose bool, src string, pkgs []string, host, rel string) error {
	dst := fmt.Sprintf("%s:%s", host, rel)
	var args []string
	switch t {
	case rsync:
		// Push all files via rsync. This is the fastest method.
		args = []string{"--archive", "--info=progress2", "--compress", src + "/", dst}
		if verbose {
			args = append([]string{"-v"}, args...)
		}
	case pscp, scp:
		// Push all files via pscp/scp, provided by PuTTY/OpenSSH.
		//
		// It is slower than rsync and will fail if one of the destination
		// executable is under use, but it is a reasonable fallback.
		// TODO(maruel): pscp/scp with an alternate name, then plink/ssh in to
		// rename the files.
		args = []string{"-C", "-p", "-r"}
		for _, pkg := range pkgs {
			args = append(args, filepath.Join(src, filepath.Base(pkg)))
		}
		if verbose {
			args = append([]string{"-v"}, args...)
		}
		args = append(args, dst)
	default:
		return errors.New("please make sure at least one of rsync, scp or pscp is in PATH")
	}
	if err := run(t.String(), args...); err != nil {
		return err
	}
	if runtime.GOOS == "windows" {
		// On Windows, the +x bit is lost, so we are required to ssh in to change
		// the file mode.
		args = []string{host, "chmod", "+x"}
		for _, pkg := range pkgs {
			args = append(args, filepath.Join(rel, filepath.Base(pkg)))
		}
		switch t {
		case rsync, scp:
			return run("ssh", args...)
		case pscp:
			return run("plink", args...)
		}
	}
	return nil

}

// detect returns which tool to use.
func detect() tool {
	if _, err := exec.Command("rsync", "--version").CombinedOutput(); err == nil {
		return rsync
	}
	if runtime.GOOS == "windows" {
		if _, err := exec.Command("pscp", "-V").CombinedOutput(); err == nil {
			return pscp
		}
	}
	_, err := exec.Command("scp", "-V").CombinedOutput()
	if err2, ok := err.(*exec.Error); ok && err2.Err == exec.ErrNotFound {
		return none
	}
	return scp
}

// toPkg returns one or multiple packages matching the relpath.
func toPkg(item string) ([]string, error) {
	out, err := exec.Command("go", "list", item).CombinedOutput()
	s := strings.TrimSpace(string(out))
	if err != nil {
		return nil, fmt.Errorf("failed to list package %q: %v\n%s", item, err, s)
	}
	return strings.Split(s, "\n"), nil
}

// pushInner does the actual work: build then push.
func pushInner(verbose bool, t tool, pkgs []string, host, rel, d string) error {
	// First build everything.
	for _, pkg := range pkgs {
		fmt.Printf("- Building %s\n", pkg)
		if err := run("go", "build", "-v", "-i", "-o", filepath.Join(d, filepath.Base(pkg)), pkg); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to build %s\n", pkg)
			return err
		}
	}

	// Then push it all as one swoop.
	fmt.Printf("- Pushing %d executables to %s in %s via %s\n", len(pkgs), rel, host, t)
	return t.push(verbose, d, pkgs, host, rel)
}

// push wraps pushInner with a temporary directory.
func push(verbose bool, t tool, items []string, host, rel string) error {
	// First convert the passed strings into real package names.
	var pkgs []string
	for _, item := range items {
		i, err := toPkg(item)
		if err != nil {
			return err
		}
		pkgs = append(pkgs, i...)
	}

	d, err := ioutil.TempDir("", "push")
	if err != nil {
		return err
	}
	err = pushInner(verbose, t, pkgs, host, rel, d)
	if err1 := os.RemoveAll(d); err == nil {
		err = err1
	}
	return err
}

func mainImpl() error {
	goarch := flag.String("goarch", "arm", "GOARCH value to use")
	goos := flag.String("goos", "linux", "GOOS value to use")
	rel := flag.String("rel", ".", "directory on remote host to push files into")
	host := flag.String("host", os.Getenv("PUSH_HOST"), "host to push to; defaults to content of environment variable PUSH_HOST")
	verbose := flag.Bool("v", false, "verbose output")
	flag.Parse()
	if flag.NArg() == 0 {
		return errors.New("expected argument, try -help")
	}
	if !*verbose {
		log.SetOutput(ioutil.Discard)
	}

	t := detect()
	if t == none {
		return errors.New("Please make sure at least one of rsync, scp or pscp is in PATH")
	}

	// Simplify our life and just set it process wide.
	os.Setenv("GOARCH", *goarch)
	os.Setenv("GOOS", *goos)
	return push(*verbose, t, flag.Args(), *host, *rel)
}

func main() {
	if err := mainImpl(); err != nil {
		fmt.Fprintf(os.Stderr, "push: %s\n\nVisit https://github.com/periph/bootstrap#troubleshooting-push for help.\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package water

import (
	"fmt"

	"github.com/deifyed/water/pkg/config"
	"github.com/deifyed/water/pkg/context"
	"github.com/deifyed/water/pkg/logging"
	"github.com/deifyed/water/pkg/template"
	"github.com/spf13/afero"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func RunE(fs *afero.Afero) func(*cobra.Command, []string) error {
	return func(cmd *cobra.Command, args []string) error {
		log := logging.GetLogger()

		if len(args) == 0 {
			return fmt.Errorf("no arguments provided. See --help for usage")
		}

		targetPath := args[0]
		templateDir := viper.GetString(config.TemplatesDirectory)

		exists, err := fs.Exists(targetPath)
		if err != nil {
			return fmt.Errorf("checking target path existence: %w", err)
		}

		if !exists {
			return fmt.Errorf("target path \"%s\" does not exist, please create it before watering", targetPath)
		}

		targetContext, err := context.GatherContext(fs, targetPath)
		if err != nil {
			return fmt.Errorf("gathering context: %w", err)
		}

		template, err := template.Discover(fs, templateDir, targetContext)
		if err != nil {
			return fmt.Errorf("discovering template: %w", err)
		}

		if targetContext.TargetType == context.TargetTypeFile {
			err = fs.WriteReader(targetPath, template)
			if err != nil {
				return fmt.Errorf("writing template: %w", err)
			}
		} else {
			log.Debugf("target path is a directory, don't know how to handle that yet")
		}

		return nil
	}
}
<commit_msg>👌 Simplify conditional<commit_after>package water

import (
	"fmt"

	"github.com/deifyed/water/pkg/config"
	"github.com/deifyed/water/pkg/context"
	"github.com/deifyed/water/pkg/logging"
	"github.com/deifyed/water/pkg/template"
	"github.com/spf13/afero"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

func RunE(fs *afero.Afero) func(*cobra.Command, []string) error {
	return func(cmd *cobra.Command, args []string) error {
		log := logging.GetLogger()

		if len(args) == 0 {
			return fmt.Errorf("no arguments provided. See --help for usage")
		}

		targetPath := args[0]
		templateDir := viper.GetString(config.TemplatesDirectory)

		exists, err := fs.Exists(targetPath)
		if err != nil {
			return fmt.Errorf("checking target path existence: %w", err)
		}

		if !exists {
			return fmt.Errorf("target path \"%s\" does not exist, please create it before watering", targetPath)
		}

		targetContext, err := context.GatherContext(fs, targetPath)
		if err != nil {
			return fmt.Errorf("gathering context: %w", err)
		}

		template, err := template.Discover(fs, templateDir, targetContext)
		if err != nil {
			return fmt.Errorf("discovering template: %w", err)
		}

		if targetContext.TargetType != context.TargetTypeFile {
			log.Debugf("target path is a directory, don't know how to handle that yet")

			return nil
		}

		err = fs.WriteReader(targetPath, template)
		if err != nil {
			return fmt.Errorf("writing template: %w", err)
		}

		return nil
	}
}
<|endoftext|>