<commit_before>package authboss

import (
	"html/template"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"golang.org/x/crypto/bcrypt"
)

// Cfg is the singleton instance of Config
var Cfg = NewConfig()

// Config holds all the configuration for both authboss and it's modules.
type Config struct {
	// MountPath is the path to mount authboss's routes at (eg /auth).
	MountPath string
	// ViewsPath is the path to search for overridden templates.
	ViewsPath string
	// RootURL is the scheme+host+port of the web application (eg https://www.happiness.com:8080) for url generation.  No trailing slash.
	RootURL string
	// BCryptCost is the cost of the bcrypt password hashing function.
	BCryptCost int

	// PrimaryID is the primary identifier of the user. Set to one of:
	// authboss.StoreEmail, authboss.StoreUsername (StoreEmail is default)
	PrimaryID string

	// Layout that all authboss views will be inserted into.
	Layout *template.Template
	// LayoutHTMLEmail is for emails going out in HTML form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutHTMLEmail *template.Template
	// LayoutTextEmail is for emails going out in text form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutTextEmail *template.Template
	// LayoutDataMaker is a function that can provide authboss with the layout's
	// template data. It will be merged with the data being provided for the current
	// view in order to render the templates.
	LayoutDataMaker ViewDataMaker

	// OAuth2Providers lists all providers that can be used. See
	// OAuthProvider documentation for more details.
	OAuth2Providers map[string]OAuth2Provider

	// ErrorHandler handles would be 500 errors.
	ErrorHandler http.Handler
	// BadRequestHandler handles would be 400 errors.
	BadRequestHandler http.Handler
	// NotFoundHandler handles would be 404 errors.
	NotFoundHandler http.Handler

	// AuthLoginOKPath is the redirect path after a successful authentication.
	AuthLoginOKPath string
	// AuthLoginFailPath is the redirect path after a failed authentication.
	AuthLoginFailPath string
	// AuthLogoutOKPath is the redirect path after a log out.
	AuthLogoutOKPath string

	// RecoverOKPath is the redirect path after a successful recovery of a password.
	RecoverOKPath string
	// RecoverTokenDuration controls how long a token sent via email for password
	// recovery is valid for.
	RecoverTokenDuration time.Duration

	// RegisterOKPath is the redirect path after a successful registration.
	RegisterOKPath string

	// Policies control validation of form fields and are automatically run
	// against form posts that include the fields.
	Policies []Validator
	// ConfirmFields are fields that are supposed to be submitted with confirmation
	// fields alongside them, passwords, emails etc.
	ConfirmFields []string

	// ExpireAfter controls the time an account is idle before being logged out
	// by the ExpireMiddleware.
	ExpireAfter time.Duration

	// LockAfter this many tries.
	LockAfter int
	// LockWindow is the waiting time before the number of attemps are reset.
	LockWindow time.Duration
	// LockDuration is how long an account is locked for.
	LockDuration time.Duration

	// EmailFrom is the email address authboss e-mails come from.
	EmailFrom string
	// EmailSubjectPrefix is used to add something to the front of the authboss
	// email subjects.
	EmailSubjectPrefix string

	// XSRFName is the name of the xsrf token to put in the hidden form fields.
	XSRFName string
	// XSRFMaker is a function that returns an xsrf token for the current non-POST request.
	XSRFMaker XSRF

	// Storer is the interface through which Authboss accesses the web apps database.
	Storer Storer
	// OAuth2Storer is a different kind of storer only meant for OAuth2.
	OAuth2Storer OAuth2Storer
	// CookieStoreMaker must be defined to provide an interface capapable of storing cookies
	// for the given response, and reading them from the request.
	CookieStoreMaker CookieStoreMaker
	// SessionStoreMaker must be defined to provide an interface capable of storing session-only
	// values for the given response, and reading them from the request.
	SessionStoreMaker SessionStoreMaker
	// LogWriter is written to when errors occur, as well as on startup to show which modules are loaded
	// and which routes they registered. By default writes to io.Discard.
	LogWriter io.Writer
	// Callbacks is an internal mechanism that can be used by implementers and will be set automatically.
	Callbacks *Callbacks
	// Mailer is the mailer being used to send e-mails out. Authboss defines two loggers for use
	// LogMailer and SMTPMailer, the default is a LogMailer to io.Discard.
	Mailer Mailer
}

// NewConfig creates a config full of healthy default values.
// Notable exceptions to default values are the Storers.
// This method is called automatically on startup and is set to authboss.Cfg
// so implementers need not call it. Primarily exported for testing.
func NewConfig() *Config {
	return &Config{
		MountPath:  "/",
		ViewsPath:  "./",
		RootURL:    "http://localhost:8080",
		BCryptCost: bcrypt.DefaultCost,

		PrimaryID: StoreEmail,

		Layout:          template.Must(template.New("").Parse(`<!DOCTYPE html><html><body>{{template "authboss" .}}</body></html>`)),
		LayoutHTMLEmail: template.Must(template.New("").Parse(`<!DOCTYPE html><html><body>{{template "authboss" .}}</body></html>`)),
		LayoutTextEmail: template.Must(template.New("").Parse(`{{template "authboss" .}}`)),

		AuthLoginOKPath:   "/",
		AuthLoginFailPath: "/",
		AuthLogoutOKPath:  "/",

		RecoverOKPath:        "/",
		RecoverTokenDuration: time.Duration(24) * time.Hour,

		RegisterOKPath: "/",

		Policies: []Validator{
			Rules{
				FieldName:       "username",
				Required:        true,
				MinLength:       2,
				MaxLength:       4,
				AllowWhitespace: false,
			},
			Rules{
				FieldName: "password",
				Required:  true,
				MinLength: 4,
				MaxLength: 8,

				AllowWhitespace: false,
			},
		},
		ConfirmFields: []string{
			StorePassword, ConfirmPrefix + StorePassword,
		},

		ExpireAfter: 60 * time.Minute,

		LockAfter:    3,
		LockWindow:   5 * time.Minute,
		LockDuration: 5 * time.Hour,

		LogWriter: ioutil.Discard,
		Callbacks: NewCallbacks(),
		Mailer:    LogMailer(ioutil.Discard),
	}
}
<commit_msg>Added ResponseTmpl field to config, so that I can use this to render templates that are already loaded<commit_after>package authboss

import (
	"html/template"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"golang.org/x/crypto/bcrypt"
)

// Cfg is the singleton instance of Config
var Cfg = NewConfig()

// Config holds all the configuration for both authboss and it's modules.
type Config struct {
	// MountPath is the path to mount authboss's routes at (eg /auth).
	MountPath string
	// ViewsPath is the path to search for overridden templates.
	ViewsPath string
	// RootURL is the scheme+host+port of the web application (eg https://www.happiness.com:8080) for url generation.  No trailing slash.
	RootURL string
	// BCryptCost is the cost of the bcrypt password hashing function.
	BCryptCost int

	// PrimaryID is the primary identifier of the user. Set to one of:
	// authboss.StoreEmail, authboss.StoreUsername (StoreEmail is default)
	PrimaryID string

	// Layout that all authboss views will be inserted into.
	Layout *template.Template
	// LayoutHTMLEmail is for emails going out in HTML form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutHTMLEmail *template.Template
	// LayoutTextEmail is for emails going out in text form, authbosses e-mail templates
	// will be inserted into this layout.
	LayoutTextEmail *template.Template
	// LayoutDataMaker is a function that can provide authboss with the layout's
	// template data. It will be merged with the data being provided for the current
	// view in order to render the templates.
	LayoutDataMaker ViewDataMaker

	// OAuth2Providers lists all providers that can be used. See
	// OAuthProvider documentation for more details.
	OAuth2Providers map[string]OAuth2Provider

	// ErrorHandler handles would be 500 errors.
	ErrorHandler http.Handler
	// BadRequestHandler handles would be 400 errors.
	BadRequestHandler http.Handler
	// NotFoundHandler handles would be 404 errors.
	NotFoundHandler http.Handler

	// AuthLoginOKPath is the redirect path after a successful authentication.
	AuthLoginOKPath string
	// AuthLoginFailPath is the redirect path after a failed authentication.
	AuthLoginFailPath string
	// AuthLogoutOKPath is the redirect path after a log out.
	AuthLogoutOKPath string

	// RecoverOKPath is the redirect path after a successful recovery of a password.
	RecoverOKPath string
	// RecoverTokenDuration controls how long a token sent via email for password
	// recovery is valid for.
	RecoverTokenDuration time.Duration

	// RegisterOKPath is the redirect path after a successful registration.
	RegisterOKPath string

	// Policies control validation of form fields and are automatically run
	// against form posts that include the fields.
	Policies []Validator
	// ConfirmFields are fields that are supposed to be submitted with confirmation
	// fields alongside them, passwords, emails etc.
	ConfirmFields []string

	// ExpireAfter controls the time an account is idle before being logged out
	// by the ExpireMiddleware.
	ExpireAfter time.Duration

	// LockAfter this many tries.
	LockAfter int
	// LockWindow is the waiting time before the number of attemps are reset.
	LockWindow time.Duration
	// LockDuration is how long an account is locked for.
	LockDuration time.Duration

	// EmailFrom is the email address authboss e-mails come from.
	EmailFrom string
	// EmailSubjectPrefix is used to add something to the front of the authboss
	// email subjects.
	EmailSubjectPrefix string

	// XSRFName is the name of the xsrf token to put in the hidden form fields.
	XSRFName string
	// XSRFMaker is a function that returns an xsrf token for the current non-POST request.
	XSRFMaker XSRF

	// Storer is the interface through which Authboss accesses the web apps database.
	Storer Storer
	// OAuth2Storer is a different kind of storer only meant for OAuth2.
	OAuth2Storer OAuth2Storer
	// CookieStoreMaker must be defined to provide an interface capapable of storing cookies
	// for the given response, and reading them from the request.
	CookieStoreMaker CookieStoreMaker
	// SessionStoreMaker must be defined to provide an interface capable of storing session-only
	// values for the given response, and reading them from the request.
	SessionStoreMaker SessionStoreMaker
	// LogWriter is written to when errors occur, as well as on startup to show which modules are loaded
	// and which routes they registered. By default writes to io.Discard.
	LogWriter io.Writer
	// Callbacks is an internal mechanism that can be used by implementers and will be set automatically.
	Callbacks *Callbacks
	// Mailer is the mailer being used to send e-mails out. Authboss defines two loggers for use
	// LogMailer and SMTPMailer, the default is a LogMailer to io.Discard.
	Mailer Mailer

	// This is for use in my kesho app the templates for rendering auth
	ResponseTmpl  *template.Template
}

