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

//+build linux

package main

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

	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/rkt/config"
	"github.com/coreos/rkt/stage0"
	"github.com/coreos/rkt/store"
)

var (
	defaultStage1Image string // either set by linker, or guessed in init()

	cmdRun = &Command{
		Name:    "run",
		Summary: "Run image(s) in a pod in rkt",
		Usage:   "[--volume name,kind=host,...] IMAGE [-- image-args...[---]]...",
		Description: `IMAGE should be a string referencing an image; either a hash, local file on disk, or URL.
They will be checked in that order and the first match will be used.

An "--" may be used to inhibit rkt run's parsing of subsequent arguments,
which will instead be appended to the preceding image app's exec arguments.
End the image arguments with a lone "---" to resume argument parsing.`,
		Run:                  runRun,
		Flags:                &runFlags,
		WantsFlagsTerminator: true,
	}
	runFlags        flag.FlagSet
	flagStage1Image string
	flagVolumes     volumeList
	flagPorts       portList
	flagPrivateNet  bool
	flagInheritEnv  bool
	flagExplicitEnv envMap
	flagInteractive bool
	flagNoOverlay   bool
	flagLocal       bool
)

func init() {
	commands = append(commands, cmdRun)

	// if not set by linker, try discover the directory rkt is running
	// from, and assume the default stage1.aci is stored alongside it.
	if defaultStage1Image == "" {
		if exePath, err := os.Readlink("/proc/self/exe"); err == nil {
			defaultStage1Image = filepath.Join(filepath.Dir(exePath), "stage1.aci")
		}
	}

	runFlags.StringVar(&flagStage1Image, "stage1-image", defaultStage1Image, `image to use as stage1. Local paths and http/https URLs are supported. If empty, rkt will look for a file called "stage1.aci" in the same directory as rkt itself`)
	runFlags.Var(&flagVolumes, "volume", "volumes to mount into the pod")
	runFlags.Var(&flagPorts, "port", "ports to expose on the host (requires --private-net)")
	runFlags.BoolVar(&flagPrivateNet, "private-net", false, "give pod a private network")
	runFlags.BoolVar(&flagInheritEnv, "inherit-env", false, "inherit all environment variables not set by apps")
	runFlags.BoolVar(&flagNoOverlay, "no-overlay", false, "disable overlay filesystem")
	runFlags.Var(&flagExplicitEnv, "set-env", "an environment variable to set for apps in the form name=value")
	runFlags.BoolVar(&flagInteractive, "interactive", false, "run pod interactively")
	runFlags.Var((*appAsc)(&rktApps), "signature", "local signature file to use in validating the preceding image")
	runFlags.BoolVar(&flagLocal, "local", false, "use only local images (do not discover or download from remote URLs)")
	flagVolumes = volumeList{}
	flagPorts = portList{}
}

func runRun(args []string) (exit int) {
	if flagInteractive && len(args) > 1 {
		stderr("run: interactive option only supports one image")
		return 1
	}

	if len(flagPorts) > 0 && !flagPrivateNet {
		stderr("--port flag requires --private-net")
		return 1
	}

	if globalFlags.Dir == "" {
		log.Printf("dir unset - using temporary directory")
		var err error
		globalFlags.Dir, err = ioutil.TempDir("", "rkt")
		if err != nil {
			stderr("error creating temporary directory: %v", err)
			return 1
		}
	}

	err := parseApps(&rktApps, args, &runFlags, true)
	if err != nil {
		stderr("run: error parsing app image arguments: %v", err)
		return 1
	}

	if rktApps.Count() < 1 {
		stderr("run: must provide at least one image")
		return 1
	}

	ds, err := store.NewStore(globalFlags.Dir)
	if err != nil {
		stderr("run: cannot open store: %v", err)
		return 1
	}

	config, err := config.GetConfig()
	if err != nil {
		stderr("run: cannot get configuration: %v", err)
		return 1
	}
	fn := &finder{
		imageActionData: imageActionData{
			ds:                 ds,
			headers:            config.AuthPerHost,
			insecureSkipVerify: globalFlags.InsecureSkipVerify,
			debug:              globalFlags.Debug,
		},
		local: flagLocal,
	}
	s1img, err := fn.findImage(flagStage1Image, "", false)
	if err != nil {
		stderr("Error finding stage1 image %q: %v", flagStage1Image, err)
		return 1
	}

	fn.ks = getKeystore()
	if err := fn.findImages(&rktApps); err != nil {
		stderr("%v", err)
		return 1
	}

	p, err := newPod()
	if err != nil {
		stderr("Error creating new pod: %v", err)
		return 1
	}

	cfg := stage0.CommonConfig{
		Store:       ds,
		Stage1Image: *s1img,
		UUID:        p.uuid,
		Debug:       globalFlags.Debug,
	}

	pcfg := stage0.PrepareConfig{
		CommonConfig: cfg,
		Apps:         &rktApps,
		Volumes:      []types.Volume(flagVolumes),
		Ports:        []types.ExposedPort(flagPorts),
		InheritEnv:   flagInheritEnv,
		ExplicitEnv:  flagExplicitEnv.Strings(),
		UseOverlay:   !flagNoOverlay && common.SupportsOverlay(),
	}
	err = stage0.Prepare(pcfg, p.path(), p.uuid)
	if err != nil {
		stderr("run: error setting up stage0: %v", err)
		return 1
	}

	// get the lock fd for run
	lfd, err := p.Fd()
	if err != nil {
		stderr("Error getting pod lock fd: %v", err)
		return 1
	}

	// skip prepared by jumping directly to run, we own this pod
	if err := p.xToRun(); err != nil {
		stderr("run: unable to transition to run: %v", err)
		return 1
	}

	rcfg := stage0.RunConfig{
		CommonConfig: cfg,
		PrivateNet:   flagPrivateNet,
		LockFd:       lfd,
		Interactive:  flagInteractive,
		Images:       rktApps.GetImageIDs(),
	}
	stage0.Run(rcfg, p.path()) // execs, never returns

	return 1
}

// volumeList implements the flag.Value interface to contain a set of mappings
// from mount label --> mount path
type volumeList []types.Volume

func (vl *volumeList) Set(s string) error {
	vol, err := types.VolumeFromString(s)
	if err != nil {
		return err
	}

	*vl = append(*vl, *vol)
	return nil
}

func (vl *volumeList) String() string {
	var vs []string
	for _, v := range []types.Volume(*vl) {
		vs = append(vs, v.String())
	}
	return strings.Join(vs, " ")
}

// portList implements the flag.Value interface to contain a set of mappings
// from port name --> host port
type portList []types.ExposedPort

func (pl *portList) Set(s string) error {
	parts := strings.SplitN(s, ":", 2)
	if len(parts) != 2 {
		return fmt.Errorf("%q is not in name:port format", s)
	}

	name, err := types.NewACName(parts[0])
	if err != nil {
		return fmt.Errorf("%q is not a valid port name: %v", parts[0], err)
	}

	port, err := strconv.ParseUint(parts[1], 10, 16)
	if err != nil {
		return fmt.Errorf("%q is not a valid port number", parts[1])
	}

	p := types.ExposedPort{
		Name:     *name,
		HostPort: uint(port),
	}

	*pl = append(*pl, p)
	return nil
}

func (pl *portList) String() string {
	var ps []string
	for _, p := range []types.ExposedPort(*pl) {
		ps = append(ps, fmt.Sprintf("%v:%v", p.Name, p.HostPort))
	}
	return strings.Join(ps, " ")
}

// envMap implements the flag.Value interface to contain a set of name=value mappings
type envMap struct {
	mapping map[string]string
}

func (e *envMap) Set(s string) error {
	if e.mapping == nil {
		e.mapping = make(map[string]string)
	}
	pair := strings.SplitN(s, "=", 2)
	if len(pair) != 2 {
		return fmt.Errorf("environment variable must be specified as name=value")
	}
	if _, exists := e.mapping[pair[0]]; exists {
		return fmt.Errorf("environment variable %q already set", pair[0])
	}
	e.mapping[pair[0]] = pair[1]
	return nil
}

func (e *envMap) String() string {
	return strings.Join(e.Strings(), "\n")
}

func (e *envMap) Strings() []string {
	var env []string
	for n, v := range e.mapping {
		env = append(env, n+"="+v)
	}
	return env
}
<commit_msg>rkt: bug fix: -interactive doesnt work with args rkt complains with "run: interactive option only supports one image" when trying to execute an image in interactive mode with arguments<commit_after>// Copyright 2014 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//+build linux

package main

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

	"github.com/coreos/rkt/Godeps/_workspace/src/github.com/appc/spec/schema/types"
	"github.com/coreos/rkt/common"
	"github.com/coreos/rkt/rkt/config"
	"github.com/coreos/rkt/stage0"
	"github.com/coreos/rkt/store"
)

var (
	defaultStage1Image string // either set by linker, or guessed in init()

	cmdRun = &Command{
		Name:    "run",
		Summary: "Run image(s) in a pod in rkt",
		Usage:   "[--volume name,kind=host,...] IMAGE [-- image-args...[---]]...",
		Description: `IMAGE should be a string referencing an image; either a hash, local file on disk, or URL.
They will be checked in that order and the first match will be used.

An "--" may be used to inhibit rkt run's parsing of subsequent arguments,
which will instead be appended to the preceding image app's exec arguments.
End the image arguments with a lone "---" to resume argument parsing.`,
		Run:                  runRun,
		Flags:                &runFlags,
		WantsFlagsTerminator: true,
	}
	runFlags        flag.FlagSet
	flagStage1Image string
	flagVolumes     volumeList
	flagPorts       portList
	flagPrivateNet  bool
	flagInheritEnv  bool
	flagExplicitEnv envMap
	flagInteractive bool
	flagNoOverlay   bool
	flagLocal       bool
)

