<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.8.1+git"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	printVersion  bool
	ignoreFailure bool
	sources       struct {
		file            string
		configDrive     string
		metadataService bool
		url             string
		procCmdLine     bool
	}
	convertNetconf string
	workspace      string
	sshKeyName     string
)

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&sources.metadataService, "from-metadata-service", false, "Download data from metadata service")
	flag.StringVar(&sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files (requires the -from-configdrive flag)")
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

func main() {
	flag.Parse()

	die := func() {
		if ignoreFailure {
			os.Exit(0)
		}
		os.Exit(1)
	}

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if convertNetconf != "" && sources.configDrive == "" {
		fmt.Println("-convert-netconf flag requires -from-configdrive")
		os.Exit(1)
	}

	switch convertNetconf {
	case "":
	case "debian":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian'\n", convertNetconf)
		os.Exit(1)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-metadata-service, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		die()
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\n", err)
		die()
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		die()
	}

	// Extract IPv4 addresses from metadata if possible
	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			die()
		}
	}

	env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName, subs)

	var ccm, ccu *initialize.CloudConfig
	var script *system.Script
	if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil {
		fmt.Printf("Failed to parse meta-data: %v\n", err)
		die()
	}
	if ud, err := initialize.ParseUserData(string(userdataBytes)); err != nil {
		fmt.Printf("Failed to parse user-data: %v\n", err)
		die()
	} else {
		switch t := ud.(type) {
		case *initialize.CloudConfig:
			ccu = t
		case system.Script:
			script = &t
		}
	}

	var cc *initialize.CloudConfig
	if ccm != nil && ccu != nil {
		fmt.Println("Merging cloud-config from meta-data and user-data")
		merged := mergeCloudConfig(*ccu, *ccm)
		cc = &merged
	} else if ccm != nil && ccu == nil {
		fmt.Println("Processing cloud-config from meta-data")
		cc = ccm
	} else if ccm == nil && ccu != nil {
		fmt.Println("Processing cloud-config from user-data")
		cc = ccu
	} else {
		fmt.Println("No cloud-config data to handle.")
	}

	if cc != nil {
		if err = initialize.Apply(*cc, env); err != nil {
			fmt.Printf("Failed to apply cloud-config: %v\n", err)
			die()
		}
	}

	if script != nil {
		if err = runScript(*script, env); err != nil {
			fmt.Printf("Failed to run script: %v\n", err)
			die()
		}
	}
}

// mergeCloudConfig merges certain options from mdcc (a CloudConfig derived from
// meta-data) onto udcc (a CloudConfig derived from user-data), if they are
// not already set on udcc (i.e. user-data always takes precedence)
// NB: This needs to be kept in sync with ParseMetadata so that it tracks all
// elements of a CloudConfig which that function can populate.
func mergeCloudConfig(mdcc, udcc initialize.CloudConfig) (cc initialize.CloudConfig) {
	if mdcc.Hostname != "" {
		if udcc.Hostname != "" {
			fmt.Printf("Warning: user-data hostname (%s) overrides metadata hostname (%s)", udcc.Hostname, mdcc.Hostname)
		} else {
			udcc.Hostname = mdcc.Hostname
		}

	}
	for _, key := range mdcc.SSHAuthorizedKeys {
		udcc.SSHAuthorizedKeys = append(udcc.SSHAuthorizedKeys, key)
	}
	if mdcc.NetworkConfigPath != "" {
		if udcc.NetworkConfigPath != "" {
			fmt.Printf("Warning: user-data NetworkConfigPath %s overrides metadata NetworkConfigPath %s", udcc.NetworkConfigPath, mdcc.NetworkConfigPath)
		} else {
			udcc.NetworkConfigPath = mdcc.NetworkConfigPath
		}
	}
	return udcc
}

// getDatasources creates a slice of possible Datasources for cloudinit based
// on the different source command-line flags.
func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if sources.file != "" {
		dss = append(dss, datasource.NewLocalFile(sources.file))
	}
	if sources.url != "" {
		dss = append(dss, datasource.NewRemoteFile(sources.url))
	}
	if sources.configDrive != "" {
		dss = append(dss, datasource.NewConfigDrive(sources.configDrive))
	}
	if sources.metadataService {
		dss = append(dss, datasource.NewMetadataService())
	}
	if sources.procCmdLine {
		dss = append(dss, datasource.NewProcCmdline())
	}
	return dss
}

// selectDatasource attempts to choose a valid Datasource to use based on its
// current availability. The first Datasource to report to be available is
// returned. Datasources will be retried if possible if they are not
// immediately available. If all Datasources are permanently unavailable or
// datasourceTimeout is reached before one becomes available, nil is returned.
func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.Tick(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.Tick(datasourceTimeout):
	}

	close(stop)
	return s
}

// TODO(jonboulle): this should probably be refactored and moved into a different module
func runScript(script system.Script, env *initialize.Environment) error {
	err := initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}
	path, err := initialize.PersistScriptInWorkspace(script, env.Workspace())
	if err == nil {
		var name string
		name, err = system.ExecuteScript(path)
		initialize.PersistUnitNameInWorkspace(name, env.Workspace())
	}
	return err
}
<commit_msg>coreos-cloudinit: bump to 0.8.2<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"sync"
	"time"

	"github.com/coreos/coreos-cloudinit/datasource"
	"github.com/coreos/coreos-cloudinit/initialize"
	"github.com/coreos/coreos-cloudinit/pkg"
	"github.com/coreos/coreos-cloudinit/system"
)

const (
	version               = "0.8.2"
	datasourceInterval    = 100 * time.Millisecond
	datasourceMaxInterval = 30 * time.Second
	datasourceTimeout     = 5 * time.Minute
)

var (
	printVersion  bool
	ignoreFailure bool
	sources       struct {
		file            string
		configDrive     string
		metadataService bool
		url             string
		procCmdLine     bool
	}
	convertNetconf string
	workspace      string
	sshKeyName     string
)

func init() {
	flag.BoolVar(&printVersion, "version", false, "Print the version and exit")
	flag.BoolVar(&ignoreFailure, "ignore-failure", false, "Exits with 0 status in the event of malformed input from user-data")
	flag.StringVar(&sources.file, "from-file", "", "Read user-data from provided file")
	flag.StringVar(&sources.configDrive, "from-configdrive", "", "Read data from provided cloud-drive directory")
	flag.BoolVar(&sources.metadataService, "from-metadata-service", false, "Download data from metadata service")
	flag.StringVar(&sources.url, "from-url", "", "Download user-data from provided url")
	flag.BoolVar(&sources.procCmdLine, "from-proc-cmdline", false, fmt.Sprintf("Parse %s for '%s=<url>', using the cloud-config served by an HTTP GET to <url>", datasource.ProcCmdlineLocation, datasource.ProcCmdlineCloudConfigFlag))
	flag.StringVar(&convertNetconf, "convert-netconf", "", "Read the network config provided in cloud-drive and translate it from the specified format into networkd unit files (requires the -from-configdrive flag)")
	flag.StringVar(&workspace, "workspace", "/var/lib/coreos-cloudinit", "Base directory coreos-cloudinit should use to store data")
	flag.StringVar(&sshKeyName, "ssh-key-name", initialize.DefaultSSHKeyName, "Add SSH keys to the system with the given name")
}

func main() {
	flag.Parse()

	die := func() {
		if ignoreFailure {
			os.Exit(0)
		}
		os.Exit(1)
	}

	if printVersion == true {
		fmt.Printf("coreos-cloudinit version %s\n", version)
		os.Exit(0)
	}

	if convertNetconf != "" && sources.configDrive == "" {
		fmt.Println("-convert-netconf flag requires -from-configdrive")
		os.Exit(1)
	}

	switch convertNetconf {
	case "":
	case "debian":
	default:
		fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian'\n", convertNetconf)
		os.Exit(1)
	}

	dss := getDatasources()
	if len(dss) == 0 {
		fmt.Println("Provide at least one of --from-file, --from-configdrive, --from-metadata-service, --from-url or --from-proc-cmdline")
		os.Exit(1)
	}

	ds := selectDatasource(dss)
	if ds == nil {
		fmt.Println("No datasources available in time")
		die()
	}

	fmt.Printf("Fetching user-data from datasource of type %q\n", ds.Type())
	userdataBytes, err := ds.FetchUserdata()
	if err != nil {
		fmt.Printf("Failed fetching user-data from datasource: %v\n", err)
		die()
	}

	fmt.Printf("Fetching meta-data from datasource of type %q\n", ds.Type())
	metadataBytes, err := ds.FetchMetadata()
	if err != nil {
		fmt.Printf("Failed fetching meta-data from datasource: %v\n", err)
		die()
	}

	// Extract IPv4 addresses from metadata if possible
	var subs map[string]string
	if len(metadataBytes) > 0 {
		subs, err = initialize.ExtractIPsFromMetadata(metadataBytes)
		if err != nil {
			fmt.Printf("Failed extracting IPs from meta-data: %v\n", err)
			die()
		}
	}

	env := initialize.NewEnvironment("/", ds.ConfigRoot(), workspace, convertNetconf, sshKeyName, subs)

	var ccm, ccu *initialize.CloudConfig
	var script *system.Script
	if ccm, err = initialize.ParseMetaData(string(metadataBytes)); err != nil {
		fmt.Printf("Failed to parse meta-data: %v\n", err)
		die()
	}
	if ud, err := initialize.ParseUserData(string(userdataBytes)); err != nil {
		fmt.Printf("Failed to parse user-data: %v\n", err)
		die()
	} else {
		switch t := ud.(type) {
		case *initialize.CloudConfig:
			ccu = t
		case system.Script:
			script = &t
		}
	}

	var cc *initialize.CloudConfig
	if ccm != nil && ccu != nil {
		fmt.Println("Merging cloud-config from meta-data and user-data")
		merged := mergeCloudConfig(*ccu, *ccm)
		cc = &merged
	} else if ccm != nil && ccu == nil {
		fmt.Println("Processing cloud-config from meta-data")
		cc = ccm
	} else if ccm == nil && ccu != nil {
		fmt.Println("Processing cloud-config from user-data")
		cc = ccu
	} else {
		fmt.Println("No cloud-config data to handle.")
	}

	if cc != nil {
		if err = initialize.Apply(*cc, env); err != nil {
			fmt.Printf("Failed to apply cloud-config: %v\n", err)
			die()
		}
	}

	if script != nil {
		if err = runScript(*script, env); err != nil {
			fmt.Printf("Failed to run script: %v\n", err)
			die()
		}
	}
}

// mergeCloudConfig merges certain options from mdcc (a CloudConfig derived from
// meta-data) onto udcc (a CloudConfig derived from user-data), if they are
// not already set on udcc (i.e. user-data always takes precedence)
// NB: This needs to be kept in sync with ParseMetadata so that it tracks all
// elements of a CloudConfig which that function can populate.
func mergeCloudConfig(mdcc, udcc initialize.CloudConfig) (cc initialize.CloudConfig) {
	if mdcc.Hostname != "" {
		if udcc.Hostname != "" {
			fmt.Printf("Warning: user-data hostname (%s) overrides metadata hostname (%s)", udcc.Hostname, mdcc.Hostname)
		} else {
			udcc.Hostname = mdcc.Hostname
		}

	}
	for _, key := range mdcc.SSHAuthorizedKeys {
		udcc.SSHAuthorizedKeys = append(udcc.SSHAuthorizedKeys, key)
	}
	if mdcc.NetworkConfigPath != "" {
		if udcc.NetworkConfigPath != "" {
			fmt.Printf("Warning: user-data NetworkConfigPath %s overrides metadata NetworkConfigPath %s", udcc.NetworkConfigPath, mdcc.NetworkConfigPath)
		} else {
			udcc.NetworkConfigPath = mdcc.NetworkConfigPath
		}
	}
	return udcc
}

// getDatasources creates a slice of possible Datasources for cloudinit based
// on the different source command-line flags.
func getDatasources() []datasource.Datasource {
	dss := make([]datasource.Datasource, 0, 5)
	if sources.file != "" {
		dss = append(dss, datasource.NewLocalFile(sources.file))
	}
	if sources.url != "" {
		dss = append(dss, datasource.NewRemoteFile(sources.url))
	}
	if sources.configDrive != "" {
		dss = append(dss, datasource.NewConfigDrive(sources.configDrive))
	}
	if sources.metadataService {
		dss = append(dss, datasource.NewMetadataService())
	}
	if sources.procCmdLine {
		dss = append(dss, datasource.NewProcCmdline())
	}
	return dss
}

