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

package status

import (
	"fmt"
	"os"
	"strconv"

	"github.com/juju/cmd"
	"github.com/juju/errors"
	"launchpad.net/gnuflag"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/cmd/juju/common"
	"github.com/juju/juju/cmd/modelcmd"
	"github.com/juju/juju/juju/osenv"
)

// NewStatusHistoryCommand returns a command that reports the history
// of status changes for the specified unit.
func NewStatusHistoryCommand() cmd.Command {
	return modelcmd.Wrap(&statusHistoryCommand{})
}

type statusHistoryCommand struct {
	modelcmd.ModelCommandBase
	out           cmd.Output
	outputContent string
	backlogSize   int
	isoTime       bool
	unitName      string
}

var statusHistoryDoc = `
This command will report the history of status changes for
a given unit.
The statuses for the unit workload and/or agent are available.
-type supports:
    juju-unit: will show statuses for the unit's juju agent.
    workload: will show statuses for the unit's workload.
    unit: will show workload and juju agent combined for the specified unit.
    juju-machine: will show statuses for machine's juju agent.
    machine: will show statuses for machines.
    juju-container: will show statuses for the container's juju agent.
    container: will show statuses for containers.
 and sorted by time of occurrence.
`

func (c *statusHistoryCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "status-history",
		Args:    "[-n N] <unit>",
		Purpose: "output past statuses for a unit",
		Doc:     statusHistoryDoc,
	}
}

func (c *statusHistoryCommand) SetFlags(f *gnuflag.FlagSet) {
	f.StringVar(&c.outputContent, "type", "combined", "type of statuses to be displayed [agent|workload|combined|machine|machineInstance|container|containerinstance].")
	f.IntVar(&c.backlogSize, "n", 20, "size of logs backlog.")
	f.BoolVar(&c.isoTime, "utc", false, "display time as UTC in RFC3339 format")
}

func (c *statusHistoryCommand) Init(args []string) error {
	switch {
	case len(args) > 1:
		return errors.Errorf("unexpected arguments after unit name.")
	case len(args) == 0:
		return errors.Errorf("unit name is missing.")
	default:
		c.unitName = args[0]
	}
	// If use of ISO time not specified on command line,
	// check env var.
	if !c.isoTime {
		var err error
		envVarValue := os.Getenv(osenv.JujuStatusIsoTimeEnvKey)
		if envVarValue != "" {
			if c.isoTime, err = strconv.ParseBool(envVarValue); err != nil {
				return errors.Annotatef(err, "invalid %s env var, expected true|false", osenv.JujuStatusIsoTimeEnvKey)
			}
		}
	}
	kind := params.HistoryKind(c.outputContent)
	switch kind {
	case params.KindUnit, params.KindUnitAgent, params.KindWorkload,
		params.KindMachineInstance, params.KindMachine, params.KindContainer,
		params.KindContainerInstance:
		return nil
	}
	return errors.Errorf("unexpected status type %q", c.outputContent)
}

func (c *statusHistoryCommand) Run(ctx *cmd.Context) error {
	apiclient, err := c.NewAPIClient()
	if err != nil {
		return fmt.Errorf(connectionError, c.ConnectionName(), err)
	}
	defer apiclient.Close()
	var statuses *params.StatusHistoryResults
	kind := params.HistoryKind(c.outputContent)
	statuses, err = apiclient.StatusHistory(kind, c.unitName, c.backlogSize)
	if err != nil {
		if len(statuses.Statuses) == 0 {
			return errors.Trace(err)
		}
		// Display any error, but continue to print status if some was returned
		fmt.Fprintf(ctx.Stderr, "%v\n", err)
	} else if len(statuses.Statuses) == 0 {
		return errors.Errorf("no status history available")
	}
	table := [][]string{{"TIME", "TYPE", "STATUS", "MESSAGE"}}
	lengths := []int{1, 1, 1, 1}
	for _, v := range statuses.Statuses {
		fields := []string{common.FormatTime(v.Since, c.isoTime), string(v.Kind), string(v.Status), v.Info}
		for k, v := range fields {
			if len(v) > lengths[k] {
				lengths[k] = len(v)
			}
		}
		table = append(table, fields)
	}
	f := fmt.Sprintf("%%-%ds\t%%-%ds\t%%-%ds\t%%-%ds\n", lengths[0], lengths[1], lengths[2], lengths[3])
	for _, v := range table {
		fmt.Printf(f, v[0], v[1], v[2], v[3])
	}
	return nil
}
<commit_msg>Fixed documentation issues in status-history<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package status

import (
	"fmt"
	"os"
	"strconv"

	"github.com/juju/cmd"
	"github.com/juju/errors"
	"launchpad.net/gnuflag"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/cmd/juju/common"
	"github.com/juju/juju/cmd/modelcmd"
	"github.com/juju/juju/juju/osenv"
)

// NewStatusHistoryCommand returns a command that reports the history
// of status changes for the specified unit.
func NewStatusHistoryCommand() cmd.Command {
	return modelcmd.Wrap(&statusHistoryCommand{})
}

type statusHistoryCommand struct {
	modelcmd.ModelCommandBase
	out           cmd.Output
	outputContent string
	backlogSize   int
	isoTime       bool
	unitName      string
}

var statusHistoryDoc = `
This command will report the history of status changes for
a given entity.
The statuses are available for the following types.
-type supports:
    juju-unit: will show statuses for the unit's juju agent.
    workload: will show statuses for the unit's workload.
    unit: will show workload and juju agent combined for the specified unit.
    juju-machine: will show statuses for machine's juju agent.
    machine: will show statuses for machines.
    juju-container: will show statuses for the container's juju agent.
    container: will show statuses for containers.
 and sorted by time of occurrence.
 The default is unit.
`

func (c *statusHistoryCommand) Info() *cmd.Info {
	return &cmd.Info{
		Name:    "status-history",
		Args:    "[-n N] [--type T] [--utc] <entity name>",
		Purpose: "output past statuses for the passed entity",
		Doc:     statusHistoryDoc,
	}
}

func (c *statusHistoryCommand) SetFlags(f *gnuflag.FlagSet) {
	f.StringVar(&c.outputContent, "type", "unit", "type of statuses to be displayed [agent|workload|combined|machine|machineInstance|container|containerinstance].")
	f.IntVar(&c.backlogSize, "n", 20, "size of logs backlog.")
	f.BoolVar(&c.isoTime, "utc", false, "display time as UTC in RFC3339 format")
}

func (c *statusHistoryCommand) Init(args []string) error {
	switch {
	case len(args) > 1:
		return errors.Errorf("unexpected arguments after entity name.")
	case len(args) == 0:
		return errors.Errorf("entity name is missing.")
	default:
		c.unitName = args[0]
	}
	// If use of ISO time not specified on command line,
	// check env var.
	if !c.isoTime {
		var err error
		envVarValue := os.Getenv(osenv.JujuStatusIsoTimeEnvKey)
		if envVarValue != "" {
			if c.isoTime, err = strconv.ParseBool(envVarValue); err != nil {
				return errors.Annotatef(err, "invalid %s env var, expected true|false", osenv.JujuStatusIsoTimeEnvKey)
			}
		}
	}
	kind := params.HistoryKind(c.outputContent)
	switch kind {
	case params.KindUnit, params.KindUnitAgent, params.KindWorkload,
		params.KindMachineInstance, params.KindMachine, params.KindContainer,
		params.KindContainerInstance:
		return nil
	}
	return errors.Errorf("unexpected status type %q", c.outputContent)
}

func (c *statusHistoryCommand) Run(ctx *cmd.Context) error {
	apiclient, err := c.NewAPIClient()
	if err != nil {
		return fmt.Errorf(connectionError, c.ConnectionName(), err)
	}
	defer apiclient.Close()
	var statuses *params.StatusHistoryResults
	kind := params.HistoryKind(c.outputContent)
	statuses, err = apiclient.StatusHistory(kind, c.unitName, c.backlogSize)
	if err != nil {
		if len(statuses.Statuses) == 0 {
			return errors.Trace(err)
		}
		// Display any error, but continue to print status if some was returned
		fmt.Fprintf(ctx.Stderr, "%v\n", err)
	} else if len(statuses.Statuses) == 0 {
		return errors.Errorf("no status history available")
	}
	table := [][]string{{"TIME", "TYPE", "STATUS", "MESSAGE"}}
	lengths := []int{1, 1, 1, 1}
	for _, v := range statuses.Statuses {
		fields := []string{common.FormatTime(v.Since, c.isoTime), string(v.Kind), string(v.Status), v.Info}
		for k, v := range fields {
			if len(v) > lengths[k] {
				lengths[k] = len(v)
			}
		}
		table = append(table, fields)
	}
	f := fmt.Sprintf("%%-%ds\t%%-%ds\t%%-%ds\t%%-%ds\n", lengths[0], lengths[1], lengths[2], lengths[3])
	for _, v := range table {
		fmt.Printf(f, v[0], v[1], v[2], v[3])
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/devinmcgloin/morph/src/env"
	_ "github.com/go-sql-driver/mysql" // want sql drivers to init, work with the database/sql package.
	"github.com/jmoiron/sqlx"
)

func main() {
	log.Println("Connecting to db...")

	// Create the database handle, confirm driver is
	db, err := sqlx.Open("mysql", env.Getenv("DB_URL", "root:@/morph"))
	if err != nil {
		log.Fatal(err)
	}
	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Clearing db tables...")

	db.MustExec("DROP TABLE users")

	db.MustExec("DROP TABLE images")

	db.MustExec("DROP TABLE sources")

	db.MustExec("DROP TABLE locations")

	db.MustExec("DROP TABLE albums")

	log.Println("Tables Cleared")

}
<commit_msg>exec not must exec<commit_after>package main

import (
	"log"

	"github.com/devinmcgloin/morph/src/env"
	_ "github.com/go-sql-driver/mysql" // want sql drivers to init, work with the database/sql package.
	"github.com/jmoiron/sqlx"
)

func main() {
	log.Println("Connecting to db...")

	// Create the database handle, confirm driver is
	db, err := sqlx.Open("mysql", env.Getenv("DB_URL", "root:@/morph"))
	if err != nil {
		log.Fatal(err)
	}
	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Clearing db tables...")

	db.Exec("DROP TABLE users")

	db.Exec("DROP TABLE images")

	db.Exec("DROP TABLE sources")

	db.Exec("DROP TABLE locations")

	db.Exec("DROP TABLE albums")

	log.Println("Tables Cleared")

}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"path"
	"strings"

	"github.com/thijzert/speeldoos/lib/ziptraverser"
	speeldoos "github.com/thijzert/speeldoos/pkg"
)

type fixableError string

func (f fixableError) Error() string {
	return string(f)
}

func fixErr(format string, a ...interface{}) fixableError {
	return fixableError(fmt.Sprintf(format, a...))
}

type checkF func(*speeldoos.Carrier) []error

var allChecks []checkF = []checkF{
	check_carrierID,
	check_sourceFiles,
	check_composers,
}