// NewConfig creates a config full of healthy default values.
// Notable exceptions to default values are the Storers.
// This method is called automatically on startup and is set to authboss.Cfg
// so implementers need not call it. Primarily exported for testing.
func NewConfig() *Config {
	return &Config{
		MountPath:  "/",
		ViewsPath:  "./",
		RootURL:    "http://localhost:8080",
		BCryptCost: bcrypt.DefaultCost,

		PrimaryID: StoreEmail,

		Layout:          template.Must(template.New("").Parse(`<!DOCTYPE html><html><body>{{template "authboss" .}}</body></html>`)),
		LayoutHTMLEmail: template.Must(template.New("").Parse(`<!DOCTYPE html><html><body>{{template "authboss" .}}</body></html>`)),
		LayoutTextEmail: template.Must(template.New("").Parse(`{{template "authboss" .}}`)),

		AuthLoginOKPath:   "/",
		AuthLoginFailPath: "/",
		AuthLogoutOKPath:  "/",

		RecoverOKPath:        "/",
		RecoverTokenDuration: time.Duration(24) * time.Hour,

		RegisterOKPath: "/",

		Policies: []Validator{
			Rules{
				FieldName:       "username",
				Required:        true,
				MinLength:       2,
				MaxLength:       4,
				AllowWhitespace: false,
			},
			Rules{
				FieldName: "password",
				Required:  true,
				MinLength: 4,
				MaxLength: 8,

				AllowWhitespace: false,
			},
		},
		ConfirmFields: []string{
			StorePassword, ConfirmPrefix + StorePassword,
		},

		ExpireAfter: 60 * time.Minute,

		LockAfter:    3,
		LockWindow:   5 * time.Minute,
		LockDuration: 5 * time.Hour,

		LogWriter: ioutil.Discard,
		Callbacks: NewCallbacks(),
		Mailer:    LogMailer(ioutil.Discard),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/michaelsauter/crane/print"
	"gopkg.in/v1/yaml"
	"io/ioutil"
	"os"
	"path/filepath"
)

type Manifest struct {
	Containers Containers          `json:"containers" yaml:"containers"`
	Groups     map[string][]string `json:"groups" yaml:"groups"`
}

func determineTargetedContainers(manifest Manifest, specifiedGroup string) []string {
	// If group is not given, all containers
	if len(specifiedGroup) == 0 {
		var containers []string
		for i := 0; i < len(manifest.Containers); i++ {
			containers = append(containers, manifest.Containers[i].Name)
		}
		return containers
	}
	// Select specified group from listed groups
	for name, containers := range manifest.Groups {
		if name == specifiedGroup {
			return containers
		}
	}
	// Otherwise, the group is just the specified container
	return append([]string{}, specifiedGroup)
}

func getManifest(options Options) Manifest {
	if len(options.config) > 0 {
		return unmarshalJSON([]byte(options.config))
	} else {
		for _, f := range manifestFiles() {
			if _, err := os.Stat(f); err == nil {
				return readCraneData(f)
			}
		}
	}
	panic(StatusError{fmt.Errorf("No configuration found %v", manifestFiles()), 78})
}

func getContainers(options Options) Containers {
	manifest := getManifest(options)
	targetedContainers := determineTargetedContainers(manifest, options.group)
	return manifest.Containers.filter(targetedContainers)
}

func readCraneData(filename string) Manifest {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(StatusError{err, 74})
	}

	if filename == "Cranefile" {
		print.Notice("Using a Cranefile is deprecated. Please use crane.json/crane.yaml instead.\n")
	}

	ext := filepath.Ext(filename)
	if ext == ".json" {
		return unmarshalJSON(data)
	} else if ext == ".yml" || ext == ".yaml" {
		return unmarshalYAML(data)
	} else if ext == "" {
		return unmarshalJSON(data)
	} else {
		panic(StatusError{errors.New("Unrecognized file extension"), 65})
	}
}

// Thanks to https://github.com/markpeek/packer/commit/5bf33a0e91b2318a40c42e9bf855dcc8dd4cdec5
func displaySyntaxError(data []byte, syntaxError error) (err error) {
	syntax, ok := syntaxError.(*json.SyntaxError)
	if !ok {
		err = syntaxError
		return
	}
	newline := []byte{'\x0a'}
	space := []byte{' '}

	start, end := bytes.LastIndex(data[:syntax.Offset], newline)+1, len(data)
	if idx := bytes.Index(data[start:], newline); idx >= 0 {
		end = start + idx
	}

	line, pos := bytes.Count(data[:start], newline)+1, int(syntax.Offset)-start-1

	err = fmt.Errorf("\nError in line %d: %s \n%s\n%s^", line, syntaxError, data[start:end], bytes.Repeat(space, pos))
	return
}

func unmarshalJSON(data []byte) Manifest {
	var manifest Manifest
	err := json.Unmarshal(data, &manifest)
	if err != nil {
		err = displaySyntaxError(data, err)
		panic(StatusError{err, 65})
	}
	return manifest
}

func unmarshalYAML(data []byte) Manifest {
	var manifest Manifest
	err := yaml.Unmarshal(data, &manifest)
	if err != nil {
		err = displaySyntaxError(data, err)
		panic(StatusError{err, 65})
	}
	return manifest
}
<commit_msg>USAGE for invalid group/container reference<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/michaelsauter/crane/print"
	"gopkg.in/v1/yaml"
	"io/ioutil"
	"os"
	"path/filepath"
)

type Manifest struct {
	Containers Containers          `json:"containers" yaml:"containers"`
	Groups     map[string][]string `json:"groups" yaml:"groups"`
}

func determineTargetedContainers(manifest Manifest, specifiedGroup string) []string {
	// If group is not given, all containers
	if len(specifiedGroup) == 0 {
		var containers []string
		for i := 0; i < len(manifest.Containers); i++ {
			containers = append(containers, manifest.Containers[i].Name)
		}
		return containers
	}
	// Select specified group from listed groups
	for name, containers := range manifest.Groups {
		if name == specifiedGroup {
			return containers
		}
	}
	// The group might just be a container reference itself
	for i := 0; i < len(manifest.Containers); i++ {
		if manifest.Containers[i].Name == specifiedGroup {
			return append([]string{}, specifiedGroup)
		}
	}
	// Otherwise, fail verbosely
	panic(StatusError{fmt.Errorf("no group nor container matching `%s`", specifiedGroup), 64})
}

func getManifest(options Options) Manifest {
	if len(options.config) > 0 {
		return unmarshalJSON([]byte(options.config))
	} else {
		for _, f := range manifestFiles() {
			if _, err := os.Stat(f); err == nil {
				return readCraneData(f)
			}
		}
	}
	panic(StatusError{fmt.Errorf("No configuration found %v", manifestFiles()), 78})
}

func getContainers(options Options) Containers {
	manifest := getManifest(options)
	targetedContainers := determineTargetedContainers(manifest, options.group)
	return manifest.Containers.filter(targetedContainers)
}

func readCraneData(filename string) Manifest {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(StatusError{err, 74})
	}

	if filename == "Cranefile" {
		print.Notice("Using a Cranefile is deprecated. Please use crane.json/crane.yaml instead.\n")
	}

	ext := filepath.Ext(filename)
	if ext == ".json" {
		return unmarshalJSON(data)
	} else if ext == ".yml" || ext == ".yaml" {
		return unmarshalYAML(data)
	} else if ext == "" {
		return unmarshalJSON(data)
	} else {
		panic(StatusError{errors.New("Unrecognized file extension"), 65})
	}
}

// Thanks to https://github.com/markpeek/packer/commit/5bf33a0e91b2318a40c42e9bf855dcc8dd4cdec5
func displaySyntaxError(data []byte, syntaxError error) (err error) {
	syntax, ok := syntaxError.(*json.SyntaxError)
	if !ok {
		err = syntaxError
		return
	}
	newline := []byte{'\x0a'}
	space := []byte{' '}

	start, end := bytes.LastIndex(data[:syntax.Offset], newline)+1, len(data)
	if idx := bytes.Index(data[start:], newline); idx >= 0 {
		end = start + idx
	}

	line, pos := bytes.Count(data[:start], newline)+1, int(syntax.Offset)-start-1

	err = fmt.Errorf("\nError in line %d: %s \n%s\n%s^", line, syntaxError, data[start:end], bytes.Repeat(space, pos))
	return
}

func unmarshalJSON(data []byte) Manifest {
	var manifest Manifest
	err := json.Unmarshal(data, &manifest)
	if err != nil {
		err = displaySyntaxError(data, err)
		panic(StatusError{err, 65})
	}
	return manifest
}

func unmarshalYAML(data []byte) Manifest {
	var manifest Manifest
	err := yaml.Unmarshal(data, &manifest)
	if err != nil {
		err = displaySyntaxError(data, err)
		panic(StatusError{err, 65})
	}
	return manifest
}
<|endoftext|>


<commit_before>package torrent

import (
	"github.com/anacrolix/torrent/dht"
	"github.com/anacrolix/torrent/iplist"
	"github.com/anacrolix/torrent/storage"
)