// selectDatasource attempts to choose a valid Datasource to use based on its
// current availability. The first Datasource to report to be available is
// returned. Datasources will be retried if possible if they are not
// immediately available. If all Datasources are permanently unavailable or
// datasourceTimeout is reached before one becomes available, nil is returned.
func selectDatasource(sources []datasource.Datasource) datasource.Datasource {
	ds := make(chan datasource.Datasource)
	stop := make(chan struct{})
	var wg sync.WaitGroup

	for _, s := range sources {
		wg.Add(1)
		go func(s datasource.Datasource) {
			defer wg.Done()

			duration := datasourceInterval
			for {
				fmt.Printf("Checking availability of %q\n", s.Type())
				if s.IsAvailable() {
					ds <- s
					return
				} else if !s.AvailabilityChanges() {
					return
				}
				select {
				case <-stop:
					return
				case <-time.Tick(duration):
					duration = pkg.ExpBackoff(duration, datasourceMaxInterval)
				}
			}
		}(s)
	}

	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	var s datasource.Datasource
	select {
	case s = <-ds:
	case <-done:
	case <-time.Tick(datasourceTimeout):
	}

	close(stop)
	return s
}

// TODO(jonboulle): this should probably be refactored and moved into a different module
func runScript(script system.Script, env *initialize.Environment) error {
	err := initialize.PrepWorkspace(env.Workspace())
	if err != nil {
		fmt.Printf("Failed preparing workspace: %v\n", err)
		return err
	}
	path, err := initialize.PersistScriptInWorkspace(script, env.Workspace())
	if err == nil {
		var name string
		name, err = system.ExecuteScript(path)
		initialize.PersistUnitNameInWorkspace(name, env.Workspace())
	}
	return err
}
<|endoftext|>


<commit_before>package stow

import (
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"io"
)

// Codec provides a mechanism for storing/retriving objects as streams of data.
type Codec interface {
	NewEncoder(io.Writer) Encoder
	NewDecoder(io.Reader) Decoder
}

// Encoder is used to encode objects
type Encoder interface {
	Encode(interface{}) error
}

// Decoder is used to decode objects
type Decoder interface {
	Decode(interface{}) error
}

var (
	_ Codec = XMLCodec{}
	_ Codec = JSONCodec{}
	_ Codec = GobCodec{}
)

// XMLCodec is used to encode/decode XML
type XMLCodec struct{}

// NewEncoder returns a new xml encoder which writes to w
func (c XMLCodec) NewEncoder(w io.Writer) Encoder {
	return xml.NewEncoder(w)
}

// NewDecoder returns a new xml decoder which reads from r
func (c XMLCodec) NewDecoder(r io.Reader) Decoder {
	return xml.NewDecoder(r)
}

// JSONCodec is used to encode/decode JSON
type JSONCodec struct{}

// NewEncoder retuns a new json encoder which writes to w
func (c JSONCodec) NewEncoder(w io.Writer) Encoder {
	return json.NewEncoder(w)
}

// NewDecoder returns a new json decoder which reads from r
func (c JSONCodec) NewDecoder(r io.Reader) Decoder {
	return json.NewDecoder(r)
}

// GobCodec is used to encode/decode using the Gob format.
type GobCodec struct{}

// Gob Shortcuts

func Register(value interface{}) {
	gob.Register(value)
}

func RegisterName(name string, value interface{}) {
	gob.RegisterName(name, value)
}

// NewEncoder returns a new gob encoder which writes to w
func (c GobCodec) NewEncoder(w io.Writer) Encoder {
	return gob.NewEncoder(w)
}

// NewDecoder returns a new gob decoder which reads from r
func (c GobCodec) NewDecoder(r io.Reader) Decoder {
	return gob.NewDecoder(r)
}
<commit_msg>added godoc<commit_after>package stow

import (
	"encoding/gob"
	"encoding/json"
	"encoding/xml"
	"io"
)

// Codec provides a mechanism for storing/retriving objects as streams of data.
type Codec interface {
	NewEncoder(io.Writer) Encoder
	NewDecoder(io.Reader) Decoder
}

// Encoder is used to encode objects
type Encoder interface {
	Encode(interface{}) error
}

// Decoder is used to decode objects
type Decoder interface {
	Decode(interface{}) error
}

var (
	_ Codec = XMLCodec{}
	_ Codec = JSONCodec{}
	_ Codec = GobCodec{}
)

// XMLCodec is used to encode/decode XML
type XMLCodec struct{}

// NewEncoder returns a new xml encoder which writes to w
func (c XMLCodec) NewEncoder(w io.Writer) Encoder {
	return xml.NewEncoder(w)
}

// NewDecoder returns a new xml decoder which reads from r
func (c XMLCodec) NewDecoder(r io.Reader) Decoder {
	return xml.NewDecoder(r)
}

// JSONCodec is used to encode/decode JSON
type JSONCodec struct{}

// NewEncoder retuns a new json encoder which writes to w
func (c JSONCodec) NewEncoder(w io.Writer) Encoder {
	return json.NewEncoder(w)
}

// NewDecoder returns a new json decoder which reads from r
func (c JSONCodec) NewDecoder(r io.Reader) Decoder {
	return json.NewDecoder(r)
}

// GobCodec is used to encode/decode using the Gob format.
type GobCodec struct{}

// Register registers the type using gob.Register for use with NewStore() and the GobCodec.
func Register(value interface{}) {
	gob.Register(value)
}

// RegisterName registers the type using gob.RegisterName for use with NewStore() and the GobCodec.
func RegisterName(name string, value interface{}) {
	gob.RegisterName(name, value)
}

// NewEncoder returns a new gob encoder which writes to w
func (c GobCodec) NewEncoder(w io.Writer) Encoder {
	return gob.NewEncoder(w)
}

// NewDecoder returns a new gob decoder which reads from r
func (c GobCodec) NewDecoder(r io.Reader) Decoder {
	return gob.NewDecoder(r)
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"github.com/olekukonko/tablewriter"
	"io"
	"net/http"
	"os"
	"strings"
)

func containsStr(slice []string, item string) bool {
	set := make(map[string]struct{}, len(slice))
	for _, s := range slice {
		set[s] = struct{}{}
	}
	_, ok := set[item]
	return ok
}

func main() {

	if os.Args[1] == "-update" {
		db, _ := os.Create(os.Getenv("HOME") + "/.cheat_sheets.db")
		defer db.Close()
		resp, _ := http.Get("https://github.com/mvrpl/Terminal-Cheat-Sheet/blob/master/cheat_sheets.db?raw=true")
		defer resp.Body.Close()
		io.Copy(db, resp.Body)
		fmt.Println("Banco de dados atualizado com sucesso!")
		os.Exit(0)
	}

	Program := flag.String("program", "", "Cheat Sheet for the program. (Required)")
	flag.Parse()

	db, _ := sql.Open("sqlite3", os.Getenv("HOME")+"/.cheat_sheets.db")
	rows, err := db.Query("SELECT * FROM " + *Program)
	dbtables, err := db.Query("select name from sqlite_master where type = 'table'")

	tables := []string{}
	for dbtables.Next() {
		var name string
		_ = dbtables.Scan(&name)
		tables = append(tables, name)
	}

	if containsStr(tables, *Program) != true {
		fmt.Println("Program not exists in database!")
		os.Exit(1)
	}

	if err != nil {
		panic(err)
	}

	var data map[string][]map[string]string
	data = make(map[string][]map[string]string)

	for rows.Next() {
		var command string
		var about string
		var session string
		_ = rows.Scan(&command, &about, &session)
		commands := map[string]string{
			command: about,
		}
		data[session] = append(data[session], commands)
	}

	for key, value := range data {
		fmt.Println("+" + strings.Repeat("-", len(key)+2) + "+")
		fmt.Println("| \033[1m" + strings.ToUpper(key) + "\033[0m |")
		table := tablewriter.NewWriter(os.Stdout)
		table.SetHeader([]string{"Command", "Description"})
		table.SetRowLine(true)
		table.SetRowSeparator("-")
		for _, v := range value {
			for cmd, desc := range v {
				outline := []string{cmd, desc}
				table.Append(outline)
			}
		}
		table.Render()
	}
}
<commit_msg>Modified calls to program.<commit_after>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"github.com/olekukonko/tablewriter"
	"io"
	"net/http"
	"os"
	"strings"
)

func containsStr(slice []string, item string) bool {
	set := make(map[string]struct{}, len(slice))
	for _, s := range slice {
		set[s] = struct{}{}
	}
	_, ok := set[item]
	return ok
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func updateDB() {
	db, err := os.Create(os.Getenv("HOME") + "/.cheat_sheets.db")
	check(err)
	defer db.Close()
	resp, err := http.Get("https://github.com/mvrpl/Terminal-Cheat-Sheet/blob/master/cheat_sheets.db?raw=true")
	check(err)
	defer resp.Body.Close()
	io.Copy(db, resp.Body)
}

func main() {

	if len(os.Args) <= 1 {
		fmt.Println("HELP")
		os.Exit(0)
	}

	if _, err := os.Stat(os.Getenv("HOME") + "/.cheat_sheets.db"); os.IsNotExist(err) {
		fmt.Println("Banco de dados instalado com sucesso!")
		updateDB()
	}

	if os.Args[1] == "-update" {
		updateDB()
		fmt.Println("Banco de dados atualizado com sucesso!")
		os.Exit(0)
	}

	Program := os.Args[1]

	db, _ := sql.Open("sqlite3", os.Getenv("HOME")+"/.cheat_sheets.db")
	rows, _ := db.Query("SELECT * FROM " + Program)
	dbtables, err := db.Query("select name from sqlite_master where type = 'table'")
	check(err)

	tables := []string{}
	for dbtables.Next() {
		var name string
		_ = dbtables.Scan(&name)
		tables = append(tables, name)
	}

	if containsStr(tables, Program) != true {
		fmt.Println("Sofware nao existe na base da dados.")
		fmt.Println("Disponiveis:")
		for _, soft := range tables {
			fmt.Println("  - " + soft)
		}
		os.Exit(0)
	}

	var data map[string][]map[string]string
	data = make(map[string][]map[string]string)

	for rows.Next() {
		var command string
		var about string
		var session string
		_ = rows.Scan(&command, &about, &session)
		commands := map[string]string{
			command: about,
		}
		data[session] = append(data[session], commands)
	}

	for key, value := range data {
		fmt.Println("+" + strings.Repeat("-", len(key)+2) + "+")
		fmt.Println("| \033[1m" + strings.ToUpper(key) + "\033[0m |")
		table := tablewriter.NewWriter(os.Stdout)
		table.SetHeader([]string{"Comando", "Descricao"})
		table.SetRowLine(true)
		table.SetRowSeparator("-")
		for _, v := range value {
			for cmd, desc := range v {
				outline := []string{cmd, desc}
				table.Append(outline)
			}
		}
		table.Render()
	}
}
<|endoftext|>


<commit_before>package fcm

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/spacemonkeygo/errors"
	"github.com/spacemonkeygo/spacelog"
)

const (
	endpoint                = "https://fcm.googleapis.com/fcm/send"
	defaultMinBackoff       = 1 * time.Second
	defaultMaxBackoff       = 10 * time.Second
	defaultMaxRetryAttempts = 5
)

var (
	nowHook   = time.Now   // for testing
	sleepHook = time.Sleep // for testing
	logger    = spacelog.GetLogger()
	Error     = errors.NewClass("fcm")
)

type FcmClient interface {
	Send(ctx context.Context, m HttpMessage) error
}

type HttpClient interface {
	Do(req *http.Request) (resp *http.Response, err error)
}

type Store interface {
	// Called when a registration token should be updated
	Update(ctx context.Context, oldRegId, newRegId string) error
	// Called when a registration token should be removed because the application
	// was removed from the device, or an unrecoverable error occurred
	Delete(ctx context.Context, regId string) error
}

type Client struct {
	apiKey  string
	client  HttpClient
	store   Store
	options *ClientOptions
}