func check_main(args []string) {
	allCarr, err := allCarriersWithErrors()
	if err != nil {
		log.Fatalf("Unable to open library: %s", err)
	}

	exitStatus := 0

	for _, pc := range allCarr {
		if pc.Error != nil {
			exitStatus = 1
			log.Printf("Parse error in %s: %s", pc.Filename, pc.Error)
			continue
		}

		modified := false

		for _, f := range allChecks {
			errs := f(pc.Carrier)
			if errs != nil {
				for _, e := range errs {
					if ff, ok := e.(fixableError); ok {
						modified = true
						fmt.Printf("%s: %s (fixed)\n", pc.Filename, ff)
					} else {
						exitStatus = 1
						fmt.Printf("%s: %s\n", pc.Filename, e.Error())
					}
				}
			}
		}

		if modified {
			pc.Carrier.Write(pc.Filename)
		}
	}

	os.Exit(exitStatus)
}

func check_carrierID(foo *speeldoos.Carrier) []error {
	if foo.ID == "" {
		return []error{fmt.Errorf("no carrier ID")}
	}
	return nil
}

func check_sourceFiles(foo *speeldoos.Carrier) []error {
	rv := []error{}

	seen := make([]string, 0)
	zm := ziptraverser.New()
	defer zm.Close()

	for _, perf := range foo.Performances {
		for _, sf := range perf.SourceFiles {
			if !zm.Exists(path.Join(Config.LibraryDir, sf.Filename)) {
				rv = append(rv, fmt.Errorf("source file missing: %s", sf))
			}

			for _, ssf := range seen {
				if sf.Filename == ssf {
					rv = append(rv, fmt.Errorf("duplicate source file: %s", sf))
				}
			}
			seen = append(seen, sf.Filename)
		}
	}

	return rv
}

func check_composers(foo *speeldoos.Carrier) []error {
	rv := []error{}
	for i, perf := range foo.Performances {
		if perf.Work.Composer.ID == "" || perf.Work.Composer.ID == "2222" {
			name := perf.Work.Composer.Name

			if name == "" && perf.Work.Composer.ID == "" {
				continue
			} else if name == "Anonymous" {
				foo.Performances[i].Work.Composer.ID = "Anonymous_work"
			} else {
				foo.Performances[i].Work.Composer.ID = strings.Replace(name, " ", "_", -1)
			}

			rv = append(rv, fixErr("empty composer ID for '%s'", name))
		}
	}

	return rv
}
<commit_msg>Add option to 'check' to only check selected carriers<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"path"
	"strings"

	"github.com/thijzert/speeldoos/lib/ziptraverser"
	speeldoos "github.com/thijzert/speeldoos/pkg"
)

type fixableError string

func (f fixableError) Error() string {
	return string(f)
}

func fixErr(format string, a ...interface{}) fixableError {
	return fixableError(fmt.Sprintf(format, a...))
}

type checkF func(*speeldoos.Carrier) []error

var allChecks []checkF = []checkF{
	check_carrierID,
	check_sourceFiles,
	check_composers,
}

func check_main(args []string) {
	allCarr, err := allCarriersWithErrors()
	if err != nil {
		log.Fatalf("Unable to open library: %s", err)
	}

	exitStatus := 0

	for _, pc := range allCarr {
		if pc.Error != nil {
			exitStatus = 1
			log.Printf("Parse error in %s: %s", pc.Filename, pc.Error)
			continue
		}

		if len(args) > 0 {
			found := false
			for _, arg := range args {
				if pc.Carrier.ID == arg {
					found = true
				}
			}
			if !found {
				continue
			}
		}

		errorsFound := false
		modified := false

		for _, f := range allChecks {
			errs := f(pc.Carrier)
			if errs != nil {
				for _, e := range errs {
					errorsFound = true
					if ff, ok := e.(fixableError); ok {
						modified = true
						fmt.Printf("%s: %s (fixed)\n", pc.Filename, ff)
					} else {
						exitStatus = 1
						fmt.Printf("%s: %s\n", pc.Filename, e.Error())
					}
				}
			}
		}

		if modified {
			pc.Carrier.Write(pc.Filename)
		}
		if !errorsFound {
			fmt.Printf("%s: no errors\n", pc.Filename)
		}
	}

	os.Exit(exitStatus)
}

func check_carrierID(foo *speeldoos.Carrier) []error {
	if foo.ID == "" {
		return []error{fmt.Errorf("no carrier ID")}
	}
	return nil
}

func check_sourceFiles(foo *speeldoos.Carrier) []error {
	rv := []error{}

	seen := make([]string, 0)
	ztr := ziptraverser.New()
	defer ztr.Close()

	for _, perf := range foo.Performances {
		for _, sf := range perf.SourceFiles {
			if !ztr.Exists(path.Join(Config.LibraryDir, sf.Filename)) {
				rv = append(rv, fmt.Errorf("source file missing: %s", sf))
			}

			for _, ssf := range seen {
				if sf.Filename == ssf {
					rv = append(rv, fmt.Errorf("duplicate source file: %s", sf))
				}
			}
			seen = append(seen, sf.Filename)
		}
	}

	return rv
}

func check_composers(foo *speeldoos.Carrier) []error {
	rv := []error{}
	for i, perf := range foo.Performances {
		if perf.Work.Composer.ID == "" || perf.Work.Composer.ID == "2222" {
			name := perf.Work.Composer.Name

			if name == "" && perf.Work.Composer.ID == "" {
				continue
			} else if name == "Anonymous" {
				foo.Performances[i].Work.Composer.ID = "Anonymous_work"
			} else {
				foo.Performances[i].Work.Composer.ID = strings.Replace(name, " ", "_", -1)
			}

			rv = append(rv, fixErr("empty composer ID for '%s'", name))
		}
	}

	return rv
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/thijzert/go-rcfile"
	"log"
	"os"
	"path/filepath"
)

var Config = struct {
	ConcurrentJobs int
	LibraryDir     string
	Extract        struct {
		Bitrate string
	}
	Grep struct {
		CaseSensitive bool
	}
	Init struct {
		OutputFile                              string
		TrackFormat, DiscFormat                 string
		Composer                                string
		Year                                    int
		Soloist, Orchestra, Ensemble, Conductor string
		Discs                                   string
	}
	Seedvault struct {
		InputXml, OutputDir             string
		CoverImage, InlayImage, Booklet string
		EACLogfile, Cuesheet            string
		NameAfterComposer               bool
		Tracker                         string
		DArchive, D320, DV0, DV2, DV6   bool
	}
}{}

var cmdline = flag.NewFlagSet("speeldoos", flag.ContinueOnError)

func init() {
	// Global settings
	cmdline.IntVar(&Config.ConcurrentJobs, "j", 2, "Number of concurrent jobs")
	cmdline.StringVar(&Config.LibraryDir, "library_dir", ".", "Search speeldoos files in this directory")

	// Settings for `sd extract`
	cmdline.StringVar(&Config.Extract.Bitrate, "extract.bitrate", "64k", "Output audio bitrate (mp3)")

	// Settings for `sd grep`
	cmdline.BoolVar(&Config.Grep.CaseSensitive, "grep.I", false, "Perforn case-sensitive matching")

	// Settings for `sd init`
	cmdline.StringVar(&Config.Init.OutputFile, "init.output_file", "", "Output XML file")

	cmdline.StringVar(&Config.Init.TrackFormat, "init.track_format", "track_%02d.flac", "Filename format of the track number")
	cmdline.StringVar(&Config.Init.DiscFormat, "init.disc_format", "disc_%02d", "Directory name format of the disc number")

	cmdline.StringVar(&Config.Init.Composer, "init.composer", "2222", "Preset the composer of each work")
	cmdline.IntVar(&Config.Init.Year, "init.year", 2222, "Preset the year of each performance")

	cmdline.StringVar(&Config.Init.Soloist, "init.soloist", "", "Pre-fill a soloist in each performance")
	cmdline.StringVar(&Config.Init.Orchestra, "init.orchestra", "", "Pre-fill an orchestra in each performance")
	cmdline.StringVar(&Config.Init.Ensemble, "init.ensemble", "", "Pre-fill an ensemble in each performance")
	cmdline.StringVar(&Config.Init.Conductor, "init.conductor", "", "Pre-fill a conductor in each performance")

	cmdline.StringVar(&Config.Init.Discs, "init.discs", "", "A space separated list of the number of tracks in each disc, for a multi-disc release.")

	// Settings pertaining to `sd seedvault`
	cmdline.StringVar(&Config.Seedvault.InputXml, "seedvault.input_xml", "", "Input XML file")
	cmdline.StringVar(&Config.Seedvault.OutputDir, "seedvault.output_dir", "seedvault", "Output directory")

	cmdline.StringVar(&Config.Seedvault.CoverImage, "seedvault.cover_image", "", "Path to cover image")
	cmdline.StringVar(&Config.Seedvault.InlayImage, "seedvault.inlay_image", "", "Path to inlay image")
	cmdline.StringVar(&Config.Seedvault.Booklet, "seedvault.booklet", "", "Path to booklet PDF")
	cmdline.StringVar(&Config.Seedvault.EACLogfile, "seedvault.eac_logfile", "", "Path to EAC log file")
	cmdline.StringVar(&Config.Seedvault.Cuesheet, "seedvault.cuesheet", "", "Path to cuesheet")

	cmdline.BoolVar(&Config.Seedvault.NameAfterComposer, "name_after_composer", false, "Name the album after the first composer rather than the first performer")

	cmdline.StringVar(&Config.Seedvault.Tracker, "seedvault.tracker", "", "URL to private tracker")

	cmdline.BoolVar(&Config.Seedvault.DArchive, "seedvault.archive", true, "Create a speeldoos archive")
	cmdline.BoolVar(&Config.Seedvault.D320, "seedvault.320", false, "Also encode MP3-320")
	cmdline.BoolVar(&Config.Seedvault.DV0, "seedvault.v0", false, "Also encode V0")
	cmdline.BoolVar(&Config.Seedvault.DV2, "seedvault.v2", false, "Also encode V2")
	cmdline.BoolVar(&Config.Seedvault.DV6, "seedvault.v6", false, "Also encode V6 (for audiobooks)")

	// Parse config file first, and override with anything on the commandline
	rcfile.ParseInto(cmdline, "speeldoosrc")
	cmdline.Parse(os.Args[1:])

	// HACK: Create aliases for subcommand-specific flags, then call flag.Parse() again.
	if len(os.Args) > 1 && getSubCmd(os.Args[1]) != nil {
		prefix := os.Args[1] + "."
		ff := make([]*flag.Flag, 0, 10)
		cmdline.VisitAll(func(f *flag.Flag) {
			if len(f.Name) > len(prefix) && f.Name[0:len(prefix)] == prefix {
				ff = append(ff, f)
			}
		})
		for _, f := range ff {
			cmdline.Var(f.Value, f.Name[len(prefix):], f.Usage)
		}
		cmdline.Parse(os.Args[2:])
	}

	// Sanity checks

	if Config.ConcurrentJobs < 1 {
		Config.ConcurrentJobs = 1
	}
}

type SubCommand func([]string)