func init() {
	commands = append(commands, cmdRun)

	// if not set by linker, try discover the directory rkt is running
	// from, and assume the default stage1.aci is stored alongside it.
	if defaultStage1Image == "" {
		if exePath, err := os.Readlink("/proc/self/exe"); err == nil {
			defaultStage1Image = filepath.Join(filepath.Dir(exePath), "stage1.aci")
		}
	}

	runFlags.StringVar(&flagStage1Image, "stage1-image", defaultStage1Image, `image to use as stage1. Local paths and http/https URLs are supported. If empty, rkt will look for a file called "stage1.aci" in the same directory as rkt itself`)
	runFlags.Var(&flagVolumes, "volume", "volumes to mount into the pod")
	runFlags.Var(&flagPorts, "port", "ports to expose on the host (requires --private-net)")
	runFlags.BoolVar(&flagPrivateNet, "private-net", false, "give pod a private network")
	runFlags.BoolVar(&flagInheritEnv, "inherit-env", false, "inherit all environment variables not set by apps")
	runFlags.BoolVar(&flagNoOverlay, "no-overlay", false, "disable overlay filesystem")
	runFlags.Var(&flagExplicitEnv, "set-env", "an environment variable to set for apps in the form name=value")
	runFlags.BoolVar(&flagInteractive, "interactive", false, "run pod interactively")
	runFlags.Var((*appAsc)(&rktApps), "signature", "local signature file to use in validating the preceding image")
	runFlags.BoolVar(&flagLocal, "local", false, "use only local images (do not discover or download from remote URLs)")
	flagVolumes = volumeList{}
	flagPorts = portList{}
}

func runRun(args []string) (exit int) {
	if len(flagPorts) > 0 && !flagPrivateNet {
		stderr("--port flag requires --private-net")
		return 1
	}

	if globalFlags.Dir == "" {
		log.Printf("dir unset - using temporary directory")
		var err error
		globalFlags.Dir, err = ioutil.TempDir("", "rkt")
		if err != nil {
			stderr("error creating temporary directory: %v", err)
			return 1
		}
	}

	err := parseApps(&rktApps, args, &runFlags, true)
	if err != nil {
		stderr("run: error parsing app image arguments: %v", err)
		return 1
	}

	if flagInteractive && rktApps.Count() > 1 {
		stderr("run: interactive option only supports one image")
		return 1
	}

	if rktApps.Count() < 1 {
		stderr("run: must provide at least one image")
		return 1
	}

	ds, err := store.NewStore(globalFlags.Dir)
	if err != nil {
		stderr("run: cannot open store: %v", err)
		return 1
	}

	config, err := config.GetConfig()
	if err != nil {
		stderr("run: cannot get configuration: %v", err)
		return 1
	}
	fn := &finder{
		imageActionData: imageActionData{
			ds:                 ds,
			headers:            config.AuthPerHost,
			insecureSkipVerify: globalFlags.InsecureSkipVerify,
			debug:              globalFlags.Debug,
		},
		local: flagLocal,
	}
	s1img, err := fn.findImage(flagStage1Image, "", false)
	if err != nil {
		stderr("Error finding stage1 image %q: %v", flagStage1Image, err)
		return 1
	}

	fn.ks = getKeystore()
	if err := fn.findImages(&rktApps); err != nil {
		stderr("%v", err)
		return 1
	}

	p, err := newPod()
	if err != nil {
		stderr("Error creating new pod: %v", err)
		return 1
	}

	cfg := stage0.CommonConfig{
		Store:       ds,
		Stage1Image: *s1img,
		UUID:        p.uuid,
		Debug:       globalFlags.Debug,
	}

	pcfg := stage0.PrepareConfig{
		CommonConfig: cfg,
		Apps:         &rktApps,
		Volumes:      []types.Volume(flagVolumes),
		Ports:        []types.ExposedPort(flagPorts),
		InheritEnv:   flagInheritEnv,
		ExplicitEnv:  flagExplicitEnv.Strings(),
		UseOverlay:   !flagNoOverlay && common.SupportsOverlay(),
	}
	err = stage0.Prepare(pcfg, p.path(), p.uuid)
	if err != nil {
		stderr("run: error setting up stage0: %v", err)
		return 1
	}

	// get the lock fd for run
	lfd, err := p.Fd()
	if err != nil {
		stderr("Error getting pod lock fd: %v", err)
		return 1
	}

	// skip prepared by jumping directly to run, we own this pod
	if err := p.xToRun(); err != nil {
		stderr("run: unable to transition to run: %v", err)
		return 1
	}

	rcfg := stage0.RunConfig{
		CommonConfig: cfg,
		PrivateNet:   flagPrivateNet,
		LockFd:       lfd,
		Interactive:  flagInteractive,
		Images:       rktApps.GetImageIDs(),
	}
	stage0.Run(rcfg, p.path()) // execs, never returns

	return 1
}

// volumeList implements the flag.Value interface to contain a set of mappings
// from mount label --> mount path
type volumeList []types.Volume

func (vl *volumeList) Set(s string) error {
	vol, err := types.VolumeFromString(s)
	if err != nil {
		return err
	}

	*vl = append(*vl, *vol)
	return nil
}

func (vl *volumeList) String() string {
	var vs []string
	for _, v := range []types.Volume(*vl) {
		vs = append(vs, v.String())
	}
	return strings.Join(vs, " ")
}

// portList implements the flag.Value interface to contain a set of mappings
// from port name --> host port
type portList []types.ExposedPort

func (pl *portList) Set(s string) error {
	parts := strings.SplitN(s, ":", 2)
	if len(parts) != 2 {
		return fmt.Errorf("%q is not in name:port format", s)
	}

	name, err := types.NewACName(parts[0])
	if err != nil {
		return fmt.Errorf("%q is not a valid port name: %v", parts[0], err)
	}

	port, err := strconv.ParseUint(parts[1], 10, 16)
	if err != nil {
		return fmt.Errorf("%q is not a valid port number", parts[1])
	}

	p := types.ExposedPort{
		Name:     *name,
		HostPort: uint(port),
	}

	*pl = append(*pl, p)
	return nil
}

func (pl *portList) String() string {
	var ps []string
	for _, p := range []types.ExposedPort(*pl) {
		ps = append(ps, fmt.Sprintf("%v:%v", p.Name, p.HostPort))
	}
	return strings.Join(ps, " ")
}

// envMap implements the flag.Value interface to contain a set of name=value mappings
type envMap struct {
	mapping map[string]string
}

func (e *envMap) Set(s string) error {
	if e.mapping == nil {
		e.mapping = make(map[string]string)
	}
	pair := strings.SplitN(s, "=", 2)
	if len(pair) != 2 {
		return fmt.Errorf("environment variable must be specified as name=value")
	}
	if _, exists := e.mapping[pair[0]]; exists {
		return fmt.Errorf("environment variable %q already set", pair[0])
	}
	e.mapping[pair[0]] = pair[1]
	return nil
}

func (e *envMap) String() string {
	return strings.Join(e.Strings(), "\n")
}

func (e *envMap) Strings() []string {
	var env []string
	for n, v := range e.mapping {
		env = append(env, n+"="+v)
	}
	return env
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio-xl/pkg/probe"
)

// rm specific flags.
var (
	rmFlagRecursive = cli.BoolFlag{
		Name:  "recursive, r",
		Usage: "Remove recursively.",
	}
	rmFlagForce = cli.BoolFlag{
		Name:  "force",
		Usage: "Force a dangerous remove operation.",
	}
	rmFlagIncomplete = cli.BoolFlag{
		Name:  "incomplete, I",
		Usage: "Remove an incomplete upload(s).",
	}
	rmFlagFake = cli.BoolFlag{
		Name:  "fake",
		Usage: "Perform a fake remove operation.",
	}
	rmFlagHelp = cli.BoolFlag{
		Name:  "help, h",
		Usage: "Help of rm.",
	}
)

// remove a file or folder.
var rmCmd = cli.Command{
	Name:   "rm",
	Usage:  "Remove file or bucket [WARNING: Use with care].",
	Action: mainRm,
	Flags:  []cli.Flag{rmFlagRecursive, rmFlagForce, rmFlagIncomplete, rmFlagFake, rmFlagHelp},
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] TARGET [TARGET ...]

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Remove a file.
      $ mc {{.Name}} 1999/old-backup.tgz

   2. Remove contents of a folder, excluding its sub-folders.
     $ mc {{.Name}} --force https://s3.amazonaws.com/jazz-songs/louis/

   3. Remove contents of a folder recursively.
     $ mc {{.Name}} --force --recursive https://s3.amazonaws.com/jazz-songs/louis/

   4. Remove all matching objects with this prefix.
     $ mc {{.Name}} --force --force https://s3.amazonaws.com/ogg/gunmetal

   5. Drop an incomplete upload of an object.
      $ mc {{.Name}} --incomplete https://s3.amazonaws.com/jazz-songs/louis/file01.mp3

   6. Drop all incomplete uploads recursively matching this prefix.
      $ mc {{.Name}} --incomplete --force --recursive https://s3.amazonaws.com/jazz-songs/louis/