type ClientOptions struct {
	MinBackoff       time.Duration
	MaxBackoff       time.Duration
	MaxRetryAttempts int
}

func DefaultClientOptions() *ClientOptions {
	return &ClientOptions{
		MinBackoff:       defaultMinBackoff,
		MaxBackoff:       defaultMaxBackoff,
		MaxRetryAttempts: defaultMaxRetryAttempts,
	}
}

func NewDefaultClient(apiKey string, store Store) *Client {
	return NewFcmClient(apiKey, http.DefaultClient, store, nil)
}

// When options == nil, default values are used
func NewFcmClient(apiKey string, client HttpClient, store Store,
	options *ClientOptions) *Client {
	if options == nil {
		options = DefaultClientOptions()
	}

	return &Client{
		apiKey:  apiKey,
		client:  client,
		store:   store,
		options: options,
	}
}

type response struct {
	httpResp   *HttpResponse
	statusCode int
	// nil when no retryAfter is set
	retryAfter *time.Duration
}

func NewHttpMessage(registrationIds []string, data Data, notif *Notification) *HttpMessage {
	return &HttpMessage{
		RegistrationIds: registrationIds,
		Data:            data,
		Notification:    notif,
	}
}

// Sends HttpMessages, retries with exponential backoff, processes replies to the Store
func (c *Client) Send(ctx context.Context, m HttpMessage) error {
	registrationIds := m.RegistrationIds

	// Backoff to use when there is no retryAfter header
	currentBackoff := c.options.MinBackoff
Loop:
	for attempts := 1; ; {
		resp, err := c.send(&m)
		if err != nil {
			return Error.Wrap(fmt.Errorf("error sending request to FCM HTTP server: %v", err))
		}

		// TODO also process 500's
		switch resp.statusCode {
		case http.StatusBadRequest:
			return fmt.Errorf("Bad Request, invalid json")
		case http.StatusUnauthorized:
			return fmt.Errorf("Unauthorized")
		case http.StatusOK:
			toRetryRegIds, err := c.processResp(ctx, registrationIds, resp)
			if err != nil {
				return err
			}
			if toRetryRegIds != nil {
				m.RegistrationIds = toRetryRegIds

				backoff := c.calcBackoff(resp.retryAfter, currentBackoff)
				if resp.retryAfter == nil {
					currentBackoff = backoff
				}

				logger.Noticef("RegistrationIds: %v (attempt %d of %d)", toRetryRegIds,
					attempts, c.options.MaxRetryAttempts)
				attempts += 1
				// TODO send in context with cancelation
				sleepHook(backoff)
				continue
			} else {
				break Loop
			}
		}
		if attempts >= c.options.MaxRetryAttempts+1 {
			return fmt.Errorf("Exhausted retry attempts")
		}
	}
	return nil
}

// uses retryAfter if available, otherwise backs off to max backoff
func (c *Client) calcBackoff(retryAfter *time.Duration,
	currentBackoff time.Duration) (backoff time.Duration) {
	if retryAfter != nil {
		if *retryAfter < c.options.MinBackoff {
			return c.options.MinBackoff
		}
		return *retryAfter
	}
	// TODO somehow use the first backoff value
	backoff = currentBackoff * 2
	if backoff > c.options.MaxBackoff {
		return c.options.MaxBackoff
	} else if backoff < c.options.MinBackoff {
		return c.options.MinBackoff
	}
	return backoff
}

func (c *Client) processResp(ctx context.Context, registrationIds []string,
	resp *response) (toRetry []string,
	err error) {
	httpResp := resp.httpResp
	// All successful
	if httpResp.Failure == 0 && httpResp.CanonicalIds == 0 {
		return nil, nil
	}

	for i, result := range httpResp.Results {
		regId := registrationIds[i]
		// Check for canonical ID
		if result.MessageId != "" {
			if result.RegistrationId != "" {
				logger.Debugf("update: %s to %s", regId, result.RegistrationId)
				err = c.store.Update(ctx, regId, result.RegistrationId)
				if err != nil {
					return nil, err
				}
			}
			continue
		}

		if isRetry(result.Error) {
			toRetry = append(toRetry, regId)
		} else {
			logger.Noticef("RegistrationId: %s error: %s", regId, result.Error)
			// Probably an unrecoverable error or NotRegistered
			logger.Debugf("Deleting: %v", regId)
			err = c.store.Delete(ctx, regId)
			if err != nil {
				return nil, err
			}
		}
	}

	return toRetry, nil
}

func (c *Client) send(message *HttpMessage) (*response, error) {
	logger.Debugf("message: %v", message)

	data, err := json.Marshal(message)
	if err != nil {
		return nil, Error.Wrap(err)
	}
	logger.Debugf("send json %s", data)

	req, err := http.NewRequest("POST", endpoint, bytes.NewReader(data))
	if err != nil {
		return nil, Error.Wrap(err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", fmt.Sprintf("key=%s", c.apiKey))
	logger.Debugf("request: %v", req)

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	httpResp := &HttpResponse{}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	logger.Debugf("response: %v", string(body))
	err = json.Unmarshal(body, &httpResp)
	if err != nil {
		return nil, err
	}

	retryAfter, err := parseRetryAfter(resp.Header.Get("Retry-After"))
	if err != nil {
		return nil, err
	}

	return &response{
		httpResp:   httpResp,
		statusCode: resp.StatusCode,
		retryAfter: retryAfter,
	}, nil
}

func isRetry(err string) bool {
	return err == "Unavailable" || err == "InternalServerError"
}

// Two formats:
// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
// Retry-After: 120
func parseRetryAfter(date string) (*time.Duration, error) {
	// No header set
	if date == "" {
		return nil, nil
	}

	d, err := time.ParseDuration(date + "s")
	if err != nil {
		t, err := http.ParseTime(date)
		if t.Before(nowHook()) {
			return nil, nil
		}
		if err != nil {
			return nil, err
		}
		d = t.Sub(nowHook())
	}
	return &d, nil
}
<commit_msg>include failure reasons if nothing is sent successfully<commit_after>package fcm

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/spacemonkeygo/errors"
	"github.com/spacemonkeygo/spacelog"
)

const (
	endpoint                = "https://fcm.googleapis.com/fcm/send"
	defaultMinBackoff       = 1 * time.Second
	defaultMaxBackoff       = 10 * time.Second
	defaultMaxRetryAttempts = 5
)

var (
	nowHook   = time.Now   // for testing
	sleepHook = time.Sleep // for testing
	logger    = spacelog.GetLogger()
	Error     = errors.NewClass("fcm")
)

type FcmClient interface {
	Send(ctx context.Context, m HttpMessage) error
}

type HttpClient interface {
	Do(req *http.Request) (resp *http.Response, err error)
}

type Store interface {
	// Called when a registration token should be updated
	Update(ctx context.Context, oldRegId, newRegId string) error
	// Called when a registration token should be removed because the application
	// was removed from the device, or an unrecoverable error occurred
	Delete(ctx context.Context, regId string) error
}

type Client struct {
	apiKey  string
	client  HttpClient
	store   Store
	options *ClientOptions
}

type ClientOptions struct {
	MinBackoff       time.Duration
	MaxBackoff       time.Duration
	MaxRetryAttempts int
}

func DefaultClientOptions() *ClientOptions {
	return &ClientOptions{
		MinBackoff:       defaultMinBackoff,
		MaxBackoff:       defaultMaxBackoff,
		MaxRetryAttempts: defaultMaxRetryAttempts,
	}
}

func NewDefaultClient(apiKey string, store Store) *Client {
	return NewFcmClient(apiKey, http.DefaultClient, store, nil)
}

// When options == nil, default values are used
func NewFcmClient(apiKey string, client HttpClient, store Store,
	options *ClientOptions) *Client {
	if options == nil {
		options = DefaultClientOptions()
	}

	return &Client{
		apiKey:  apiKey,
		client:  client,
		store:   store,
		options: options,
	}
}

type response struct {
	httpResp   *HttpResponse
	statusCode int
	// nil when no retryAfter is set
	retryAfter *time.Duration
}

func NewHttpMessage(registrationIds []string, data Data, notif *Notification) *HttpMessage {
	return &HttpMessage{
		RegistrationIds: registrationIds,
		Data:            data,
		Notification:    notif,
	}
}

// Sends HttpMessages, retries with exponential backoff, processes replies to the Store
func (c *Client) Send(ctx context.Context, m HttpMessage) error {
	registrationIds := m.RegistrationIds

	// Backoff to use when there is no retryAfter header
	currentBackoff := c.options.MinBackoff
Loop:
	for attempts := 1; ; {
		resp, err := c.send(&m)
		if err != nil {
			return Error.Wrap(fmt.Errorf("error sending request to FCM HTTP server: %v", err))
		}

		// TODO also process 500's
		switch resp.statusCode {
		case http.StatusBadRequest:
			return fmt.Errorf("Bad Request, invalid json")
		case http.StatusUnauthorized:
			return fmt.Errorf("Unauthorized")
		case http.StatusOK:
			toRetryRegIds, err := c.processResp(ctx, registrationIds, resp)
			if err != nil {
				return err
			}
			if toRetryRegIds != nil {
				m.RegistrationIds = toRetryRegIds

				backoff := c.calcBackoff(resp.retryAfter, currentBackoff)
				if resp.retryAfter == nil {
					currentBackoff = backoff
				}

				logger.Noticef("RegistrationIds: %v (attempt %d of %d)", toRetryRegIds,
					attempts, c.options.MaxRetryAttempts)
				attempts += 1
				// TODO send in context with cancelation
				sleepHook(backoff)
				continue
			} else {
				break Loop
			}
		}
		if attempts >= c.options.MaxRetryAttempts+1 {
			return fmt.Errorf("Exhausted retry attempts")
		}
	}
	return nil
}

// uses retryAfter if available, otherwise backs off to max backoff
func (c *Client) calcBackoff(retryAfter *time.Duration,
	currentBackoff time.Duration) (backoff time.Duration) {
	if retryAfter != nil {
		if *retryAfter < c.options.MinBackoff {
			return c.options.MinBackoff
		}
		return *retryAfter
	}
	// TODO somehow use the first backoff value
	backoff = currentBackoff * 2
	if backoff > c.options.MaxBackoff {
		return c.options.MaxBackoff
	} else if backoff < c.options.MinBackoff {
		return c.options.MinBackoff
	}
	return backoff
}

func (c *Client) processResp(ctx context.Context, registrationIds []string,
	resp *response) (toRetry []string,
	err error) {
	httpResp := resp.httpResp
	// All successful
	if httpResp.Failure == 0 && httpResp.CanonicalIds == 0 {
		return nil, nil
	}

	failureReasons := ""

	for i, result := range httpResp.Results {
		regId := registrationIds[i]
		// Check for canonical ID
		if result.MessageId != "" {
			if result.RegistrationId != "" {
				logger.Debugf("update: %s to %s", regId, result.RegistrationId)
				err = c.store.Update(ctx, regId, result.RegistrationId)
				if err != nil {
					return nil, err
				}
			}
			continue
		}

		if isRetry(result.Error) {
			toRetry = append(toRetry, regId)
		} else {
			logger.Noticef("RegistrationId: %s error: %s", regId, result.Error)
			failureReasons += fmt.Sprintf("%d: %s\n", i, result.Error)
			// Probably an unrecoverable error or NotRegistered
			logger.Debugf("Deleting: %v", regId)
			err = c.store.Delete(ctx, regId)
			if err != nil {
				return nil, err
			}
		}
	}

	if httpResp.Success == 0 {
		return nil, fmt.Errorf("No notification sent successfully. Errors:\n" + failureReasons)
	}

	return toRetry, nil
}

func (c *Client) send(message *HttpMessage) (*response, error) {
	logger.Debugf("message: %v", message)

	data, err := json.Marshal(message)
	if err != nil {
		return nil, Error.Wrap(err)
	}
	logger.Debugf("send json %s", data)

	req, err := http.NewRequest("POST", endpoint, bytes.NewReader(data))
	if err != nil {
		return nil, Error.Wrap(err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", fmt.Sprintf("key=%s", c.apiKey))
	logger.Debugf("request: %v", req)

	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	httpResp := &HttpResponse{}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	logger.Debugf("response: %v", string(body))
	err = json.Unmarshal(body, &httpResp)
	if err != nil {
		return nil, err
	}

	retryAfter, err := parseRetryAfter(resp.Header.Get("Retry-After"))
	if err != nil {
		return nil, err
	}

	return &response{
		httpResp:   httpResp,
		statusCode: resp.StatusCode,
		retryAfter: retryAfter,
	}, nil
}

func isRetry(err string) bool {
	return err == "Unavailable" || err == "InternalServerError"
}

// Two formats:
// Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
// Retry-After: 120
func parseRetryAfter(date string) (*time.Duration, error) {
	// No header set
	if date == "" {
		return nil, nil
	}

	d, err := time.ParseDuration(date + "s")
	if err != nil {
		t, err := http.ParseTime(date)
		if t.Before(nowHook()) {
			return nil, nil
		}
		if err != nil {
			return nil, err
		}
		d = t.Sub(nowHook())
	}
	return &d, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"path/filepath"
	"regexp"
	"text/template"
)

type Project struct {
	Name       string
	FirstName  string
	SecondName string
	UserId     string
	UserName   string
	UserEmail  string
	Host       string
	License    string
	Typ        string
}

func NewProject(name, typ string, user UserConfig) *Project {
	firstName, secondName := ValidateName(name)
	return &Project{name, firstName, secondName, user.Id, user.Name, user.Email, user.Host, user.License, typ}
}

func (proj Project) Create() {
	buildDir := filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.Name)
	if proj.Exists() {
		commandLineError(projectExists)
	}
	os.MkdirAll(buildDir, 0744)
	createFileFromTemplate(proj.Name, "templates/"+proj.Typ+"/proj.go.tpl", proj.SecondName+".go", proj)
	if proj.Typ == "pkg" {
		os.MkdirAll(filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.FirstName, "examples"), 0744)
		createFileFromTemplate(proj.Name, "templates/"+proj.Typ+"/proj_test.go.tpl", proj.SecondName+"_test.go", proj)
		createFileFromTemplate(proj.FirstName, "templates/"+proj.Typ+"/example.go.tpl", "examples/"+proj.SecondName+"_example.go", proj)
	}
	createFileFromTemplate(proj.FirstName, "templates/"+proj.Typ+"/README.md.tpl", "README.md", proj)
	createFileFromTemplate(proj.FirstName, "templates/license/"+proj.License+".tpl", "LICENSE", proj)
	createFileFromTemplate(proj.FirstName, "templates/VERSION.tpl", "VERSION", proj)
	createFileFromTemplate(proj.FirstName, "templates/AUTHORS.tpl", "AUTHORS", proj)
	creationReady()
}

func (proj Project) Exists() bool {
	_, err := os.Stat(filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.Name))
	return err == nil
}