func getSubCmd(name string) SubCommand {
	if name == "extract" {
		return extract_main
	} else if name == "grep" {
		return grep_main
	} else if name == "init" {
		return init_main
	} else if name == "seedvault" {
		return seedvault_main
	} else {
		return nil
	}
}

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s COMMAND [options]\n", filepath.Base(os.Args[0]))
		os.Exit(1)
		return
	}

	cmd := getSubCmd(os.Args[1])
	args := cmdline.Args()
	if cmd != nil {
		cmd(args)
	} else {
		fmt.Fprintf(os.Stderr, "Unknown subcommand %s.\n", os.Args[1])
		os.Exit(1)
		return
	}
}

func croak(e error) {
	if e != nil {
		log.Fatal(e)
	}
}

func ncroak(n int, e error) int {
	croak(e)
	return n
}
<commit_msg>Vim fold markers<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/thijzert/go-rcfile"
	"log"
	"os"
	"path/filepath"
)

var Config = struct {
	ConcurrentJobs int
	LibraryDir     string
	Extract        struct {
		Bitrate string
	}
	Grep struct {
		CaseSensitive bool
	}
	Init struct {
		OutputFile                              string
		TrackFormat, DiscFormat                 string
		Composer                                string
		Year                                    int
		Soloist, Orchestra, Ensemble, Conductor string
		Discs                                   string
	}
	Seedvault struct {
		InputXml, OutputDir             string
		CoverImage, InlayImage, Booklet string
		EACLogfile, Cuesheet            string
		NameAfterComposer               bool
		Tracker                         string
		DArchive, D320, DV0, DV2, DV6   bool
	}
}{}

var cmdline = flag.NewFlagSet("speeldoos", flag.ContinueOnError)

func init() {
	// Settings {{{
	// Global settings {{{
	cmdline.IntVar(&Config.ConcurrentJobs, "j", 2, "Number of concurrent jobs")
	cmdline.StringVar(&Config.LibraryDir, "library_dir", ".", "Search speeldoos files in this directory")

	// }}}
	// Settings for `sd extract` {{{
	cmdline.StringVar(&Config.Extract.Bitrate, "extract.bitrate", "64k", "Output audio bitrate (mp3)")

	// }}}
	// Settings for `sd grep` {{{
	cmdline.BoolVar(&Config.Grep.CaseSensitive, "grep.I", false, "Perforn case-sensitive matching")

	// }}}
	// Settings for `sd init` {{{
	cmdline.StringVar(&Config.Init.OutputFile, "init.output_file", "", "Output XML file")

	cmdline.StringVar(&Config.Init.TrackFormat, "init.track_format", "track_%02d.flac", "Filename format of the track number")
	cmdline.StringVar(&Config.Init.DiscFormat, "init.disc_format", "disc_%02d", "Directory name format of the disc number")

	cmdline.StringVar(&Config.Init.Composer, "init.composer", "2222", "Preset the composer of each work")
	cmdline.IntVar(&Config.Init.Year, "init.year", 2222, "Preset the year of each performance")

	cmdline.StringVar(&Config.Init.Soloist, "init.soloist", "", "Pre-fill a soloist in each performance")
	cmdline.StringVar(&Config.Init.Orchestra, "init.orchestra", "", "Pre-fill an orchestra in each performance")
	cmdline.StringVar(&Config.Init.Ensemble, "init.ensemble", "", "Pre-fill an ensemble in each performance")
	cmdline.StringVar(&Config.Init.Conductor, "init.conductor", "", "Pre-fill a conductor in each performance")

	cmdline.StringVar(&Config.Init.Discs, "init.discs", "", "A space separated list of the number of tracks in each disc, for a multi-disc release.")

	// }}}
	// Settings pertaining to `sd seedvault` {{{
	cmdline.StringVar(&Config.Seedvault.InputXml, "seedvault.input_xml", "", "Input XML file")
	cmdline.StringVar(&Config.Seedvault.OutputDir, "seedvault.output_dir", "seedvault", "Output directory")

	cmdline.StringVar(&Config.Seedvault.CoverImage, "seedvault.cover_image", "", "Path to cover image")
	cmdline.StringVar(&Config.Seedvault.InlayImage, "seedvault.inlay_image", "", "Path to inlay image")
	cmdline.StringVar(&Config.Seedvault.Booklet, "seedvault.booklet", "", "Path to booklet PDF")
	cmdline.StringVar(&Config.Seedvault.EACLogfile, "seedvault.eac_logfile", "", "Path to EAC log file")
	cmdline.StringVar(&Config.Seedvault.Cuesheet, "seedvault.cuesheet", "", "Path to cuesheet")

	cmdline.BoolVar(&Config.Seedvault.NameAfterComposer, "name_after_composer", false, "Name the album after the first composer rather than the first performer")

	cmdline.StringVar(&Config.Seedvault.Tracker, "seedvault.tracker", "", "URL to private tracker")

	cmdline.BoolVar(&Config.Seedvault.DArchive, "seedvault.archive", true, "Create a speeldoos archive")
	cmdline.BoolVar(&Config.Seedvault.D320, "seedvault.320", false, "Also encode MP3-320")
	cmdline.BoolVar(&Config.Seedvault.DV0, "seedvault.v0", false, "Also encode V0")
	cmdline.BoolVar(&Config.Seedvault.DV2, "seedvault.v2", false, "Also encode V2")
	cmdline.BoolVar(&Config.Seedvault.DV6, "seedvault.v6", false, "Also encode V6 (for audiobooks)")

	// }}}
	// }}}

	// Parse config file first, and override with anything on the commandline
	rcfile.ParseInto(cmdline, "speeldoosrc")
	cmdline.Parse(os.Args[1:])

	// HACK: Create aliases for subcommand-specific flags, then call flag.Parse() again.
	if len(os.Args) > 1 && getSubCmd(os.Args[1]) != nil {
		prefix := os.Args[1] + "."
		ff := make([]*flag.Flag, 0, 10)
		cmdline.VisitAll(func(f *flag.Flag) {
			if len(f.Name) > len(prefix) && f.Name[0:len(prefix)] == prefix {
				ff = append(ff, f)
			}
		})
		for _, f := range ff {
			cmdline.Var(f.Value, f.Name[len(prefix):], f.Usage)
		}
		cmdline.Parse(os.Args[2:])
	}

	// Sanity checks

	if Config.ConcurrentJobs < 1 {
		Config.ConcurrentJobs = 1
	}
}

type SubCommand func([]string)

func getSubCmd(name string) SubCommand {
	if name == "extract" {
		return extract_main
	} else if name == "grep" {
		return grep_main
	} else if name == "init" {
		return init_main
	} else if name == "seedvault" {
		return seedvault_main
	} else {
		return nil
	}
}

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintf(os.Stderr, "Usage: %s COMMAND [options]\n", filepath.Base(os.Args[0]))
		os.Exit(1)
		return
	}

	cmd := getSubCmd(os.Args[1])
	args := cmdline.Args()
	if cmd != nil {
		cmd(args)
	} else {
		fmt.Fprintf(os.Stderr, "Unknown subcommand %s.\n", os.Args[1])
		os.Exit(1)
		return
	}
}

func croak(e error) {
	if e != nil {
		log.Fatal(e)
	}
}

func ncroak(n int, e error) int {
	croak(e)
	return n
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"strconv"
	"time"

	"github.com/nelhage/taktician/ai"
	"github.com/nelhage/taktician/playtak"
	"github.com/nelhage/taktician/tak"
)

func timeBound(remaining time.Duration) time.Duration {
	return *limit
}

type Taktician struct {
	client *playtak.Client
	ai     *ai.MinimaxAI
}

func (t *Taktician) NewGame(g *Game) {
	t.ai = ai.NewMinimax(ai.MinimaxConfig{
		Size:  g.size,
		Depth: *depth,
		Debug: *debug,

		NoSort:  !*sort,
		NoTable: !*table,
	})
}

func (t *Taktician) GetMove(p *tak.Position, mine, theirs time.Duration) tak.Move {
	return t.ai.GetMove(p, timeBound(mine))
}

func (t *Taktician) GameOver() {
	t.ai = nil
}

func (t *Taktician) HandleChat(who string, msg string) {
	cmd, arg := parseCommand(msg)
	if cmd == "" {
		return
	}
	log.Printf("chat from=%q msg=%q", who, msg)
	switch cmd {
	case "size":
		sz, err := strconv.Atoi(arg)
		if err != nil {
			log.Printf("bad size size=%q", arg)
			return
		}
		if sz == 5 || sz == 6 {
			*size = sz
			t.client.SendCommand("Seek",
				strconv.Itoa(*size),
				strconv.Itoa(int(gameTime.Seconds())),
				strconv.Itoa(int(increment.Seconds())))
		}
	}
}

func (t *Taktician) AcceptUndo() bool {
	return false
}
<commit_msg>taktician: allow size 4<commit_after>package main

import (
	"log"
	"strconv"
	"time"

	"github.com/nelhage/taktician/ai"
	"github.com/nelhage/taktician/playtak"
	"github.com/nelhage/taktician/tak"
)

func timeBound(remaining time.Duration) time.Duration {
	return *limit
}

type Taktician struct {
	client *playtak.Client
	ai     *ai.MinimaxAI
}

func (t *Taktician) NewGame(g *Game) {
	t.ai = ai.NewMinimax(ai.MinimaxConfig{
		Size:  g.size,
		Depth: *depth,
		Debug: *debug,

		NoSort:  !*sort,
		NoTable: !*table,
	})
}

func (t *Taktician) GetMove(p *tak.Position, mine, theirs time.Duration) tak.Move {
	return t.ai.GetMove(p, timeBound(mine))
}

func (t *Taktician) GameOver() {
	t.ai = nil
}

func (t *Taktician) HandleChat(who string, msg string) {
	cmd, arg := parseCommand(msg)
	if cmd == "" {
		return
	}
	log.Printf("chat from=%q msg=%q", who, msg)
	switch cmd {
	case "size":
		sz, err := strconv.Atoi(arg)
		if err != nil {
			log.Printf("bad size size=%q", arg)
			return
		}
		if sz >= 4 && sz <= 6 {
			*size = sz
			t.client.SendCommand("Seek",
				strconv.Itoa(*size),
				strconv.Itoa(int(gameTime.Seconds())),
				strconv.Itoa(int(increment.Seconds())))
		}
	}
}

func (t *Taktician) AcceptUndo() bool {
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/exec"
	"time"

	pb "github.com/brotherlogic/gobuildslave/proto"
	"github.com/brotherlogic/goserver/utils"
	pbt "github.com/brotherlogic/tracer/proto"
	"golang.org/x/net/context"
)

const (
	pendWait = time.Minute
)