// Override Client defaults.
type Config struct {
	// Store torrent file data in this directory unless TorrentDataOpener is
	// specified.
	DataDir string `long:"data-dir" description:"directory to store downloaded torrent data"`
	// The address to listen for new uTP and TCP bittorrent protocol
	// connections. DHT shares a UDP socket with uTP unless configured
	// otherwise.
	ListenAddr string `long:"listen-addr" value-name:"HOST:PORT"`
	// Don't announce to trackers. This only leaves DHT to discover peers.
	DisableTrackers bool `long:"disable-trackers"`
	DisablePEX      bool `long:"disable-pex"`
	// Don't create a DHT.
	NoDHT bool `long:"disable-dht"`
	// Overrides the default DHT configuration.
	DHTConfig dht.ServerConfig
	// Don't ever send chunks to peers.
	NoUpload bool `long:"no-upload"`
	// Upload even after there's nothing in it for us. By default uploading is
	// not altruistic.
	Seed bool `long:"seed"`
	// User-provided Client peer ID. If not present, one is generated automatically.
	PeerID string
	// For the bittorrent protocol.
	DisableUTP bool
	// For the bittorrent protocol.
	DisableTCP bool `long:"disable-tcp"`
	// Defaults to "$HOME/.config/torrent". This is where "blocklist",
	// "torrents" and other operational files are stored. TODO: Dump this
	// stuff, this is specific to the default cmd/torrent client only.
	ConfigDir string
	// Don't save or load to a cache of torrent files stored in
	// "$ConfigDir/torrents".
	DisableMetainfoCache bool
	// Called to instantiate storage for each added torrent. Provided backends
	// are in $REPO/data. If not set, the "file" implementation is used.
	DefaultStorage    storage.I
	DisableEncryption bool `long:"disable-encryption"`

	IPBlocklist *iplist.IPList
	DisableIPv6 bool `long:"disable-ipv6"`
	// Perform logging and any other behaviour that will help debug.
	Debug bool `help:"enable debug logging"`
}
<commit_msg>Fix Config.IPBlocklist type<commit_after>package torrent

import (
	"github.com/anacrolix/torrent/dht"
	"github.com/anacrolix/torrent/iplist"
	"github.com/anacrolix/torrent/storage"
)

// Override Client defaults.
type Config struct {
	// Store torrent file data in this directory unless TorrentDataOpener is
	// specified.
	DataDir string `long:"data-dir" description:"directory to store downloaded torrent data"`
	// The address to listen for new uTP and TCP bittorrent protocol
	// connections. DHT shares a UDP socket with uTP unless configured
	// otherwise.
	ListenAddr string `long:"listen-addr" value-name:"HOST:PORT"`
	// Don't announce to trackers. This only leaves DHT to discover peers.
	DisableTrackers bool `long:"disable-trackers"`
	DisablePEX      bool `long:"disable-pex"`
	// Don't create a DHT.
	NoDHT bool `long:"disable-dht"`
	// Overrides the default DHT configuration.
	DHTConfig dht.ServerConfig
	// Don't ever send chunks to peers.
	NoUpload bool `long:"no-upload"`
	// Upload even after there's nothing in it for us. By default uploading is
	// not altruistic.
	Seed bool `long:"seed"`
	// User-provided Client peer ID. If not present, one is generated automatically.
	PeerID string
	// For the bittorrent protocol.
	DisableUTP bool
	// For the bittorrent protocol.
	DisableTCP bool `long:"disable-tcp"`
	// Defaults to "$HOME/.config/torrent". This is where "blocklist",
	// "torrents" and other operational files are stored. TODO: Dump this
	// stuff, this is specific to the default cmd/torrent client only.
	ConfigDir string
	// Don't save or load to a cache of torrent files stored in
	// "$ConfigDir/torrents".
	DisableMetainfoCache bool
	// Called to instantiate storage for each added torrent. Provided backends
	// are in $REPO/data. If not set, the "file" implementation is used.
	DefaultStorage    storage.I
	DisableEncryption bool `long:"disable-encryption"`

	IPBlocklist iplist.Ranger
	DisableIPv6 bool `long:"disable-ipv6"`
	// Perform logging and any other behaviour that will help debug.
	Debug bool `help:"enable debug logging"`
}
<|endoftext|>


<commit_before>package raft

import (
	"fmt"
	"io"
	"time"
)

// Config provides any necessary configuraiton to
// the Raft server
type Config struct {
	// Time in follower state without a leader before we attempt an election
	HeartbeatTimeout time.Duration

	// Time in candidate state without a leader before we attempt an election
	ElectionTimeout time.Duration

	// Time without an Apply() operation before we heartbeat to ensure
	// a timely commit. Due to random staggering, may be delayed as much as
	// 2x this value.
	CommitTimeout time.Duration

	// MaxAppendEntries controls the maximum number of append entries
	// to send at once. We want to strike a balance between efficiency
	// and avoiding waste if the follower is going to reject because of
	// an inconsistent log
	MaxAppendEntries int

	// If we are a member of a cluster, and RemovePeer is invoked for the
	// local node, then we forget all peers and transition into the follower state.
	// If ShutdownOnRemove is is set, we additional shutdown Raft. Otherwise,
	// we can become a leader of a cluster containing only this node.
	ShutdownOnRemove bool

	// DisableBootstrapAfterElect is used to turn off EnableSingleNode
	// after the node is elected. This is used to prevent self-election
	// if the node is removed from the Raft cluster via RemovePeer. Setting
	// it to false will keep the bootstrap mode, allowing the node to self-elect
	// and potentially bootstrap a seperate cluster.
	DisableBootstrapAfterElect bool

	// TrailingLogs controls how many logs we leave after a snapshot. This is
	// used so that we can quickly replay logs on a follower instead of being
	// forced to send an entire snapshot.
	TrailingLogs uint64

	// SnapshotInterval controls how often we check if we should perform a snapshot.
	// We randomly stagger between this value and 2x this value to avoid the entire
	// cluster from performing a snapshot at once
	SnapshotInterval time.Duration

	// SnapshotThreshold controls how many outstanding logs there must be before
	// we perform a snapshot. This is to prevent excessive snapshots when we can
	// just replay a small set of logs.
	SnapshotThreshold uint64

	// EnableSingleNode allows for a single node mode of operation. This
	// is false by default, which prevents a lone node from electing itself
	// leader.
	EnableSingleNode bool

	// LeaderLeaseTimeout is used to control how long the "lease" lasts
	// for being the leader without being able to contact a quorum
	// of nodes. If we reach this interval without contact, we will
	// step down as leader.
	LeaderLeaseTimeout time.Duration

	// LogOutput is used as a sink for logs. Defaults to os.Stderr.
	LogOutput io.Writer
}

// DefaultConfig returns a Config with usable defaults.
func DefaultConfig() *Config {
	return &Config{
		HeartbeatTimeout:           1000 * time.Millisecond,
		ElectionTimeout:            1000 * time.Millisecond,
		CommitTimeout:              50 * time.Millisecond,
		MaxAppendEntries:           64,
		ShutdownOnRemove:           true,
		DisableBootstrapAfterElect: true,
		TrailingLogs:               10240,
		SnapshotInterval:           120 * time.Second,
		SnapshotThreshold:          8192,
		EnableSingleNode:           false,
		LeaderLeaseTimeout:         500 * time.Millisecond,
	}
}

// ValidateConfig is used to validate a sane configuration
func ValidateConfig(config *Config) error {
	if config.HeartbeatTimeout < 5*time.Millisecond {
		return fmt.Errorf("Heartbeat timeout is too low")
	}
	if config.ElectionTimeout < 5*time.Millisecond {
		return fmt.Errorf("Election timeout is too low")
	}
	if config.CommitTimeout < time.Millisecond {
		return fmt.Errorf("Commit timeout is too low")
	}
	if config.MaxAppendEntries <= 0 {
		return fmt.Errorf("MaxAppendEntries must be positive")
	}
	if config.MaxAppendEntries > 1024 {
		return fmt.Errorf("MaxAppendEntries is too large")
	}
	if config.SnapshotInterval < 5*time.Millisecond {
		return fmt.Errorf("Snapshot interval is too low")
	}
	if config.LeaderLeaseTimeout < 5*time.Millisecond {
		return fmt.Errorf("Leader lease timeout is too low")
	}
	if config.LeaderLeaseTimeout > config.HeartbeatTimeout {
		return fmt.Errorf("Leader lease timeout cannot be larger than heartbeat timeout")
	}
	if config.ElectionTimeout < config.HeartbeatTimeout {
		return fmt.Errorf("Election timeout must be equal or greater than Heartbeat Timeout")
	}
	return nil
}
<commit_msg>fix typo in config.go<commit_after>package raft

import (
	"fmt"
	"io"
	"time"
)

// Config provides any necessary configuration to
// the Raft server
type Config struct {
	// Time in follower state without a leader before we attempt an election
	HeartbeatTimeout time.Duration

	// Time in candidate state without a leader before we attempt an election
	ElectionTimeout time.Duration

	// Time without an Apply() operation before we heartbeat to ensure
	// a timely commit. Due to random staggering, may be delayed as much as
	// 2x this value.
	CommitTimeout time.Duration

	// MaxAppendEntries controls the maximum number of append entries
	// to send at once. We want to strike a balance between efficiency
	// and avoiding waste if the follower is going to reject because of
	// an inconsistent log
	MaxAppendEntries int

	// If we are a member of a cluster, and RemovePeer is invoked for the
	// local node, then we forget all peers and transition into the follower state.
	// If ShutdownOnRemove is is set, we additional shutdown Raft. Otherwise,
	// we can become a leader of a cluster containing only this node.
	ShutdownOnRemove bool

	// DisableBootstrapAfterElect is used to turn off EnableSingleNode
	// after the node is elected. This is used to prevent self-election
	// if the node is removed from the Raft cluster via RemovePeer. Setting
	// it to false will keep the bootstrap mode, allowing the node to self-elect
	// and potentially bootstrap a seperate cluster.
	DisableBootstrapAfterElect bool

	// TrailingLogs controls how many logs we leave after a snapshot. This is
	// used so that we can quickly replay logs on a follower instead of being
	// forced to send an entire snapshot.
	TrailingLogs uint64

	// SnapshotInterval controls how often we check if we should perform a snapshot.
	// We randomly stagger between this value and 2x this value to avoid the entire
	// cluster from performing a snapshot at once
	SnapshotInterval time.Duration

	// SnapshotThreshold controls how many outstanding logs there must be before
	// we perform a snapshot. This is to prevent excessive snapshots when we can
	// just replay a small set of logs.
	SnapshotThreshold uint64

	// EnableSingleNode allows for a single node mode of operation. This
	// is false by default, which prevents a lone node from electing itself
	// leader.
	EnableSingleNode bool

	// LeaderLeaseTimeout is used to control how long the "lease" lasts
	// for being the leader without being able to contact a quorum
	// of nodes. If we reach this interval without contact, we will
	// step down as leader.
	LeaderLeaseTimeout time.Duration

	// LogOutput is used as a sink for logs. Defaults to os.Stderr.
	LogOutput io.Writer
}