`,
}

// Structured message depending on the type of console.
type rmMessage struct {
	Status string `json:"status"`
	URL    string `json:"url"`
}

// Colorized message for console printing.
func (r rmMessage) String() string {
	return console.Colorize("Remove", fmt.Sprintf("Removed ‘%s’.", r.URL))
}

// JSON'ified message for scripting.
func (r rmMessage) JSON() string {
	msgBytes, e := json.Marshal(r)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(msgBytes)
}

// Validate command line arguments.
func checkRmSyntax(ctx *cli.Context) {
	isForce := ctx.Bool("force")
	isRecursive := ctx.Bool("recursive")

	if !ctx.Args().Present() {
		exitCode := 1
		cli.ShowCommandHelpAndExit(ctx, "rm", exitCode)
	}

	if isRecursive && !isForce {
		fatalIf(errDummy().Trace(),
			"Recursive removal requires --force option. Please review carefully before performing this *DANGEROUS* operation.")
	}
}

// Remove a single object.
func rm(url string, isIncomplete, isFake bool) *probe.Error {
	clnt, err := url2Client(url)
	if err != nil {
		return err.Trace(url)
	}

	if isFake { // It is a fake remove. Return success.
		return nil
	}

	if err = clnt.Remove(isIncomplete); err != nil {
		return err.Trace(url)
	}

	return nil
}

// Remove all objects recursively.
func rmAll(url string, isRecursive, isIncomplete, isFake bool) {
	// Initialize new client.
	clnt, err := url2Client(url)
	if err != nil {
		errorIf(err.Trace(url), "Invalid URL ‘"+url+"’.")
		return // End of journey.
	}

	/* Disable recursion and only list this folder's contents. We
	perform manual depth-first recursion ourself here. */
	nonRecursive := false
	for entry := range clnt.List(nonRecursive, isIncomplete) {
		if entry.Err != nil {
			errorIf(entry.Err.Trace(url), "Unable to list ‘"+url+"’.")
			return // End of journey.
		}

		if entry.Type.IsDir() && isRecursive {
			// Add separator at the end to remove all its contents.
			url := entry.URL
			url.Path = strings.TrimSuffix(entry.URL.Path, string(entry.URL.Separator)) + string(entry.URL.Separator)

			// Recursively remove contents of this directory.
			rmAll(url.String(), isRecursive, isIncomplete, isFake)
		}

		// Regular type.
		if err = rm(entry.URL.String(), isIncomplete, isFake); err != nil {
			errorIf(err.Trace(entry.URL.String()), "Unable to remove ‘"+entry.URL.String()+"’.")
			continue
		}
		printMsg(rmMessage{Status: "success", URL: entry.URL.String()})
	}
}

// main for rm command.
func mainRm(ctx *cli.Context) {
	checkRmSyntax(ctx)

	// rm specific flags.
	isForce := ctx.Bool("force")
	isIncomplete := ctx.Bool("incomplete")
	isRecursive := ctx.Bool("recursive")
	isFake := ctx.Bool("fake")

	// Set color.
	console.SetColor("Remove", color.New(color.FgGreen, color.Bold))

	// Parse args.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	// Support multiple targets.
	for _, url := range URLs {
		if isRecursive && isForce {
			rmAll(url, isRecursive, isIncomplete, isFake)
		} else {
			if err := rm(url, isIncomplete, isFake); err != nil {
				errorIf(err.Trace(url), "Unable to remove ‘"+url+"’.")
				continue
			}
			printMsg(rmMessage{Status: "success", URL: url})
		}
	}
}
<commit_msg>Do a stat on files for non-recursive rm before removing to detect non-existing files<commit_after>/*
 * Minio Client (C) 2014, 2015 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/fatih/color"
	"github.com/minio/cli"
	"github.com/minio/mc/pkg/console"
	"github.com/minio/minio-xl/pkg/probe"
)

// rm specific flags.
var (
	rmFlagRecursive = cli.BoolFlag{
		Name:  "recursive, r",
		Usage: "Remove recursively.",
	}
	rmFlagForce = cli.BoolFlag{
		Name:  "force",
		Usage: "Force a dangerous remove operation.",
	}
	rmFlagIncomplete = cli.BoolFlag{
		Name:  "incomplete, I",
		Usage: "Remove an incomplete upload(s).",
	}
	rmFlagFake = cli.BoolFlag{
		Name:  "fake",
		Usage: "Perform a fake remove operation.",
	}
	rmFlagHelp = cli.BoolFlag{
		Name:  "help, h",
		Usage: "Help of rm.",
	}
)

// remove a file or folder.
var rmCmd = cli.Command{
	Name:   "rm",
	Usage:  "Remove file or bucket [WARNING: Use with care].",
	Action: mainRm,
	Flags:  []cli.Flag{rmFlagRecursive, rmFlagForce, rmFlagIncomplete, rmFlagFake, rmFlagHelp},
	CustomHelpTemplate: `NAME:
   mc {{.Name}} - {{.Usage}}

USAGE:
   mc {{.Name}} [FLAGS] TARGET [TARGET ...]

FLAGS:
  {{range .Flags}}{{.}}
  {{end}}
EXAMPLES:
   1. Remove a file.
      $ mc {{.Name}} 1999/old-backup.tgz

   2. Remove contents of a folder, excluding its sub-folders.
     $ mc {{.Name}} --force https://s3.amazonaws.com/jazz-songs/louis/

   3. Remove contents of a folder recursively.
     $ mc {{.Name}} --force --recursive https://s3.amazonaws.com/jazz-songs/louis/

   4. Remove all matching objects with this prefix.
     $ mc {{.Name}} --force --force https://s3.amazonaws.com/ogg/gunmetal

   5. Drop an incomplete upload of an object.
      $ mc {{.Name}} --incomplete https://s3.amazonaws.com/jazz-songs/louis/file01.mp3

   6. Drop all incomplete uploads recursively matching this prefix.
      $ mc {{.Name}} --incomplete --force --recursive https://s3.amazonaws.com/jazz-songs/louis/