func (s *Server) runTransition(ctx context.Context, job *pb.JobAssignment) {
	utils.SendTrace(ctx, fmt.Sprintf("run_transition_%v", job.State), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
	stState := job.State
	switch job.State {
	case pb.State_ACKNOWLEDGED:
		key := s.scheduleBuild(ctx, job.Job)
		s.stateMap[job.Job.Name] = fmt.Sprintf("SCHED: %v", key)
		if job.Job.NonBootstrap {
			if key != "" {
				job.Server = s.Registry.Identifier
				job.State = pb.State_BUILT
				job.RunningVersion = key
			}
		} else {
			job.CommandKey = key
			job.State = pb.State_BUILDING
			job.Server = s.Registry.Identifier
		}
	case pb.State_BUILDING:
		if s.taskComplete(job.CommandKey) {
			job.State = pb.State_BUILT
		}
	case pb.State_BUILT:
		output := s.scheduler.getOutput(job.CommandKey)
		if len(output) > 0 {
			if job.BuildFail == 5 {
				s.deliverCrashReport(ctx, job, output)
			}
			job.BuildFail++
			job.State = pb.State_DIED
		} else {
			job.BuildFail = 0
			key := s.scheduleRun(job.Job)
			job.CommandKey = key
			job.StartTime = time.Now().Unix()
			job.State = pb.State_PENDING
			if _, ok := s.pendingMap[time.Now().Weekday()]; !ok {
				s.pendingMap[time.Now().Weekday()] = make(map[string]int)
			}
			s.pendingMap[time.Now().Weekday()][job.Job.Name]++
		}
	case pb.State_PENDING:
		s.stateMap[job.Job.Name] = fmt.Sprintf("OUTPUT = %v", s.scheduler.getOutput(job.CommandKey))
		if time.Now().Add(-time.Minute).Unix() > job.StartTime {
			job.State = pb.State_RUNNING
		}
	case pb.State_RUNNING:
		if s.taskComplete(job.CommandKey) {
			output := s.scheduler.getOutput(job.CommandKey)
			s.stateMap[job.Job.Name] = fmt.Sprintf("COMPLETE = %v", output)
			s.deliverCrashReport(ctx, job, output)
			job.State = pb.State_DIED
		}

		if s.discover.discover(job.Job.Name, s.Registry.Identifier) != nil {
			s.RaiseIssue(ctx, "Cannot Discover Running Server", fmt.Sprintf("%v on %v is not discoverable, despite running", job.Job.Name, s.Registry.Identifier), false)
		}

		// Restart this job if we need to
		if job.Job.NonBootstrap {
			version := s.getVersion(ctx, job.Job)
			if version != job.RunningVersion {
				s.stateMap[job.Job.Name] = fmt.Sprintf("VERSION_MISMATCH = %v,%v", version, job.RunningVersion)
				s.scheduler.killJob(job.CommandKey)
				job.State = pb.State_ACKNOWLEDGED
			}
		}
	case pb.State_DIED:
		job.State = pb.State_ACKNOWLEDGED
	}

	if job.State != stState {
		s.stateTime[job.Job.Name] = time.Now()
	}

	utils.SendTrace(ctx, fmt.Sprintf("end_transition_%v_%v", job.State, stState), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
	utils.SendTrace(ctx, fmt.Sprintf("end_transition_func_%v", job.State), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
}

type translator interface {
	build(job *pb.Job) *exec.Cmd
	run(job *pb.Job) *exec.Cmd
}

type checker interface {
	isAlive(ctx context.Context, job *pb.JobAssignment) bool
}

func (s *Server) getVersion(ctx context.Context, job *pb.Job) string {
	versions, _ := s.builder.build(ctx, job)

	if len(versions) == 0 {
		return ""
	}

	return versions[0].Version

}

// scheduleBuild builds out the job, returning the current version
func (s *Server) scheduleBuild(ctx context.Context, job *pb.Job) string {
	utils.SendTrace(ctx, fmt.Sprintf("schedule_build_%v", job.NonBootstrap), time.Now(), pbt.Milestone_MARKER, job.Name)
	if !job.NonBootstrap {
		c := s.translator.build(job)
		return s.scheduler.Schedule(&rCommand{command: c})
	}

	versions, err := s.builder.build(ctx, job)

	if len(versions) == 0 {
		s.stateMap[job.Name] = fmt.Sprintf("No Versions: %v", err)
		return ""
	}

	t := time.Now()
	err = s.builder.copy(ctx, versions[0])
	if err != nil {
		s.stateMap[job.Name] = fmt.Sprintf("Copy fail (%v) -> %v", time.Now().Sub(t), err)
		return ""
	}
	s.stateMap[job.Name] = fmt.Sprintf("Found version %v", versions[0].Version)
	return versions[0].Version
}

func (s *Server) scheduleRun(job *pb.Job) string {
	c := s.translator.run(job)
	return s.scheduler.Schedule(&rCommand{command: c})
}

func (s *Server) taskComplete(key string) bool {
	return s.scheduler.schedulerComplete(key)
}
<commit_msg>Add job died alert<commit_after>package main

import (
	"fmt"
	"os/exec"
	"time"

	pb "github.com/brotherlogic/gobuildslave/proto"
	"github.com/brotherlogic/goserver/utils"
	pbt "github.com/brotherlogic/tracer/proto"
	"golang.org/x/net/context"
)

const (
	pendWait = time.Minute
)

func (s *Server) runTransition(ctx context.Context, job *pb.JobAssignment) {
	utils.SendTrace(ctx, fmt.Sprintf("run_transition_%v", job.State), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
	stState := job.State
	switch job.State {
	case pb.State_ACKNOWLEDGED:
		key := s.scheduleBuild(ctx, job.Job)
		s.stateMap[job.Job.Name] = fmt.Sprintf("SCHED: %v", key)
		if job.Job.NonBootstrap {
			if key != "" {
				job.Server = s.Registry.Identifier
				job.State = pb.State_BUILT
				job.RunningVersion = key
			}
		} else {
			job.CommandKey = key
			job.State = pb.State_BUILDING
			job.Server = s.Registry.Identifier
		}
	case pb.State_BUILDING:
		if s.taskComplete(job.CommandKey) {
			job.State = pb.State_BUILT
		}
	case pb.State_BUILT:
		output := s.scheduler.getOutput(job.CommandKey)
		if len(output) > 0 {
			if job.BuildFail == 5 {
				s.deliverCrashReport(ctx, job, output)
			}
			job.BuildFail++
			job.State = pb.State_DIED
		} else {
			job.BuildFail = 0
			key := s.scheduleRun(job.Job)
			job.CommandKey = key
			job.StartTime = time.Now().Unix()
			job.State = pb.State_PENDING
			if _, ok := s.pendingMap[time.Now().Weekday()]; !ok {
				s.pendingMap[time.Now().Weekday()] = make(map[string]int)
			}
			s.pendingMap[time.Now().Weekday()][job.Job.Name]++
		}
	case pb.State_PENDING:
		s.stateMap[job.Job.Name] = fmt.Sprintf("OUTPUT = %v", s.scheduler.getOutput(job.CommandKey))
		if time.Now().Add(-time.Minute).Unix() > job.StartTime {
			job.State = pb.State_RUNNING
		}
	case pb.State_RUNNING:
		if s.taskComplete(job.CommandKey) {
			output := s.scheduler.getOutput(job.CommandKey)
			s.stateMap[job.Job.Name] = fmt.Sprintf("COMPLETE = %v", output)
			s.deliverCrashReport(ctx, job, output)
			job.State = pb.State_DIED
		}

		if s.discover.discover(job.Job.Name, s.Registry.Identifier) != nil {
			s.RaiseIssue(ctx, "Cannot Discover Running Server", fmt.Sprintf("%v on %v is not discoverable, despite running", job.Job.Name, s.Registry.Identifier), false)
		}

		// Restart this job if we need to
		if job.Job.NonBootstrap {
			version := s.getVersion(ctx, job.Job)
			if version != job.RunningVersion {
				s.stateMap[job.Job.Name] = fmt.Sprintf("VERSION_MISMATCH = %v,%v", version, job.RunningVersion)
				s.scheduler.killJob(job.CommandKey)
				job.State = pb.State_ACKNOWLEDGED
			}
		}
	case pb.State_DIED:
		job.State = pb.State_ACKNOWLEDGED
	}

	if job.State != stState {
		s.stateTime[job.Job.Name] = time.Now()
	}

	if job.State == pb.State_DIED {
		s.RaiseIssue(ctx, "Job Died", fmt.Sprintf("Job %v has died", job.Job.Name))
	}

	utils.SendTrace(ctx, fmt.Sprintf("end_transition_%v_%v", job.State, stState), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
	utils.SendTrace(ctx, fmt.Sprintf("end_transition_func_%v", job.State), time.Now(), pbt.Milestone_MARKER, job.Job.Name)
}

type translator interface {
	build(job *pb.Job) *exec.Cmd
	run(job *pb.Job) *exec.Cmd
}

type checker interface {
	isAlive(ctx context.Context, job *pb.JobAssignment) bool
}

func (s *Server) getVersion(ctx context.Context, job *pb.Job) string {
	versions, _ := s.builder.build(ctx, job)

	if len(versions) == 0 {
		return ""
	}

	return versions[0].Version

}

// scheduleBuild builds out the job, returning the current version
func (s *Server) scheduleBuild(ctx context.Context, job *pb.Job) string {
	utils.SendTrace(ctx, fmt.Sprintf("schedule_build_%v", job.NonBootstrap), time.Now(), pbt.Milestone_MARKER, job.Name)
	if !job.NonBootstrap {
		c := s.translator.build(job)
		return s.scheduler.Schedule(&rCommand{command: c})
	}

	versions, err := s.builder.build(ctx, job)

	if len(versions) == 0 {
		s.stateMap[job.Name] = fmt.Sprintf("No Versions: %v", err)
		return ""
	}

	t := time.Now()
	err = s.builder.copy(ctx, versions[0])
	if err != nil {
		s.stateMap[job.Name] = fmt.Sprintf("Copy fail (%v) -> %v", time.Now().Sub(t), err)
		return ""
	}
	s.stateMap[job.Name] = fmt.Sprintf("Found version %v", versions[0].Version)
	return versions[0].Version
}

func (s *Server) scheduleRun(job *pb.Job) string {
	c := s.translator.run(job)
	return s.scheduler.Schedule(&rCommand{command: c})
}

func (s *Server) taskComplete(key string) bool {
	return s.scheduler.schedulerComplete(key)
}
<|endoftext|>


<commit_before>// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package graph

// Iterator is an item iterator.
type Iterator interface {
	// Next advances the iterator and returns whether
	// the next call to the item method will return a
	// non-nil item.
	//
	// Next should be called prior to any call to the
	// iterator's item retrieval method after the
	// iterator has been obtained or reset.
	//
	// The order of iteration is implementation
	// dependent.
	Next() bool

	// Len returns the number of items remaining in the
	// iterator.
	//
	// If the number of items in the iterator is unknown,
	// too large to materialize or too costly to calculate
	// then Len may return a negative value.
	// In this case the consuming function must be able
	// to operate on the items of the iterator directly
	// without materializing the items into a slice.
	// The magnitude of a negative length has
	// implementation-dependent semantics.
	Len() int

	// Reset returns the iterator to its start position.
	Reset()
}

// Nodes is a Node iterator.
type Nodes interface {
	Iterator

	// Node returns the current Node from the iterator.
	Node() Node
}

// NodeSlicer wraps the NodeSlice method.
type NodeSlicer interface {
	// NodeSlice returns the set of nodes remaining
	// to be iterated by a Nodes iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	NodeSlice() []Node
}

// NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method
// is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf.
func NodesOf(it Nodes) []Node {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case NodeSlicer:
		return it.NodeSlice()
	}
	nodes := make([]Node, 0, n)
	for it.Next() {
		nodes = append(nodes, it.Node())
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes
}

// Edges is an Edge iterator.
type Edges interface {
	Iterator

	// Edge returns the current Edge from the iterator.
	Edge() Edge
}

// EdgeSlicer wraps the EdgeSlice method.
type EdgeSlicer interface {
	// EdgeSlice returns the set of edges remaining
	// to be iterated by an Edges iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	EdgeSlice() []Edge
}

// EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used
// to obtain the edges. It is safe to pass a nil Edges to EdgesOf.
func EdgesOf(it Edges) []Edge {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case EdgeSlicer:
		return it.EdgeSlice()
	}
	edges := make([]Edge, 0, n)
	for it.Next() {
		edges = append(edges, it.Edge())
	}
	if len(edges) == 0 {
		return nil
	}
	return edges
}

// WeightedEdges is a WeightedEdge iterator.
type WeightedEdges interface {
	Iterator

	// Edge returns the current Edge from the iterator.
	WeightedEdge() WeightedEdge
}

// WeightedEdgeSlicer wraps the WeightedEdgeSlice method.
type WeightedEdgeSlicer interface {
	// EdgeSlice returns the set of edges remaining
	// to be iterated by an Edges iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	WeightedEdgeSlice() []WeightedEdge
}

// WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the
// WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges
// to WeightedEdgesOf.
func WeightedEdgesOf(it WeightedEdges) []WeightedEdge {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case WeightedEdgeSlicer:
		return it.WeightedEdgeSlice()
	}
	edges := make([]WeightedEdge, 0, n)
	for it.Next() {
		edges = append(edges, it.WeightedEdge())
	}
	if len(edges) == 0 {
		return nil
	}
	return edges
}

// Lines is a Line iterator.
type Lines interface {
	Iterator

	// Line returns the current Line from the iterator.
	Line() Line
}

// LineSlicer wraps the LineSlice method.
type LineSlicer interface {
	// LineSlice returns the set of lines remaining
	// to be iterated by an Lines iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	LineSlice() []Line
}

// LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used
// to obtain the lines. It is safe to pass a nil Lines to LinesOf.
func LinesOf(it Lines) []Line {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case LineSlicer:
		return it.LineSlice()
	}
	lines := make([]Line, 0, n)
	for it.Next() {
		lines = append(lines, it.Line())
	}
	if len(lines) == 0 {
		return nil
	}
	return lines
}

// WeightedLines is a WeightedLine iterator.
type WeightedLines interface {
	Iterator

	// Line returns the current Line from the iterator.
	WeightedLine() WeightedLine
}

// WeightedLineSlicer wraps the WeightedLineSlice method.
type WeightedLineSlicer interface {
	// LineSlice returns the set of lines remaining
	// to be iterated by an Lines iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	WeightedLineSlice() []WeightedLine
}

// WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the
// WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines
// to WeightedLinesOf.
func WeightedLinesOf(it WeightedLines) []WeightedLine {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case WeightedLineSlicer:
		return it.WeightedLineSlice()
	}
	lines := make([]WeightedLine, 0, n)
	for it.Next() {
		lines = append(lines, it.WeightedLine())
	}
	if len(lines) == 0 {
		return nil
	}
	return lines
}

// Empty is an empty set of nodes, edges or lines. It should be used when
// a graph returns a zero-length Iterator. Empty implements the slicer
// interfaces for nodes, edges and lines, returning nil for each of these.
const Empty = nothing

var (
	_ Iterator           = Empty
	_ Nodes              = Empty
	_ NodeSlicer         = Empty
	_ Edges              = Empty
	_ EdgeSlicer         = Empty
	_ WeightedEdges      = Empty
	_ WeightedEdgeSlicer = Empty
	_ Lines              = Empty
	_ LineSlicer         = Empty
	_ WeightedLines      = Empty
	_ WeightedLineSlicer = Empty
)

const nothing = empty(true)

type empty bool

func (empty) Next() bool                        { return false }
func (empty) Len() int                          { return 0 }
func (empty) Reset()                            {}
func (empty) Node() Node                        { return nil }
func (empty) NodeSlice() []Node                 { return nil }
func (empty) Edge() Edge                        { return nil }
func (empty) EdgeSlice() []Edge                 { return nil }
func (empty) WeightedEdge() WeightedEdge        { return nil }
func (empty) WeightedEdgeSlice() []WeightedEdge { return nil }
func (empty) Line() Line                        { return nil }
func (empty) LineSlice() []Line                 { return nil }
func (empty) WeightedLine() WeightedLine        { return nil }
func (empty) WeightedLineSlice() []WeightedLine { return nil }
<commit_msg>graph: make state of empty less contradictory and provide debugging strings<commit_after>// Copyright ©2018 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package graph

// Iterator is an item iterator.
type Iterator interface {
	// Next advances the iterator and returns whether
	// the next call to the item method will return a
	// non-nil item.
	//
	// Next should be called prior to any call to the
	// iterator's item retrieval method after the
	// iterator has been obtained or reset.
	//
	// The order of iteration is implementation
	// dependent.
	Next() bool

	// Len returns the number of items remaining in the
	// iterator.
	//
	// If the number of items in the iterator is unknown,
	// too large to materialize or too costly to calculate
	// then Len may return a negative value.
	// In this case the consuming function must be able
	// to operate on the items of the iterator directly
	// without materializing the items into a slice.
	// The magnitude of a negative length has
	// implementation-dependent semantics.
	Len() int

	// Reset returns the iterator to its start position.
	Reset()
}

// Nodes is a Node iterator.
type Nodes interface {
	Iterator

	// Node returns the current Node from the iterator.
	Node() Node
}

// NodeSlicer wraps the NodeSlice method.
type NodeSlicer interface {
	// NodeSlice returns the set of nodes remaining
	// to be iterated by a Nodes iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	NodeSlice() []Node
}

// NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method
// is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf.
func NodesOf(it Nodes) []Node {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case NodeSlicer:
		return it.NodeSlice()
	}
	nodes := make([]Node, 0, n)
	for it.Next() {
		nodes = append(nodes, it.Node())
	}
	if len(nodes) == 0 {
		return nil
	}
	return nodes
}