func ParseName(projName string) []string {
	delimeter := "/"
	if projName == "" {
		return make([]string, 0)
	}
	reg := regexp.MustCompile(delimeter)
	indexes := reg.FindAllStringIndex(projName, -1)
	laststart := 0
	result := make([]string, len(indexes)+1)
	for i, element := range indexes {
		result[i] = projName[laststart:element[0]]
		laststart = element[1]
	}
	result[len(indexes)] = projName[laststart:len(projName)]
	return result
}

func ValidateName(projName string) (firstName string, secondName string) {
	partsProjName := ParseName(projName)
	if l := len(partsProjName); l == 0 || l > 2 {
		commandLineError(wrongProjectName)
	} else if l == 1 {
		firstName = projName
		secondName = projName
	} else {
		if partsProjName[0] == "" || partsProjName[1] == "" {
			commandLineError(wrongProjectName)
		}
		firstName = partsProjName[0]
		secondName = partsProjName[1]
	}
	return
}

func createFileFromTemplate(projName, temp, dest string, proj Project) {
	filename := filepath.Join(SRCPATH, proj.Host, proj.UserId, projName, dest)
	tempfile := filepath.Join(GOBIPATH, temp)
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		t, _ := template.ParseFiles(tempfile)
		f, _ := os.Create(filename)
		t.Execute(f, proj)
		fileCreated(filepath.Join(proj.Host, proj.UserId, projName, dest))
	}
}
<commit_msg>code.google.com compatibility<commit_after>package main

import (
	"os"
	"path/filepath"
	"regexp"
	"text/template"
)

type Project struct {
	Name       string
	FirstName  string
	SecondName string
	UserId     string
	UserName   string
	UserEmail  string
	Host       string
	License    string
	Typ        string
}

func NewProject(name, typ string, user UserConfig) *Project {
	firstName, secondName := ValidateName(name)
	return &Project{name, firstName, secondName, user.Id, user.Name, user.Email, user.Host, user.License, typ}
}

func (proj Project) Create() {
	var buildDir, buildDirFirst string
	if proj.Host == "code.google.com" {
		buildDir = filepath.Join(SRCPATH, proj.Host, "p", proj.Name)
		buildDirFirst = filepath.Join(SRCPATH, proj.Host, "p", proj.FirstName)
	} else {
		buildDir = filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.Name)
		buildDirFirst = filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.FirstName)
	}
	if proj.Exists() {
		commandLineError(projectExists)
	}
	os.MkdirAll(buildDir, 0744)
	createFileFromTemplate(proj.Name, "templates/"+proj.Typ+"/proj.go.tpl", proj.SecondName+".go", proj)
	if proj.Typ == "pkg" {
		os.MkdirAll(filepath.Join(buildDirFirst, "examples"), 0744)
		createFileFromTemplate(proj.Name, "templates/"+proj.Typ+"/proj_test.go.tpl", proj.SecondName+"_test.go", proj)
		createFileFromTemplate(proj.FirstName, "templates/"+proj.Typ+"/example.go.tpl", "examples/"+proj.SecondName+"_example.go", proj)
	}
	createFileFromTemplate(proj.FirstName, "templates/"+proj.Typ+"/README.md.tpl", "README.md", proj)
	createFileFromTemplate(proj.FirstName, "templates/license/"+proj.License+".tpl", "LICENSE", proj)
	createFileFromTemplate(proj.FirstName, "templates/VERSION.tpl", "VERSION", proj)
	createFileFromTemplate(proj.FirstName, "templates/AUTHORS.tpl", "AUTHORS", proj)
	creationReady()
}

func (proj Project) Exists() bool {
	_, err := os.Stat(filepath.Join(SRCPATH, proj.Host, proj.UserId, proj.Name))
	return err == nil
}

func ParseName(projName string) []string {
	delimeter := "/"
	if projName == "" {
		return make([]string, 0)
	}
	reg := regexp.MustCompile(delimeter)
	indexes := reg.FindAllStringIndex(projName, -1)
	laststart := 0
	result := make([]string, len(indexes)+1)
	for i, element := range indexes {
		result[i] = projName[laststart:element[0]]
		laststart = element[1]
	}
	result[len(indexes)] = projName[laststart:len(projName)]
	return result
}

func ValidateName(projName string) (firstName string, secondName string) {
	partsProjName := ParseName(projName)
	if l := len(partsProjName); l == 0 || l > 2 {
		commandLineError(wrongProjectName)
	} else if l == 1 {
		firstName = projName
		secondName = projName
	} else {
		if partsProjName[0] == "" || partsProjName[1] == "" {
			commandLineError(wrongProjectName)
		}
		firstName = partsProjName[0]
		secondName = partsProjName[1]
	}
	return
}

func createFileFromTemplate(projName, temp, dest string, proj Project) {
	var filename, tempfile string
	if proj.Host == "code.google.com" {
		filename = filepath.Join(SRCPATH, proj.Host, "p", projName, dest)
	} else {
		filename = filepath.Join(SRCPATH, proj.Host, proj.UserId, projName, dest)
	}
	tempfile = filepath.Join(GOBIPATH, temp)
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		t, _ := template.ParseFiles(tempfile)
		f, _ := os.Create(filename)
		t.Execute(f, proj)
		fileCreated(filename)
	}
}
<|endoftext|>


<commit_before>// Package fwk provides a set of tools to process High Energy Physics events data.
// fwk is a components-based framework, a-la Gaudi, with builtin support for concurrency.
//
// A fwk application consists of a set of components (fwk.Task) which are:
//  - (optionally) configured
//  - started
//  - given the chance to process each event
//  - stopped
//
// Helper components (fwk.Svc) can provide additional features (such as a
// whiteboard/event-store service, a data-flow service, ...) but do not
// typically take (directly) part of the event processing.
//
// Typically, users will implement fwk.Tasks, ie:
//
//   type MyTask struct {
//     fwk.TaskBase
//   }
//
//   // Configure is called once, after having read the properties
//   // from the data-cards.
//   func (tsk *MyTask) Configure(ctx fwk.Context) error { return nil }
//
//   // StartTask is called once (sequentially), just before
//   // the main event-loop processing.
//   func (tsk *MyTask) StartTask(ctx fwk.Context) error { return nil }
//
//   // Process is called for each event, (quite) possibly concurrently.
//   func (tsk *MyTask) Process(ctx fwk.Context)   error { return nil }
//
//   // StopTask is called once (sequentially), just after the
//   // main event-loop processing finished.
//   func (tsk *MyTask) StopTask(ctx fwk.Context)  error { return nil }
//
// A fwk application processes data and leverages concurrency at
// two different levels:
//  - event-level concurrency: multiple events are processed concurrently
//    at any given time, during the event loop;
//  - task-level concurrency: during the event loop, multiple tasks are
//    executing concurrently.
//
// To ensure the proper self-consistency of the global processed event,
// components need to express their data dependencies (input(s)) as well
// as the data they produce (output(s)) for downstream components.
// This is achieved by the concept of a fwk.Port.
// A fwk.Port consists of a pair { Name string; Type reflect.Type }
// where 'Name' is the unique location in the event-store,
// and 'Type' the expected 'go' type of the data at that event-store location.
//
// fwk.Ports can be either INPUT ports or OUTPUT ports.
// Components declare INPUT ports and OUTPUT ports during the 'Configure' stage
// of a fwk application, like so:
//
//  t := reflect.TypeOf([]Electron{})
//  err = component.DeclInPort("Electrons", t)
//  err = component.DeclOutPort("ReScaledElectrons", t)
//
// Then, during the event processing, one gets and puts data from/to the store
// like so:
//
//   func (tsk *MyTask) Process(ctx fwk.Context) error {
//      var err error
//
//      // retrieve the store associated with this event / region-of-interest
//      store := ctx.Store()
//
//      v, err := store.Get("Electrons")
//      if err != nil {
//         return err
//      }
//      eles := v.([]Electron) // type-cast to the correct (underlying) type
//
//      // create output collection
//      out := make([]Electron, 0, len(eles))
//
//      // make sure the collection be put in the store
//      defer func() {
//         err = store.Put("ReScaledElectrons", out)
//      }()
//
//      // ... do some massaging with 'eles' and 'out'
//
//      return err
//   }
package fwk
<commit_msg>doc: wording<commit_after>// Package fwk provides a set of tools to process High Energy Physics events data.
// fwk is a components-based framework, a-la Gaudi, with builtin support for concurrency.
//
// A fwk application consists of a set of components (fwk.Task) which are:
//  - (optionally) configured
//  - started
//  - given the chance to process each event
//  - stopped
//
// Helper components (fwk.Svc) can provide additional features (such as a
// whiteboard/event-store service, a data-flow service, ...) but do not
// typically take (directly) part of the event processing.
//
// Typically, users will implement fwk.Tasks, ie:
//
//   type MyTask struct {
//     fwk.TaskBase
//   }
//
//   // Configure is called once, after having read the properties
//   // from the data-cards.
//   func (tsk *MyTask) Configure(ctx fwk.Context) error { return nil }
//
//   // StartTask is called once (sequentially), just before
//   // the main event-loop processing.
//   func (tsk *MyTask) StartTask(ctx fwk.Context) error { return nil }
//
//   // Process is called for each event, (quite) possibly concurrently.
//   func (tsk *MyTask) Process(ctx fwk.Context)   error { return nil }
//
//   // StopTask is called once (sequentially), just after the
//   // main event-loop processing finished.
//   func (tsk *MyTask) StopTask(ctx fwk.Context)  error { return nil }
//
// A fwk application processes data and leverages concurrency at
// two different levels:
//  - event-level concurrency: multiple events are processed concurrently
//    at any given time, during the event loop;
//  - task-level concurrency: during the event loop, multiple tasks are
//    executing concurrently.
//
// To ensure the proper self-consistency of the global processed event,
// components need to express their data dependencies (input(s)) as well
// as the data they produce (output(s)) for downstream components.
// This is achieved by the concept of a fwk.Port.
// A fwk.Port consists of a pair { Name string; Type reflect.Type }
// where 'Name' is the unique location in the event-store,
// and 'Type' the expected 'go' type of the data at that event-store location.
//
// fwk.Ports can be either INPUT ports or OUTPUT ports.
// Components declare INPUT ports and OUTPUT ports during the 'Configure' stage
// of a fwk application, like so:
//
//  t := reflect.TypeOf([]Electron{})
//  err = component.DeclInPort("Electrons", t)
//  err = component.DeclOutPort("ReScaledElectrons", t)
//
// Then, during the event processing, one gets and puts data from/to the store
// like so:
//
//   func (tsk *MyTask) Process(ctx fwk.Context) error {
//      var err error
//
//      // retrieve the store associated with this event / region-of-interest
//      store := ctx.Store()
//
//      v, err := store.Get("Electrons")
//      if err != nil {
//         return err
//      }
//      eles := v.([]Electron) // type-cast to the correct (underlying) type
//
//      // create output collection
//      out := make([]Electron, 0, len(eles))
//
//      // make sure the collection will be put in the store
//      defer func() {
//         err = store.Put("ReScaledElectrons", out)
//      }()
//
//      // ... do some massaging with 'eles' and 'out'
//
//      return err
//   }
package fwk
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"strings"
)