// DefaultConfig returns a Config with usable defaults.
func DefaultConfig() *Config {
	return &Config{
		HeartbeatTimeout:           1000 * time.Millisecond,
		ElectionTimeout:            1000 * time.Millisecond,
		CommitTimeout:              50 * time.Millisecond,
		MaxAppendEntries:           64,
		ShutdownOnRemove:           true,
		DisableBootstrapAfterElect: true,
		TrailingLogs:               10240,
		SnapshotInterval:           120 * time.Second,
		SnapshotThreshold:          8192,
		EnableSingleNode:           false,
		LeaderLeaseTimeout:         500 * time.Millisecond,
	}
}

// ValidateConfig is used to validate a sane configuration
func ValidateConfig(config *Config) error {
	if config.HeartbeatTimeout < 5*time.Millisecond {
		return fmt.Errorf("Heartbeat timeout is too low")
	}
	if config.ElectionTimeout < 5*time.Millisecond {
		return fmt.Errorf("Election timeout is too low")
	}
	if config.CommitTimeout < time.Millisecond {
		return fmt.Errorf("Commit timeout is too low")
	}
	if config.MaxAppendEntries <= 0 {
		return fmt.Errorf("MaxAppendEntries must be positive")
	}
	if config.MaxAppendEntries > 1024 {
		return fmt.Errorf("MaxAppendEntries is too large")
	}
	if config.SnapshotInterval < 5*time.Millisecond {
		return fmt.Errorf("Snapshot interval is too low")
	}
	if config.LeaderLeaseTimeout < 5*time.Millisecond {
		return fmt.Errorf("Leader lease timeout is too low")
	}
	if config.LeaderLeaseTimeout > config.HeartbeatTimeout {
		return fmt.Errorf("Leader lease timeout cannot be larger than heartbeat timeout")
	}
	if config.ElectionTimeout < config.HeartbeatTimeout {
		return fmt.Errorf("Election timeout must be equal or greater than Heartbeat Timeout")
	}
	return nil
}
<|endoftext|>


<commit_before>// config.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/naoina/toml"
)

// Config holds our parameters
type Config struct {
	User string
	Password string
}

// Check the parameter for either tag or filename
func checkName(file string) string {
	// Full path, MUST have .toml
	if bfile := []byte(file); bfile[0] == '/' {
		if !strings.HasSuffix(file, ".toml") {
			return ""
		}
		return file
	}
	// Check for tag
	if !strings.HasSuffix(file, ".toml") {
		// file must be a tag so add a "."
		return filepath.Join(os.Getenv("HOME"),
			fmt.Sprintf(".%s", file),
			"config.toml")
	}
	return file
}

// LoadConfig reads a file as a TOML document and return the structure
func LoadConfig(file string) (c *Config, err error) {
	// Check for tag
	sFile := checkName(file)

	c = new(Config)
	buf, err := ioutil.ReadFile(sFile)
	if err != nil {
		return c, fmt.Errorf("Can not read %s", sFile)
	}

	err = toml.Unmarshal(buf, &c)
	if err != nil {
		return c, fmt.Errorf("Error parsing toml %s: %v",
			sFile, err)
	}

	return c, nil
}
<commit_msg>Un-import errors.<commit_after>// config.go
//
// This file implements the configuration part for when you need the API
// key to modify things in the Atlas configuration and manage measurements.

package atlas

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/naoina/toml"
)

// Config holds our parameters
type Config struct {
	User string
	Password string
}

// Check the parameter for either tag or filename
func checkName(file string) string {
	// Full path, MUST have .toml
	if bfile := []byte(file); bfile[0] == '/' {
		if !strings.HasSuffix(file, ".toml") {
			return ""
		}
		return file
	}
	// Check for tag
	if !strings.HasSuffix(file, ".toml") {
		// file must be a tag so add a "."
		return filepath.Join(os.Getenv("HOME"),
			fmt.Sprintf(".%s", file),
			"config.toml")
	}
	return file
}

// LoadConfig reads a file as a TOML document and return the structure
func LoadConfig(file string) (c *Config, err error) {
	// Check for tag
	sFile := checkName(file)

	c = new(Config)
	buf, err := ioutil.ReadFile(sFile)
	if err != nil {
		return c, fmt.Errorf("Can not read %s", sFile)
	}

	err = toml.Unmarshal(buf, &c)
	if err != nil {
		return c, fmt.Errorf("Error parsing toml %s: %v",
			sFile, err)
	}

	return c, nil
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com

package main

import (
	"fmt"
	gcfg "gopkg.in/gcfg.v1"
	"time"
)

type config struct {
	ES struct {
		StateESHost string // ElasticSearch host for state information
		EventESHost string // ElasticSearch host for event information
		EventIndex  string // Index containing events
		StateIndex  string // geomodel state index
	}

	Geo struct {
		CollapseMaximum  int    // Maximum allowable collapse for branch locality (km)
		MovementWindow   string // time.Duration for movement heuristic
		MovementDistance int    // Distance for movement heuristic (km)
	}

	MozDef struct {
		MozDefURL string // URL for MozDef event publishing
	}

	General struct {
		Context string // Context name
		Plugins string // Plugin directory path
		MaxMind string // Path to MaxMind DB
	}

	Timer struct {
		State          int    // State interval in seconds
		MaxQueryWindow int    // Maximum query window in seconds
		Merge          int    // Merge interval in seconds
		ExpireEvents   string // time.Duration specifying how to prune events
		Offset         string // time.Duration specifying standoff for query window
	}

	// Not expected to be in the configuration file, but other options we
	// want to store as part of the configuration.
	deleteStateIndex bool // Remove state index on startup
	initialOffset    int  // If creating initial state, start from this far back (seconds)
	noSendAlert      bool // Don't send alerts to MozDef
	overrides				 []Override
}

var cfg config

func (c *config) validate() error {
	if c.ES.StateESHost == "" {
		return fmt.Errorf("es..stateeshost must be set")
	}
	if c.ES.EventESHost == "" {
		return fmt.Errorf("es..eventeshost must be set")
	}
	if c.ES.EventIndex == "" {
		return fmt.Errorf("es..eventindex must be set")
	}
	if c.ES.StateIndex == "" {
		return fmt.Errorf("es..stateindex must be set")
	}
	if c.General.Context == "" {
		return fmt.Errorf("general..context must be set")
	}
	if c.General.Plugins == "" {
		return fmt.Errorf("general..plugins must be set")
	}
	if c.General.MaxMind == "" {
		return fmt.Errorf("general..maxmind must be set")
	}
	if c.MozDef.MozDefURL == "" {
		return fmt.Errorf("mozdef..mozdefurl must be set")
	}
	if c.Timer.State < 10 {
		return fmt.Errorf("timer..state must be >= 10")
	}
	if c.Timer.Merge < 10 {
		return fmt.Errorf("timer..merge must be >= 10")
	}
	if c.Timer.MaxQueryWindow < 60 {
		return fmt.Errorf("timer..maxquerywindow must be >= 60")
	}
	if c.Timer.ExpireEvents == "" {
		return fmt.Errorf("timer..expireevents must be set")
	}
	if c.Timer.Offset != "" {
		_, err := time.ParseDuration(c.Timer.Offset)
		if err != nil {
			return err
		}
	}
	_, err := time.ParseDuration(c.Timer.ExpireEvents)
	if err != nil {
		return err
	}
	_, err = time.ParseDuration(c.Geo.MovementWindow)
	if err != nil {
		return err
	}
	if c.Geo.MovementDistance < 500 {
		return fmt.Errorf("geo..movementdistance must be >= 500")
	}
	return nil
}

func (c *config) loadConfiguration(path string) error {
	err := gcfg.ReadFileInto(&cfg, path)
	if err != nil {
		return err
	}
	return c.validate()
}
<commit_msg>Fix format of new overrides line<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com

package main

import (
	"fmt"
	gcfg "gopkg.in/gcfg.v1"
	"time"
)

type config struct {
	ES struct {
		StateESHost string // ElasticSearch host for state information
		EventESHost string // ElasticSearch host for event information
		EventIndex  string // Index containing events
		StateIndex  string // geomodel state index
	}

	Geo struct {
		CollapseMaximum  int    // Maximum allowable collapse for branch locality (km)
		MovementWindow   string // time.Duration for movement heuristic
		MovementDistance int    // Distance for movement heuristic (km)
	}

	MozDef struct {
		MozDefURL string // URL for MozDef event publishing
	}

	General struct {
		Context string // Context name
		Plugins string // Plugin directory path
		MaxMind string // Path to MaxMind DB
	}

	Timer struct {
		State          int    // State interval in seconds
		MaxQueryWindow int    // Maximum query window in seconds
		Merge          int    // Merge interval in seconds
		ExpireEvents   string // time.Duration specifying how to prune events
		Offset         string // time.Duration specifying standoff for query window
	}

	// Not expected to be in the configuration file, but other options we
	// want to store as part of the configuration.
	deleteStateIndex bool // Remove state index on startup
	initialOffset    int  // If creating initial state, start from this far back (seconds)
	noSendAlert      bool // Don't send alerts to MozDef
	overrides		[]Override // Keeps track of custom ip -> city,country overrides
}

var cfg config

func (c *config) validate() error {
	if c.ES.StateESHost == "" {
		return fmt.Errorf("es..stateeshost must be set")
	}
	if c.ES.EventESHost == "" {
		return fmt.Errorf("es..eventeshost must be set")
	}
	if c.ES.EventIndex == "" {
		return fmt.Errorf("es..eventindex must be set")
	}
	if c.ES.StateIndex == "" {
		return fmt.Errorf("es..stateindex must be set")
	}
	if c.General.Context == "" {
		return fmt.Errorf("general..context must be set")
	}
	if c.General.Plugins == "" {
		return fmt.Errorf("general..plugins must be set")
	}
	if c.General.MaxMind == "" {
		return fmt.Errorf("general..maxmind must be set")
	}
	if c.MozDef.MozDefURL == "" {
		return fmt.Errorf("mozdef..mozdefurl must be set")
	}
	if c.Timer.State < 10 {
		return fmt.Errorf("timer..state must be >= 10")
	}
	if c.Timer.Merge < 10 {
		return fmt.Errorf("timer..merge must be >= 10")
	}
	if c.Timer.MaxQueryWindow < 60 {
		return fmt.Errorf("timer..maxquerywindow must be >= 60")
	}
	if c.Timer.ExpireEvents == "" {
		return fmt.Errorf("timer..expireevents must be set")
	}
	if c.Timer.Offset != "" {
		_, err := time.ParseDuration(c.Timer.Offset)
		if err != nil {
			return err
		}
	}
	_, err := time.ParseDuration(c.Timer.ExpireEvents)
	if err != nil {
		return err
	}
	_, err = time.ParseDuration(c.Geo.MovementWindow)
	if err != nil {
		return err
	}
	if c.Geo.MovementDistance < 500 {
		return fmt.Errorf("geo..movementdistance must be >= 500")
	}
	return nil
}

func (c *config) loadConfiguration(path string) error {
	err := gcfg.ReadFileInto(&cfg, path)
	if err != nil {
		return err
	}
	return c.validate()
}
<|endoftext|>


<commit_before>package gopher

var config = map[string]map[string]interface{}{
	"LOGGER": {
		"FullTimestamp": true,
	},
	"ROUTER": {
		"name": "Router",
	},
	"RENDERER": {
		"provider": "Renderer",
	},
}
<commit_msg>switch to using config provider constants<commit_after>package gopher

var config = map[string]map[string]interface{}{
	LOGGER: {
		"FullTimestamp": true,
	},
	ROUTER: {
		"name": "Router",
	},
	RENDERER: {
		"provider": "Renderer",
	},
}
<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

type Settings struct {
	Token      string `json:"token"`
	ProjectId  string `json:"project_id"`
	Host       string `json:"host"`
	Protocol   string `json:"protocol"`
	Port       int    `json:"port"`
	ApiVersion string `json:"api_version"`
}

var (
	presets = map[string]Settings{
		"worker": Settings{Protocol: "https", Port: 443, ApiVersion: "2", Host: "worker-aws-us-east-1.iron.io"},
		"mq":     Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "mq-aws-us-east-1.iron.io"},
		"cache":  Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "cache-aws-us-east-1.iron.io"},
	}
)