// Edges is an Edge iterator.
type Edges interface {
	Iterator

	// Edge returns the current Edge from the iterator.
	Edge() Edge
}

// EdgeSlicer wraps the EdgeSlice method.
type EdgeSlicer interface {
	// EdgeSlice returns the set of edges remaining
	// to be iterated by an Edges iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	EdgeSlice() []Edge
}

// EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used
// to obtain the edges. It is safe to pass a nil Edges to EdgesOf.
func EdgesOf(it Edges) []Edge {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case EdgeSlicer:
		return it.EdgeSlice()
	}
	edges := make([]Edge, 0, n)
	for it.Next() {
		edges = append(edges, it.Edge())
	}
	if len(edges) == 0 {
		return nil
	}
	return edges
}

// WeightedEdges is a WeightedEdge iterator.
type WeightedEdges interface {
	Iterator

	// Edge returns the current Edge from the iterator.
	WeightedEdge() WeightedEdge
}

// WeightedEdgeSlicer wraps the WeightedEdgeSlice method.
type WeightedEdgeSlicer interface {
	// EdgeSlice returns the set of edges remaining
	// to be iterated by an Edges iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	WeightedEdgeSlice() []WeightedEdge
}

// WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the
// WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges
// to WeightedEdgesOf.
func WeightedEdgesOf(it WeightedEdges) []WeightedEdge {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case WeightedEdgeSlicer:
		return it.WeightedEdgeSlice()
	}
	edges := make([]WeightedEdge, 0, n)
	for it.Next() {
		edges = append(edges, it.WeightedEdge())
	}
	if len(edges) == 0 {
		return nil
	}
	return edges
}

// Lines is a Line iterator.
type Lines interface {
	Iterator

	// Line returns the current Line from the iterator.
	Line() Line
}

// LineSlicer wraps the LineSlice method.
type LineSlicer interface {
	// LineSlice returns the set of lines remaining
	// to be iterated by an Lines iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	LineSlice() []Line
}

// LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used
// to obtain the lines. It is safe to pass a nil Lines to LinesOf.
func LinesOf(it Lines) []Line {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case LineSlicer:
		return it.LineSlice()
	}
	lines := make([]Line, 0, n)
	for it.Next() {
		lines = append(lines, it.Line())
	}
	if len(lines) == 0 {
		return nil
	}
	return lines
}

// WeightedLines is a WeightedLine iterator.
type WeightedLines interface {
	Iterator

	// Line returns the current Line from the iterator.
	WeightedLine() WeightedLine
}

// WeightedLineSlicer wraps the WeightedLineSlice method.
type WeightedLineSlicer interface {
	// LineSlice returns the set of lines remaining
	// to be iterated by an Lines iterator.
	// The holder of the iterator may arbitrarily
	// change elements in the returned slice, but
	// those changes may be reflected to other
	// iterators.
	WeightedLineSlice() []WeightedLine
}

// WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the
// WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines
// to WeightedLinesOf.
func WeightedLinesOf(it WeightedLines) []WeightedLine {
	if it == nil {
		return nil
	}
	n := it.Len()
	switch {
	case n == 0:
		return nil
	case n < 0:
		n = 0
	}
	switch it := it.(type) {
	case WeightedLineSlicer:
		return it.WeightedLineSlice()
	}
	lines := make([]WeightedLine, 0, n)
	for it.Next() {
		lines = append(lines, it.WeightedLine())
	}
	if len(lines) == 0 {
		return nil
	}
	return lines
}

// Empty is an empty set of nodes, edges or lines. It should be used when
// a graph returns a zero-length Iterator. Empty implements the slicer
// interfaces for nodes, edges and lines, returning nil for each of these.
const Empty = nothing

var (
	_ Iterator           = Empty
	_ Nodes              = Empty
	_ NodeSlicer         = Empty
	_ Edges              = Empty
	_ EdgeSlicer         = Empty
	_ WeightedEdges      = Empty
	_ WeightedEdgeSlicer = Empty
	_ Lines              = Empty
	_ LineSlicer         = Empty
	_ WeightedLines      = Empty
	_ WeightedLineSlicer = Empty
)

const nothing = empty(0)

type empty int

func (empty) Next() bool                        { return false }
func (empty) Len() int                          { return 0 }
func (empty) Reset()                            {}
func (empty) Node() Node                        { return nil }
func (empty) NodeSlice() []Node                 { return nil }
func (empty) Edge() Edge                        { return nil }
func (empty) EdgeSlice() []Edge                 { return nil }
func (empty) WeightedEdge() WeightedEdge        { return nil }
func (empty) WeightedEdgeSlice() []WeightedEdge { return nil }
func (empty) Line() Line                        { return nil }
func (empty) LineSlice() []Line                 { return nil }
func (empty) WeightedLine() WeightedLine        { return nil }
func (empty) WeightedLineSlice() []WeightedLine { return nil }

func (empty) String() string   { return "<empty>" }
func (empty) GoString() string { return "graph.Empty" }
<|endoftext|>


<commit_before>package host

import (
	"sync/atomic"
	"testing"
	"time"
)

// blockingPortForward is a dependency set that causes the host port forward
// call at startup to block for 10 seconds, simulating the amount of blocking
// that can occur in production.
//
// blockingPortForward will also cause managedClearPort to always return an
// error.
type blockingPortForward struct {
	productionDependencies
}