const (
	defaultPlaceholder = "{{}}"
)

var originalSttyState bytes.Buffer

func isPipe(f *os.File) bool {
	s, err := f.Stat()
	if err != nil {
		return false
	}

	return s.Mode()&os.ModeNamedPipe != 0
}

var usage = `fzz allows you to run a command interactively.

Usage:

	fzz command

The command has to include the placeholder '{{}}'.
`

func main() {
	flag.Parse()

	if len(flag.Args()) < 2 {
		fmt.Fprintf(os.Stderr, usage)
		os.Exit(2)
	}

	tty, err := NewTTY()
	if err != nil {
		log.Fatal(err)
	}

	err = tty.getSttyState(&originalSttyState)
	if err != nil {
		log.Fatal(err)
	}
	defer tty.setSttyState(&originalSttyState)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		tty.setSttyState(&originalSttyState)
		os.Exit(1)
	}()

	tty.setSttyState(bytes.NewBufferString("cbreak"))
	tty.setSttyState(bytes.NewBufferString("-echo"))

	cmdTemplate := strings.Join(flag.Args(), " ")
	printer := NewPrinter(tty, tty.cols, tty.rows-3)
	runner := &Runner{
		printer:     printer,
		template:    cmdTemplate,
		placeholder: defaultPlaceholder,
	}

	if isPipe(os.Stdin) {
		// TODO: maybe use io.ReadAll here, and use []byte as runner.stdinbuf
		stdinbuf := new(bytes.Buffer)
		io.Copy(stdinbuf, os.Stdin)
		runner.stdinbuf = stdinbuf
	} else {
		runner.stdinbuf = nil
	}

	input := make([]byte, 0)
	b := make([]byte, 1)

	for {
		tty.resetScreen()
		tty.printPrompt(input[:len(input)])

		if len(input) > 0 {
			runner.killCurrent()

			go func() {
				runner.runWithInput(input[:len(input)])
				tty.cursorAfterPrompt(len(input))
			}()
		}

		tty.Read(b)
		switch b[0] {
		case 127:
			// Backspace
			if len(input) > 1 {
				input = input[:len(input)-1]
			} else if len(input) == 1 {
				input = nil
			}
		case 4, 10, 13:
			// Ctrl-D, line feed, carriage return
			tty.resetScreen()
			runner.writeCmdStdout(os.Stdout)
			return
		default:
			// TODO: Default is wrong here. Only append printable characters to
			// input
			input = append(input, b...)
		}
	}
}
<commit_msg>Restructuring<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"strings"
)

const defaultPlaceholder = "{{}}"

var originalSttyState bytes.Buffer

var usage = `fzz allows you to run a command interactively.

Usage:

	fzz command

The command has to include the placeholder '{{}}'.
`

func isPipe(f *os.File) bool {
	s, err := f.Stat()
	if err != nil {
		return false
	}

	return s.Mode()&os.ModeNamedPipe != 0
}

func main() {
	flag.Parse()

	if len(flag.Args()) < 2 {
		fmt.Fprintf(os.Stderr, usage)
		os.Exit(2)
	}

	tty, err := NewTTY()
	if err != nil {
		log.Fatal(err)
	}

	err = tty.getSttyState(&originalSttyState)
	if err != nil {
		log.Fatal(err)
	}
	defer tty.setSttyState(&originalSttyState)

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		<-c
		tty.setSttyState(&originalSttyState)
		os.Exit(1)
	}()

	tty.setSttyState(bytes.NewBufferString("cbreak"))
	tty.setSttyState(bytes.NewBufferString("-echo"))

	cmdTemplate := strings.Join(flag.Args(), " ")
	printer := NewPrinter(tty, tty.cols, tty.rows-3)
	runner := &Runner{
		printer:     printer,
		template:    cmdTemplate,
		placeholder: defaultPlaceholder,
	}

	if isPipe(os.Stdin) {
		// TODO: maybe use io.ReadAll here, and use []byte as runner.stdinbuf
		stdinbuf := new(bytes.Buffer)
		io.Copy(stdinbuf, os.Stdin)
		runner.stdinbuf = stdinbuf
	} else {
		runner.stdinbuf = nil
	}

	input := make([]byte, 0)
	b := make([]byte, 1)

	for {
		tty.resetScreen()
		tty.printPrompt(input[:len(input)])

		if len(input) > 0 {
			runner.killCurrent()

			go func() {
				runner.runWithInput(input[:len(input)])
				tty.cursorAfterPrompt(len(input))
			}()
		}

		tty.Read(b)
		switch b[0] {
		case 127:
			// Backspace
			if len(input) > 1 {
				input = input[:len(input)-1]
			} else if len(input) == 1 {
				input = nil
			}
		case 4, 10, 13:
			// Ctrl-D, line feed, carriage return
			tty.resetScreen()
			runner.writeCmdStdout(os.Stdout)
			return
		default:
			// TODO: Default is wrong here. Only append printable characters to
			// input
			input = append(input, b...)
		}
	}
}
<|endoftext|>


<commit_before>package testutil

import (
	"os"
	"path/filepath"

	"veyron.io/tools/lib/envutil"
	"veyron.io/tools/lib/runutil"
	"veyron.io/tools/lib/util"
)

// VeyronBrowserTest runs an integration test for the veyron browser.
//
// TODO(aghassemi): Port the veyron browser test logic from shell to Go.
func VeyronBrowserTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}

	// Initialize the test.
	cleanup, err := initTest(ctx, testName, []string{"web"})
	if err != nil {
		return nil, err
	}
	defer cleanup()

	// Invoke "make clean" for the veyron browser.
	browserDir := filepath.Join(root, "veyron-browser")
	if err := ctx.Run().Function(runutil.Chdir(browserDir)); err != nil {
		return nil, err
	}
	if err := ctx.Run().Command("make", "clean"); err != nil {
		return nil, err
	}

	// Invoke "make test" for the veyron browser.
	provaOutputFile := filepath.Join(os.Getenv("TMPDIR"), "veyron_browser_test.out")
	opts := ctx.Run().Opts()
	env := envutil.NewSnapshotFromOS()
	env.Set("PROVA_OUTPUT_FILE", provaOutputFile)
	opts.Env = env.Map()
	if err := ctx.Run().CommandWithOpts(opts, "make", "test"); err != nil {
		return &TestResult{Status: TestFailed}, nil
	}

	return &TestResult{Status: TestPassed}, nil
}
<commit_msg>veyron/tools/: Moving the test output file for veyron browser from temp to the root of workspace.<commit_after>package testutil

import (
	"path/filepath"

	"veyron.io/tools/lib/envutil"
	"veyron.io/tools/lib/runutil"
	"veyron.io/tools/lib/util"
)

// VeyronBrowserTest runs an integration test for the veyron browser.
//
// TODO(aghassemi): Port the veyron browser test logic from shell to Go.
func VeyronBrowserTest(ctx *util.Context, testName string) (*TestResult, error) {
	root, err := util.VeyronRoot()
	if err != nil {
		return nil, err
	}
	provaOutputFile := filepath.Join(root, "veyron_browser_test.out")

	// Initialize the test.
	cleanup, err := initTest(ctx, testName, []string{"web"})
	if err != nil {
		return nil, err
	}
	defer cleanup()

	// Invoke "make clean" for the veyron browser and remove the test output file if it exists.
	browserDir := filepath.Join(root, "veyron-browser")
	if err := ctx.Run().Function(runutil.Chdir(browserDir)); err != nil {
		return nil, err
	}
	if err := ctx.Run().Command("make", "clean"); err != nil {
		return nil, err
	}
	if err := ctx.Run().Function(runutil.RemoveAll(provaOutputFile)); err != nil {
		return nil, err
	}

	// Invoke "make test" for the veyron browser.
	opts := ctx.Run().Opts()
	env := envutil.NewSnapshotFromOS()
	env.Set("PROVA_OUTPUT_FILE", provaOutputFile)
	opts.Env = env.Map()
	if err := ctx.Run().CommandWithOpts(opts, "make", "test"); err != nil {
		return &TestResult{Status: TestFailed}, nil
	}

	return &TestResult{Status: TestPassed}, nil
}
<|endoftext|>


<commit_before>// Package strumt provides a way to defines scenarios for prompting
// informations on command line
package strumt

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

// Step represents a scenario step
type Step struct {
	prompt string
	inputs []string
	err    error
}

// NewPrompts creates a new prompt from stdin
func NewPrompts() Prompts {
	return Prompts{reader: bufio.NewReader(os.Stdin), writer: os.Stdout, prompts: map[string]Prompter{}}
}

// NewPromptsFromReaderAndWriter creates a new prompt from a given reader and writer
// , useful for testing purpose for instance by providing a buffer
func NewPromptsFromReaderAndWriter(reader io.Reader, writer io.Writer) Prompts {
	return Prompts{reader: bufio.NewReader(reader), writer: writer, prompts: map[string]Prompter{}}
}

// Prompts stores all defined prompts and current
// running prompt
type Prompts struct {
	currentPrompt Prompter
	prompts       map[string]Prompter
	reader        *bufio.Reader
	writer        io.Writer
	scenario      []Step
}

func (p *Prompts) parse() ([]string, Prompter, error) {
	var nextPrompt Prompter
	var inputs []string
	var err error

	switch prompt := p.currentPrompt.(type) {
	case LinePrompter:
		var input string

		input, err = parseLine(p.reader, prompt)

		if prompt.GetNextOnSuccess(input) != "" {
			nextPrompt = p.prompts[prompt.GetNextOnSuccess(input)]
		}

		inputs = append(inputs, input)
	case MultilinePrompter:
		inputs, err = parseMultipleLine(p.reader, prompt)

		if prompt.GetNextOnSuccess(inputs) != "" {
			nextPrompt = p.prompts[prompt.GetNextOnSuccess(inputs)]
		}
	}

	if err != nil {
		nextPrompt = p.prompts[p.currentPrompt.GetNextOnError(err)]
	}

	return inputs, nextPrompt, err
}

func (p *Prompts) appendScenario(promptString string, inputs []string, err error) {
	p.scenario = append(
		p.scenario,
		Step{
			promptString,
			inputs,
			err,
		},
	)
}

// AddLinePrompter add a new LinePrompter mapped to a given id
func (p *Prompts) AddLinePrompter(id string, prompt LinePrompter) {
	p.prompts[id] = prompt
}

// AddMultilinePrompter add a new MultilinePrompter mapped to a given id
func (p *Prompts) AddMultilinePrompter(id string, prompt MultilinePrompter) {
	p.prompts[id] = prompt
}