// fullProduct is like "iron_worker" and "iron_mq", not "worker" or "mq", to
// keep some flexibility in future.
func Config(fullProduct string) (settings Settings) {
	pair := strings.SplitN(fullProduct, "_", 2)
	if len(pair) != 2 {
		panic("Invalid product name, has to use prefix.")
	}
	family, product := pair[0], pair[1]

	base, found := presets[product]

	if !found {
		base = Settings{
			Protocol:   "https",
			Port:       443,
			ApiVersion: "1",
			Host:       product + "-aws-us-east-1.iron.io",
		}
	}

	(&base).globalConfig(family, product)
	(&base).globalEnv(family, product)
	(&base).productEnv(family, product)
	(&base).localConfig(family, product)

	return base
}

func (s *Settings) globalConfig(family, product string) {
	if u, err := user.Current(); err == nil {
		path := filepath.Join(u.HomeDir, ".iron.json")
		s.UseConfigFile(family, product, path)
	}
}

// The environment variables the scheme looks for are all of the same formula:
// the camel-cased product name is switched to an underscore (“IronWorker”
// becomes “iron_worker”) and converted to be all capital letters. For the
// global environment variables, “IRON” is used by itself. The value being
// loaded is then joined by an underscore to the name, and again capitalised.
// For example, to retrieve the OAuth token, the client looks for “IRON_TOKEN”.
func (s *Settings) globalEnv(family, product string) {
	eFamily := strings.ToUpper(family) + "_"
	s.commonEnv(eFamily)
}

// In the case of product-specific variables (which override global variables),
// it would be “IRON_WORKER_TOKEN” (for IronWorker).
func (s *Settings) productEnv(family, product string) {
	eProduct := strings.ToUpper(family) + "_" + strings.ToUpper(product) + "_"
	s.commonEnv(eProduct)
}

func (s *Settings) localConfig(family, product string) {
	s.UseConfigFile(family, product, "iron.json")
}

func (s *Settings) commonEnv(prefix string) {
	if token := os.Getenv(prefix + "TOKEN"); token != "" {
		s.Token = token
	}
	if pid := os.Getenv(prefix + "PROJECT_ID"); pid != "" {
		s.ProjectId = pid
	}
	if host := os.Getenv(prefix + "HOST"); host != "" {
		s.Host = host
	}
	if prot := os.Getenv(prefix + "PROTOCOL"); prot != "" {
		s.Protocol = prot
	}
	if port := os.Getenv(prefix + "PORT"); port != "" {
		n, err := strconv.ParseInt(port, 10, 32)
		if err != nil {
			panic(err)
		}
		s.Port = int(n)
	}
	if vers := os.Getenv(prefix + "API_VERSION"); vers != "" {
		s.ApiVersion = vers
	}
}

func (s *Settings) UseConfigFile(family, product, path string) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	data := map[string]interface{}{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		panic("Invalid JSON in " + path + ": " + err.Error())
	}

	s.commonConfigMap(data)

	ipData, found := data[family+"_"+product]
	if found {
		pData := ipData.(map[string]interface{})
		s.commonConfigMap(pData)
	}
}

func (s *Settings) commonConfigMap(data map[string]interface{}) {
	if token, found := data["token"]; found {
		s.Token = token.(string)
	}
	if projectId, found := data["project_id"]; found {
		s.ProjectId = projectId.(string)
	}
	if host, found := data["host"]; found {
		s.Host = host.(string)
	}
	if prot, found := data["protocol"]; found {
		s.Protocol = prot.(string)
	}
	if port, found := data["port"]; found {
		s.Port = int(port.(float64))
	}
	if vers, found := data["api_version"]; found {
		s.ApiVersion = vers.(string)
	}
}
<commit_msg>cleanup<commit_after>package config

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

type Settings struct {
	Token      string `json:"token"`
	ProjectId  string `json:"project_id"`
	Host       string `json:"host"`
	Protocol   string `json:"protocol"`
	Port       int    `json:"port"`
	ApiVersion string `json:"api_version"`
}

var (
	presets = map[string]Settings{
		"worker": Settings{Protocol: "https", Port: 443, ApiVersion: "2", Host: "worker-aws-us-east-1.iron.io"},
		"mq":     Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "mq-aws-us-east-1.iron.io"},
		"cache":  Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "cache-aws-us-east-1.iron.io"},
	}
)

// fullProduct is like "iron_worker" and "iron_mq", not "worker" or "mq", to
// keep some flexibility in future.
func Config(fullProduct string) (settings Settings) {
	pair := strings.SplitN(fullProduct, "_", 2)
	if len(pair) != 2 {
		panic("Invalid product name, has to use prefix.")
	}
	family, product := pair[0], pair[1]

	base, found := presets[product]

	if !found {
		base = Settings{
			Protocol:   "https",
			Port:       443,
			ApiVersion: "1",
			Host:       product + "-aws-us-east-1.iron.io",
		}
	}

	base.globalConfig(family, product)
	base.globalEnv(family, product)
	base.productEnv(family, product)
	base.localConfig(family, product)

	return base
}

func (s *Settings) globalConfig(family, product string) {
	if u, err := user.Current(); err == nil {
		path := filepath.Join(u.HomeDir, ".iron.json")
		s.UseConfigFile(family, product, path)
	}
}

// The environment variables the scheme looks for are all of the same formula:
// the camel-cased product name is switched to an underscore (“IronWorker”
// becomes “iron_worker”) and converted to be all capital letters. For the
// global environment variables, “IRON” is used by itself. The value being
// loaded is then joined by an underscore to the name, and again capitalised.
// For example, to retrieve the OAuth token, the client looks for “IRON_TOKEN”.
func (s *Settings) globalEnv(family, product string) {
	eFamily := strings.ToUpper(family) + "_"
	s.commonEnv(eFamily)
}

// In the case of product-specific variables (which override global variables),
// it would be “IRON_WORKER_TOKEN” (for IronWorker).
func (s *Settings) productEnv(family, product string) {
	eProduct := strings.ToUpper(family) + "_" + strings.ToUpper(product) + "_"
	s.commonEnv(eProduct)
}

func (s *Settings) localConfig(family, product string) {
	s.UseConfigFile(family, product, "iron.json")
}

func (s *Settings) commonEnv(prefix string) {
	if token := os.Getenv(prefix + "TOKEN"); token != "" {
		s.Token = token
	}
	if pid := os.Getenv(prefix + "PROJECT_ID"); pid != "" {
		s.ProjectId = pid
	}
	if host := os.Getenv(prefix + "HOST"); host != "" {
		s.Host = host
	}
	if prot := os.Getenv(prefix + "PROTOCOL"); prot != "" {
		s.Protocol = prot
	}
	if port := os.Getenv(prefix + "PORT"); port != "" {
		n, err := strconv.ParseInt(port, 10, 32)
		if err != nil {
			panic(err)
		}
		s.Port = int(n)
	}
	if vers := os.Getenv(prefix + "API_VERSION"); vers != "" {
		s.ApiVersion = vers
	}
}

func (s *Settings) UseConfigFile(family, product, path string) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	data := map[string]interface{}{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		panic("Invalid JSON in " + path + ": " + err.Error())
	}

	s.commonConfigMap(data)

	ipData, found := data[family+"_"+product]
	if found {
		pData := ipData.(map[string]interface{})
		s.commonConfigMap(pData)
	}
}

func (s *Settings) commonConfigMap(data map[string]interface{}) {
	if token, found := data["token"]; found {
		s.Token = token.(string)
	}
	if projectId, found := data["project_id"]; found {
		s.ProjectId = projectId.(string)
	}
	if host, found := data["host"]; found {
		s.Host = host.(string)
	}
	if prot, found := data["protocol"]; found {
		s.Protocol = prot.(string)
	}
	if port, found := data["port"]; found {
		s.Port = int(port.(float64))
	}
	if vers, found := data["api_version"]; found {
		s.ApiVersion = vers.(string)
	}
}
<|endoftext|>


<commit_before>// -*- tab-width: 4; -*-

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/go-yaml/yaml"
)

type Config struct {
	Nick      string
	Twturl    string
	Twtfile   string
	Following map[string]string // nick -> url
	nicks     map[string]string // normalizeURL(url) -> nick
}

func (conf *Config) Parse(data []byte) error {
	return yaml.Unmarshal(data, conf)
}