// disrupt will cause the port forward call to block for 10 seconds, but still
// complete normally. disrupt will also cause managedClearPort to return an
// error.
func (blockingPortForward) disrupt(s string) bool {
	// Return an error when clearing the port.
	if s == "managedClearPort return error" {
		return true
	}

	// Block during port forwarding.
	if s == "managedForwardPort" {
		time.Sleep(time.Second * 3)
	}
	return false
}

// TestPortFowardBlocking checks that the host does not accidentally call a
// write on a closed logger due to a long-running port forward call.
func TestPortForwardBlocking(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	ht, err := newMockHostTester(blockingPortForward{}, "TestPortForwardBlocking")
	if err != nil {
		t.Fatal(err)
	}

	// The close operation would previously fail here because of improper
	// thread control regarding upnp and shutdown.
	err = ht.Close()
	if err != nil {
		t.Fatal(err)
	}

	// The trailing sleep is needed to catch the previously existing error
	// where the host was not shutting down correctly. Currently, the extra
	// sleep does nothing, but in the regression a logging panic would occur.
	time.Sleep(time.Second * 4)
}

// TestHostWorkingState checks that the host properly updates its working
// state
func TestHostWorkingState(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()

	workingStateFrequency = 5 * time.Second

	ht, err := newHostTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}

	if ht.host.WorkingState() != WorkingStateChecking {
		t.Fatal("expected working state to initially be WorkingStateChecking")
	}

	atomic.StoreUint64(&ht.host.atomicSettingsCalls, workingStateThreshold+1)

	time.Sleep(workingStateFrequency)
	time.Sleep(time.Second)

	if ht.host.WorkingState() != WorkingStateWorking {
		t.Fatal("expected host working status to be WorkingStateWorking after incrementing status calls")
	}

	time.Sleep(workingStateFrequency)
	time.Sleep(time.Second)

	if ht.host.WorkingState() != WorkingStateNotWorking {
		t.Fatal("expected host working status to be WorkingStateNotWorking after waiting workingStateFrequency with no settings calls")
	}
}

// TestHostConnectabilityState checks that the host properly updates its connectable
// state
func TestHostConnectabilityState(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()

	connectabilityCheckFrequency = 5 * time.Second

	ht, err := newHostTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}

	if ht.host.ConnectabilityState() != ConnectabilityStateChecking {
		t.Fatal("expected connectability state to initially be ConnectablityStateChecking")
	}

	time.Sleep(connectabilityCheckFrequency)
	time.Sleep(time.Second)

	if ht.host.ConnectabilityState() != ConnectabilityStateConnectable {
		t.Fatal("expected connectability state to be ConnectabilityStateConnectable")
	}
}
<commit_msg>fix race caused by changing Frequency after t.Parallel<commit_after>package host

import (
	"sync/atomic"
	"testing"
	"time"
)

// blockingPortForward is a dependency set that causes the host port forward
// call at startup to block for 10 seconds, simulating the amount of blocking
// that can occur in production.
//
// blockingPortForward will also cause managedClearPort to always return an
// error.
type blockingPortForward struct {
	productionDependencies
}

// disrupt will cause the port forward call to block for 10 seconds, but still
// complete normally. disrupt will also cause managedClearPort to return an
// error.
func (blockingPortForward) disrupt(s string) bool {
	// Return an error when clearing the port.
	if s == "managedClearPort return error" {
		return true
	}

	// Block during port forwarding.
	if s == "managedForwardPort" {
		time.Sleep(time.Second * 3)
	}
	return false
}

// TestPortFowardBlocking checks that the host does not accidentally call a
// write on a closed logger due to a long-running port forward call.
func TestPortForwardBlocking(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	t.Parallel()
	ht, err := newMockHostTester(blockingPortForward{}, "TestPortForwardBlocking")
	if err != nil {
		t.Fatal(err)
	}

	// The close operation would previously fail here because of improper
	// thread control regarding upnp and shutdown.
	err = ht.Close()
	if err != nil {
		t.Fatal(err)
	}

	// The trailing sleep is needed to catch the previously existing error
	// where the host was not shutting down correctly. Currently, the extra
	// sleep does nothing, but in the regression a logging panic would occur.
	time.Sleep(time.Second * 4)
}

// TestHostWorkingState checks that the host properly updates its working
// state
func TestHostWorkingState(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	workingStateFrequency = 5 * time.Second

	t.Parallel()

	ht, err := newHostTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}

	if ht.host.WorkingState() != WorkingStateChecking {
		t.Fatal("expected working state to initially be WorkingStateChecking")
	}

	atomic.StoreUint64(&ht.host.atomicSettingsCalls, workingStateThreshold+1)

	time.Sleep(workingStateFrequency)
	time.Sleep(time.Second)

	if ht.host.WorkingState() != WorkingStateWorking {
		t.Fatal("expected host working status to be WorkingStateWorking after incrementing status calls")
	}

	time.Sleep(workingStateFrequency)
	time.Sleep(time.Second)

	if ht.host.WorkingState() != WorkingStateNotWorking {
		t.Fatal("expected host working status to be WorkingStateNotWorking after waiting workingStateFrequency with no settings calls")
	}
}

// TestHostConnectabilityState checks that the host properly updates its connectable
// state
func TestHostConnectabilityState(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	connectabilityCheckFrequency = 5 * time.Second

	t.Parallel()

	ht, err := newHostTester(t.Name())
	if err != nil {
		t.Fatal(err)
	}

	if ht.host.ConnectabilityState() != ConnectabilityStateChecking {
		t.Fatal("expected connectability state to initially be ConnectablityStateChecking")
	}

	time.Sleep(connectabilityCheckFrequency)
	time.Sleep(time.Second)

	if ht.host.ConnectabilityState() != ConnectabilityStateConnectable {
		t.Fatal("expected connectability state to be ConnectabilityStateConnectable")
	}
}
<|endoftext|>


<commit_before>/*
ProxyCache - universal cache filling algorithm

Basic idea is as follows: instead of trying to making cache lookups and determining if you
should perform some expensive calculation, you pass calculation fetcher as a delegate into
ProxyCache which will figure out caching state by itself and use fetcher if necessary.

Algorithm considers various parameters that might affect caching behavior:
*/
package pcache

import (
	"errors"
	"fmt"
	"reflect"
	"time"
)

// Storage backend is assumed to implement some kind of cache replacement algorithm
type Store interface {
	Get(string, interface{}) (bool, *time.Time, *time.Time) // (key, target) -> (retrieved, creation_time, last_fetch_time)
	Set(string, interface{}, time.Duration) error           // (key, item, expire) -> error
}

type Locker interface {
	IsLocked(string) bool
	AcquireLock(string, time.Duration) Lock // (key, timeout) -> Lock
	WaitForRelease(string) bool             // key -> was_released
}

type Lock interface {
	Release()
}

func PCacheCall(
	store Store,
	locker Locker,

	key string,
	target interface{},

	fetcher func() (interface{}, error),
	validator func(interface{}) bool,

	expire time.Duration,
	ttl time.Duration,
	throttle time.Duration,
	timeout time.Duration,
) error {
	var getAfterRelease = func() bool {
		done_ch := make(chan bool, 1)
		go func() {
			done_ch <- locker.WaitForRelease(key)
		}()
		select {
		case <-time.After(timeout):
			return false
		case ok := <-done_ch:
			if ok {
				retrieved, _, _ := store.Get(key, target)
				return retrieved // TODO: optimize
			}
			return false
		}
	}
	var fetchAndSet = func() chan interface{} {
		ch := make(chan interface{}, 1)
		go func() {
			lock := locker.AcquireLock(key, timeout)
			if lock == nil {
				ch <- getAfterRelease()
				return
			}
			defer lock.Release()
			item, _ := fetcher()
			if validator(item) == true {
				ch <- item
				store.Set(key, item, expire)
			} else {
				ch <- nil
			}
		}()
		return ch
	}

	retrieved, creationTime, lastFetchTime := store.Get(key, target)

	switch {

	case retrieved:
		fmt.Printf("validator: %+v", validator)
		var invalid = false
		if validator != nil {
			invalid = validator(target) == false
		}
		if creationTime != nil || invalid {
			var now = time.Now()
			var age = now.Sub(*creationTime)
			var sinceLastFetch = now.Sub(*lastFetchTime)
			if age > ttl || invalid {
				if sinceLastFetch > throttle {
					go func() {
						<-fetchAndSet()
					}()
				}
			}
		}
		if invalid {
			return errors.New("invalid item retrieved")
		}
		return nil

	case locker.IsLocked(key):
		if getAfterRelease() {
			return nil
		} else {
			return errors.New("getAfterRelease not ok")
		}

	default:
		if lastFetchTime != nil {
			var sinceLastFetch = time.Now().Sub(*lastFetchTime)
			if sinceLastFetch < throttle {
				return errors.New("refresh throttled while item is nil")
			}
		}
		select {
		case result := <-fetchAndSet():
			if result == nil {
				return errors.New("invalid item fetched")
			}
			return setToValue(target, result)
		case <-time.After(timeout):
			return errors.New("timeout")
		}

	}
}

func setToValue(target, value interface{}) error {
	var tgt, val reflect.Value
	tgt = reflect.Indirect(reflect.ValueOf(target))
	val = reflect.ValueOf(value)
	if val.Type() == tgt.Type() {
		tgt.Set(val)
	} else {
		val = reflect.Indirect(val)
		if val.Type() == tgt.Type() {
			tgt.Set(val)
		}
	}
	return nil
}
<commit_msg>doc update<commit_after>/*
ProxyCache - universal cache filling algorithm

Basic idea is as follows: instead of trying to making cache lookups and determining if you
should perform some expensive calculation, you pass calculation fetcher as a delegate into
ProxyCache which will figure out caching state by itself and use fetcher if necessary.

Parameters

Algorithm considers various parameters that might affect caching behavior: item expiration,
ttl (specified per-request), request timeout, throttle time between fetcher calls, results
of validation (preformed by validator func).
*/
package pcache

import (
	"errors"
	"fmt"
	"reflect"
	"time"
)

// Storage backend is assumed to implement some kind of cache replacement algorithm
type Store interface {
	Get(string, interface{}) (bool, *time.Time, *time.Time) // (key, target) -> (retrieved, creation_time, last_fetch_time)
	Set(string, interface{}, time.Duration) error           // (key, item, expire) -> error
}

type Locker interface {
	IsLocked(string) bool
	AcquireLock(string, time.Duration) Lock // (key, timeout) -> Lock
	WaitForRelease(string) bool             // key -> was_released
}

type Lock interface {
	Release()
}