// SetFirst defines from which prompt, the prompt sequence has to start
func (p *Prompts) SetFirst(id string) {
	p.currentPrompt = p.prompts[id]
}

// GetScenario retrieves all steps done during
// prompt
func (p *Prompts) GetScenario() []Step {
	return p.scenario
}

// Run executes prompt sequence
func (p *Prompts) Run() {
	p.scenario = []Step{}

	for {
		var err error
		inputs := []string{}

		prompt := p.currentPrompt
		renderPrompt(p.writer, prompt)

		inputs, nextPrompt, err := p.parse()

		if err != nil {
			renderError(p.writer, prompt, err)
		}

		p.appendScenario(prompt.GetPromptString(), inputs, err)

		if nextPrompt == nil {
			return
		}

		p.currentPrompt = nextPrompt
	}
}

func isMultilineEnd(reader *bufio.Reader) (bool, error) {
	bn, err := reader.ReadByte()

	if err == io.EOF {
		return true, nil
	}

	if bn == '\n' {
		return true, nil
	}

	if err := reader.UnreadByte(); err != nil {
		return false, err
	}

	return false, nil
}

func parseMultipleLine(reader *bufio.Reader, prompt MultilinePrompter) ([]string, error) {
	inputs := []string{}

	for {
		input, err := reader.ReadString('\n')
		input = strings.TrimRight(input, "\n")

		if err != nil {
			return []string{}, err
		}

		inputs = append(inputs, input)

		end, err := isMultilineEnd(reader)

		if err != nil {
			return []string{}, err
		}

		if end {
			break
		}
	}

	if err := prompt.Parse(inputs); err != nil {
		return inputs, err
	}

	return inputs, nil
}

func parseLine(reader *bufio.Reader, prompt LinePrompter) (string, error) {
	input, err := reader.ReadString('\n')
	input = strings.TrimRight(input, "\n")

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

	if err := prompt.Parse(input); err != nil {
		return input, err
	}

	return input, nil
}

func renderPrompt(writer io.Writer, prompt Prompter) {
	switch pr := prompt.(type) {
	case PromptRenderer:
		pr.PrintPrompt(prompt.GetPromptString())
	default:
		fmt.Fprintf(writer, "%s : \n", prompt.GetPromptString())
	}
}

func renderError(writer io.Writer, prompt Prompter, err error) {
	switch pr := prompt.(type) {
	case ErrorRenderer:
		pr.PrintError(err)
	default:
		fmt.Fprintf(writer, "%s\n", err.Error())
	}
}
<commit_msg>Update doc<commit_after>// Package strumt provides a way to defines scenarios for prompting
// informations on command line
package strumt

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

// Step represents a scenario step which is
// the result of on prompt execution. We store
// the prompt string, inputs that the user has given,
// and the prompt error if one occured
type Step struct {
	prompt string
	inputs []string
	err    error
}

// NewPrompts creates a new prompt from stdin
func NewPrompts() Prompts {
	return Prompts{reader: bufio.NewReader(os.Stdin), writer: os.Stdout, prompts: map[string]Prompter{}}
}

// NewPromptsFromReaderAndWriter creates a new prompt from a given reader and writer
// , useful for testing purpose
func NewPromptsFromReaderAndWriter(reader io.Reader, writer io.Writer) Prompts {
	return Prompts{reader: bufio.NewReader(reader), writer: writer, prompts: map[string]Prompter{}}
}

// Prompts stores all defined prompts and current
// running prompt
type Prompts struct {
	currentPrompt Prompter
	prompts       map[string]Prompter
	reader        *bufio.Reader
	writer        io.Writer
	scenario      []Step
}

func (p *Prompts) parse() ([]string, Prompter, error) {
	var nextPrompt Prompter
	var inputs []string
	var err error

	switch prompt := p.currentPrompt.(type) {
	case LinePrompter:
		var input string

		input, err = parseLine(p.reader, prompt)

		if prompt.GetNextOnSuccess(input) != "" {
			nextPrompt = p.prompts[prompt.GetNextOnSuccess(input)]
		}

		inputs = append(inputs, input)
	case MultilinePrompter:
		inputs, err = parseMultipleLine(p.reader, prompt)

		if prompt.GetNextOnSuccess(inputs) != "" {
			nextPrompt = p.prompts[prompt.GetNextOnSuccess(inputs)]
		}
	}

	if err != nil {
		nextPrompt = p.prompts[p.currentPrompt.GetNextOnError(err)]
	}

	return inputs, nextPrompt, err
}

func (p *Prompts) appendScenario(promptString string, inputs []string, err error) {
	p.scenario = append(
		p.scenario,
		Step{
			promptString,
			inputs,
			err,
		},
	)
}

// AddLinePrompter add a new LinePrompter mapped to a given id
func (p *Prompts) AddLinePrompter(id string, prompt LinePrompter) {
	p.prompts[id] = prompt
}

// AddMultilinePrompter add a new MultilinePrompter mapped to a given id
func (p *Prompts) AddMultilinePrompter(id string, prompt MultilinePrompter) {
	p.prompts[id] = prompt
}

// SetFirst defines from which prompt the prompt sequence has to start
func (p *Prompts) SetFirst(id string) {
	p.currentPrompt = p.prompts[id]
}

// GetScenario retrieves all steps done during
// a prompt sequence
func (p *Prompts) GetScenario() []Step {
	return p.scenario
}

// Run executes a prompt sequence
func (p *Prompts) Run() {
	p.scenario = []Step{}

	for {
		var err error
		inputs := []string{}

		prompt := p.currentPrompt
		renderPrompt(p.writer, prompt)

		inputs, nextPrompt, err := p.parse()

		if err != nil {
			renderError(p.writer, prompt, err)
		}

		p.appendScenario(prompt.GetPromptString(), inputs, err)

		if nextPrompt == nil {
			return
		}

		p.currentPrompt = nextPrompt
	}
}

func isMultilineEnd(reader *bufio.Reader) (bool, error) {
	bn, err := reader.ReadByte()

	if err == io.EOF {
		return true, nil
	}

	if bn == '\n' {
		return true, nil
	}

	if err := reader.UnreadByte(); err != nil {
		return false, err
	}

	return false, nil
}

func parseMultipleLine(reader *bufio.Reader, prompt MultilinePrompter) ([]string, error) {
	inputs := []string{}

	for {
		input, err := reader.ReadString('\n')
		input = strings.TrimRight(input, "\n")

		if err != nil {
			return []string{}, err
		}

		inputs = append(inputs, input)

		end, err := isMultilineEnd(reader)

		if err != nil {
			return []string{}, err
		}

		if end {
			break
		}
	}

	if err := prompt.Parse(inputs); err != nil {
		return inputs, err
	}

	return inputs, nil
}

func parseLine(reader *bufio.Reader, prompt LinePrompter) (string, error) {
	input, err := reader.ReadString('\n')
	input = strings.TrimRight(input, "\n")

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

	if err := prompt.Parse(input); err != nil {
		return input, err
	}

	return input, nil
}

func renderPrompt(writer io.Writer, prompt Prompter) {
	switch pr := prompt.(type) {
	case PromptRenderer:
		pr.PrintPrompt(prompt.GetPromptString())
	default:
		fmt.Fprintf(writer, "%s : \n", prompt.GetPromptString())
	}
}

func renderError(writer io.Writer, prompt Prompter, err error) {
	switch pr := prompt.(type) {
	case ErrorRenderer:
		pr.PrintError(err)
	default:
		fmt.Fprintf(writer, "%s\n", err.Error())
	}
}
<|endoftext|>


<commit_before>//go:generate templates -s templates -o templates/templates.go
package schematic

import (
	"bytes"
	"fmt"
	"go/format"
	"strings"
	"text/template"

	bundle "github.com/interagent/schematic/templates"
)

var templates *template.Template

func init() {
	templates = template.New("package.tmpl").Funcs(helpers)
	templates = template.Must(bundle.Parse(templates))
}

func clean(gen []byte) ([]byte, error) {
	// Remove blank lines added by text/template
	bytes := newlines.ReplaceAll(gen, []byte(""))

	// Format sources
	clean, err := format.Source(bytes)
	// TODO: If formatting errors, return the error instead of the broken,
	// unformatted code
	if err != nil {
		return gen, err
	}
	return clean, nil
}

func (s *Schema) Generate() ([]byte, error) {
	// Default to hyper schema for backwards compatibility
	if s.Schema == nil || *s.Schema == "" {
		return s.generateHyperSchema()
	}
	switch *s.Schema {
	case "http://json-schema.org/schema#", "http://json-schema.org/draft-04/schema#",
		"http://json-schema.org/draft-03/schema#":
		return s.generateSchema()
	case "http://json-schema.org/hyper-schema#", "http://json-schema.org/draft-04/hyper-schema#",
		"http://json-schema.org/draft-03/hyper-schema#":
		return s.generateHyperSchema()
	}
	return nil, fmt.Errorf("unknown $schema keyword %s", *s.Schema)
}

func (s *Schema) generateSchema() ([]byte, error) {
	var buf bytes.Buffer

	name := strings.ToLower(strings.Split(s.Title, " ")[0])
	templates.ExecuteTemplate(&buf, "package.tmpl", name)

	// TODO: Check if we need time.
	templates.ExecuteTemplate(&buf, "imports.tmpl", []string{})

	context := struct {
		Name       string
		Definition *Schema
	}{
		Name:       name,
		Definition: s,
	}

	templates.ExecuteTemplate(&buf, "struct.tmpl", context)
	return clean(buf.Bytes())
}

// Generate generates code according to the schema.
func (s *Schema) generateHyperSchema() ([]byte, error) {
	var buf bytes.Buffer

	for i := 0; i < 2; i++ {
		s.Resolve(nil)
	}

	name := strings.ToLower(strings.Split(s.Title, " ")[0])
	templates.ExecuteTemplate(&buf, "hyperpackage.tmpl", name)

	// TODO: Check if we need time.
	templates.ExecuteTemplate(&buf, "imports.tmpl", []string{
		"encoding/json", "fmt", "io", "reflect",
		"net/http", "runtime", "time", "bytes",
		// TODO: Change for google/go-querystring if pull request #5 gets merged
		// https://github.com/google/go-querystring/pull/5
		"github.com/ernesto-jimenez/go-querystring/query",
	})
	templates.ExecuteTemplate(&buf, "service.tmpl", struct {
		Name    string
		URL     string
		Version string
	}{
		Name:    name,
		URL:     s.URL(),
		Version: s.Version,
	})

	for _, name := range sortedKeys(s.Properties) {
		schema := s.Properties[name]
		// Skipping definitions because there is no links, nor properties.
		if schema.Links == nil && schema.Properties == nil {
			continue
		}

		context := struct {
			Name       string
			Definition *Schema
		}{
			Name:       name,
			Definition: schema,
		}

		templates.ExecuteTemplate(&buf, "struct.tmpl", context)
		templates.ExecuteTemplate(&buf, "funcs.tmpl", context)
	}

	return clean(buf.Bytes())
}

// Resolve resolves reference inside the schema.
func (s *Schema) Resolve(r *Schema) *Schema {
	if r == nil {
		r = s
	}
	for n, d := range s.Definitions {
		s.Definitions[n] = d.Resolve(r)
	}
	for n, p := range s.Properties {
		s.Properties[n] = p.Resolve(r)
	}
	for n, p := range s.PatternProperties {
		s.PatternProperties[n] = p.Resolve(r)
	}
	if s.Items != nil {
		s.Items = s.Items.Resolve(r)
	}
	if s.Ref != nil {
		s = s.Ref.Resolve(r)
	}
	if len(s.OneOf) > 0 {
		s = s.OneOf[0].Ref.Resolve(r)
	}
	if len(s.AnyOf) > 0 {
		s = s.AnyOf[0].Ref.Resolve(r)
	}
	for _, l := range s.Links {
		l.Resolve(r)
	}
	return s
}

// Types returns the array of types described by this schema.
func (s *Schema) Types() (types []string, err error) {
	if arr, ok := s.Type.([]interface{}); ok {
		for _, v := range arr {
			types = append(types, v.(string))
		}
	} else if str, ok := s.Type.(string); ok {
		types = append(types, str)
	} else {
		err = fmt.Errorf("unknown type %v", s.Type)
	}
	return types, err
}