func (conf *Config) Read(confdir string) string {
	var paths []string
	if confdir != "" {
		paths = append(paths, confdir)
	} else {
		if xdg := os.Getenv("XDG_BASE_DIR"); xdg != "" {
			paths = append(paths, fmt.Sprintf("%s/config/twet", xdg))
		}
		paths = append(paths,
			fmt.Sprintf("%s/config/twet", homedir),
			fmt.Sprintf("%s/Library/Application Support/twet", homedir),
			fmt.Sprintf("%s/.twet", homedir))
	}

	filename := "config.yaml"

	foundpath := ""
	for _, path := range paths {
		configfile := fmt.Sprintf("%s/%s", path, filename)
		data, err := ioutil.ReadFile(configfile)
		if err != nil {
			// try next path
			continue
		}
		if err := conf.Parse(data); err != nil {
			log.Fatal(fmt.Sprintf("error parsing config file: %s: %s", filename, err))
		}
		foundpath = path
		break
	}
	if foundpath == "" {
		log.Fatal(fmt.Sprintf("config file %q not found; looked in: %q", filename, paths))
	}
	return foundpath
}

func (conf *Config) urlToNick(url string) string {
	if conf.nicks == nil {
		conf.nicks = make(map[string]string)
		for n, u := range conf.Following {
			if u = NormalizeURL(u); u == "" {
				continue
			}
			conf.nicks[u] = n
		}
		if conf.Nick != "" && conf.Twturl != "" {
			conf.nicks[NormalizeURL(conf.Twturl)] = conf.Nick
		}
	}
	return conf.nicks[NormalizeURL(url)]
}
<commit_msg>Use XDG_CONFIG_HOME instead; correct fallback to .config<commit_after>// -*- tab-width: 4; -*-

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/go-yaml/yaml"
)

type Config struct {
	Nick      string
	Twturl    string
	Twtfile   string
	Following map[string]string // nick -> url
	nicks     map[string]string // normalizeURL(url) -> nick
}

func (conf *Config) Parse(data []byte) error {
	return yaml.Unmarshal(data, conf)
}

func (conf *Config) Read(confdir string) string {
	var paths []string
	if confdir != "" {
		paths = append(paths, confdir)
	} else {
		if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
			paths = append(paths, fmt.Sprintf("%s/twet", xdg))
		}
		paths = append(paths,
			fmt.Sprintf("%s/.config/twet", homedir),
			fmt.Sprintf("%s/Library/Application Support/twet", homedir),
			fmt.Sprintf("%s/.twet", homedir))
	}

	filename := "config.yaml"

	foundpath := ""
	for _, path := range paths {
		configfile := fmt.Sprintf("%s/%s", path, filename)
		data, err := ioutil.ReadFile(configfile)
		if err != nil {
			// try next path
			continue
		}
		if err := conf.Parse(data); err != nil {
			log.Fatal(fmt.Sprintf("error parsing config file: %s: %s", filename, err))
		}
		foundpath = path
		break
	}
	if foundpath == "" {
		log.Fatal(fmt.Sprintf("config file %q not found; looked in: %q", filename, paths))
	}
	return foundpath
}

func (conf *Config) urlToNick(url string) string {
	if conf.nicks == nil {
		conf.nicks = make(map[string]string)
		for n, u := range conf.Following {
			if u = NormalizeURL(u); u == "" {
				continue
			}
			conf.nicks[u] = n
		}
		if conf.Nick != "" && conf.Twturl != "" {
			conf.nicks[NormalizeURL(conf.Twturl)] = conf.Nick
		}
	}
	return conf.nicks[NormalizeURL(url)]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strconv"

	// keep 3rd-party imports separate from stdlib with an empty line
	flag "github.com/ogier/pflag"
	"github.com/vaughan0/go-ini"
)

// boot2docker config.
var B2D struct {
	// NOTE: separate sections with blank lines so gofmt doesn't change
	// indentation all the time.

	// basic config
	VBM      string // VirtualBox management utility
	SSH      string // SSH client executable
	VM       string // virtual machine name
	Dir      string // boot2docker directory
	ISO      string // boot2docker ISO image path
	DiskSize uint   // VM disk image size (MB)
	Memory   uint   // VM memory size (MB)

	// NAT network: port forwarding
	SSHPort    uint16 // host SSH port (forward to port 22 in VM)
	DockerPort uint16 // host Docker port (forward to port 4243 in VM)

	// host-only network
	HostIP         string
	DHCPIP         string
	NetworkMask    string
	LowerIPAddress string
	UpperIPAddress string
	DHCPEnabled    string
}

func getCfgDir(name string) (string, error) {
	if b2dDir := os.Getenv("BOOT2DOCKER_DIR"); b2dDir != "" {
		return b2dDir, nil
	}

	// *nix
	if home := os.Getenv("HOME"); home != "" {
		return filepath.Join(home, name), nil
	}

	// Windows
	for _, env := range []string{
		"APPDATA",
		"LOCALAPPDATA",
		"USERPROFILE",
	} {
		if val := os.Getenv(env); val != "" {
			return filepath.Join(val, "boot2docker"), nil
		}
	}
	// Fallback to current working directory as a last resort
	cwd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return filepath.Join(cwd, name), nil
}

// Read configuration from both profile and flags. Flags override profile.
func config() (err error) {

	if B2D.Dir, err = getCfgDir(".boot2docker"); err != nil {
		return fmt.Errorf("failed to get current directory: %s", err)
	}

	filename := os.Getenv("BOOT2DOCKER_PROFILE")
	if filename == "" {
		filename = filepath.Join(B2D.Dir, "profile")
	}
	profile, err := getProfile(filename)
	if err != nil && !os.IsNotExist(err) { // undefined/empty profile works
		return err
	}

	if p := os.Getenv("VBOX_INSTALL_PATH"); p != "" && runtime.GOOS == "windows" {
		B2D.VBM = profile.Get("", "vbm", filepath.Join(p, "VBoxManage.exe"))
	} else {
		B2D.VBM = profile.Get("", "vbm", "VBoxManage")
	}

	B2D.SSH = profile.Get("", "ssh", "ssh")
	B2D.VM = profile.Get("", "vm", "boot2docker-vm")
	B2D.ISO = profile.Get("", "iso", filepath.Join(B2D.Dir, "boot2docker.iso"))

	if diskSize, err := strconv.ParseUint(profile.Get("", "disksize", "20000"), 10, 32); err != nil {
		return fmt.Errorf("invalid disk image size: %s", err)
	} else {
		B2D.DiskSize = uint(diskSize)
	}

	if memory, err := strconv.ParseUint(profile.Get("", "memory", "1024"), 10, 32); err != nil {
		return fmt.Errorf("invalid memory size: %s", err)
	} else {
		B2D.Memory = uint(memory)
	}

	if sshPort, err := strconv.ParseUint(profile.Get("", "sshport", "2022"), 10, 16); err != nil {
		return fmt.Errorf("invalid SSH port: %s", err)
	} else {
		B2D.SSHPort = uint16(sshPort)
	}

	if dockerPort, err := strconv.ParseUint(profile.Get("", "dockerport", "4243"), 10, 16); err != nil {
		return fmt.Errorf("invalid DockerPort: %s", err)
	} else {
		B2D.DockerPort = uint16(dockerPort)
	}

	// Host only networking settings
	B2D.HostIP = profile.Get("", "hostiP", "192.168.59.3")
	B2D.DHCPIP = profile.Get("", "dhcpip", "192.168.59.99")
	B2D.NetworkMask = profile.Get("", "netmask", "255.255.255.0")
	B2D.LowerIPAddress = profile.Get("", "lowerip", "192.168.59.103")
	B2D.UpperIPAddress = profile.Get("", "upperip", "192.168.59.254")
	B2D.DHCPEnabled = profile.Get("", "dhcp", "Yes")

	// Commandline flags override profile settings.
	flag.StringVar(&B2D.VBM, "vbm", B2D.VBM, "Path to VirtualBox management utility")
	flag.StringVar(&B2D.SSH, "ssh", B2D.SSH, "Path to SSH client utility")
	flag.StringVarP(&B2D.Dir, "dir", "d", B2D.Dir, "boot2docker config directory")
	flag.StringVar(&B2D.ISO, "iso", B2D.ISO, "Path to boot2docker ISO image")
	flag.UintVarP(&B2D.DiskSize, "disksize", "s", B2D.DiskSize, "boot2docker disk image size (in MB)")
	flag.UintVarP(&B2D.Memory, "memory", "m", B2D.Memory, "Virtual machine memory size (in MB)")
	flag.Var(newUint16Value(B2D.SSHPort, &B2D.SSHPort), "sshport", "Host SSH port (forward to port 22 in VM)")
	flag.Var(newUint16Value(B2D.DockerPort, &B2D.DockerPort), "dockerport", "Host Docker port (forward to port 4243 in VM)")
	flag.StringVar(&B2D.HostIP, "hostip", B2D.HostIP, "VirtualBox host-only network IP address")
	flag.StringVar(&B2D.NetworkMask, "netmask", B2D.NetworkMask, "VirtualBox host-only network mask")
	flag.StringVar(&B2D.DHCPEnabled, "dhcp", B2D.DHCPEnabled, "Enable VirtualBox host-only network DHCP")
	flag.StringVar(&B2D.DHCPIP, "dhcpip", B2D.DHCPIP, "VirtualBox host-only network DHCP server address")
	flag.StringVar(&B2D.LowerIPAddress, "lowerip", B2D.LowerIPAddress, "VirtualBox host-only network DHCP lower bound")
	flag.StringVar(&B2D.UpperIPAddress, "upperip", B2D.UpperIPAddress, "VirtualBox host-only network DHCP upper bound")

	flag.Parse()

	// Name of VM is the second argument.
	if vm := flag.Arg(1); vm != "" {
		B2D.VM = vm
	}
	return
}

// boot2docker configuration profile.
type Profile struct {
	ini.File
}

func getProfile(filename string) (*Profile, error) {
	f, err := ini.LoadFile(filename)
	return &Profile{f}, err
}

func (f *Profile) Get(section, key, fallback string) string {
	if val, ok := f.File.Get(section, key); ok {
		return os.ExpandEnv(val)
	}
	return fallback
}

// The missing flag.Uint16Var value type.
type uint16Value uint16