`,
}

// Structured message depending on the type of console.
type rmMessage struct {
	Status string `json:"status"`
	URL    string `json:"url"`
}

// Colorized message for console printing.
func (r rmMessage) String() string {
	return console.Colorize("Remove", fmt.Sprintf("Removed ‘%s’.", r.URL))
}

// JSON'ified message for scripting.
func (r rmMessage) JSON() string {
	msgBytes, e := json.Marshal(r)
	fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
	return string(msgBytes)
}

// Validate command line arguments.
func checkRmSyntax(ctx *cli.Context) {
	isForce := ctx.Bool("force")
	isRecursive := ctx.Bool("recursive")

	if !ctx.Args().Present() {
		exitCode := 1
		cli.ShowCommandHelpAndExit(ctx, "rm", exitCode)
	}

	if !isRecursive {
		URLs, err := args2URLs(ctx.Args())
		fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")
		for _, url := range URLs {
			if _, _, err := url2Stat(url); err != nil {
				fatalIf(err.Trace(url), "Unable to stat.")
			}
		}
	}

	if isRecursive && !isForce {
		fatalIf(errDummy().Trace(),
			"Recursive removal requires --force option. Please review carefully before performing this *DANGEROUS* operation.")
	}
}

// Remove a single object.
func rm(url string, isIncomplete, isFake bool) *probe.Error {
	clnt, err := url2Client(url)
	if err != nil {
		return err.Trace(url)
	}

	if isFake { // It is a fake remove. Return success.
		return nil
	}

	if err = clnt.Remove(isIncomplete); err != nil {
		return err.Trace(url)
	}

	return nil
}

// Remove all objects recursively.
func rmAll(url string, isRecursive, isIncomplete, isFake bool) {
	// Initialize new client.
	clnt, err := url2Client(url)
	if err != nil {
		errorIf(err.Trace(url), "Invalid URL ‘"+url+"’.")
		return // End of journey.
	}

	/* Disable recursion and only list this folder's contents. We
	perform manual depth-first recursion ourself here. */
	nonRecursive := false
	for entry := range clnt.List(nonRecursive, isIncomplete) {
		if entry.Err != nil {
			errorIf(entry.Err.Trace(url), "Unable to list ‘"+url+"’.")
			return // End of journey.
		}

		if entry.Type.IsDir() && isRecursive {
			// Add separator at the end to remove all its contents.
			url := entry.URL
			url.Path = strings.TrimSuffix(entry.URL.Path, string(entry.URL.Separator)) + string(entry.URL.Separator)

			// Recursively remove contents of this directory.
			rmAll(url.String(), isRecursive, isIncomplete, isFake)
		}

		// Regular type.
		if err = rm(entry.URL.String(), isIncomplete, isFake); err != nil {
			errorIf(err.Trace(entry.URL.String()), "Unable to remove ‘"+entry.URL.String()+"’.")
			continue
		}
		printMsg(rmMessage{Status: "success", URL: entry.URL.String()})
	}
}

// main for rm command.
func mainRm(ctx *cli.Context) {
	checkRmSyntax(ctx)

	// rm specific flags.
	isForce := ctx.Bool("force")
	isIncomplete := ctx.Bool("incomplete")
	isRecursive := ctx.Bool("recursive")
	isFake := ctx.Bool("fake")

	// Set color.
	console.SetColor("Remove", color.New(color.FgGreen, color.Bold))

	// Parse args.
	URLs, err := args2URLs(ctx.Args())
	fatalIf(err.Trace(ctx.Args()...), "Unable to parse arguments.")

	// Support multiple targets.
	for _, url := range URLs {
		if isRecursive && isForce {
			rmAll(url, isRecursive, isIncomplete, isFake)
		} else {
			if err := rm(url, isIncomplete, isFake); err != nil {
				errorIf(err.Trace(url), "Unable to remove ‘"+url+"’.")
				continue
			}
			printMsg(rmMessage{Status: "success", URL: url})
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"github.com/juju/utils/set"
	gc "gopkg.in/check.v1"
)

type MigrationSuite struct{}

var _ = gc.Suite(&MigrationSuite{})

func (s *MigrationSuite) TestKnownCollections(c *gc.C) {
	completedCollections := set.NewStrings(
		environmentsC,
	)

	// THIS SET WILL BE REMOVED WHEN MIGRATIONS ARE COMPLETE
	todoCollections := set.NewStrings(
		envUsersC,
		envUserLastConnectionC,
		blocksC,
		cleanupsC,
		sequenceC,
		leasesC,
		charmsC,
		servicesC,
		unitsC,
		minUnitsC,
		assignUnitC,
		meterStatusC,
		settingsrefsC,
		relationsC,
		relationScopesC,
		containerRefsC,
		instanceDataC,
		machinesC,
		rebootC,
		blockDevicesC,
		filesystemsC,
		filesystemAttachmentsC,
		storageInstancesC,
		storageAttachmentsC,
		volumesC,
		volumeAttachmentsC,
		ipaddressesC,
		networkInterfacesC,
		networksC,
		openedPortsC,
		requestedNetworksC,
		subnetsC,
		actionsC,
		actionNotificationsC,
		"payloads",
		annotationsC,
		settingsC,
		constraintsC,
		storageConstraintsC,
		statusesC,
		statusesHistoryC,
		spacesC,
		cloudimagemetadataC,
	)

	envCollections := set.NewStrings()
	for name, info := range allCollections() {
		if !info.global {
			envCollections.Add(name)
		}
	}

	remainder := envCollections.Difference(completedCollections)
	remainder = remainder.Difference(todoCollections)

	// If this test fails, it means that a new collection has been added
	// but migrations for it has not been done. This is a Bad Thing™.
	c.Assert(remainder, gc.HasLen, 0)
}
<commit_msg>More testing.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package state

import (
	"reflect"

	"github.com/juju/utils/set"
	gc "gopkg.in/check.v1"
)

type MigrationSuite struct{}

var _ = gc.Suite(&MigrationSuite{})

func (s *MigrationSuite) TestKnownCollections(c *gc.C) {
	completedCollections := set.NewStrings(
		environmentsC,
	)

	// THIS SET WILL BE REMOVED WHEN MIGRATIONS ARE COMPLETE
	todoCollections := set.NewStrings(
		// environment
		blocksC,
		cleanupsC,
		cloudimagemetadataC,
		envUsersC,
		envUserLastConnectionC,
		sequenceC,

		// machine
		containerRefsC,
		instanceDataC,
		machinesC,
		rebootC,
		ipaddressesC,

		// service / unit
		assignUnitC,
		charmsC,
		leasesC,
		minUnitsC,
		openedPortsC,
		"payloads",
		servicesC,
		unitsC,

		// relation
		relationsC,
		relationScopesC,

		// storage
		blockDevicesC,
		filesystemsC,
		filesystemAttachmentsC,
		storageInstancesC,
		storageAttachmentsC,
		storageConstraintsC,
		volumesC,
		volumeAttachmentsC,

		// network
		networksC,
		networkInterfacesC,
		requestedNetworksC,
		subnetsC,
		spacesC,

		// actions
		actionsC,
		actionNotificationsC,

		// done as part of machines/services/units
		annotationsC,
		constraintsC,
		settingsC,
		statusesC,
		statusesHistoryC,

		// uncategorised
		meterStatusC,
		settingsrefsC,
	)

	envCollections := set.NewStrings()
	for name, info := range allCollections() {
		if !info.global {
			envCollections.Add(name)
		}
	}

	remainder := envCollections.Difference(completedCollections)
	remainder = remainder.Difference(todoCollections)

	// If this test fails, it means that a new collection has been added
	// but migrations for it has not been done. This is a Bad Thing™.
	c.Assert(remainder, gc.HasLen, 0)
}

func (s *MigrationSuite) TestEnvironmentDocFields(c *gc.C) {
	fields := set.NewStrings(
		// uuid and name are constructed from the model config
		"UUID",
		"Name",
		// life will always be alive, or we won't be migrating
		"Life",
		"Owner",
		// server uuid is recreated when the new model is created in the
		// new controller (yay name changes).
		"ServerUUID",
		// Both of the times for dying and death are empty as the model
		// is alive.
		"TimeOfDying",
		"TimeOfDeath",
	)
	expected := getExportedFields(environmentDoc{})
	unknown := expected.Difference(fields)
	// If this test fails, it means that extra fields have been added to the
	// environmentDoc without thinking about the migration implications.
	c.Assert(unknown, gc.HasLen, 0)
}

func getExportedFields(arg interface{}) set.Strings {
	t := reflect.TypeOf(arg)
	result := set.NewStrings()

	count := t.NumField()
	for i := 0; i < count; i++ {
		f := t.Field(i)
		// empty PkgPath means exported field.
		// see https://golang.org/pkg/reflect/#StructField
		if f.PkgPath == "" {
			result.Add(f.Name)
		}
	}

	return result
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/aws/aws-sdk-go/service/route53/route53iface"
)

var comment = "Updated by lacrosse: github.com/lowply/lacrosse"

type Route53 struct {
	Client route53iface.Route53API
	Id     string
	Req    *Request
}

func NewRoute53(req *Request) (*Route53, error) {
	sess, err := session.NewSession(&aws.Config{
		Credentials: credentials.NewSharedCredentials("", req.Profile),
	})
	if err != nil {
		return nil, err
	}

	r := &Route53{
		Client: route53.New(sess),
		Id:     "",
		Req:    req,
	}

	return r, nil
}

func (r *Route53) GetHostedZoneId(domain string) (string, error) {
	params := &route53.ListHostedZonesInput{}
	resp, err := r.Client.ListHostedZones(params)
	if err != nil {
		return "", err
	}
	for _, v := range resp.HostedZones {
		if *v.Name == domain+"." {
			return strings.Split(*v.Id, "/")[2], nil
		}
	}
	return "", errors.New("Domain " + domain + " was not found in the hosted zone list.")
}

func (r *Route53) RequestChange() (*route53.ChangeResourceRecordSetsOutput, error) {
	id, err := r.GetHostedZoneId(r.Req.Domain)
	if err != nil {
		return nil, err
	}

	r.Id = id

	params := r.CreateNewParams()
	fmt.Println("New param created: \n\n" + params.GoString() + "\n")

	resp, err := r.Client.ChangeResourceRecordSets(params)
	if err != nil {
		return nil, err
	}
	fmt.Println("Got response for the request: \n\n" + resp.GoString() + "\n")
	return resp, nil
}

func (r *Route53) CheckStatus(resp *route53.ChangeResourceRecordSetsOutput) error {
	id := &route53.GetChangeInput{Id: resp.ChangeInfo.Id}
	fmt.Println("Waiting for request " + *id.Id + " to be reflected...")
	err := r.Client.WaitUntilResourceRecordSetsChanged(id)
	if err != nil {
		return err
	}
	fmt.Println("Done.")
	return nil
}

func (r *Route53) CreateNewParams() *route53.ChangeResourceRecordSetsInput {
	if r.Req.Type == "TXT" {
		r.Req.Value = "\"" + r.Req.Value + "\""
	}
	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: []*route53.Change{
				{
					Action: aws.String(r.Req.Action),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(r.Req.Domain),
						Type: aws.String(r.Req.Type),
						ResourceRecords: []*route53.ResourceRecord{
							{
								Value: aws.String(r.Req.Value),
							},
						},
						TTL: aws.Int64(r.Req.TTL),
					},
				},
			},
			Comment: aws.String(comment),
		},
		HostedZoneId: aws.String(r.Id),
	}
	return params
}
<commit_msg>Removed some fmt.Println()<commit_after>package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/aws/aws-sdk-go/service/route53/route53iface"
)

var comment = "Updated by lacrosse: github.com/lowply/lacrosse"

type Route53 struct {
	Client route53iface.Route53API
	Id     string
	Req    *Request
}

func NewRoute53(req *Request) (*Route53, error) {
	sess, err := session.NewSession(&aws.Config{
		Credentials: credentials.NewSharedCredentials("", req.Profile),
	})
	if err != nil {
		return nil, err
	}

	r := &Route53{
		Client: route53.New(sess),
		Id:     "",
		Req:    req,
	}

	return r, nil
}

func (r *Route53) GetHostedZoneId(domain string) (string, error) {
	params := &route53.ListHostedZonesInput{}
	resp, err := r.Client.ListHostedZones(params)
	if err != nil {
		return "", err
	}
	for _, v := range resp.HostedZones {
		if *v.Name == domain+"." {
			return strings.Split(*v.Id, "/")[2], nil
		}
	}
	return "", errors.New("Domain " + domain + " was not found in the hosted zone list.")
}

func (r *Route53) RequestChange() (*route53.ChangeResourceRecordSetsOutput, error) {
	id, err := r.GetHostedZoneId(r.Req.Domain)
	if err != nil {
		return nil, err
	}
	r.Id = id
	params := r.CreateNewParams()
	resp, err := r.Client.ChangeResourceRecordSets(params)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

func (r *Route53) CheckStatus(resp *route53.ChangeResourceRecordSetsOutput) error {
	id := &route53.GetChangeInput{Id: resp.ChangeInfo.Id}
	fmt.Println("Waiting for request " + *id.Id + " to be reflected...")
	err := r.Client.WaitUntilResourceRecordSetsChanged(id)
	if err != nil {
		return err
	}
	fmt.Println("Done.")
	return nil
}

func (r *Route53) CreateNewParams() *route53.ChangeResourceRecordSetsInput {
	if r.Req.Type == "TXT" {
		r.Req.Value = "\"" + r.Req.Value + "\""
	}
	params := &route53.ChangeResourceRecordSetsInput{
		ChangeBatch: &route53.ChangeBatch{
			Changes: []*route53.Change{
				{
					Action: aws.String(r.Req.Action),
					ResourceRecordSet: &route53.ResourceRecordSet{
						Name: aws.String(r.Req.Domain),
						Type: aws.String(r.Req.Type),
						ResourceRecords: []*route53.ResourceRecord{
							{
								Value: aws.String(r.Req.Value),
							},
						},
						TTL: aws.Int64(r.Req.TTL),
					},
				},
			},
			Comment: aws.String(comment),
		},
		HostedZoneId: aws.String(r.Id),
	}
	return params
}
<|endoftext|>


<commit_before>package controllers

import (
	"html/template"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/yosssi/ace-proxy"
	"github.com/yosssi/orgs.io/app/models"
)

// Top represents a top controller.
type Top struct {
	Config   *models.Config
	AceProxy *proxy.Proxy
}

// Index represents an index action.
func (ctrl *Top) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	tplc, errc := ctrl.AceProxy.Load("layout/base", "top/index", nil)

	var tpl *template.Template

	select {
	case tpl = <-tplc:
	case err := <-errc:
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if err := tpl.Execute(w, nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// NewTop creates and returns a top controller.
func NewTop(config *models.Config, aceProxy *proxy.Proxy) *Top {
	return &Top{
		Config:   config,
		AceProxy: aceProxy,
	}
}
<commit_msg>Update app/controllers/top.go<commit_after>package controllers

import (
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/yosssi/ace-proxy"
	"github.com/yosssi/orgs.io/app/models"
)

// Top represents a top controller.
type Top struct {
	Config   *models.Config
	AceProxy *proxy.Proxy
}

// Index represents an index action.
func (ctrl *Top) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	tpl, err := ctrl.AceProxy.Load("layout/base", "top/index", nil)

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if err := tpl.Execute(w, nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// NewTop creates and returns a top controller.
func NewTop(config *models.Config, aceProxy *proxy.Proxy) *Top {
	return &Top{
		Config:   config,
		AceProxy: aceProxy,
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 The Cockroach 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. See the AUTHORS file
// for names of contributors.
//
// Author: jqmp (jaqueramaphan@gmail.com)

package rpc

// TODO(jqmp): The use of TLS here is just a proof of concept; its security
// properties haven't been analyzed or audited.

import (
	"bufio"
	"crypto/tls"
	"io"
	"net"
	"net/http"
	"net/rpc"

	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/log"
)

// tlsListen wraps either net.Listen or crypto/tls.Listen, depending on the contents of
// the passed TLS Config.
func tlsListen(network, address string, config *tls.Config) (net.Listener, error) {
	if config == nil {
		if network != "unix" {
			log.Warningf("listening via %s to %s without TLS", network, address)
		}
		return net.Listen(network, address)
	}
	return tls.Listen(network, address, config)
}

// tlsDial wraps either net.Dial or crypto/tls.Dial, depending on the contents of
// the passed TLS Config.
func tlsDial(network, address string, config *tls.Config) (net.Conn, error) {
	if config == nil {
		if network != "unix" {
			log.Warningf("connecting via %s to %s without TLS", network, address)
		}
		return net.Dial(network, address)
	}
	return tls.Dial(network, address, config)
}

// tlsDialHTTP connects to an HTTP RPC server at the specified address.
func tlsDialHTTP(network, address string, config *tls.Config) (net.Conn, error) {
	conn, err := tlsDial(network, address, config)
	if err != nil {
		return conn, err
	}

	// Note: this code was adapted from net/rpc.DialHTTPPath.
	io.WriteString(conn, "CONNECT "+rpc.DefaultRPCPath+" HTTP/1.0\n\n")

	// Require successful HTTP response before switching to RPC protocol.
	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {
		return conn, nil
	}
	if err == nil {
		err = util.Errorf("unexpected HTTP response: %s", resp.Status)
	}
	conn.Close()
	return nil, err
}
<commit_msg>Simplify<commit_after>// Copyright 2014 The Cockroach 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. See the AUTHORS file
// for names of contributors.
//
// Author: jqmp (jaqueramaphan@gmail.com)

package rpc

// TODO(jqmp): The use of TLS here is just a proof of concept; its security
// properties haven't been analyzed or audited.

import (
	"bufio"
	"crypto/tls"
	"io"
	"net"
	"net/http"
	"net/rpc"

	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/log"
)

// tlsListen wraps either net.Listen or crypto/tls.Listen, depending on the contents of
// the passed TLS Config.
func tlsListen(network, address string, config *tls.Config) (net.Listener, error) {
	if config == nil {
		if network != "unix" {
			log.Warningf("listening via %s to %s without TLS", network, address)
		}
		return net.Listen(network, address)
	}
	return tls.Listen(network, address, config)
}

// tlsDial wraps either net.Dial or crypto/tls.Dial, depending on the contents of
// the passed TLS Config.
func tlsDial(network, address string, config *tls.Config) (net.Conn, error) {
	if config == nil {
		if network != "unix" {
			log.Warningf("connecting via %s to %s without TLS", network, address)
		}
		return net.Dial(network, address)
	}
	return tls.Dial(network, address, config)
}

// tlsDialHTTP connects to an HTTP RPC server at the specified address.
func tlsDialHTTP(network, address string, config *tls.Config) (net.Conn, error) {
	conn, err := tlsDial(network, address, config)
	if err != nil {
		return conn, err
	}

	// Note: this code was adapted from net/rpc.DialHTTPPath.
	io.WriteString(conn, "CONNECT "+rpc.DefaultRPCPath+" HTTP/1.0\n\n")

	// Require successful HTTP response before switching to RPC protocol.
	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
	if err == nil {
		if resp.Status == connected {
			return conn, nil
		}
		err = util.Errorf("unexpected HTTP response: %s", resp.Status)
	}
	conn.Close()
	return nil, err
}
<|endoftext|>


<commit_before>package rsa

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
)

//rsa
func RsaEncrypt(publicKey []byte, origData []byte) ([]byte, error) {
	block, _ := pem.Decode(publicKey)
	if block == nil {
		return nil, errors.New("public key error")
	}

	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	pub := pubInterface.(*rsa.PublicKey)
	return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}

//rsa
func RsaDecrypt(privateKey []byte, ciphertest []byte) ([]byte, error) {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return nil, errors.New("pricate key error!")
	}

	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertest)
}

//sign
func Sign(priv *rsa.PrivateKey, hash crypto.Hash, data []byte) (signed []byte, err error) {
	return rsa.SignPKCS1v15(rand.Reader, priv, hash, data)
}

//unsign
func Unsign(pub *rsa.PublicKey, hash crypto.Hash, hashed, sign []byte) error {
	return rsa.VerifyPKCS1v15(pub, hash, hashed, sign)
}
<commit_msg>add comment<commit_after>package rsa

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
)

//RsaEncrypt return RSA encryption of data
func RsaEncrypt(publicKey []byte, origData []byte) ([]byte, error) {
	block, _ := pem.Decode(publicKey)
	if block == nil {
		return nil, errors.New("public key error")
	}

	pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	pub := pubInterface.(*rsa.PublicKey)
	return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}

//RsaDecrypt return RSA decryption of data.
func RsaDecrypt(privateKey []byte, ciphertest []byte) ([]byte, error) {
	block, _ := pem.Decode(privateKey)
	if block == nil {
		return nil, errors.New("pricate key error!")
	}

	priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertest)
}

//Sign
func Sign(priv *rsa.PrivateKey, hash crypto.Hash, data []byte) (signed []byte, err error) {
	return rsa.SignPKCS1v15(rand.Reader, priv, hash, data)
}

//Unsign
func Unsign(pub *rsa.PublicKey, hash crypto.Hash, hashed, sign []byte) error {
	return rsa.VerifyPKCS1v15(pub, hash, hashed, sign)
}
<|endoftext|>


<commit_before>package fetch

import (
	"compress/bzip2"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/notnil/chess"
	"github.com/srom/chessbot/common"
	"gopkg.in/freeeve/pgn.v1"
)

const DIMENSION = 768 // 8 * 8 squares * 12 piece types
const CHAN_BUFFER = 1e4

func YieldTriplets(urls <-chan string) <-chan *common.ChessBotTriplet {
	features := make(chan *common.ChessBotTriplet, CHAN_BUFFER)
	go func() {
		defer close(features)
		for url := range urls {
			log.Printf("Reading data from %v", url)
			response, err := http.Get(url)
			if err != nil {
				log.Printf("Error reading url %v: %v", url, err)
				continue
			}

			reader := bzip2.NewReader(response.Body)

			ps := pgn.NewPGNScanner(reader)
			for ps.Next() {
				game, err := ps.Scan()
				if err != nil {
					log.Printf("Error reading game: %v", err)
					continue
				}
				parseGame(game, features)
			}
		}
	}()
	return features
}

func parseGame(game *pgn.Game, features chan *common.ChessBotTriplet) {
	board := pgn.NewBoard()
	var parent *common.BoardBits
	for i, move := range game.Moves {
		if i == 0 {
			parent = getBoardBits(board)
		}

		pgnBoard := pgn.FENFromBoard(board).String()
		randomNextBoard, err := getRandomNextBoard(pgnBoard)
		if err != nil {
			log.Printf("Error getting random board: %v", err)
			return
		}

		random := getBoardBits(randomNextBoard)

		board.MakeMove(move)

		observed := getBoardBits(board)

		features <- getTriplet(parent, observed, random)
	}
}

func getBoardBits(board *pgn.Board) *common.BoardBits {
	pieces := make([]uint32, 0, DIMENSION)
	for _, piece := range common.PIECES {
		for _, position := range common.POSITIONS {
			if board.GetPiece(position) == piece {
				pieces = append(pieces, 1)
			} else {
				pieces = append(pieces, 0)
			}
		}
	}
	return &common.BoardBits{
		Pieces: pieces,
	}
}

func getTriplet(parent, observed, random *common.BoardBits) *common.ChessBotTriplet {
	return &common.ChessBotTriplet{
		Parent:   parent,
		Observed: observed,
		Random:   random,
	}
}

func getRandomNextBoard(boardFen string) (*pgn.Board, error) {
	fen, err := chess.FEN(boardFen)
	if err != nil {
		return nil, err
	}
	chessGame := chess.NewGame(fen)
	moves := chessGame.ValidMoves()
	move := randomMove(moves)
	chessGame.Move(move)
	return pgn.NewBoardFEN(chessGame.FEN())
}

func randomMove(moves []*chess.Move) *chess.Move {
	rand.Seed(time.Now().UnixNano())
	index := rand.Intn(len(moves))
	return moves[index]
}
<commit_msg>Be resilient to panic in Scan<commit_after>package fetch

import (
	"compress/bzip2"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/notnil/chess"
	"github.com/srom/chessbot/common"
	"gopkg.in/freeeve/pgn.v1"
)

const DIMENSION = 768 // 8 * 8 squares * 12 piece types
const CHAN_BUFFER = 1e4

func YieldTriplets(urls <-chan string) <-chan *common.ChessBotTriplet {
	rand.Seed(time.Now().UnixNano())
	features := make(chan *common.ChessBotTriplet, CHAN_BUFFER)
	go func() {
		defer close(features)
		for url := range urls {
			log.Printf("Reading data from %v", url)
			response, err := http.Get(url)
			if err != nil {
				log.Printf("Error reading url %v: %v", url, err)
				continue
			}
			scanGames(response, features)
		}
	}()
	return features
}

func scanGames(response *http.Response, features chan *common.ChessBotTriplet) {
	defer func() {
		if r := recover(); r != nil {
		    log.Printf("Recovered: %v", r)
		}
	}()

	reader := bzip2.NewReader(response.Body)

	ps := pgn.NewPGNScanner(reader)
	for ps.Next() {
		scanGame(ps, features)
	}
}

func scanGame(ps *pgn.PGNScanner, features chan *common.ChessBotTriplet) {
	game, err := ps.Scan()
	if err != nil {
		log.Printf("Error reading game: %v", err)
		return
	}
	parseGame(game, features)
}

func parseGame(game *pgn.Game, features chan *common.ChessBotTriplet) {
	board := pgn.NewBoard()
	var parent *common.BoardBits
	for i, move := range game.Moves {
		if i == 0 {
			parent = getBoardBits(board)
		}

		pgnBoard := pgn.FENFromBoard(board).String()
		randomNextBoard, err := getRandomNextBoard(pgnBoard)
		if err != nil {
			log.Printf("Error getting random board: %v", err)
			return
		}

		random := getBoardBits(randomNextBoard)

		board.MakeMove(move)

		observed := getBoardBits(board)

		features <- getTriplet(parent, observed, random)
	}
}

func getBoardBits(board *pgn.Board) *common.BoardBits {
	pieces := make([]uint32, 0, DIMENSION)
	for _, piece := range common.PIECES {
		for _, position := range common.POSITIONS {
			if board.GetPiece(position) == piece {
				pieces = append(pieces, 1)
			} else {
				pieces = append(pieces, 0)
			}
		}
	}
	return &common.BoardBits{
		Pieces: pieces,
	}
}

func getTriplet(parent, observed, random *common.BoardBits) *common.ChessBotTriplet {
	return &common.ChessBotTriplet{
		Parent:   parent,
		Observed: observed,
		Random:   random,
	}
}

func getRandomNextBoard(boardFen string) (*pgn.Board, error) {
	fen, err := chess.FEN(boardFen)
	if err != nil {
		return nil, err
	}
	chessGame := chess.NewGame(fen)
	moves := chessGame.ValidMoves()
	move := randomMove(moves)
	chessGame.Move(move)
	return pgn.NewBoardFEN(chessGame.FEN())
}

func randomMove(moves []*chess.Move) *chess.Move {
	index := rand.Intn(len(moves))
	return moves[index]
}
<|endoftext|>


<commit_before>package gzip

import (
	"internal/testenv"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// Per golang.org/issue/14937, check that every .gz file
// in the tree has a zero mtime.
func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
	if testing.Short() && testenv.Builder() == "" {
		t.Skip("skipping in short mode")
	}
	goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
	if err != nil {
		t.Fatal("error evaluating GOROOT: ", err)
	}
	var files []string
	err = filepath.Walk(goroot, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && strings.HasSuffix(path, ".gz") {
			files = append(files, path)
		}
		return nil
	})
	if err != nil {
		if os.IsNotExist(err) {
			t.Skipf("skipping: GOROOT directory not found: %s", runtime.GOROOT())
		}
		t.Fatal("error collecting list of .gz files in GOROOT: ", err)
	}
	if len(files) == 0 {
		t.Fatal("expected to find some .gz files under GOROOT")
	}
	for _, path := range files {
		checkZeroMTime(t, path)
	}
}

func checkZeroMTime(t *testing.T, path string) {
	f, err := os.Open(path)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	gz, err := NewReader(f)
	if err != nil {
		t.Errorf("cannot read gzip file %s: %s", path, err)
		return
	}
	defer gz.Close()
	if !gz.ModTime.IsZero() {
		t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
	}
}
<commit_msg>compress/gzip: skip TestGZIPFilesHaveZeroMTimes on non-builders<commit_after>package gzip

import (
	"internal/testenv"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// TestGZIPFilesHaveZeroMTimes checks that every .gz file in the tree
// has a zero MTIME. This is a requirement for the Debian maintainers
// to be able to have deterministic packages.
//
// See https://golang.org/issue/14937.
func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
	// To avoid spurious false positives due to untracked GZIP files that
	// may be in the user's GOROOT (Issue 18604), we only run this test on
	// the builders, which should have a clean checkout of the tree.
	if testenv.Builder() == "" {
		t.Skip("skipping test on non-builder")
	}
	goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
	if err != nil {
		t.Fatal("error evaluating GOROOT: ", err)
	}
	var files []string
	err = filepath.Walk(goroot, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if !info.IsDir() && strings.HasSuffix(path, ".gz") {
			files = append(files, path)
		}
		return nil
	})
	if err != nil {
		if os.IsNotExist(err) {
			t.Skipf("skipping: GOROOT directory not found: %s", runtime.GOROOT())
		}
		t.Fatal("error collecting list of .gz files in GOROOT: ", err)
	}
	if len(files) == 0 {
		t.Fatal("expected to find some .gz files under GOROOT")
	}
	for _, path := range files {
		checkZeroMTime(t, path)
	}
}

func checkZeroMTime(t *testing.T, path string) {
	f, err := os.Open(path)
	if err != nil {
		t.Error(err)
		return
	}
	defer f.Close()
	gz, err := NewReader(f)
	if err != nil {
		t.Errorf("cannot read gzip file %s: %s", path, err)
		return
	}
	defer gz.Close()
	if !gz.ModTime.IsZero() {
		t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

// maxArrayLen is the size of uint, which determines
// the maximum length of any array.
const maxArrayLen = 1<<((32<<(^uint(0)>>63))-1) - 1

// All non-std package dependencies live in this file,
// so porting to different environment is easy (just update functions).

func pruneSignExt(v []byte, pos bool) (n int) {
	if len(v) < 2 {
	} else if pos && v[0] == 0 {
		for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
		}
	} else if !pos && v[0] == 0xff {
		for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
		}
	}
	return
}

func halfFloatToFloatBits(h uint16) (f uint32) {
	// retrofitted from:
	// - OGRE (Object-Oriented Graphics Rendering Engine)
	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html

	s := uint32(h >> 15)
	m := uint32(h & 0x03ff)
	e := int32((h >> 10) & 0x1f)

	if e == 0 {
		if m == 0 { // plus or minus 0
			return s << 31
		}
		// Denormalized number -- renormalize it
		for (m & 0x0400) == 0 {
			m <<= 1
			e -= 1
		}
		e += 1
		m &= ^uint32(0x0400)
	} else if e == 31 {
		if m == 0 { // Inf
			return (s << 31) | 0x7f800000
		}
		return (s << 31) | 0x7f800000 | (m << 13) // NaN
	}
	e = e + (127 - 15)
	m = m << 13
	return (s << 31) | (uint32(e) << 23) | m
}

func floatToHalfFloatBits(i uint32) (h uint16) {
	// retrofitted from:
	// - OGRE (Object-Oriented Graphics Rendering Engine)
	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
	// - http://www.java2s.com/example/java-utility-method/float-to/floattohalf-float-f-fae00.html
	s := (i >> 16) & 0x8000
	e := int32(((i >> 23) & 0xff) - (127 - 15))
	m := i & 0x7fffff

	var h32 uint32

	if e <= 0 {
		if e < -10 { // zero
			h32 = s // track -0 vs +0
		} else {
			m = (m | 0x800000) >> uint32(1-e)
			h32 = s | (m >> 13)
		}
	} else if e == 0xff-(127-15) {
		if m == 0 { // Inf
			h32 = s | 0x7c00
		} else { // NAN
			m >>= 13
			var me uint32
			if m == 0 {
				me = 1
			}
			h32 = s | 0x7c00 | m | me
		}
	} else {
		if e > 30 { // Overflow
			h32 = s | 0x7c00
		} else {
			h32 = s | (uint32(e) << 10) | (m >> 13)
		}
	}
	h = uint16(h32)
	return
}

// growCap will return a new capacity for a slice, given the following:
//   - oldCap: current capacity
//   - unit: in-memory size of an element
//   - num: number of elements to add
func growCap(oldCap, unit, num uint) (newCap uint) {
	// appendslice logic (if cap < 1024, *2, else *1.25):
	//   leads to many copy calls, especially when copying bytes.
	//   bytes.Buffer model (2*cap + n): much better for bytes.
	// smarter way is to take the byte-size of the appended element(type) into account

	// maintain 1 thresholds:
	// t1: if cap <= t1, newcap = 2x
	//     else          newcap = 1.5x
	//
	// t1 is always >= 1024.
	// This means that, if unit size >= 16, then always do 2x or 1.5x (ie t1, t2, t3 are all same)
	//
	// With this, appending for bytes increase by:
	//    100% up to 4K
	//     50% beyond that

	// unit can be 0 e.g. for struct{}{}; handle that appropriately
	maxCap := num + (oldCap * 3 / 2)
	if unit == 0 || maxCap > MaxArrayLen || maxCap < oldCap { // handle wraparound, etc
		return maxArrayLen
	}

	var t1 uint = 1024 // default thresholds for large values
	if unit <= 4 {
		t1 = 8 * 1024
	} else if unit <= 16 {
		t1 = 2 * 1024
	}

	newCap = 2 + num
	if oldCap > 0 {
		if oldCap <= t1 { // [0,t1]
			newCap = num + (oldCap * 2)
		} else { // (t1,infinity]
			newCap = maxCap
		}
	}

	// ensure newCap takes multiples of a cache line (size is a multiple of 64)
	t1 = newCap * unit
	if t2 := t1 % 64; t2 != 0 {
		t1 += 64 - t2
		newCap = t1 / unit
	}

	return
}
<commit_msg>codec: fix maxArrayLen<commit_after>// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a MIT license found in the LICENSE file.

package codec

// maxArrayLen is the size of uint, which determines
// the maximum length of any array.
const maxArrayLen = 1<<((32<<(^uint(0)>>63))-1) - 1

// All non-std package dependencies live in this file,
// so porting to different environment is easy (just update functions).

func pruneSignExt(v []byte, pos bool) (n int) {
	if len(v) < 2 {
	} else if pos && v[0] == 0 {
		for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
		}
	} else if !pos && v[0] == 0xff {
		for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
		}
	}
	return
}

func halfFloatToFloatBits(h uint16) (f uint32) {
	// retrofitted from:
	// - OGRE (Object-Oriented Graphics Rendering Engine)
	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html

	s := uint32(h >> 15)
	m := uint32(h & 0x03ff)
	e := int32((h >> 10) & 0x1f)

	if e == 0 {
		if m == 0 { // plus or minus 0
			return s << 31
		}
		// Denormalized number -- renormalize it
		for (m & 0x0400) == 0 {
			m <<= 1
			e -= 1
		}
		e += 1
		m &= ^uint32(0x0400)
	} else if e == 31 {
		if m == 0 { // Inf
			return (s << 31) | 0x7f800000
		}
		return (s << 31) | 0x7f800000 | (m << 13) // NaN
	}
	e = e + (127 - 15)
	m = m << 13
	return (s << 31) | (uint32(e) << 23) | m
}

func floatToHalfFloatBits(i uint32) (h uint16) {
	// retrofitted from:
	// - OGRE (Object-Oriented Graphics Rendering Engine)
	//   function: halfToFloatI https://www.ogre3d.org/docs/api/1.9/_ogre_bitwise_8h_source.html
	// - http://www.java2s.com/example/java-utility-method/float-to/floattohalf-float-f-fae00.html
	s := (i >> 16) & 0x8000
	e := int32(((i >> 23) & 0xff) - (127 - 15))
	m := i & 0x7fffff

	var h32 uint32

	if e <= 0 {
		if e < -10 { // zero
			h32 = s // track -0 vs +0
		} else {
			m = (m | 0x800000) >> uint32(1-e)
			h32 = s | (m >> 13)
		}
	} else if e == 0xff-(127-15) {
		if m == 0 { // Inf
			h32 = s | 0x7c00
		} else { // NAN
			m >>= 13
			var me uint32
			if m == 0 {
				me = 1
			}
			h32 = s | 0x7c00 | m | me
		}
	} else {
		if e > 30 { // Overflow
			h32 = s | 0x7c00
		} else {
			h32 = s | (uint32(e) << 10) | (m >> 13)
		}
	}
	h = uint16(h32)
	return
}

// growCap will return a new capacity for a slice, given the following:
//   - oldCap: current capacity
//   - unit: in-memory size of an element
//   - num: number of elements to add
func growCap(oldCap, unit, num uint) (newCap uint) {
	// appendslice logic (if cap < 1024, *2, else *1.25):
	//   leads to many copy calls, especially when copying bytes.
	//   bytes.Buffer model (2*cap + n): much better for bytes.
	// smarter way is to take the byte-size of the appended element(type) into account

	// maintain 1 thresholds:
	// t1: if cap <= t1, newcap = 2x
	//     else          newcap = 1.5x
	//
	// t1 is always >= 1024.
	// This means that, if unit size >= 16, then always do 2x or 1.5x (ie t1, t2, t3 are all same)
	//
	// With this, appending for bytes increase by:
	//    100% up to 4K
	//     50% beyond that

	// unit can be 0 e.g. for struct{}{}; handle that appropriately
	maxCap := num + (oldCap * 3 / 2)
	if unit == 0 || maxCap > maxArrayLen || maxCap < oldCap { // handle wraparound, etc
		return maxArrayLen
	}

	var t1 uint = 1024 // default thresholds for large values
	if unit <= 4 {
		t1 = 8 * 1024
	} else if unit <= 16 {
		t1 = 2 * 1024
	}

	newCap = 2 + num
	if oldCap > 0 {
		if oldCap <= t1 { // [0,t1]
			newCap = num + (oldCap * 2)
		} else { // (t1,infinity]
			newCap = maxCap
		}
	}

	// ensure newCap takes multiples of a cache line (size is a multiple of 64)
	t1 = newCap * unit
	if t2 := t1 % 64; t2 != 0 {
		t1 += 64 - t2
		newCap = t1 / unit
	}

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Jaime Lopez. All rights reserved.
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file.

// The datatypes/collection package provides new structures and
// behaviours to the iteration of non-sorted unique element and homogeneous
// lists accepting primitives types and complex user structs as well.

// This part of package contains the core behaviour

package collection

import (
	"datatypes/generic"
	"reflect"
)

// Generic element
type Element interface{}

// A list of elements
// elements := ElementList{"element1", "element2"}
type ElementList []Element

// Generic elements collection
// Used as parameter type in order to allow encapsulate any
// kind of iterable object including ElementList as well
type CollectionElements interface{}

// Non-sorted unique element and homogeneous lists
type Collection struct {
	definition reflect.Type
	elements   []Element
}

// Adds a single element to the collection
// The collection must to be homogeneous so the specified element
// should be the same type such the other elements already stored in the collection.
// If the collection is empty and has no elements, it will take the type of
// that element as type definition for the collection
func (col *Collection) Add(element Element) {
	if col.IsEmpty() {
		col.definition = reflect.TypeOf(element)
	}

	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	if col.Contains(element) {
		NewDuplicatedElementError()
	}

	col.elements = append(col.elements, element)
}

// Inserts a range (slice) inside the collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) AddRange(elements CollectionElements) {
	for _, element := range generic.ToSlice(elements) {
		col.Add(element)
	}
}

// Adds the elements contained in the parameter collection inside the instanced collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) AddCollection(collection *Collection) {
	col.AddRange(collection.elements)
}

// Returns the first element without removing it from the collection
func (col *Collection) First() Element {
	return col.elements[0]
}

// Returns the last element without removing it from the collection
func (col *Collection) Last() Element {
	return col.elements[len(col.elements)-1]
}

// Although a collection is an unsorted data structure list and the position
// of the elements could be changed, this method allows to return an specific index position.
// Be aware that the order of elements could be changed constantly such it's described before
func (col *Collection) ElementAt(position int) Element {
	return col.elements[position]
}

// Returns the stored collection elements as slice of this elements
// This is the proper way to iterate over all the elements of the collection
// treating them as a normal range
func (col *Collection) Elements() []Element {
	return col.elements
}

// Extract the first element and return it
// Keep in mind that this method will modify the collection elements substracting that element
func (col *Collection) Extract() Element {
	element := col.First()
	col.elements = col.elements[1:]

	return element
}

// Sets a new value for a specified index element
func (col *Collection) Set(position int, element Element) {
	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	col.elements[position] = element
}

// Removes an specified already stored element
// If it's not found the method will return an error
func (col *Collection) Delete(element Element) {
	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	for index, current := range col.elements {
		if reflect.DeepEqual(current, element) {
			col.elements = append(col.elements[:index], col.elements[index+1:]...)

			return
		}
	}

	NewElementNotFoundError()
}

// Removes all the found elements contained in the specified range (slice)
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) DeleteRange(elements CollectionElements) {
	for _, element := range generic.ToSlice(elements) {
		col.Delete(element)
	}
}

// Removes all the found elements contained in the specified collection from the instaced collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) DeleteCollection(collection *Collection) {
	col.DeleteRange(collection.elements)
}

// Checks if the specified element is already existing in the collection
func (col *Collection) Contains(element Element) bool {
	for _, iterator := range col.elements {
		if reflect.DeepEqual(iterator, element) {
			return true
		}
	}

	return false
}

// Checks if any of the parameter elements there are already contained in the collection
func (col *Collection) ContainsAny(elements CollectionElements) (result bool) {
	defer func() {
		if recover() != nil {
			result = false
		}
	}()

	for _, element := range generic.ToSlice(elements) {
		if col.Contains(element) {
			return true
		}
	}

	return
}

// Returns the number of elements inside the collection
func (col *Collection) Size() int {
	return len(col.elements)
}

// Checks if the collection is empty or not
func (col *Collection) IsEmpty() bool {
	return col.Size() == 0
}

func (col *Collection) isHomogeneousWith(element Element) bool {
	return col.definition == reflect.TypeOf(element)
}

// Instances a new empty collection
func NewEmptyCollection() *Collection {
	return new(Collection)
}

// This method allows to instance a new Collection with a group of elements
// It accepts an enumerable
func NewCollection(elements CollectionElements) (collection *Collection) {
	collection = new(Collection)

	defer func(collection *Collection) {
		if recover() != nil {
			collection.Add(elements)
		}
	}(collection)

	collection.AddRange(elements)

	return
}
<commit_msg>Test for travis<commit_after>// Copyright (c) 2017 Jaime Lopez. All rights reserved.
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file.

// The datatypes/collection package provides new structures and
// behaviours to the iteration of non-sorted unique element and homogeneous
// lists accepting primitives types and complex user structs as well.

// This part of package contains the core behaviour

package collection

import (
	"reflect"

	"github.com/jaimelopez/datatypes/generic"
)

// Generic element
type Element interface{}

// A list of elements
// elements := ElementList{"element1", "element2"}
type ElementList []Element

// Generic elements collection
// Used as parameter type in order to allow encapsulate any
// kind of iterable object including ElementList as well
type CollectionElements interface{}

// Non-sorted unique element and homogeneous lists
type Collection struct {
	definition reflect.Type
	elements   []Element
}

// Adds a single element to the collection
// The collection must to be homogeneous so the specified element
// should be the same type such the other elements already stored in the collection.
// If the collection is empty and has no elements, it will take the type of
// that element as type definition for the collection
func (col *Collection) Add(element Element) {
	if col.IsEmpty() {
		col.definition = reflect.TypeOf(element)
	}

	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	if col.Contains(element) {
		NewDuplicatedElementError()
	}

	col.elements = append(col.elements, element)
}

// Inserts a range (slice) inside the collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) AddRange(elements CollectionElements) {
	for _, element := range generic.ToSlice(elements) {
		col.Add(element)
	}
}

// Adds the elements contained in the parameter collection inside the instanced collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) AddCollection(collection *Collection) {
	col.AddRange(collection.elements)
}

// Returns the first element without removing it from the collection
func (col *Collection) First() Element {
	return col.elements[0]
}

// Returns the last element without removing it from the collection
func (col *Collection) Last() Element {
	return col.elements[len(col.elements)-1]
}

// Although a collection is an unsorted data structure list and the position
// of the elements could be changed, this method allows to return an specific index position.
// Be aware that the order of elements could be changed constantly such it's described before
func (col *Collection) ElementAt(position int) Element {
	return col.elements[position]
}

// Returns the stored collection elements as slice of this elements
// This is the proper way to iterate over all the elements of the collection
// treating them as a normal range
func (col *Collection) Elements() []Element {
	return col.elements
}

// Extract the first element and return it
// Keep in mind that this method will modify the collection elements substracting that element
func (col *Collection) Extract() Element {
	element := col.First()
	col.elements = col.elements[1:]

	return element
}

// Sets a new value for a specified index element
func (col *Collection) Set(position int, element Element) {
	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	col.elements[position] = element
}

// Removes an specified already stored element
// If it's not found the method will return an error
func (col *Collection) Delete(element Element) {
	if !col.isHomogeneousWith(element) {
		NewInvalidElementTypeError(col.definition.Name())
	}

	for index, current := range col.elements {
		if reflect.DeepEqual(current, element) {
			col.elements = append(col.elements[:index], col.elements[index+1:]...)

			return
		}
	}

	NewElementNotFoundError()
}

// Removes all the found elements contained in the specified range (slice)
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) DeleteRange(elements CollectionElements) {
	for _, element := range generic.ToSlice(elements) {
		col.Delete(element)
	}
}

// Removes all the found elements contained in the specified collection from the instaced collection
// If the parameter can't be converted to a iterable data type it's return an error
func (col *Collection) DeleteCollection(collection *Collection) {
	col.DeleteRange(collection.elements)
}

// Checks if the specified element is already existing in the collection
func (col *Collection) Contains(element Element) bool {
	for _, iterator := range col.elements {
		if reflect.DeepEqual(iterator, element) {
			return true
		}
	}

	return false
}

// Checks if any of the parameter elements there are already contained in the collection
func (col *Collection) ContainsAny(elements CollectionElements) (result bool) {
	defer func() {
		if recover() != nil {
			result = false
		}
	}()

	for _, element := range generic.ToSlice(elements) {
		if col.Contains(element) {
			return true
		}
	}

	return
}

// Returns the number of elements inside the collection
func (col *Collection) Size() int {
	return len(col.elements)
}

// Checks if the collection is empty or not
func (col *Collection) IsEmpty() bool {
	return col.Size() == 0
}

func (col *Collection) isHomogeneousWith(element Element) bool {
	return col.definition == reflect.TypeOf(element)
}

// Instances a new empty collection
func NewEmptyCollection() *Collection {
	return new(Collection)
}

// This method allows to instance a new Collection with a group of elements
// It accepts an enumerable
func NewCollection(elements CollectionElements) (collection *Collection) {
	collection = new(Collection)

	defer func(collection *Collection) {
		if recover() != nil {
			collection.Add(elements)
		}
	}(collection)

	collection.AddRange(elements)

	return
}
<|endoftext|>


<commit_before>package build

import (
	"flag"
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgOnly []string

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.Var((*stringSliceValue)(&cfgOnly), "only", "only build the given builds by name")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tplData, err := ioutil.ReadFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to read template file: %s", err))
		return 1
	}

	// Parse the template into a machine-usable format
	log.Println("Parsing template...")
	tpl, err := packer.ParseTemplate(tplData)
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:     env.Builder,
		Hook:        env.Hook,
		Provisioner: env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	buildNames := tpl.BuildNames()
	builds := make([]packer.Build, 0, len(buildNames))
	for _, buildName := range buildNames {
		if len(cfgOnly) > 0 {
			found := false
			for _, only := range cfgOnly {
				if buildName == only {
					found = true
					break
				}
			}

			if !found {
				log.Printf("Skipping build '%s' because not specified by -only.", buildName)
				continue
			}
		}

		log.Printf("Creating build: %s", buildName)
		build, err := tpl.Build(buildName, components)
		if err != nil {
			env.Ui().Error(fmt.Sprintf("Failed to create build '%s': \n\n%s", buildName, err))
			return 1
		}

		builds = append(builds, build)
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorYellow,
		packer.UiColorBlue,
		packer.UiColorMagenta,
		packer.UiColorCyan,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		var ui packer.Ui

		ui = &packer.ColoredUi{
			colors[i%len(colors)],
			env.Ui(),
		}

		ui = &packer.PrefixedUi{
			fmt.Sprintf("==> %s", b.Name()),
			fmt.Sprintf("    %s", b.Name()),
			ui,
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		err := b.Prepare(buildUis[b.Name()])
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var wg sync.WaitGroup
	artifacts := make(map[string]packer.Artifact)
	for _, b := range builds {
		log.Printf("Starting build run: %s", b.Name())

		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Run the build in a goroutine
		go func() {
			defer wg.Done()
			artifacts[b.Name()] = b.Run(buildUis[b.Name()])
		}()
	}

	// Handle signals
	var interruptWg sync.WaitGroup
	interrupted := false
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)

	go func() {
		<-sigCh
		interruptWg.Add(1)
		defer interruptWg.Done()
		interrupted = true

		log.Println("Interrupted! Cancelling builds...")

		var wg sync.WaitGroup
		for _, b := range builds {
			wg.Add(1)

			go func() {
				defer wg.Done()

				log.Printf("Stopping build: %s", b.Name())
				b.Cancel()
			}()
		}

		wg.Wait()
	}()

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	wg.Wait()
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	// Output all the artifacts
	env.Ui().Say("\n==> The build completed! The artifacts created were:")
	for name, artifact := range artifacts {
		env.Ui().Say(fmt.Sprintf("--> %s:", name))
		env.Ui().Say(artifact.String())
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<commit_msg>command/build: Output nothign if artifact is nil<commit_after>package build

import (
	"flag"
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgOnly []string

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.Var((*stringSliceValue)(&cfgOnly), "only", "only build the given builds by name")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tplData, err := ioutil.ReadFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to read template file: %s", err))
		return 1
	}

	// Parse the template into a machine-usable format
	log.Println("Parsing template...")
	tpl, err := packer.ParseTemplate(tplData)
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:     env.Builder,
		Hook:        env.Hook,
		Provisioner: env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	buildNames := tpl.BuildNames()
	builds := make([]packer.Build, 0, len(buildNames))
	for _, buildName := range buildNames {
		if len(cfgOnly) > 0 {
			found := false
			for _, only := range cfgOnly {
				if buildName == only {
					found = true
					break
				}
			}

			if !found {
				log.Printf("Skipping build '%s' because not specified by -only.", buildName)
				continue
			}
		}

		log.Printf("Creating build: %s", buildName)
		build, err := tpl.Build(buildName, components)
		if err != nil {
			env.Ui().Error(fmt.Sprintf("Failed to create build '%s': \n\n%s", buildName, err))
			return 1
		}

		builds = append(builds, build)
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorYellow,
		packer.UiColorBlue,
		packer.UiColorMagenta,
		packer.UiColorCyan,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		var ui packer.Ui

		ui = &packer.ColoredUi{
			colors[i%len(colors)],
			env.Ui(),
		}

		ui = &packer.PrefixedUi{
			fmt.Sprintf("==> %s", b.Name()),
			fmt.Sprintf("    %s", b.Name()),
			ui,
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		err := b.Prepare(buildUis[b.Name()])
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var wg sync.WaitGroup
	artifacts := make(map[string]packer.Artifact)
	for _, b := range builds {
		log.Printf("Starting build run: %s", b.Name())

		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Run the build in a goroutine
		go func() {
			defer wg.Done()
			artifacts[b.Name()] = b.Run(buildUis[b.Name()])
		}()
	}

	// Handle signals
	var interruptWg sync.WaitGroup
	interrupted := false
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)

	go func() {
		<-sigCh
		interruptWg.Add(1)
		defer interruptWg.Done()
		interrupted = true

		log.Println("Interrupted! Cancelling builds...")

		var wg sync.WaitGroup
		for _, b := range builds {
			wg.Add(1)

			go func() {
				defer wg.Done()

				log.Printf("Stopping build: %s", b.Name())
				b.Cancel()
			}()
		}

		wg.Wait()
	}()

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	wg.Wait()
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	// Output all the artifacts
	env.Ui().Say("\n==> The build completed! The artifacts created were:")
	for name, artifact := range artifacts {
		env.Ui().Say(fmt.Sprintf("--> %s:", name))

		if artifact != nil {
			env.Ui().Say(artifact.String())
		} else {
			env.Ui().Say("<nothing>")
		}
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<|endoftext|>