func PCacheCall(
	store Store,
	locker Locker,

	key string,
	target interface{},

	fetcher func() (interface{}, error),
	validator func(interface{}) bool,

	expire time.Duration,
	ttl time.Duration,
	throttle time.Duration,
	timeout time.Duration,
) error {
	var getAfterRelease = func() bool {
		done_ch := make(chan bool, 1)
		go func() {
			done_ch <- locker.WaitForRelease(key)
		}()
		select {
		case <-time.After(timeout):
			return false
		case ok := <-done_ch:
			if ok {
				retrieved, _, _ := store.Get(key, target)
				return retrieved // TODO: optimize
			}
			return false
		}
	}
	var fetchAndSet = func() chan interface{} {
		ch := make(chan interface{}, 1)
		go func() {
			lock := locker.AcquireLock(key, timeout)
			if lock == nil {
				ch <- getAfterRelease()
				return
			}
			defer lock.Release()
			item, _ := fetcher()
			if validator(item) == true {
				ch <- item
				store.Set(key, item, expire)
			} else {
				ch <- nil
			}
		}()
		return ch
	}

	retrieved, creationTime, lastFetchTime := store.Get(key, target)

	switch {

	case retrieved:
		fmt.Printf("validator: %+v", validator)
		var invalid = false
		if validator != nil {
			invalid = validator(target) == false
		}
		if creationTime != nil || invalid {
			var now = time.Now()
			var age = now.Sub(*creationTime)
			var sinceLastFetch = now.Sub(*lastFetchTime)
			if age > ttl || invalid {
				if sinceLastFetch > throttle {
					go func() {
						<-fetchAndSet()
					}()
				}
			}
		}
		if invalid {
			return errors.New("invalid item retrieved")
		}
		return nil

	case locker.IsLocked(key):
		if getAfterRelease() {
			return nil
		} else {
			return errors.New("getAfterRelease not ok")
		}

	default:
		if lastFetchTime != nil {
			var sinceLastFetch = time.Now().Sub(*lastFetchTime)
			if sinceLastFetch < throttle {
				return errors.New("refresh throttled while item is nil")
			}
		}
		select {
		case result := <-fetchAndSet():
			if result == nil {
				return errors.New("invalid item fetched")
			}
			return setToValue(target, result)
		case <-time.After(timeout):
			return errors.New("timeout")
		}

	}
}

func setToValue(target, value interface{}) error {
	var tgt, val reflect.Value
	tgt = reflect.Indirect(reflect.ValueOf(target))
	val = reflect.ValueOf(value)
	if val.Type() == tgt.Type() {
		tgt.Set(val)
	} else {
		val = reflect.Indirect(val)
		if val.Type() == tgt.Type() {
			tgt.Set(val)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package kubectl

import "os/exec"

type Kubectl struct {
	bin string
	args []string
}

func New(b string, a []string) *Kubectl {
	return &Kubectl{bin: b, args: a}
}

func (k *Kubectl) Exec() (string, error) {
	c := exec.Command(k.bin, k.args...)
	o, err := c.Output()
	return string(o), err
}

func WhereIs() (k string, err error) {
	k, err = exec.LookPath("kubectl")
	return
}
<commit_msg>Some house cleaning. Make the code more idiomatic.<commit_after>package kubectl

import "os/exec"

type Kubectl struct {
	bin  string
	args []string
}

func NewKubectl(bin string, args []string) (kubectl *Kubectl, err error) {
	if bin == "default" {
		bin, err = WhereIs()
	}
	kubectl = &Kubectl{bin: bin, args: args}
	return
}

func WhereIs() (kubectlBinPath string, err error) {
	kubectlBinPath, err = exec.LookPath("kubectl")
	return
}

func (k *Kubectl) Exec() (string, error) {
	command := exec.Command(k.bin, k.args...)
	commandOutput, err := command.Output()
	return string(commandOutput), err
}
<|endoftext|>


<commit_before>package check

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs       = []string{"Godeps", "vendor", "third_party", "testdata"}
	skipSuffixes   = []string{".pb.go", ".pb.gw.go", ".generated.go", "bindata.go", "_string.go"}
	skipFirstLines = []string{"code generated", "generated", "autogenerated", "@generated", "code autogenerated", "auto-generated"}
)

func addSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) (filenames, skipped []string, err error) {
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, fmt.Sprintf("/%s/", skip)) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				skipped = append(skipped, fp)
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext != ".go" {
			return nil
		}

		if autoGenerated(fp) {
			skipped = append(skipped, fp)
			return nil
		}

		filenames = append(filenames, fp)

		return nil
	}

	err = filepath.Walk(dir, visit)

	return filenames, skipped, err
}

// RenameFiles renames the provided filenames to have a ".grc.bk" extension,
// so they will not be considered in future checks.
func RenameFiles(names []string) (err error) {
	for i := range names {
		tmpErr := os.Rename(names[i], names[i]+".grc.bk")
		if tmpErr != nil {
			// save this error, but still continue with other files
			err = tmpErr
		}
	}

	return err
}

// RevertFiles removes the ".grc.bk" extension from files
func RevertFiles(names []string) (err error) {
	for i := range names {
		tmpErr := os.Rename(names[i]+".grc.bk", names[i])
		if tmpErr != nil {
			// save this error, but still continue with other files
			err = tmpErr
		}
	}

	return err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}

	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, fmt.Errorf("could not count lines: %v", err)
	}

	return count, nil
}