func newUint16Value(val uint16, p *uint16) *uint16Value {
	*p = val
	return (*uint16Value)(p)
}
func (i *uint16Value) String() string { return fmt.Sprintf("%d", *i) }
func (i *uint16Value) Set(s string) error {
	v, err := strconv.ParseUint(s, 10, 16)
	*i = uint16Value(v)
	return err
}
func (i *uint16Value) Get() interface{} {
	return uint16(*i)
}
<commit_msg>Ignore error when no profile is found<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strconv"

	// keep 3rd-party imports separate from stdlib with an empty line
	flag "github.com/ogier/pflag"
	"github.com/vaughan0/go-ini"
)

// boot2docker config.
var B2D struct {
	// NOTE: separate sections with blank lines so gofmt doesn't change
	// indentation all the time.

	// basic config
	VBM      string // VirtualBox management utility
	SSH      string // SSH client executable
	VM       string // virtual machine name
	Dir      string // boot2docker directory
	ISO      string // boot2docker ISO image path
	DiskSize uint   // VM disk image size (MB)
	Memory   uint   // VM memory size (MB)

	// NAT network: port forwarding
	SSHPort    uint16 // host SSH port (forward to port 22 in VM)
	DockerPort uint16 // host Docker port (forward to port 4243 in VM)

	// host-only network
	HostIP         string
	DHCPIP         string
	NetworkMask    string
	LowerIPAddress string
	UpperIPAddress string
	DHCPEnabled    string
}

func getCfgDir(name string) (string, error) {
	if b2dDir := os.Getenv("BOOT2DOCKER_DIR"); b2dDir != "" {
		return b2dDir, nil
	}

	// *nix
	if home := os.Getenv("HOME"); home != "" {
		return filepath.Join(home, name), nil
	}

	// Windows
	for _, env := range []string{
		"APPDATA",
		"LOCALAPPDATA",
		"USERPROFILE",
	} {
		if val := os.Getenv(env); val != "" {
			return filepath.Join(val, "boot2docker"), nil
		}
	}
	// Fallback to current working directory as a last resort
	cwd, err := os.Getwd()
	if err != nil {
		return "", err
	}
	return filepath.Join(cwd, name), nil
}

// Read configuration from both profile and flags. Flags override profile.
func config() (err error) {

	if B2D.Dir, err = getCfgDir(".boot2docker"); err != nil {
		return fmt.Errorf("failed to get current directory: %s", err)
	}

	filename := os.Getenv("BOOT2DOCKER_PROFILE")
	if filename == "" {
		filename = filepath.Join(B2D.Dir, "profile")
	}
	profile, err := getProfile(filename)
	if err != nil && !os.IsNotExist(err) { // undefined/empty profile works
		return err
	}

	if p := os.Getenv("VBOX_INSTALL_PATH"); p != "" && runtime.GOOS == "windows" {
		B2D.VBM = profile.Get("", "vbm", filepath.Join(p, "VBoxManage.exe"))
	} else {
		B2D.VBM = profile.Get("", "vbm", "VBoxManage")
	}

	B2D.SSH = profile.Get("", "ssh", "ssh")
	B2D.VM = profile.Get("", "vm", "boot2docker-vm")
	B2D.ISO = profile.Get("", "iso", filepath.Join(B2D.Dir, "boot2docker.iso"))

	if diskSize, err := strconv.ParseUint(profile.Get("", "disksize", "20000"), 10, 32); err != nil {
		return fmt.Errorf("invalid disk image size: %s", err)
	} else {
		B2D.DiskSize = uint(diskSize)
	}

	if memory, err := strconv.ParseUint(profile.Get("", "memory", "1024"), 10, 32); err != nil {
		return fmt.Errorf("invalid memory size: %s", err)
	} else {
		B2D.Memory = uint(memory)
	}

	if sshPort, err := strconv.ParseUint(profile.Get("", "sshport", "2022"), 10, 16); err != nil {
		return fmt.Errorf("invalid SSH port: %s", err)
	} else {
		B2D.SSHPort = uint16(sshPort)
	}

	if dockerPort, err := strconv.ParseUint(profile.Get("", "dockerport", "4243"), 10, 16); err != nil {
		return fmt.Errorf("invalid DockerPort: %s", err)
	} else {
		B2D.DockerPort = uint16(dockerPort)
	}

	// Host only networking settings
	B2D.HostIP = profile.Get("", "hostiP", "192.168.59.3")
	B2D.DHCPIP = profile.Get("", "dhcpip", "192.168.59.99")
	B2D.NetworkMask = profile.Get("", "netmask", "255.255.255.0")
	B2D.LowerIPAddress = profile.Get("", "lowerip", "192.168.59.103")
	B2D.UpperIPAddress = profile.Get("", "upperip", "192.168.59.254")
	B2D.DHCPEnabled = profile.Get("", "dhcp", "Yes")

	// Commandline flags override profile settings.
	flag.StringVar(&B2D.VBM, "vbm", B2D.VBM, "Path to VirtualBox management utility")
	flag.StringVar(&B2D.SSH, "ssh", B2D.SSH, "Path to SSH client utility")
	flag.StringVarP(&B2D.Dir, "dir", "d", B2D.Dir, "boot2docker config directory")
	flag.StringVar(&B2D.ISO, "iso", B2D.ISO, "Path to boot2docker ISO image")
	flag.UintVarP(&B2D.DiskSize, "disksize", "s", B2D.DiskSize, "boot2docker disk image size (in MB)")
	flag.UintVarP(&B2D.Memory, "memory", "m", B2D.Memory, "Virtual machine memory size (in MB)")
	flag.Var(newUint16Value(B2D.SSHPort, &B2D.SSHPort), "sshport", "Host SSH port (forward to port 22 in VM)")
	flag.Var(newUint16Value(B2D.DockerPort, &B2D.DockerPort), "dockerport", "Host Docker port (forward to port 4243 in VM)")
	flag.StringVar(&B2D.HostIP, "hostip", B2D.HostIP, "VirtualBox host-only network IP address")
	flag.StringVar(&B2D.NetworkMask, "netmask", B2D.NetworkMask, "VirtualBox host-only network mask")
	flag.StringVar(&B2D.DHCPEnabled, "dhcp", B2D.DHCPEnabled, "Enable VirtualBox host-only network DHCP")
	flag.StringVar(&B2D.DHCPIP, "dhcpip", B2D.DHCPIP, "VirtualBox host-only network DHCP server address")
	flag.StringVar(&B2D.LowerIPAddress, "lowerip", B2D.LowerIPAddress, "VirtualBox host-only network DHCP lower bound")
	flag.StringVar(&B2D.UpperIPAddress, "upperip", B2D.UpperIPAddress, "VirtualBox host-only network DHCP upper bound")

	flag.Parse()

	// Name of VM is the second argument.
	if vm := flag.Arg(1); vm != "" {
		B2D.VM = vm
	}
	return nil
}

// boot2docker configuration profile.
type Profile struct {
	ini.File
}

func getProfile(filename string) (*Profile, error) {
	f, err := ini.LoadFile(filename)
	return &Profile{f}, err
}

func (f *Profile) Get(section, key, fallback string) string {
	if val, ok := f.File.Get(section, key); ok {
		return os.ExpandEnv(val)
	}
	return fallback
}

// The missing flag.Uint16Var value type.
type uint16Value uint16

func newUint16Value(val uint16, p *uint16) *uint16Value {
	*p = val
	return (*uint16Value)(p)
}
func (i *uint16Value) String() string { return fmt.Sprintf("%d", *i) }
func (i *uint16Value) Set(s string) error {
	v, err := strconv.ParseUint(s, 10, 16)
	*i = uint16Value(v)
	return err
}
func (i *uint16Value) Get() interface{} {
	return uint16(*i)
}
<|endoftext|>


<commit_before>package webconform

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"
	"text/template"
)

const Template = "conform.tex.tmpl"

var funcMap = template.FuncMap{
	"divide": Divide,
}

func Divide(a, b float64) float64 { return a / b }

// Create parses the templates and runs pdflatex on the resulting tex file. It returns generated PDF.
func (c *Conform) Create(tmplDir, tmpl string) ([]byte, error) {
	c.escapeTex()
	err := c.FillOut()
	if err != nil {
		return nil, err
	}

	dst, err := ioutil.TempDir("/tmp", "pdflatex")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(dst)

	sources, err := TeXFiles(tmplDir)
	if err != nil {
		return nil, err
	}
	for _, src := range sources {
		basename := path.Base(src)
		if err := os.Symlink(src, path.Join(dst, basename)); err != nil {
			return nil, err
		}
	}

	conformTex := path.Join(dst, "conform.tex")

	// We use @@ in the tmpl, because {{ is in heavy use by TeX.
	// This also creates a dummy template called "", that we don't use.
	tmplName := path.Base(tmpl)
	t, err := template.New(tmplName).Delims("@@", "@@").Funcs(funcMap).ParseFiles(tmpl)
	if err != nil {
		return nil, err
	}
	if err := c.ExecuteTemplateAndWrite(t, tmplName, conformTex); err != nil {
		return nil, err
	}

	pdf, err := pdfLateX(dst, conformTex)
	if err != nil {
		return nil, err
	}
	return pdf, nil
}

// TeXFiles returns the tex and jpg files found in the directory dir.
func TeXFiles(dir string) ([]string, error) {
	tex := []string{}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, f := range files {
		switch path.Ext(f.Name()) {
		case ".tex", ".jpg":
			tex = append(tex, path.Join(dir, f.Name()))
		}
	}
	return tex, nil
}

func pdfLateX(dir, texfile string) ([]byte, error) {
	cmd := exec.Command("pdflatex", texfile)
	cmd.Dir = dir

	if err := cmd.Start(); err != nil {
		return nil, err
	}
	err := cmd.Wait()

	pdf := strings.Replace(texfile, ".tex", ".pdf", 1)
	data, err := ioutil.ReadFile(pdf)
	return data, err
}
<commit_msg>Fix<commit_after>package webconform

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"strings"
	"text/template"
)

const Template = "conform.tex.tmpl"

var funcMap = template.FuncMap{
	"divide": Divide,
}

func Divide(a float64, b int) float64 { return a / float64(b) }