// GoType returns the Go type for the given schema as string.
func (s *Schema) GoType() string {
	return s.goType(true, true)
}

// IsCustomType returns true if the schema declares a custom type.
func (s *Schema) IsCustomType() bool {
	return len(s.Properties) > 0
}

func (s *Schema) goType(required bool, force bool) (goType string) {
	// Resolve JSON reference/pointer
	types, err := s.Types()
	if err != nil {
		panic(err)
	}
	for _, kind := range types {
		switch kind {
		case "boolean":
			goType = "bool"
		case "string":
			switch s.Format {
			case "date-time":
				goType = "time.Time"
			default:
				goType = "string"
			}
		case "number":
			goType = "float64"
		case "integer":
			goType = "int"
		case "any":
			goType = "interface{}"
		case "array":
			if s.Items != nil {
				goType = "[]" + s.Items.goType(required, force)
			} else {
				goType = "[]interface{}"
			}
		case "object":
			// Check if patternProperties exists.
			if s.PatternProperties != nil {
				for _, prop := range s.PatternProperties {
					goType = fmt.Sprintf("map[string]%s", prop.GoType())
					break // We don't support more than one pattern for now.
				}
				continue
			}
			buf := bytes.NewBufferString("struct {")
			for _, name := range sortedKeys(s.Properties) {
				prop := s.Properties[name]
				req := contains(name, s.Required) || force
				templates.ExecuteTemplate(buf, "field.tmpl", struct {
					Definition *Schema
					Name       string
					Required   bool
					Type       string
				}{
					Definition: prop,
					Name:       name,
					Required:   req,
					Type:       prop.goType(req, force),
				})
			}
			buf.WriteString("}")
			goType = buf.String()
		case "null":
			continue
		default:
			panic(fmt.Sprintf("unknown type %s", kind))
		}
	}
	if goType == "" {
		panic(fmt.Sprintf("type not found : %s", types))
	}
	// Types allow null
	if contains("null", types) || !(required || force) {
		return "*" + goType
	}
	return goType
}

// Values returns function return values types.
func (s *Schema) Values(name string, l *Link) []string {
	var values []string
	name = returnType(name, s, l)
	if s.EmptyResult(l) {
		values = append(values, "error")
	} else if s.ReturnsCustomType(l) {
		values = append(values, fmt.Sprintf("*%s", name), "error")
	} else {
		values = append(values, s.ReturnedGoType(l), "error")
	}
	return values
}

// URL returns schema base URL.
func (s *Schema) URL() string {
	for _, l := range s.Links {
		if l.Rel == "self" {
			return l.HRef.String()
		}
	}
	return ""
}

// ReturnsCustomType returns true if the link returns a custom type.
func (s *Schema) ReturnsCustomType(l *Link) bool {
	if l.TargetSchema != nil {
		return len(l.TargetSchema.Properties) > 0
	}
	return len(s.Properties) > 0
}

// ReturnedGoType returns Go type returned by the given link as a string.
func (s *Schema) ReturnedGoType(l *Link) string {
	if l.TargetSchema != nil {
		return l.TargetSchema.goType(true, false)
	}
	return s.goType(true, false)
}

// EmptyResult retursn true if the link result should be empty.
func (s *Schema) EmptyResult(l *Link) bool {
	var (
		types []string
		err   error
	)
	if l.TargetSchema != nil {
		types, err = l.TargetSchema.Types()
	} else {
		types, err = s.Types()
	}
	if err != nil {
		return true
	}
	return len(types) == 1 && types[0] == "null"
}

// Parameters returns function parameters names and types.
func (l *Link) Parameters(name string) ([]string, map[string]string) {
	if l.HRef == nil {
		// No HRef property
		panic(fmt.Errorf("no href property declared for %s", l.Title))
	}
	var order []string
	params := make(map[string]string)
	for _, name := range l.HRef.Order {
		def := l.HRef.Schemas[name]
		order = append(order, name)
		params[name] = def.GoType()
	}
	if l.Schema != nil {
		order = append(order, "o")
		t, required := l.GoType()
		if l.AcceptsCustomType() {
			params["o"] = paramType(name, l)
		} else {
			params["o"] = t
		}
		if !required {
			params["o"] = "*" + params["o"]
		}
	}
	if l.Rel == "instances" && strings.ToUpper(l.Method) == "GET" {
		order = append(order, "lr")
		params["lr"] = "*ListRange"
	}
	return order, params
}

// AcceptsCustomType returns true if the link schema is not a primitive type
func (l *Link) AcceptsCustomType() bool {
	if l.Schema != nil && l.Schema.IsCustomType() {
		return true
	}
	return false
}

// Resolve resolve link schema and href.
func (l *Link) Resolve(r *Schema) {
	if l.Schema != nil {
		l.Schema = l.Schema.Resolve(r)
	}
	if l.TargetSchema != nil {
		l.TargetSchema = l.TargetSchema.Resolve(r)
	}
	l.HRef.Resolve(r)
}

// GoType returns Go type for the given schema as string and a bool specifying whether it is required
func (l *Link) GoType() (string, bool) {
	t := l.Schema.goType(true, false)
	if t[0] == '*' {
		return t[1:], false
	}
	return t, true
}
<commit_msg>more generous defaults for hyper-schema<commit_after>//go:generate templates -s templates -o templates/templates.go
package schematic

import (
	"bytes"
	"fmt"
	"go/format"
	"strings"
	"text/template"

	bundle "github.com/interagent/schematic/templates"
)

var templates *template.Template

func init() {
	templates = template.New("package.tmpl").Funcs(helpers)
	templates = template.Must(bundle.Parse(templates))
}

func clean(gen []byte) ([]byte, error) {
	// Remove blank lines added by text/template
	bytes := newlines.ReplaceAll(gen, []byte(""))

	// Format sources
	clean, err := format.Source(bytes)
	// TODO: If formatting errors, return the error instead of the broken,
	// unformatted code
	if err != nil {
		return gen, err
	}
	return clean, nil
}

func (s *Schema) Generate() ([]byte, error) {
	// Default to hyper schema for backwards compatibility
	if s.Schema == nil {
		return s.generateHyperSchema()
	}
	switch *s.Schema {
	case "http://json-schema.org/schema#", "http://json-schema.org/draft-04/schema#",
		"http://json-schema.org/draft-03/schema#":
		return s.generateSchema()
	}
	return s.generateHyperSchema()
}

func (s *Schema) generateSchema() ([]byte, error) {
	var buf bytes.Buffer

	name := strings.ToLower(strings.Split(s.Title, " ")[0])
	templates.ExecuteTemplate(&buf, "package.tmpl", name)

	// TODO: Check if we need time.
	templates.ExecuteTemplate(&buf, "imports.tmpl", []string{})

	context := struct {
		Name       string
		Definition *Schema
	}{
		Name:       name,
		Definition: s,
	}

	templates.ExecuteTemplate(&buf, "struct.tmpl", context)
	return clean(buf.Bytes())
}

// Generate generates code according to the schema.
func (s *Schema) generateHyperSchema() ([]byte, error) {
	var buf bytes.Buffer

	for i := 0; i < 2; i++ {
		s.Resolve(nil)
	}

	name := strings.ToLower(strings.Split(s.Title, " ")[0])
	templates.ExecuteTemplate(&buf, "hyperpackage.tmpl", name)

	// TODO: Check if we need time.
	templates.ExecuteTemplate(&buf, "imports.tmpl", []string{
		"encoding/json", "fmt", "io", "reflect",
		"net/http", "runtime", "time", "bytes",
		// TODO: Change for google/go-querystring if pull request #5 gets merged
		// https://github.com/google/go-querystring/pull/5
		"github.com/ernesto-jimenez/go-querystring/query",
	})
	templates.ExecuteTemplate(&buf, "service.tmpl", struct {
		Name    string
		URL     string
		Version string
	}{
		Name:    name,
		URL:     s.URL(),
		Version: s.Version,
	})

	for _, name := range sortedKeys(s.Properties) {
		schema := s.Properties[name]
		// Skipping definitions because there is no links, nor properties.
		if schema.Links == nil && schema.Properties == nil {
			continue
		}

		context := struct {
			Name       string
			Definition *Schema
		}{
			Name:       name,
			Definition: schema,
		}

		templates.ExecuteTemplate(&buf, "struct.tmpl", context)
		templates.ExecuteTemplate(&buf, "funcs.tmpl", context)
	}

	return clean(buf.Bytes())
}

// Resolve resolves reference inside the schema.
func (s *Schema) Resolve(r *Schema) *Schema {
	if r == nil {
		r = s
	}
	for n, d := range s.Definitions {
		s.Definitions[n] = d.Resolve(r)
	}
	for n, p := range s.Properties {
		s.Properties[n] = p.Resolve(r)
	}
	for n, p := range s.PatternProperties {
		s.PatternProperties[n] = p.Resolve(r)
	}
	if s.Items != nil {
		s.Items = s.Items.Resolve(r)
	}
	if s.Ref != nil {
		s = s.Ref.Resolve(r)
	}
	if len(s.OneOf) > 0 {
		s = s.OneOf[0].Ref.Resolve(r)
	}
	if len(s.AnyOf) > 0 {
		s = s.AnyOf[0].Ref.Resolve(r)
	}
	for _, l := range s.Links {
		l.Resolve(r)
	}
	return s
}

// Types returns the array of types described by this schema.
func (s *Schema) Types() (types []string, err error) {
	if arr, ok := s.Type.([]interface{}); ok {
		for _, v := range arr {
			types = append(types, v.(string))
		}
	} else if str, ok := s.Type.(string); ok {
		types = append(types, str)
	} else {
		err = fmt.Errorf("unknown type %v", s.Type)
	}
	return types, err
}

// GoType returns the Go type for the given schema as string.
func (s *Schema) GoType() string {
	return s.goType(true, true)
}

// IsCustomType returns true if the schema declares a custom type.
func (s *Schema) IsCustomType() bool {
	return len(s.Properties) > 0
}

func (s *Schema) goType(required bool, force bool) (goType string) {
	// Resolve JSON reference/pointer
	types, err := s.Types()
	if err != nil {
		panic(err)
	}
	for _, kind := range types {
		switch kind {
		case "boolean":
			goType = "bool"
		case "string":
			switch s.Format {
			case "date-time":
				goType = "time.Time"
			default:
				goType = "string"
			}
		case "number":
			goType = "float64"
		case "integer":
			goType = "int"
		case "any":
			goType = "interface{}"
		case "array":
			if s.Items != nil {
				goType = "[]" + s.Items.goType(required, force)
			} else {
				goType = "[]interface{}"
			}
		case "object":
			// Check if patternProperties exists.
			if s.PatternProperties != nil {
				for _, prop := range s.PatternProperties {
					goType = fmt.Sprintf("map[string]%s", prop.GoType())
					break // We don't support more than one pattern for now.
				}
				continue
			}
			buf := bytes.NewBufferString("struct {")
			for _, name := range sortedKeys(s.Properties) {
				prop := s.Properties[name]
				req := contains(name, s.Required) || force
				templates.ExecuteTemplate(buf, "field.tmpl", struct {
					Definition *Schema
					Name       string
					Required   bool
					Type       string
				}{
					Definition: prop,
					Name:       name,
					Required:   req,
					Type:       prop.goType(req, force),
				})
			}
			buf.WriteString("}")
			goType = buf.String()
		case "null":
			continue
		default:
			panic(fmt.Sprintf("unknown type %s", kind))
		}
	}
	if goType == "" {
		panic(fmt.Sprintf("type not found : %s", types))
	}
	// Types allow null
	if contains("null", types) || !(required || force) {
		return "*" + goType
	}
	return goType
}

// Values returns function return values types.
func (s *Schema) Values(name string, l *Link) []string {
	var values []string
	name = returnType(name, s, l)
	if s.EmptyResult(l) {
		values = append(values, "error")
	} else if s.ReturnsCustomType(l) {
		values = append(values, fmt.Sprintf("*%s", name), "error")
	} else {
		values = append(values, s.ReturnedGoType(l), "error")
	}
	return values
}

// URL returns schema base URL.
func (s *Schema) URL() string {
	for _, l := range s.Links {
		if l.Rel == "self" {
			return l.HRef.String()
		}
	}
	return ""
}