// determine whether the Go file was auto-generated
func autoGenerated(fp string) bool {
	file, err := os.Open(fp)
	if err != nil {
		fmt.Println(err)
		return false
	}
	defer file.Close()

	// read first line of file and determine if it might
	// be auto-generated
	scanner := bufio.NewScanner(file)
	scanner.Scan()
	line := strings.ToLower(scanner.Text())
	commentStyles := []string{"// ", "//", "/* ", "/*"}
	for _, skip := range skipFirstLines {
		for i := range commentStyles {
			if strings.HasPrefix(line, commentStyles[i]) && strings.HasPrefix(line[len(commentStyles[i]):], skip) {
				return true
			}
		}
	}
	return false
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// AddError adds an Error to FileSummary
func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return fmt.Errorf("AddError: could not parse %q - %v", out, err)
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

func displayFilename(filename string) string {
	sp := strings.Split(filename, "@")
	if len(sp) < 2 {
		return filename
	}

	fsp := strings.Split(sp[1], "/")

	return filepath.Join(fsp[1:]...)
}

// borrowed from github.com/client9/gosupplychain
// MIT LICENSE: https://github.com/client9/gosupplychain/blob/master/LICENSE
func goPkgInToGitHub(name string) string {
	dir := ""
	var pkgversion string
	var user string
	parts := strings.Split(name, "/")
	if len(parts) < 2 {
		return ""
	}
	if parts[0] != "gopkg.in" {
		return ""
	}

	idx := strings.Index(parts[1], ".")
	if idx != -1 {
		pkgversion = parts[1]
		if len(parts) > 2 {
			dir = "/" + strings.Join(parts[2:], "/")
		}
	} else {
		user = parts[1]
		pkgversion = parts[2]
		if len(parts) > 3 {
			dir = "/" + strings.Join(parts[3:], "/")
		}
	}
	idx = strings.Index(pkgversion, ".")
	if idx == -1 {
		return ""
	}
	pkg := pkgversion[:idx]
	if user == "" {
		user = "go-" + pkg
	}
	version := pkgversion[idx+1:]
	if version == "v0" {
		version = "master"
	}

	return "https://github.com/" + user + "/" + pkg + "/blob/" + version + dir
}

func fileURL(filename string) string {
	f := displayFilename(filename)

	fsp := strings.Split(filename, "@")

	repo := strings.TrimPrefix(fsp[0], "/")

	var ver string
	if len(fsp) > 1 {
		verSp := strings.Split(fsp[1], "/")
		ver = verSp[0]
	}

	var fileURL string
	base := strings.TrimPrefix(repo, "_repos/src/")
	switch {
	case strings.HasPrefix(base, "golang.org/x/"):
		var pkg string
		if len(strings.Split(base, "/")) >= 3 {
			pkg = strings.Split(base, "/")[2]
		}

		return fmt.Sprintf("https://github.com/golang/%s/blob/master%s", pkg, strings.TrimPrefix(filename, "/"+base))
	case strings.HasPrefix(base, "github.com/"):
		if len(strings.Split(base, "/")) == 4 {
			base = strings.Join(strings.Split(base, "/")[0:3], "/")
		}

		if ver != "" {
			if strings.Contains(ver, "-") {
				verSp := strings.Split(ver, "-")
				if len(verSp) > 2 {
					ver = strings.Split(ver, "-")[2]
				}
			}

			if strings.Contains(ver, "+incompatible") {
				ver = strings.TrimSuffix(ver, "+incompatible")
			}

			return fmt.Sprintf("https://%s/blob/%s/%s", base, ver, f)
		}

		return fmt.Sprintf("https://%s/blob/master%s", base, strings.TrimPrefix(filename, "/"+base))
	case strings.HasPrefix(base, "gopkg.in/"):
		return goPkgInToGitHub(base) + strings.TrimPrefix(filename, "/"+base)
	}

	return fileURL
}

func makeFilename(fn string) string {
	sp := strings.Split(fn, "/")
	switch {
	case strings.HasPrefix(fn, "/github.com"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	case strings.HasPrefix(fn, "/golang.org/x"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	case strings.HasPrefix(fn, "/gopkg.in"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	}

	return fn
}

func getFileSummaryMap(out *bufio.Scanner, dir string) (map[string]FileSummary, error) {
	fsMap := make(map[string]FileSummary)
outer:
	for out.Scan() {
		filename := strings.Split(out.Text(), ":")[0]
		if !strings.Contains(filename, dir) {
			filename = filepath.Join(dir, filename)
		}

		for _, skip := range skipSuffixes {
			if strings.HasSuffix(filename, skip) {
				continue outer
			}
		}

		if autoGenerated(filename) {
			continue outer
		}

		filename = strings.TrimPrefix(filename, "_repos/src")
		dfn := displayFilename(filename)
		fu := fileURL(filename)
		fs := fsMap[dfn]
		if fs.Filename == "" {
			// fs.Filename = makeFilename(filename)
			fs.Filename = dfn
			fs.FileURL = fu
		}
		err := fs.AddError(out.Text())
		if err != nil {
			return nil, err
		}
		fsMap[dfn] = fs
	}

	return fsMap, nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	enabledCheck := command[len(command)-1]

	// temporary disabling of misspell as it's the slowest
	// command right now
	if strings.Contains(enabledCheck, "misspell") && len(filenames) > 300 {
		log.Println("disabling misspell on large repo...")
		return 1, []FileSummary{}, nil
	}

	if strings.Contains(enabledCheck, "ineffassign") && len(filenames) > 100 {
		log.Println("disabling ineffassign on large repo...")
		return 1, []FileSummary{}, nil
	}

	params := command[1:]
	params = addSkipDirs(params)

	switch {
	case strings.Contains(enabledCheck, "cyclo"):
		params = append(params, dir)
	case strings.Contains(enabledCheck, "staticcheck"):
		params[len(params)-1] = "./..."
	default:
		params = append(params, dir+"/...")
	}

	if strings.Contains(enabledCheck, "staticcheck") {
		params[len(params)-1] = "./..."
	}

	cmd := exec.Command(command[0], params...)

	if strings.Contains(enabledCheck, "staticcheck") {
		cmd.Dir = dir
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	// the same file can appear multiple times out of order
	// in the output, so we can't go line by line, have to store
	// a map of filename to FileSummary
	var failed = []FileSummary{}

	fsMap, err := getFileSummaryMap(out, dir)
	if err != nil {
		return 0, []FileSummary{}, err
	}

	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	for _, v := range fsMap {
		failed = append(failed, v)
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<commit_msg>remove redundant if statement<commit_after>package check

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
)

var (
	skipDirs       = []string{"Godeps", "vendor", "third_party", "testdata"}
	skipSuffixes   = []string{".pb.go", ".pb.gw.go", ".generated.go", "bindata.go", "_string.go"}
	skipFirstLines = []string{"code generated", "generated", "autogenerated", "@generated", "code autogenerated", "auto-generated"}
)

func addSkipDirs(params []string) []string {
	for _, dir := range skipDirs {
		params = append(params, fmt.Sprintf("--skip=%s", dir))
	}
	return params
}

// GoFiles returns a slice of Go filenames
// in a given directory.
func GoFiles(dir string) (filenames, skipped []string, err error) {
	visit := func(fp string, fi os.FileInfo, err error) error {
		for _, skip := range skipDirs {
			if strings.Contains(fp, fmt.Sprintf("/%s/", skip)) {
				return nil
			}
		}
		if err != nil {
			fmt.Println(err) // can't walk here,
			return nil       // but continue walking elsewhere
		}
		if fi.IsDir() {
			return nil // not a file.  ignore.
		}
		fiName := fi.Name()
		for _, skip := range skipSuffixes {
			if strings.HasSuffix(fiName, skip) {
				skipped = append(skipped, fp)
				return nil
			}
		}
		ext := filepath.Ext(fiName)
		if ext != ".go" {
			return nil
		}

		if autoGenerated(fp) {
			skipped = append(skipped, fp)
			return nil
		}

		filenames = append(filenames, fp)

		return nil
	}

	err = filepath.Walk(dir, visit)

	return filenames, skipped, err
}

// RenameFiles renames the provided filenames to have a ".grc.bk" extension,
// so they will not be considered in future checks.
func RenameFiles(names []string) (err error) {
	for i := range names {
		tmpErr := os.Rename(names[i], names[i]+".grc.bk")
		if tmpErr != nil {
			// save this error, but still continue with other files
			err = tmpErr
		}
	}

	return err
}

// RevertFiles removes the ".grc.bk" extension from files
func RevertFiles(names []string) (err error) {
	for i := range names {
		tmpErr := os.Rename(names[i]+".grc.bk", names[i])
		if tmpErr != nil {
			// save this error, but still continue with other files
			err = tmpErr
		}
	}

	return err
}

// lineCount returns the number of lines in a given file
func lineCount(filepath string) (int, error) {
	out, err := exec.Command("wc", "-l", filepath).Output()
	if err != nil {
		return 0, err
	}

	// wc output is like: 999 filename.go
	count, err := strconv.Atoi(strings.Split(strings.TrimSpace(string(out)), " ")[0])
	if err != nil {
		return 0, fmt.Errorf("could not count lines: %v", err)
	}

	return count, nil
}

// determine whether the Go file was auto-generated
func autoGenerated(fp string) bool {
	file, err := os.Open(fp)
	if err != nil {
		fmt.Println(err)
		return false
	}
	defer file.Close()

	// read first line of file and determine if it might
	// be auto-generated
	scanner := bufio.NewScanner(file)
	scanner.Scan()
	line := strings.ToLower(scanner.Text())
	commentStyles := []string{"// ", "//", "/* ", "/*"}
	for _, skip := range skipFirstLines {
		for i := range commentStyles {
			if strings.HasPrefix(line, commentStyles[i]) && strings.HasPrefix(line[len(commentStyles[i]):], skip) {
				return true
			}
		}
	}
	return false
}

// Error contains the line number and the reason for
// an error output from a command
type Error struct {
	LineNumber  int    `json:"line_number"`
	ErrorString string `json:"error_string"`
}

// FileSummary contains the filename, location of the file
// on GitHub, and all of the errors related to the file
type FileSummary struct {
	Filename string  `json:"filename"`
	FileURL  string  `json:"file_url"`
	Errors   []Error `json:"errors"`
}

// AddError adds an Error to FileSummary
func (fs *FileSummary) AddError(out string) error {
	s := strings.SplitN(out, ":", 2)
	msg := strings.SplitAfterN(s[1], ":", 3)[2]

	e := Error{ErrorString: msg}
	ls := strings.Split(s[1], ":")
	ln, err := strconv.Atoi(ls[0])
	if err != nil {
		return fmt.Errorf("AddError: could not parse %q - %v", out, err)
	}
	e.LineNumber = ln

	fs.Errors = append(fs.Errors, e)

	return nil
}

func displayFilename(filename string) string {
	sp := strings.Split(filename, "@")
	if len(sp) < 2 {
		return filename
	}

	fsp := strings.Split(sp[1], "/")

	return filepath.Join(fsp[1:]...)
}

// borrowed from github.com/client9/gosupplychain
// MIT LICENSE: https://github.com/client9/gosupplychain/blob/master/LICENSE
func goPkgInToGitHub(name string) string {
	dir := ""
	var pkgversion string
	var user string
	parts := strings.Split(name, "/")
	if len(parts) < 2 {
		return ""
	}
	if parts[0] != "gopkg.in" {
		return ""
	}

	idx := strings.Index(parts[1], ".")
	if idx != -1 {
		pkgversion = parts[1]
		if len(parts) > 2 {
			dir = "/" + strings.Join(parts[2:], "/")
		}
	} else {
		user = parts[1]
		pkgversion = parts[2]
		if len(parts) > 3 {
			dir = "/" + strings.Join(parts[3:], "/")
		}
	}
	idx = strings.Index(pkgversion, ".")
	if idx == -1 {
		return ""
	}
	pkg := pkgversion[:idx]
	if user == "" {
		user = "go-" + pkg
	}
	version := pkgversion[idx+1:]
	if version == "v0" {
		version = "master"
	}

	return "https://github.com/" + user + "/" + pkg + "/blob/" + version + dir
}

func fileURL(filename string) string {
	f := displayFilename(filename)

	fsp := strings.Split(filename, "@")

	repo := strings.TrimPrefix(fsp[0], "/")

	var ver string
	if len(fsp) > 1 {
		verSp := strings.Split(fsp[1], "/")
		ver = verSp[0]
	}

	var fileURL string
	base := strings.TrimPrefix(repo, "_repos/src/")
	switch {
	case strings.HasPrefix(base, "golang.org/x/"):
		var pkg string
		if len(strings.Split(base, "/")) >= 3 {
			pkg = strings.Split(base, "/")[2]
		}

		return fmt.Sprintf("https://github.com/golang/%s/blob/master%s", pkg, strings.TrimPrefix(filename, "/"+base))
	case strings.HasPrefix(base, "github.com/"):
		if len(strings.Split(base, "/")) == 4 {
			base = strings.Join(strings.Split(base, "/")[0:3], "/")
		}

		if ver != "" {
			if strings.Contains(ver, "-") {
				verSp := strings.Split(ver, "-")
				if len(verSp) > 2 {
					ver = strings.Split(ver, "-")[2]
				}
			}

			if strings.Contains(ver, "+incompatible") {
				ver = strings.TrimSuffix(ver, "+incompatible")
			}

			return fmt.Sprintf("https://%s/blob/%s/%s", base, ver, f)
		}

		return fmt.Sprintf("https://%s/blob/master%s", base, strings.TrimPrefix(filename, "/"+base))
	case strings.HasPrefix(base, "gopkg.in/"):
		return goPkgInToGitHub(base) + strings.TrimPrefix(filename, "/"+base)
	}

	return fileURL
}

func makeFilename(fn string) string {
	sp := strings.Split(fn, "/")
	switch {
	case strings.HasPrefix(fn, "/github.com"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	case strings.HasPrefix(fn, "/golang.org/x"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	case strings.HasPrefix(fn, "/gopkg.in"):
		if len(sp) > 3 {
			return strings.Join(sp[3:], "/")
		}
	}

	return fn
}

func getFileSummaryMap(out *bufio.Scanner, dir string) (map[string]FileSummary, error) {
	fsMap := make(map[string]FileSummary)
outer:
	for out.Scan() {
		filename := strings.Split(out.Text(), ":")[0]
		if !strings.Contains(filename, dir) {
			filename = filepath.Join(dir, filename)
		}

		for _, skip := range skipSuffixes {
			if strings.HasSuffix(filename, skip) {
				continue outer
			}
		}

		if autoGenerated(filename) {
			continue outer
		}

		filename = strings.TrimPrefix(filename, "_repos/src")
		dfn := displayFilename(filename)
		fu := fileURL(filename)
		fs := fsMap[dfn]
		if fs.Filename == "" {
			// fs.Filename = makeFilename(filename)
			fs.Filename = dfn
			fs.FileURL = fu
		}
		err := fs.AddError(out.Text())
		if err != nil {
			return nil, err
		}
		fsMap[dfn] = fs
	}

	return fsMap, nil
}

// GoTool runs a given go command (for example gofmt, go tool vet)
// on a directory
func GoTool(dir string, filenames, command []string) (float64, []FileSummary, error) {
	enabledCheck := command[len(command)-1]

	// temporary disabling of misspell as it's the slowest
	// command right now
	if strings.Contains(enabledCheck, "misspell") && len(filenames) > 300 {
		log.Println("disabling misspell on large repo...")
		return 1, []FileSummary{}, nil
	}

	if strings.Contains(enabledCheck, "ineffassign") && len(filenames) > 100 {
		log.Println("disabling ineffassign on large repo...")
		return 1, []FileSummary{}, nil
	}

	params := command[1:]
	params = addSkipDirs(params)

	switch {
	case strings.Contains(enabledCheck, "cyclo"):
		params = append(params, dir)
	case strings.Contains(enabledCheck, "staticcheck"):
		params[len(params)-1] = "./..."
	default:
		params = append(params, dir+"/...")
	}

	cmd := exec.Command(command[0], params...)

	if strings.Contains(enabledCheck, "staticcheck") {
		cmd.Dir = dir
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	err = cmd.Start()
	if err != nil {
		return 0, []FileSummary{}, err
	}

	out := bufio.NewScanner(stdout)

	// the same file can appear multiple times out of order
	// in the output, so we can't go line by line, have to store
	// a map of filename to FileSummary
	var failed = []FileSummary{}

	fsMap, err := getFileSummaryMap(out, dir)
	if err != nil {
		return 0, []FileSummary{}, err
	}

	if err := out.Err(); err != nil {
		return 0, []FileSummary{}, err
	}

	for _, v := range fsMap {
		failed = append(failed, v)
	}

	err = cmd.Wait()
	if exitErr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0

		if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
			// some commands exit 1 when files fail to pass (for example go vet)
			if status.ExitStatus() != 1 {
				return 0, failed, err
				// return 0, Error{}, err
			}
		}
	}

	if len(filenames) == 1 {
		lc, err := lineCount(filenames[0])
		if err != nil {
			return 0, failed, err
		}

		var errors int
		if len(failed) != 0 {
			errors = len(failed[0].Errors)
		}

		return float64(lc-errors) / float64(lc), failed, nil
	}

	return float64(len(filenames)-len(failed)) / float64(len(filenames)), failed, nil
}
<|endoftext|>