// Create parses the templates and runs pdflatex on the resulting tex file. It returns generated PDF.
func (c *Conform) Create(tmplDir, tmpl string) ([]byte, error) {
	c.escapeTex()
	err := c.FillOut()
	if err != nil {
		return nil, err
	}

	dst, err := ioutil.TempDir("/tmp", "pdflatex")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(dst)

	sources, err := TeXFiles(tmplDir)
	if err != nil {
		return nil, err
	}
	for _, src := range sources {
		basename := path.Base(src)
		if err := os.Symlink(src, path.Join(dst, basename)); err != nil {
			return nil, err
		}
	}

	conformTex := path.Join(dst, "conform.tex")

	// We use @@ in the tmpl, because {{ is in heavy use by TeX.
	// This also creates a dummy template called "", that we don't use.
	tmplName := path.Base(tmpl)
	t, err := template.New(tmplName).Delims("@@", "@@").Funcs(funcMap).ParseFiles(tmpl)
	if err != nil {
		return nil, err
	}
	if err := c.ExecuteTemplateAndWrite(t, tmplName, conformTex); err != nil {
		return nil, err
	}

	pdf, err := pdfLateX(dst, conformTex)
	if err != nil {
		return nil, err
	}
	return pdf, nil
}

// TeXFiles returns the tex and jpg files found in the directory dir.
func TeXFiles(dir string) ([]string, error) {
	tex := []string{}
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	for _, f := range files {
		switch path.Ext(f.Name()) {
		case ".tex", ".jpg":
			tex = append(tex, path.Join(dir, f.Name()))
		}
	}
	return tex, nil
}

func pdfLateX(dir, texfile string) ([]byte, error) {
	cmd := exec.Command("pdflatex", texfile)
	cmd.Dir = dir

	if err := cmd.Start(); err != nil {
		return nil, err
	}
	err := cmd.Wait()

	pdf := strings.Replace(texfile, ".tex", ".pdf", 1)
	data, err := ioutil.ReadFile(pdf)
	return data, err
}
<|endoftext|>


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

// Package conditionalpatch shows how to conditionallly patch.
// It's in a separate package so each sample can define queryParamOpt.
package conditionalpatch

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

	healthcare "google.golang.org/api/healthcare/v1beta1"
)

// queryParamOpt is a googleapi.Option (https://godoc.org/google.golang.org/api/googleapi#CallOption)
// that adds query parameters to an API call.
type queryParamOpt struct {
	key, value string
}

func (qp queryParamOpt) Get() (string, string) { return qp.key, qp.value }

// ConditionalPatchFHIRResource conditionally patches an FHIR resource.
func ConditionalPatchFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, resourceType string, active bool) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// fhirStoreID := "my-fhir-store"
	// resourceType := "Patient"
	// active := true

	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	fhirService := healthcareService.Projects.Locations.Datasets.FhirStores.Fhir

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s", projectID, location, datasetID, fhirStoreID)

	payload := []map[string]interface{}{
		{
			"op":    "replace",
			"path":  "/active",
			"value": active,
		},
	}
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("json.Encode: %v", err)
	}

	call := fhirService.ConditionalPatch(parent, resourceType, bytes.NewReader(jsonPayload))

	call.Header().Set("Content-Type", "application/json-patch+json")

	// Refine your search by appending tags to the request in the form of query
	// parameters. This searches for resources updated in the last 48 hours.
	twoDaysAgo := time.Now().Add(-48 * time.Hour).Format("2006-01-02")
	lastUpdated := queryParamOpt{key: "_lastUpdated", value: "gt" + twoDaysAgo}

	resp, err := call.Do(lastUpdated)
	if err != nil {
		return fmt.Errorf("ConditionalPatch: %v", err)
	}

	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("could not read response: %v", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("ConditionalPatch: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	fmt.Fprintf(w, "%s", respBytes)

	return nil
}
<commit_msg>healthcare: add conditional patch region tag<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package conditionalpatch shows how to conditionallly patch.
// It's in a separate package so each sample can define queryParamOpt.
package conditionalpatch

// [START healthcare_conditional_patch_resource]

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

	healthcare "google.golang.org/api/healthcare/v1beta1"
)

// queryParamOpt is a googleapi.Option (https://godoc.org/google.golang.org/api/googleapi#CallOption)
// that adds query parameters to an API call.
type queryParamOpt struct {
	key, value string
}

func (qp queryParamOpt) Get() (string, string) { return qp.key, qp.value }

// ConditionalPatchFHIRResource conditionally patches an FHIR resource.
func ConditionalPatchFHIRResource(w io.Writer, projectID, location, datasetID, fhirStoreID, resourceType string, active bool) error {
	// projectID := "my-project"
	// location := "us-central1"
	// datasetID := "my-dataset"
	// fhirStoreID := "my-fhir-store"
	// resourceType := "Patient"
	// active := true

	ctx := context.Background()

	healthcareService, err := healthcare.NewService(ctx)
	if err != nil {
		return fmt.Errorf("healthcare.NewService: %v", err)
	}

	fhirService := healthcareService.Projects.Locations.Datasets.FhirStores.Fhir

	parent := fmt.Sprintf("projects/%s/locations/%s/datasets/%s/fhirStores/%s", projectID, location, datasetID, fhirStoreID)

	payload := []map[string]interface{}{
		{
			"op":    "replace",
			"path":  "/active",
			"value": active,
		},
	}
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("json.Encode: %v", err)
	}

	call := fhirService.ConditionalPatch(parent, resourceType, bytes.NewReader(jsonPayload))

	call.Header().Set("Content-Type", "application/json-patch+json")

	// Refine your search by appending tags to the request in the form of query
	// parameters. This searches for resources updated in the last 48 hours.
	twoDaysAgo := time.Now().Add(-48 * time.Hour).Format("2006-01-02")
	lastUpdated := queryParamOpt{key: "_lastUpdated", value: "gt" + twoDaysAgo}

	resp, err := call.Do(lastUpdated)
	if err != nil {
		return fmt.Errorf("ConditionalPatch: %v", err)
	}

	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("could not read response: %v", err)
	}

	if resp.StatusCode > 299 {
		return fmt.Errorf("ConditionalPatch: status %d %s: %s", resp.StatusCode, resp.Status, respBytes)
	}
	fmt.Fprintf(w, "%s", respBytes)

	return nil
}

// [END healthcare_conditional_patch_resource]
<|endoftext|>


<commit_before>package blinkstick

import (
	"fmt"
	"image/color"

	"github.com/boombuler/hid"
)

// Version of Blinkstick
// One Line for this, used by release.sh script
// Keep "const Version on one line"
const Version = "0.0.11"

// VendorID blinkstick
const VendorID = 0x20a0

// ProductID blinkstick
const ProductID = 0x41e5

// USBDevice ...
type USBDevice struct {
	DeviceInfo *hid.DeviceInfo
	Device     *hid.Device
}

// Blinkstick represents a blinkstick device
type Blinkstick interface {
	List() []Blinkstick
	SetColor(color.Color) error
	GetDeviceInfo() *hid.DeviceInfo
	ListFilter(hid *hid.DeviceInfo) (bool, Blinkstick)
}

// SetColor set color
func (usbDevice *USBDevice) setColor(index byte, c color.Color) error {
	if usbDevice.Device == nil {
		if err := usbDevice.Open(); err != nil {
			return err
		}
	}
	r, g, b, _ := c.RGBA()
	d := *usbDevice.Device
	return d.WriteFeature([]byte{0x05, 0x00, index, byte(r >> 8), byte(g >> 8), byte(b >> 8)})
}

// Open open a device
func (usbDevice *USBDevice) Open() error {
	device, err := usbDevice.DeviceInfo.Open()
	if err != nil {
		return fmt.Errorf("Error while opening device: %s", err)
	}
	usbDevice.Device = &device
	return nil
}

// ListFilter is used to filter device on List
type ListFilter func(*hid.DeviceInfo) (bool, Blinkstick)

// List gets all blinkstick device
func List(opts ...ListFilter) []Blinkstick {
	out := []Blinkstick{}

	if len(opts) == 0 {
		opts = append(opts, Nano{}.ListFilter)
	}

	for di := range hid.Devices() {
		if di.VendorId == VendorID && di.ProductId == ProductID {
			for _, o := range opts {
				if toKeep, blinkstick := o(di); toKeep {
					out = append(out, blinkstick)
				}
			}

		}
	}
	return out
}
<commit_msg>[auto] bump version to v0.0.12<commit_after>package blinkstick

import (
	"fmt"
	"image/color"

	"github.com/boombuler/hid"
)

// Version of Blinkstick
// One Line for this, used by release.sh script
// Keep "const Version on one line"
const Version = "0.0.12"

// VendorID blinkstick
const VendorID = 0x20a0

// ProductID blinkstick
const ProductID = 0x41e5

// USBDevice ...
type USBDevice struct {
	DeviceInfo *hid.DeviceInfo
	Device     *hid.Device
}

// Blinkstick represents a blinkstick device
type Blinkstick interface {
	List() []Blinkstick
	SetColor(color.Color) error
	GetDeviceInfo() *hid.DeviceInfo
	ListFilter(hid *hid.DeviceInfo) (bool, Blinkstick)
}

// SetColor set color
func (usbDevice *USBDevice) setColor(index byte, c color.Color) error {
	if usbDevice.Device == nil {
		if err := usbDevice.Open(); err != nil {
			return err
		}
	}
	r, g, b, _ := c.RGBA()
	d := *usbDevice.Device
	return d.WriteFeature([]byte{0x05, 0x00, index, byte(r >> 8), byte(g >> 8), byte(b >> 8)})
}

// Open open a device
func (usbDevice *USBDevice) Open() error {
	device, err := usbDevice.DeviceInfo.Open()
	if err != nil {
		return fmt.Errorf("Error while opening device: %s", err)
	}
	usbDevice.Device = &device
	return nil
}

// ListFilter is used to filter device on List
type ListFilter func(*hid.DeviceInfo) (bool, Blinkstick)

// List gets all blinkstick device
func List(opts ...ListFilter) []Blinkstick {
	out := []Blinkstick{}

	if len(opts) == 0 {
		opts = append(opts, Nano{}.ListFilter)
	}

	for di := range hid.Devices() {
		if di.VendorId == VendorID && di.ProductId == ProductID {
			for _, o := range opts {
				if toKeep, blinkstick := o(di); toKeep {
					out = append(out, blinkstick)
				}
			}

		}
	}
	return out
}
<|endoftext|>


<commit_before>package gone

import "net/http"

type Controller struct {
	ControllerName string
	ActionName     string
	Method         string
	Request        *http.Request
	Response       http.ResponseWriter
	TplPath        string
}<commit_msg>Revert "Add controller"<commit_after><|endoftext|>