// ReturnsCustomType returns true if the link returns a custom type.
func (s *Schema) ReturnsCustomType(l *Link) bool {
	if l.TargetSchema != nil {
		return len(l.TargetSchema.Properties) > 0
	}
	return len(s.Properties) > 0
}

// ReturnedGoType returns Go type returned by the given link as a string.
func (s *Schema) ReturnedGoType(l *Link) string {
	if l.TargetSchema != nil {
		return l.TargetSchema.goType(true, false)
	}
	return s.goType(true, false)
}

// EmptyResult retursn true if the link result should be empty.
func (s *Schema) EmptyResult(l *Link) bool {
	var (
		types []string
		err   error
	)
	if l.TargetSchema != nil {
		types, err = l.TargetSchema.Types()
	} else {
		types, err = s.Types()
	}
	if err != nil {
		return true
	}
	return len(types) == 1 && types[0] == "null"
}

// Parameters returns function parameters names and types.
func (l *Link) Parameters(name string) ([]string, map[string]string) {
	if l.HRef == nil {
		// No HRef property
		panic(fmt.Errorf("no href property declared for %s", l.Title))
	}
	var order []string
	params := make(map[string]string)
	for _, name := range l.HRef.Order {
		def := l.HRef.Schemas[name]
		order = append(order, name)
		params[name] = def.GoType()
	}
	if l.Schema != nil {
		order = append(order, "o")
		t, required := l.GoType()
		if l.AcceptsCustomType() {
			params["o"] = paramType(name, l)
		} else {
			params["o"] = t
		}
		if !required {
			params["o"] = "*" + params["o"]
		}
	}
	if l.Rel == "instances" && strings.ToUpper(l.Method) == "GET" {
		order = append(order, "lr")
		params["lr"] = "*ListRange"
	}
	return order, params
}

// AcceptsCustomType returns true if the link schema is not a primitive type
func (l *Link) AcceptsCustomType() bool {
	if l.Schema != nil && l.Schema.IsCustomType() {
		return true
	}
	return false
}

// Resolve resolve link schema and href.
func (l *Link) Resolve(r *Schema) {
	if l.Schema != nil {
		l.Schema = l.Schema.Resolve(r)
	}
	if l.TargetSchema != nil {
		l.TargetSchema = l.TargetSchema.Resolve(r)
	}
	l.HRef.Resolve(r)
}

// GoType returns Go type for the given schema as string and a bool specifying whether it is required
func (l *Link) GoType() (string, bool) {
	t := l.Schema.goType(true, false)
	if t[0] == '*' {
		return t[1:], false
	}
	return t, true
}
<|endoftext|>


<commit_before>package host

import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/crashreport"
	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/docker/machine/libmachine/provision"
	"github.com/docker/machine/libmachine/provision/pkgaction"
	"github.com/docker/machine/libmachine/provision/serviceaction"
	"github.com/docker/machine/libmachine/ssh"
	"github.com/docker/machine/libmachine/state"
	"github.com/docker/machine/libmachine/swarm"
)

var (
	validHostNameChars                = `^[a-zA-Z0-9][a-zA-Z0-9\-\.]*$`
	validHostNamePattern              = regexp.MustCompile(validHostNameChars)
	errMachineMustBeRunningForUpgrade = errors.New("Error: machine must be running to upgrade.")
)

type Host struct {
	ConfigVersion int
	Driver        drivers.Driver
	DriverName    string
	HostOptions   *Options
	Name          string
	RawDriver     []byte `json:"-"`
}

type Options struct {
	Driver        string
	Memory        int
	Disk          int
	EngineOptions *engine.Options
	SwarmOptions  *swarm.Options
	AuthOptions   *auth.Options
}

type Metadata struct {
	ConfigVersion int
	DriverName    string
	HostOptions   Options
}

func ValidateHostName(name string) bool {
	return validHostNamePattern.MatchString(name)
}

func (h *Host) RunSSHCommand(command string) (string, error) {
	return drivers.RunSSHCommandFromDriver(h.Driver, command)
}

func (h *Host) CreateSSHClient() (ssh.Client, error) {
	addr, err := h.Driver.GetSSHHostname()
	if err != nil {
		return ssh.ExternalClient{}, err
	}

	port, err := h.Driver.GetSSHPort()
	if err != nil {
		return ssh.ExternalClient{}, err
	}

	var auth *ssh.Auth
	if h.Driver.GetSSHKeyPath() == "" {
		auth = &ssh.Auth{}
	} else {
		auth = &ssh.Auth{
			Keys: []string{h.Driver.GetSSHKeyPath()},
		}
	}

	return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth)
}

func (h *Host) runActionForState(action func() error, desiredState state.State) error {
	if drivers.MachineInState(h.Driver, desiredState)() {
		return fmt.Errorf("Machine %q is already %s.", h.Name, strings.ToLower(desiredState.String()))
	}

	if err := action(); err != nil {
		return err
	}

	return mcnutils.WaitFor(drivers.MachineInState(h.Driver, desiredState))
}

func (h *Host) Start() error {
	return h.runActionForState(h.Driver.Start, state.Running)
}

func (h *Host) Stop() error {
	return h.runActionForState(h.Driver.Stop, state.Stopped)
}

func (h *Host) Kill() error {
	return h.runActionForState(h.Driver.Kill, state.Stopped)
}

func (h *Host) Restart() error {
	if drivers.MachineInState(h.Driver, state.Running)() {
		if err := h.Stop(); err != nil {
			return err
		}

		if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, state.Stopped)); err != nil {
			return err
		}
	}

	if err := h.Start(); err != nil {
		return err
	}

	if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, state.Running)); err != nil {
		return err
	}

	return nil
}

func (h *Host) Upgrade() error {
	machineState, err := h.Driver.GetState()
	if err != nil {
		return err
	}

	if machineState != state.Running {
		return errMachineMustBeRunningForUpgrade
	}

	provisioner, err := provision.DetectProvisioner(h.Driver)
	if err != nil {
		crashreport.Send(err, "provision.DetectProvisioner", h.Driver.DriverName(), "Upgrade")
		return err
	}

	log.Info("Upgrading docker...")
	if err := provisioner.Package("docker", pkgaction.Upgrade); err != nil {
		crashreport.Send(err, "provisioner.Package", h.Driver.DriverName(), "Upgrade")
		return err
	}

	log.Info("Restarting docker...")
	return provisioner.Service("docker", serviceaction.Restart)
}

func (h *Host) URL() (string, error) {
	return h.Driver.GetURL()
}

func (h *Host) AuthOptions() *auth.Options {
	return h.HostOptions.AuthOptions
}

func (h *Host) DockerVersion() (string, error) {
	return mcndockerclient.DockerVersion(h)
}

func (h *Host) ConfigureAuth() error {
	provisioner, err := provision.DetectProvisioner(h.Driver)
	if err != nil {
		return err
	}

	// TODO: This is kind of a hack (or is it?  I'm not really sure until
	// we have more clearly defined outlook on what the responsibilities
	// and modularity of the provisioners should be).
	//
	// Call provision to re-provision the certs properly.
	if err := provisioner.Provision(swarm.Options{}, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions); err != nil {
		return err
	}

	return nil
}
<commit_msg>FIX #2370 add feedback to the user<commit_after>package host

import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"github.com/docker/machine/libmachine/auth"
	"github.com/docker/machine/libmachine/crashreport"
	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/engine"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcndockerclient"
	"github.com/docker/machine/libmachine/mcnutils"
	"github.com/docker/machine/libmachine/provision"
	"github.com/docker/machine/libmachine/provision/pkgaction"
	"github.com/docker/machine/libmachine/provision/serviceaction"
	"github.com/docker/machine/libmachine/ssh"
	"github.com/docker/machine/libmachine/state"
	"github.com/docker/machine/libmachine/swarm"
)

var (
	validHostNameChars                = `^[a-zA-Z0-9][a-zA-Z0-9\-\.]*$`
	validHostNamePattern              = regexp.MustCompile(validHostNameChars)
	errMachineMustBeRunningForUpgrade = errors.New("Error: machine must be running to upgrade.")
)

type Host struct {
	ConfigVersion int
	Driver        drivers.Driver
	DriverName    string
	HostOptions   *Options
	Name          string
	RawDriver     []byte `json:"-"`
}

type Options struct {
	Driver        string
	Memory        int
	Disk          int
	EngineOptions *engine.Options
	SwarmOptions  *swarm.Options
	AuthOptions   *auth.Options
}

type Metadata struct {
	ConfigVersion int
	DriverName    string
	HostOptions   Options
}

func ValidateHostName(name string) bool {
	return validHostNamePattern.MatchString(name)
}

func (h *Host) RunSSHCommand(command string) (string, error) {
	return drivers.RunSSHCommandFromDriver(h.Driver, command)
}

func (h *Host) CreateSSHClient() (ssh.Client, error) {
	addr, err := h.Driver.GetSSHHostname()
	if err != nil {
		return ssh.ExternalClient{}, err
	}

	port, err := h.Driver.GetSSHPort()
	if err != nil {
		return ssh.ExternalClient{}, err
	}

	var auth *ssh.Auth
	if h.Driver.GetSSHKeyPath() == "" {
		auth = &ssh.Auth{}
	} else {
		auth = &ssh.Auth{
			Keys: []string{h.Driver.GetSSHKeyPath()},
		}
	}

	return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth)
}

func (h *Host) runActionForState(action func() error, desiredState state.State) error {
	if drivers.MachineInState(h.Driver, desiredState)() {
		return fmt.Errorf("Machine %q is already %s.", h.Name, strings.ToLower(desiredState.String()))
	}

	if err := action(); err != nil {
		return err
	}

	return mcnutils.WaitFor(drivers.MachineInState(h.Driver, desiredState))
}

func (h *Host) Start() error {
	if err := h.runActionForState(h.Driver.Start, state.Running); err != nil {
		return err
	}

	log.Infof("Machine %q was started.", h.Name)
	return nil
}

func (h *Host) Stop() error {
	if err := h.runActionForState(h.Driver.Stop, state.Stopped); err != nil {
		return err
	}

	log.Infof("Machine %q was stopped.", h.Name)
	return nil
}

func (h *Host) Kill() error {
	if err := h.runActionForState(h.Driver.Kill, state.Stopped); err != nil {
		return err
	}

	log.Infof("Machine %q was killed.", h.Name)
	return nil
}

func (h *Host) Restart() error {
	if drivers.MachineInState(h.Driver, state.Running)() {
		if err := h.Stop(); err != nil {
			return err
		}

		if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, state.Stopped)); err != nil {
			return err
		}
	}

	if err := h.Start(); err != nil {
		return err
	}

	if err := mcnutils.WaitFor(drivers.MachineInState(h.Driver, state.Running)); err != nil {
		return err
	}

	return nil
}

func (h *Host) Upgrade() error {
	machineState, err := h.Driver.GetState()
	if err != nil {
		return err
	}

	if machineState != state.Running {
		return errMachineMustBeRunningForUpgrade
	}

	provisioner, err := provision.DetectProvisioner(h.Driver)
	if err != nil {
		crashreport.Send(err, "provision.DetectProvisioner", h.Driver.DriverName(), "Upgrade")
		return err
	}

	log.Info("Upgrading docker...")
	if err := provisioner.Package("docker", pkgaction.Upgrade); err != nil {
		crashreport.Send(err, "provisioner.Package", h.Driver.DriverName(), "Upgrade")
		return err
	}

	log.Info("Restarting docker...")
	return provisioner.Service("docker", serviceaction.Restart)
}

func (h *Host) URL() (string, error) {
	return h.Driver.GetURL()
}

func (h *Host) AuthOptions() *auth.Options {
	return h.HostOptions.AuthOptions
}

func (h *Host) DockerVersion() (string, error) {
	return mcndockerclient.DockerVersion(h)
}

func (h *Host) ConfigureAuth() error {
	provisioner, err := provision.DetectProvisioner(h.Driver)
	if err != nil {
		return err
	}

	// TODO: This is kind of a hack (or is it?  I'm not really sure until
	// we have more clearly defined outlook on what the responsibilities
	// and modularity of the provisioners should be).
	//
	// Call provision to re-provision the certs properly.
	if err := provisioner.Provision(swarm.Options{}, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions); err != nil {
		return err
	}

	return nil
}
<|endoftext|>