<commit_before>// +build windows

package command

import (
	"errors"
	"time"
	"strconv"
	"syscall"
)

var (
	kernel32 = syscall.NewLazyDLL("kernel32")

	openProcess = kernel32.NewProc("OpenProcess")
	waitForSingleObject = kernel32.NewProc("WaitForSingleObject")
)

const _SYNCHRONIZE = 0x00100000
const _INFINITE = 0xFFFFFFFF

func pollPID(pid int, _ time.Duration) error {
	hProcess, _, lastError := openProcess.Call(_SYNCHRONIZE, 0, uintptr(pid))

	if hProcess == 0 {
		return errors.New("OpenProcess failed with " + lastError.Error())
	}

	result, _, lastError := waitForSingleObject.Call(hProcess, _INFINITE)

	if result != 0 {
		return errors.New("WaitForSingleObject failed with " + strconv.Itoa(int(result)) + ", last error " + lastError.Error())
	}

	return nil
}
<commit_msg>Refactor windows poll<commit_after>// +build windows

package command

import (
	"fmt"
	"syscall"
	"time"
)

func pollPID(pid int, _ time.Duration) error {
	kernel32 := syscall.NewLazyDLL("kernel32")
	openProcess := kernel32.NewProc("OpenProcess")
	waitForSingleObject := kernel32.NewProc("WaitForSingleObject")

	const (
		synchronize = 0x00100000
		infinite    = 0xFFFFFFFF
	)

	hProcess, _, lastErr := openProcess.Call(synchronize, 0, uintptr(pid))
	if hProcess == 0 {
		return fmt.Errorf("proc OpenProcess failed: %v", lastErr)
	}

	result, _, lastErr := waitForSingleObject.Call(hProcess, infinite)
	if result != 0 {
		return fmt.Errorf("proc WaitForSingleObject failed: %d %v", result, lastErr)
	}

	return nil
}
<|endoftext|>


<commit_before>package congestion

import (
	"time"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"github.com/lucas-clemente/quic-go/logging"
)

const (
	// maxDatagramSize is the default maximum packet size used in the Linux TCP implementation.
	// Used in QUIC for congestion window computations in bytes.
	maxDatagramSize         = protocol.ByteCount(protocol.MaxPacketSizeIPv4)
	maxBurstBytes           = 3 * maxDatagramSize
	renoBeta                = 0.7 // Reno backoff factor.
	maxCongestionWindow     = protocol.MaxCongestionWindowPackets * maxDatagramSize
	minCongestionWindow     = 2 * maxDatagramSize
	initialCongestionWindow = 32 * maxDatagramSize
)

type cubicSender struct {
	hybridSlowStart HybridSlowStart
	rttStats        *utils.RTTStats
	cubic           *Cubic
	pacer           *pacer
	clock           Clock

	reno bool

	// Track the largest packet that has been sent.
	largestSentPacketNumber protocol.PacketNumber

	// Track the largest packet that has been acked.
	largestAckedPacketNumber protocol.PacketNumber

	// Track the largest packet number outstanding when a CWND cutback occurs.
	largestSentAtLastCutback protocol.PacketNumber

	// Whether the last loss event caused us to exit slowstart.
	// Used for stats collection of slowstartPacketsLost
	lastCutbackExitedSlowstart bool

	// Congestion window in packets.
	congestionWindow protocol.ByteCount

	// Minimum congestion window in packets.
	minCongestionWindow protocol.ByteCount

	// Maximum congestion window.
	maxCongestionWindow protocol.ByteCount

	// Slow start congestion window in bytes, aka ssthresh.
	slowStartThreshold protocol.ByteCount

	// ACK counter for the Reno implementation.
	numAckedPackets uint64

	initialCongestionWindow    protocol.ByteCount
	initialMaxCongestionWindow protocol.ByteCount

	lastState logging.CongestionState
	tracer    logging.ConnectionTracer
}

var _ SendAlgorithm = &cubicSender{}
var _ SendAlgorithmWithDebugInfos = &cubicSender{}

// NewCubicSender makes a new cubic sender
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, tracer logging.ConnectionTracer) *cubicSender {
	return newCubicSender(clock, rttStats, reno, initialCongestionWindow, maxCongestionWindow, tracer)
}

func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount, tracer logging.ConnectionTracer) *cubicSender {
	c := &cubicSender{
		rttStats:                   rttStats,
		largestSentPacketNumber:    protocol.InvalidPacketNumber,
		largestAckedPacketNumber:   protocol.InvalidPacketNumber,
		largestSentAtLastCutback:   protocol.InvalidPacketNumber,
		initialCongestionWindow:    initialCongestionWindow,
		initialMaxCongestionWindow: initialMaxCongestionWindow,
		congestionWindow:           initialCongestionWindow,
		minCongestionWindow:        minCongestionWindow,
		slowStartThreshold:         initialMaxCongestionWindow,
		maxCongestionWindow:        initialMaxCongestionWindow,
		cubic:                      NewCubic(clock),
		clock:                      clock,
		reno:                       reno,
		tracer:                     tracer,
	}
	c.pacer = newPacer(c.BandwidthEstimate)
	if c.tracer != nil {
		c.lastState = logging.CongestionStateSlowStart
		c.tracer.UpdatedCongestionState(logging.CongestionStateSlowStart)
	}
	return c
}

// TimeUntilSend returns when the next packet should be sent.
func (c *cubicSender) TimeUntilSend(_ protocol.ByteCount) time.Time {
	return c.pacer.TimeUntilSend()
}

func (c *cubicSender) HasPacingBudget() bool {
	return c.pacer.Budget(c.clock.Now()) >= maxDatagramSize
}

func (c *cubicSender) OnPacketSent(
	sentTime time.Time,
	bytesInFlight protocol.ByteCount,
	packetNumber protocol.PacketNumber,
	bytes protocol.ByteCount,
	isRetransmittable bool,
) {
	c.pacer.SentPacket(sentTime, bytes)
	if !isRetransmittable {
		return
	}
	c.largestSentPacketNumber = packetNumber
	c.hybridSlowStart.OnPacketSent(packetNumber)
}

func (c *cubicSender) CanSend(bytesInFlight protocol.ByteCount) bool {
	return bytesInFlight < c.GetCongestionWindow()
}

func (c *cubicSender) InRecovery() bool {
	return c.largestAckedPacketNumber != protocol.InvalidPacketNumber && c.largestAckedPacketNumber <= c.largestSentAtLastCutback
}

func (c *cubicSender) InSlowStart() bool {
	return c.GetCongestionWindow() < c.slowStartThreshold
}

func (c *cubicSender) GetCongestionWindow() protocol.ByteCount {
	return c.congestionWindow
}

func (c *cubicSender) MaybeExitSlowStart() {
	if c.InSlowStart() && c.hybridSlowStart.ShouldExitSlowStart(c.rttStats.LatestRTT(), c.rttStats.MinRTT(), c.GetCongestionWindow()/maxDatagramSize) {
		// exit slow start
		c.slowStartThreshold = c.congestionWindow
		c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
	}
}

func (c *cubicSender) OnPacketAcked(
	ackedPacketNumber protocol.PacketNumber,
	ackedBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
	eventTime time.Time,
) {
	c.largestAckedPacketNumber = utils.MaxPacketNumber(ackedPacketNumber, c.largestAckedPacketNumber)
	if c.InRecovery() {
		return
	}
	c.maybeIncreaseCwnd(ackedPacketNumber, ackedBytes, priorInFlight, eventTime)
	if c.InSlowStart() {
		c.hybridSlowStart.OnPacketAcked(ackedPacketNumber)
	}
}

func (c *cubicSender) OnPacketLost(
	packetNumber protocol.PacketNumber,
	lostBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
) {
	// TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
	// already sent should be treated as a single loss event, since it's expected.
	if packetNumber <= c.largestSentAtLastCutback {
		return
	}
	c.lastCutbackExitedSlowstart = c.InSlowStart()
	c.maybeTraceStateChange(logging.CongestionStateRecovery)

	if c.reno {
		c.congestionWindow = protocol.ByteCount(float64(c.congestionWindow) * renoBeta)
	} else {
		c.congestionWindow = c.cubic.CongestionWindowAfterPacketLoss(c.congestionWindow)
	}
	if c.congestionWindow < c.minCongestionWindow {
		c.congestionWindow = c.minCongestionWindow
	}
	c.slowStartThreshold = c.congestionWindow
	c.largestSentAtLastCutback = c.largestSentPacketNumber
	// reset packet count from congestion avoidance mode. We start
	// counting again when we're out of recovery.
	c.numAckedPackets = 0
}

// Called when we receive an ack. Normal TCP tracks how many packets one ack
// represents, but quic has a separate ack for each packet.
func (c *cubicSender) maybeIncreaseCwnd(
	_ protocol.PacketNumber,
	ackedBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
	eventTime time.Time,
) {
	// Do not increase the congestion window unless the sender is close to using
	// the current window.
	if !c.isCwndLimited(priorInFlight) {
		c.cubic.OnApplicationLimited()
		c.maybeTraceStateChange(logging.CongestionStateApplicationLimited)
		return
	}
	if c.congestionWindow >= c.maxCongestionWindow {
		return
	}
	if c.InSlowStart() {
		// TCP slow start, exponential growth, increase by one for each ACK.
		c.congestionWindow += maxDatagramSize
		c.maybeTraceStateChange(logging.CongestionStateSlowStart)
		return
	}
	// Congestion avoidance
	c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
	if c.reno {
		// Classic Reno congestion avoidance.
		c.numAckedPackets++
		if c.numAckedPackets >= uint64(c.congestionWindow/maxDatagramSize) {
			c.congestionWindow += maxDatagramSize
			c.numAckedPackets = 0
		}
	} else {
		c.congestionWindow = utils.MinByteCount(c.maxCongestionWindow, c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime))
	}
}

func (c *cubicSender) isCwndLimited(bytesInFlight protocol.ByteCount) bool {
	congestionWindow := c.GetCongestionWindow()
	if bytesInFlight >= congestionWindow {
		return true
	}
	availableBytes := congestionWindow - bytesInFlight
	slowStartLimited := c.InSlowStart() && bytesInFlight > congestionWindow/2
	return slowStartLimited || availableBytes <= maxBurstBytes
}

// BandwidthEstimate returns the current bandwidth estimate
func (c *cubicSender) BandwidthEstimate() Bandwidth {
	srtt := c.rttStats.SmoothedRTT()
	if srtt == 0 {
		// If we haven't measured an rtt, the bandwidth estimate is unknown.
		return infBandwidth
	}
	return BandwidthFromDelta(c.GetCongestionWindow(), srtt)
}

// OnRetransmissionTimeout is called on an retransmission timeout
func (c *cubicSender) OnRetransmissionTimeout(packetsRetransmitted bool) {
	c.largestSentAtLastCutback = protocol.InvalidPacketNumber
	if !packetsRetransmitted {
		return
	}
	c.hybridSlowStart.Restart()
	c.cubic.Reset()
	c.slowStartThreshold = c.congestionWindow / 2
	c.congestionWindow = c.minCongestionWindow
}

// OnConnectionMigration is called when the connection is migrated (?)
func (c *cubicSender) OnConnectionMigration() {
	c.hybridSlowStart.Restart()
	c.largestSentPacketNumber = protocol.InvalidPacketNumber
	c.largestAckedPacketNumber = protocol.InvalidPacketNumber
	c.largestSentAtLastCutback = protocol.InvalidPacketNumber
	c.lastCutbackExitedSlowstart = false
	c.cubic.Reset()
	c.numAckedPackets = 0
	c.congestionWindow = c.initialCongestionWindow
	c.slowStartThreshold = c.initialMaxCongestionWindow
	c.maxCongestionWindow = c.initialMaxCongestionWindow
}

func (c *cubicSender) maybeTraceStateChange(new logging.CongestionState) {
	if c.tracer == nil || new == c.lastState {
		return
	}
	c.tracer.UpdatedCongestionState(new)
}
<commit_msg>fix tracing of congestion state updates<commit_after>package congestion

import (
	"time"

	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"github.com/lucas-clemente/quic-go/logging"
)

const (
	// maxDatagramSize is the default maximum packet size used in the Linux TCP implementation.
	// Used in QUIC for congestion window computations in bytes.
	maxDatagramSize         = protocol.ByteCount(protocol.MaxPacketSizeIPv4)
	maxBurstBytes           = 3 * maxDatagramSize
	renoBeta                = 0.7 // Reno backoff factor.
	maxCongestionWindow     = protocol.MaxCongestionWindowPackets * maxDatagramSize
	minCongestionWindow     = 2 * maxDatagramSize
	initialCongestionWindow = 32 * maxDatagramSize
)

type cubicSender struct {
	hybridSlowStart HybridSlowStart
	rttStats        *utils.RTTStats
	cubic           *Cubic
	pacer           *pacer
	clock           Clock

	reno bool

	// Track the largest packet that has been sent.
	largestSentPacketNumber protocol.PacketNumber

	// Track the largest packet that has been acked.
	largestAckedPacketNumber protocol.PacketNumber

	// Track the largest packet number outstanding when a CWND cutback occurs.
	largestSentAtLastCutback protocol.PacketNumber

	// Whether the last loss event caused us to exit slowstart.
	// Used for stats collection of slowstartPacketsLost
	lastCutbackExitedSlowstart bool

	// Congestion window in packets.
	congestionWindow protocol.ByteCount

	// Minimum congestion window in packets.
	minCongestionWindow protocol.ByteCount

	// Maximum congestion window.
	maxCongestionWindow protocol.ByteCount

	// Slow start congestion window in bytes, aka ssthresh.
	slowStartThreshold protocol.ByteCount

	// ACK counter for the Reno implementation.
	numAckedPackets uint64

	initialCongestionWindow    protocol.ByteCount
	initialMaxCongestionWindow protocol.ByteCount

	lastState logging.CongestionState
	tracer    logging.ConnectionTracer
}

var _ SendAlgorithm = &cubicSender{}
var _ SendAlgorithmWithDebugInfos = &cubicSender{}

// NewCubicSender makes a new cubic sender
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, tracer logging.ConnectionTracer) *cubicSender {
	return newCubicSender(clock, rttStats, reno, initialCongestionWindow, maxCongestionWindow, tracer)
}

func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount, tracer logging.ConnectionTracer) *cubicSender {
	c := &cubicSender{
		rttStats:                   rttStats,
		largestSentPacketNumber:    protocol.InvalidPacketNumber,
		largestAckedPacketNumber:   protocol.InvalidPacketNumber,
		largestSentAtLastCutback:   protocol.InvalidPacketNumber,
		initialCongestionWindow:    initialCongestionWindow,
		initialMaxCongestionWindow: initialMaxCongestionWindow,
		congestionWindow:           initialCongestionWindow,
		minCongestionWindow:        minCongestionWindow,
		slowStartThreshold:         initialMaxCongestionWindow,
		maxCongestionWindow:        initialMaxCongestionWindow,
		cubic:                      NewCubic(clock),
		clock:                      clock,
		reno:                       reno,
		tracer:                     tracer,
	}
	c.pacer = newPacer(c.BandwidthEstimate)
	if c.tracer != nil {
		c.lastState = logging.CongestionStateSlowStart
		c.tracer.UpdatedCongestionState(logging.CongestionStateSlowStart)
	}
	return c
}

// TimeUntilSend returns when the next packet should be sent.
func (c *cubicSender) TimeUntilSend(_ protocol.ByteCount) time.Time {
	return c.pacer.TimeUntilSend()
}

func (c *cubicSender) HasPacingBudget() bool {
	return c.pacer.Budget(c.clock.Now()) >= maxDatagramSize
}

func (c *cubicSender) OnPacketSent(
	sentTime time.Time,
	bytesInFlight protocol.ByteCount,
	packetNumber protocol.PacketNumber,
	bytes protocol.ByteCount,
	isRetransmittable bool,
) {
	c.pacer.SentPacket(sentTime, bytes)
	if !isRetransmittable {
		return
	}
	c.largestSentPacketNumber = packetNumber
	c.hybridSlowStart.OnPacketSent(packetNumber)
}

func (c *cubicSender) CanSend(bytesInFlight protocol.ByteCount) bool {
	return bytesInFlight < c.GetCongestionWindow()
}

func (c *cubicSender) InRecovery() bool {
	return c.largestAckedPacketNumber != protocol.InvalidPacketNumber && c.largestAckedPacketNumber <= c.largestSentAtLastCutback
}

func (c *cubicSender) InSlowStart() bool {
	return c.GetCongestionWindow() < c.slowStartThreshold
}

func (c *cubicSender) GetCongestionWindow() protocol.ByteCount {
	return c.congestionWindow
}

func (c *cubicSender) MaybeExitSlowStart() {
	if c.InSlowStart() && c.hybridSlowStart.ShouldExitSlowStart(c.rttStats.LatestRTT(), c.rttStats.MinRTT(), c.GetCongestionWindow()/maxDatagramSize) {
		// exit slow start
		c.slowStartThreshold = c.congestionWindow
		c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
	}
}

func (c *cubicSender) OnPacketAcked(
	ackedPacketNumber protocol.PacketNumber,
	ackedBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
	eventTime time.Time,
) {
	c.largestAckedPacketNumber = utils.MaxPacketNumber(ackedPacketNumber, c.largestAckedPacketNumber)
	if c.InRecovery() {
		return
	}
	c.maybeIncreaseCwnd(ackedPacketNumber, ackedBytes, priorInFlight, eventTime)
	if c.InSlowStart() {
		c.hybridSlowStart.OnPacketAcked(ackedPacketNumber)
	}
}

func (c *cubicSender) OnPacketLost(
	packetNumber protocol.PacketNumber,
	lostBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
) {
	// TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
	// already sent should be treated as a single loss event, since it's expected.
	if packetNumber <= c.largestSentAtLastCutback {
		return
	}
	c.lastCutbackExitedSlowstart = c.InSlowStart()
	c.maybeTraceStateChange(logging.CongestionStateRecovery)

	if c.reno {
		c.congestionWindow = protocol.ByteCount(float64(c.congestionWindow) * renoBeta)
	} else {
		c.congestionWindow = c.cubic.CongestionWindowAfterPacketLoss(c.congestionWindow)
	}
	if c.congestionWindow < c.minCongestionWindow {
		c.congestionWindow = c.minCongestionWindow
	}
	c.slowStartThreshold = c.congestionWindow
	c.largestSentAtLastCutback = c.largestSentPacketNumber
	// reset packet count from congestion avoidance mode. We start
	// counting again when we're out of recovery.
	c.numAckedPackets = 0
}

// Called when we receive an ack. Normal TCP tracks how many packets one ack
// represents, but quic has a separate ack for each packet.
func (c *cubicSender) maybeIncreaseCwnd(
	_ protocol.PacketNumber,
	ackedBytes protocol.ByteCount,
	priorInFlight protocol.ByteCount,
	eventTime time.Time,
) {
	// Do not increase the congestion window unless the sender is close to using
	// the current window.
	if !c.isCwndLimited(priorInFlight) {
		c.cubic.OnApplicationLimited()
		c.maybeTraceStateChange(logging.CongestionStateApplicationLimited)
		return
	}
	if c.congestionWindow >= c.maxCongestionWindow {
		return
	}
	if c.InSlowStart() {
		// TCP slow start, exponential growth, increase by one for each ACK.
		c.congestionWindow += maxDatagramSize
		c.maybeTraceStateChange(logging.CongestionStateSlowStart)
		return
	}
	// Congestion avoidance
	c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
	if c.reno {
		// Classic Reno congestion avoidance.
		c.numAckedPackets++
		if c.numAckedPackets >= uint64(c.congestionWindow/maxDatagramSize) {
			c.congestionWindow += maxDatagramSize
			c.numAckedPackets = 0
		}
	} else {
		c.congestionWindow = utils.MinByteCount(c.maxCongestionWindow, c.cubic.CongestionWindowAfterAck(ackedBytes, c.congestionWindow, c.rttStats.MinRTT(), eventTime))
	}
}

func (c *cubicSender) isCwndLimited(bytesInFlight protocol.ByteCount) bool {
	congestionWindow := c.GetCongestionWindow()
	if bytesInFlight >= congestionWindow {
		return true
	}
	availableBytes := congestionWindow - bytesInFlight
	slowStartLimited := c.InSlowStart() && bytesInFlight > congestionWindow/2
	return slowStartLimited || availableBytes <= maxBurstBytes
}

// BandwidthEstimate returns the current bandwidth estimate
func (c *cubicSender) BandwidthEstimate() Bandwidth {
	srtt := c.rttStats.SmoothedRTT()
	if srtt == 0 {
		// If we haven't measured an rtt, the bandwidth estimate is unknown.
		return infBandwidth
	}
	return BandwidthFromDelta(c.GetCongestionWindow(), srtt)
}

// OnRetransmissionTimeout is called on an retransmission timeout
func (c *cubicSender) OnRetransmissionTimeout(packetsRetransmitted bool) {
	c.largestSentAtLastCutback = protocol.InvalidPacketNumber
	if !packetsRetransmitted {
		return
	}
	c.hybridSlowStart.Restart()
	c.cubic.Reset()
	c.slowStartThreshold = c.congestionWindow / 2
	c.congestionWindow = c.minCongestionWindow
}

// OnConnectionMigration is called when the connection is migrated (?)
func (c *cubicSender) OnConnectionMigration() {
	c.hybridSlowStart.Restart()
	c.largestSentPacketNumber = protocol.InvalidPacketNumber
	c.largestAckedPacketNumber = protocol.InvalidPacketNumber
	c.largestSentAtLastCutback = protocol.InvalidPacketNumber
	c.lastCutbackExitedSlowstart = false
	c.cubic.Reset()
	c.numAckedPackets = 0
	c.congestionWindow = c.initialCongestionWindow
	c.slowStartThreshold = c.initialMaxCongestionWindow
	c.maxCongestionWindow = c.initialMaxCongestionWindow
}

func (c *cubicSender) maybeTraceStateChange(new logging.CongestionState) {
	if c.tracer == nil || new == c.lastState {
		return
	}
	c.tracer.UpdatedCongestionState(new)
	c.lastState = new
}
<|endoftext|>


<commit_before>// Package overrides defines overridden configurations for repositories that
// need special handling. It should be imported for side effects by all main
// packages that perform analysis work.
//
// It is separate from package config because it needs to import packages that
// config may not depend on (or else there will be an import cycle).
package overrides

import (
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/javascript"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/python"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	o := map[repo.URI]*config.Repository{
		"code.google.com/p/go": &config.Repository{
			ScanIgnore: []string{"./misc", "./test", "./doc", "./cmd", "./src/cmd"},
		},
		"github.com/joyent/node": &config.Repository{
			SourceUnits: unit.SourceUnits{
				&javascript.CommonJSPackage{
					Package:            []byte(`{}`),
					PackageName:        javascript.NodeJSStdlibUnit,
					PackageDescription: "The Node.js core API.",
					Dir:                ".",
					LibFiles: []string{
						"lib/assert.js",
						"lib/buffer.js",
						"lib/child_process.js",
						"lib/cluster.js",
						"lib/console.js",
						"lib/constants.js",
						"lib/crypto.js",
						"lib/dgram.js",
						"lib/dns.js",
						"lib/domain.js",
						"lib/events.js",
						"lib/freelist.js",
						"lib/fs.js",
						"lib/http.js",
						"lib/https.js",
						"lib/module.js",
						"lib/net.js",
						"lib/os.js",
						"lib/path.js",
						"lib/punycode.js",
						"lib/querystring.js",
						"lib/readline.js",
						"lib/repl.js",
						"lib/smalloc.js",
						"lib/stream.js",
						"lib/string_decoder.js",
						"lib/sys.js",
						"lib/timers.js",
						"lib/tls.js",
						"lib/tty.js",
						"lib/url.js",
						"lib/util.js",
						"lib/vm.js",
						"lib/zlib.js",
					},
				},
			},

			// Suppress the Python source unit that exists because the node
			// repo has *.py files.
			ScanIgnoreUnitTypes: []string{unit.Type(&python.DistPackage{})},
			ScanIgnore:          []string{"./tools", "./deps", "./test", "./src"},

			Global: config.Global{
				"jsg": &javascript.JSGConfig{
					Plugins: map[string]interface{}{
						// In this repository, the node core modules are in the
						// lib/ dir.
						"node": map[string]string{"coreModulesDir": "lib/"},

						"$(JSG_DIR)/node_modules/tern-node-api-doc/node-api-doc": map[string]string{
							"apiDocDir":      "doc/api/",
							"apiSrcDir":      "lib/",
							"generateJSPath": "tools/doc/generate.js",
						},
					},
				},
			},
		},
	}
	for repoURI, c := range o {
		config.AddOverride(repoURI, c)
	}
}
<commit_msg>skip go-restful ./examples (multiple main pkgs)<commit_after>// Package overrides defines overridden configurations for repositories that
// need special handling. It should be imported for side effects by all main
// packages that perform analysis work.
//
// It is separate from package config because it needs to import packages that
// config may not depend on (or else there will be an import cycle).
package overrides

import (
	"sourcegraph.com/sourcegraph/srcgraph/config"
	"sourcegraph.com/sourcegraph/srcgraph/repo"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/javascript"
	"sourcegraph.com/sourcegraph/srcgraph/toolchain/python"
	"sourcegraph.com/sourcegraph/srcgraph/unit"
)

func init() {
	o := map[repo.URI]*config.Repository{
		"github.com/emicklei/go-restful": &config.Repository{
			ScanIgnore: []string{"./examples"},
		},
		"code.google.com/p/go": &config.Repository{
			ScanIgnore: []string{"./misc", "./test", "./doc", "./cmd", "./src/cmd"},
		},
		"github.com/joyent/node": &config.Repository{
			SourceUnits: unit.SourceUnits{
				&javascript.CommonJSPackage{
					Package:            []byte(`{}`),
					PackageName:        javascript.NodeJSStdlibUnit,
					PackageDescription: "The Node.js core API.",
					Dir:                ".",
					LibFiles: []string{
						"lib/assert.js",
						"lib/buffer.js",
						"lib/child_process.js",
						"lib/cluster.js",
						"lib/console.js",
						"lib/constants.js",
						"lib/crypto.js",
						"lib/dgram.js",
						"lib/dns.js",
						"lib/domain.js",
						"lib/events.js",
						"lib/freelist.js",
						"lib/fs.js",
						"lib/http.js",
						"lib/https.js",
						"lib/module.js",
						"lib/net.js",
						"lib/os.js",
						"lib/path.js",
						"lib/punycode.js",
						"lib/querystring.js",
						"lib/readline.js",
						"lib/repl.js",
						"lib/smalloc.js",
						"lib/stream.js",
						"lib/string_decoder.js",
						"lib/sys.js",
						"lib/timers.js",
						"lib/tls.js",
						"lib/tty.js",
						"lib/url.js",
						"lib/util.js",
						"lib/vm.js",
						"lib/zlib.js",
					},
				},
			},

			// Suppress the Python source unit that exists because the node
			// repo has *.py files.
			ScanIgnoreUnitTypes: []string{unit.Type(&python.DistPackage{})},
			ScanIgnore:          []string{"./tools", "./deps", "./test", "./src"},

			Global: config.Global{
				"jsg": &javascript.JSGConfig{
					Plugins: map[string]interface{}{
						// In this repository, the node core modules are in the
						// lib/ dir.
						"node": map[string]string{"coreModulesDir": "lib/"},

						"$(JSG_DIR)/node_modules/tern-node-api-doc/node-api-doc": map[string]string{
							"apiDocDir":      "doc/api/",
							"apiSrcDir":      "lib/",
							"generateJSPath": "tools/doc/generate.js",
						},
					},
				},
			},
		},
	}
	for repoURI, c := range o {
		config.AddOverride(repoURI, c)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"time"
)

// Prefix Const
const (
	prefix = "jade:"
)

// 'global' variables
var (
	// command line argument
	Token string
	// error logging
	Log         *log.Logger
	currentTime string
	self        *discordgo.User
)

// initalize variables
func init() {
	executable, e := os.Executable()
	if e != nil {
		panic(e)
	}
	path := filepath.Dir(executable)

	// command line argument
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.Parse()
	// error logging
	currentTime = time.Now().Format("2006-01-02@15h04m")
	file, err := os.Create(path + ".logs@" + currentTime + ".log")
	if err != nil {
		panic(err)
	}
	Log = log.New(file, "", log.Ldate|log.Ltime|log.Llongfile|log.LUTC)
}

// Main
func main() {

	// Create a new Discord session using the provided bot token.
	// token must be prefaced with "Bot "
	bot, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Bot Event Handlers
	bot.AddHandler(messageCreate)
	bot.AddHandler(ready)

	// Open a websocket connection to Discord and begin listening.
	err = bot.Open()

	if err != nil {
		fmt.Println("error opening connection,", err)
		Log.Println("error opening connection,", err)
		return
	}

	// Wait here until CTRL-C or other term signal is received.
	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc

	// Cleanly close down the Discord session.
	bot.Close()
}

// This function is called when the bot connects to discord
func ready(discordSession *discordgo.Session, discordReady *discordgo.Ready) {
	discordSession.UpdateStatus(0, "prefix: \""+prefix+" \"")
	self = discordReady.User
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(discordSession *discordgo.Session,
	discordMessage *discordgo.MessageCreate) {

	message := parseText(discordMessage.Message.Content)
	// Ignore all messages created by the bot itself
	if discordMessage.Author.Bot == true {
		return
	}

	// commands
	if message[0] == prefix && len(message) > 1 {
		switch message[1] {
		case "discord":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"https://discord.gg/PGVh2M8")
		case "invite":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"<https://discordapp.com/oauth2/authorize?client_id=331204502277586945&scope=bot&permissions=379968>")
		case "help", "commands":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"not even god can help you now :)")
		case "about", "credits":
			discordSession.ChannelMessageSendEmbed(discordMessage.ChannelID, getCredits())
		default:
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				":?")
		}
	}

	// text responses
	textResponse, shouldRespond := getTextResponse(discordMessage.Content)

	if shouldRespond {
		discordSession.ChannelMessageSend(discordMessage.ChannelID, textResponse)
	}

	if isMentioned(discordMessage.Mentions) {
		discordSession.ChannelMessageSend(discordMessage.ChannelID,
			"hello! :D\nby the way my prefix is '`jade: `'. just incase you wanted to know! :p")
	}
}

// checks messages for contents, returns a response if it contains one
// emojis are sourced from the 'jade.moe' server
func getTextResponse(message string) (string, bool) {
	response := ""
	contentFound := false
	fmt.Println(message)

	// problem with current method, multiple responses are not created if there are multiple matches
	// sure looks a hell of a lot cleaner than a lot of if statements though
	switch {
	case strings.Contains(message, "owo"):
		response = "oh woah whats this? :o"
		contentFound = true
	case strings.Contains(message, "love you"):
		response = "i love you too!! :D"
		contentFound = true
	case strings.Contains(message, "good dog"):
		response = "best friend!"
		contentFound = true
	case strings.Contains(message, "teef"):
		response = "<:jadeteefs:317080214364618753>"
		contentFound = true
	case strings.Contains(message, "kissjade"):
		response = "<:jb_embarrassed:432756486406537217><:jade_hearts:432685108085129246>"
		contentFound = true
	case strings.Contains(message, "pats"):
		response = "<:jb_headpats:432962465437843466>"
		contentFound = true
	case strings.Contains(message, "thinking"), strings.Contains(message, "🤔"):
		response = "<:jadethinking:395982297490522122>"
		contentFound = true
	}

	return response, contentFound
}

func isMentioned(users []*discordgo.User) bool {
	for _, ele := range users {
		if ele.Username == self.Username {
			return true
		}
	}
	return false
}

func getCredits() *discordgo.MessageEmbed {
	embed := &discordgo.MessageEmbed{
		Color: 0x4bec13,
		Type:  "About",
		Fields: []*discordgo.MessageEmbedField{
			&discordgo.MessageEmbedField{
				Name:   "Jadebot",
				Value:  "Created by \\🐙\\🐙#0413 ( http://oct2pus.tumblr.com/ )\nJadebot uses the 'discordgo' library\n( https://github.com/bwmarrin/discordgo/ )",
				Inline: false,
			},
			&discordgo.MessageEmbedField{
				Name:   "Special Thanks",
				Value:  "Avatar By Chuchumi ( http://chuchumi.tumblr.com/ )\nOriginal Avatar by sun gun#0373 ( http://taiyoooh.tumblr.com )\nEmojis by Dzuk#1671",
				Inline: false,
			},
			&discordgo.MessageEmbedField{
				Name:   "Disclaimer",
				Value:  "Jadebot uses **Mutant Standard Emoji** (https://mutant.tech)\n**Mutant Standard Emoji** are licensed under CC-BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/) ",
				Inline: false,
			},
		},
		Thumbnail: &discordgo.MessageEmbedThumbnail{
			URL: self.AvatarURL(""),
		},
	}

	return embed
}

// logs errors
func checkError(err error) bool {
	if err != nil {
		fmt.Println("error: ", err)
		Log.Println("error: ", err)
		return true
	}
	return false
}

// converts text to lowercase substrings
func parseText(m string) []string {

	m = strings.ToLower(m)
	return strings.Split(m, " ")
}
<commit_msg>changed help to a short explaination of what happened<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/bwmarrin/discordgo"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"time"
)

// Prefix Const
const (
	prefix = "jade:"
)

// 'global' variables
var (
	// command line argument
	Token string
	// error logging
	Log         *log.Logger
	currentTime string
	self        *discordgo.User
)

// initalize variables
func init() {
	executable, e := os.Executable()
	if e != nil {
		panic(e)
	}
	path := filepath.Dir(executable)

	// command line argument
	flag.StringVar(&Token, "t", "", "Bot Token")
	flag.Parse()
	// error logging
	currentTime = time.Now().Format("2006-01-02@15h04m")
	file, err := os.Create(path + ".logs@" + currentTime + ".log")
	if err != nil {
		panic(err)
	}
	Log = log.New(file, "", log.Ldate|log.Ltime|log.Llongfile|log.LUTC)
}

// Main
func main() {

	// Create a new Discord session using the provided bot token.
	// token must be prefaced with "Bot "
	bot, err := discordgo.New("Bot " + Token)
	if err != nil {
		fmt.Println("error creating Discord session,", err)
		return
	}

	// Bot Event Handlers
	bot.AddHandler(messageCreate)
	bot.AddHandler(ready)

	// Open a websocket connection to Discord and begin listening.
	err = bot.Open()

	if err != nil {
		fmt.Println("error opening connection,", err)
		Log.Println("error opening connection,", err)
		return
	}

	// Wait here until CTRL-C or other term signal is received.
	fmt.Println("Bot is now running.  Press CTRL-C to exit.")
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
	<-sc

	// Cleanly close down the Discord session.
	bot.Close()
}

// This function is called when the bot connects to discord
func ready(discordSession *discordgo.Session, discordReady *discordgo.Ready) {
	discordSession.UpdateStatus(0, "prefix: \""+prefix+" \"")
	self = discordReady.User
}

// This function will be called (due to AddHandler above) every time a new
// message is created on any channel that the autenticated bot has access to.
func messageCreate(discordSession *discordgo.Session,
	discordMessage *discordgo.MessageCreate) {

	message := parseText(discordMessage.Message.Content)
	// Ignore all messages created by the bot itself
	if discordMessage.Author.Bot == true {
		return
	}

	// commands
	if message[0] == prefix && len(message) > 1 {
		switch message[1] {
		case "discord":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"https://discord.gg/PGVh2M8")
		case "invite":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"<https://discordapp.com/oauth2/authorize?client_id=331204502277586945&scope=bot&permissions=379968>")
		case "help", "commands":
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"im in the middle of being rewriten because of an issue involving the bot library i was previously using, which is why i was offline until now! Please give me a moment while I reassemble myself. <:jb_teefs:469677925336219649>, i could also use some input on what you want first! you should check my `discord` and tell me there!")
		case "about", "credits":
			discordSession.ChannelMessageSendEmbed(discordMessage.ChannelID, getCredits())
		default:
			discordSession.ChannelMessageSend(discordMessage.ChannelID,
				"i don't quite understand, maybe you should ask for `help` ;P")

		}
	}

	// text responses
	textResponse, shouldRespond := getTextResponse(discordMessage.Content)

	if shouldRespond {
		discordSession.ChannelMessageSend(discordMessage.ChannelID, textResponse)
	}

	if isMentioned(discordMessage.Mentions) {
		discordSession.ChannelMessageSend(discordMessage.ChannelID,
			"hello! :D\nby the way my prefix is '`jade: `'. just incase you wanted to know! :p")
	}
}

// checks messages for contents, returns a response if it contains one
// emojis are sourced from the 'jade.moe' server
func getTextResponse(message string) (string, bool) {
	response := ""
	contentFound := false
	// problem with current method, multiple responses are not created if there are multiple matches
	// sure looks a hell of a lot cleaner than a lot of if statements though
	switch {
	case strings.Contains(message, "owo"):
		response = "oh woah whats this? :o"
		contentFound = true
	case strings.Contains(message, "love you"):
		response = "i love you too!! :D"
		contentFound = true
	case strings.Contains(message, "good dog"):
		response = "best friend!"
		contentFound = true
	case strings.Contains(message, "teef"):
		response = "<:jadeteefs:317080214364618753>"
		contentFound = true
	case strings.Contains(message, "kissjade"):
		response = "<:jb_embarrassed:432756486406537217><:jade_hearts:432685108085129246>"
		contentFound = true
	case strings.Contains(message, "pats"):
		response = "<:jb_headpats:432962465437843466>"
		contentFound = true
	case strings.Contains(message, "thinking"), strings.Contains(message, "🤔"):
		response = "<:jadethinking:395982297490522122>"
		contentFound = true
	}

	return response, contentFound
}

func isMentioned(users []*discordgo.User) bool {
	for _, ele := range users {
		if ele.Username == self.Username {
			return true
		}
	}
	return false
}

func getCredits() *discordgo.MessageEmbed {
	embed := &discordgo.MessageEmbed{
		Color: 0x4bec13,
		Type:  "About",
		Fields: []*discordgo.MessageEmbedField{
			&discordgo.MessageEmbedField{
				Name:   "Jadebot",
				Value:  "Created by \\🐙\\🐙#0413 ( http://oct2pus.tumblr.com/ )\nJadebot uses the 'discordgo' library\n( https://github.com/bwmarrin/discordgo/ )",
				Inline: false,
			},
			&discordgo.MessageEmbedField{
				Name:   "Special Thanks",
				Value:  "Avatar By Chuchumi ( http://chuchumi.tumblr.com/ )\nOriginal Avatar by sun gun#0373 ( http://taiyoooh.tumblr.com )\nEmojis by Dzuk#1671",
				Inline: false,
			},
			&discordgo.MessageEmbedField{
				Name:   "Disclaimer",
				Value:  "Jadebot uses **Mutant Standard Emoji** (https://mutant.tech)\n**Mutant Standard Emoji** are licensed under CC-BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/) ",
				Inline: false,
			},
		},
		Thumbnail: &discordgo.MessageEmbedThumbnail{
			URL: self.AvatarURL(""),
		},
	}

	return embed
}

// logs errors
func checkError(err error) bool {
	if err != nil {
		fmt.Println("error: ", err)
		Log.Println("error: ", err)
		return true
	}
	return false
}

// converts text to lowercase substrings
func parseText(m string) []string {

	m = strings.ToLower(m)
	return strings.Split(m, " ")
}
<|endoftext|>


<commit_before>package main

import "fmt"

type Int int

func (a *Int) duplicar(){
  *a *= 2
}

func main() {
  var a Int = 4
  fmt.Println("a:",a)
  a.duplicar()
  fmt.Println("a:",a)
}
<commit_msg>Playgroung: Añadiendo comentarios a oogo/bultin/bi.go<commit_after>package main

import "fmt"

// Es necesario hacer esto porque no se puede aplicar métodos
// con tipos de datos no escrito en el mismo archivo. En este
// caso int es un built-in types
type Int int

// Ejemplo de OOP con built-in type
func (a *Int) duplicar(){
  *a *= 2
}

func main() {
  var a Int = 4
  fmt.Println("a:",a)
  a.duplicar()
  fmt.Println("a:",a)
}
<|endoftext|>


<commit_before>package collector

import (
	"bufio"
	"context"
	"io"
	"strings"
	"time"

	"github.com/bcicen/ctop/models"
	api "github.com/fsouza/go-dockerclient"
)

type DockerLogs struct {
	id     string
	client *api.Client
	done   chan bool
}

func NewDockerLogs(id string, client *api.Client) *DockerLogs {
	return &DockerLogs{
		id:     id,
		client: client,
		done:   make(chan bool),
	}
}

func (l *DockerLogs) Stream() chan models.Log {
	r, w := io.Pipe()
	logCh := make(chan models.Log)
	ctx, cancel := context.WithCancel(context.Background())

	opts := api.LogsOptions{
		Context:      ctx,
		Container:    l.id,
		OutputStream: w,
		//ErrorStream:  w,
		Stdout:      true,
		Stderr:      true,
		Tail:        "20",
		Follow:      true,
		Timestamps:  true,
		RawTerminal: true,
	}

	// read io pipe into channel
	go func() {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			parts := strings.SplitN(scanner.Text(), " ", 2)
			ts := l.parseTime(parts[0])
			logCh <- models.Log{Timestamp: ts, Message: parts[1]}
		}
	}()

	// connect to container log stream
	go func() {
		err := l.client.Logs(opts)
		if err != nil {
			log.Errorf("error reading container logs: %s", err)
		}
		log.Infof("log reader stopped for container: %s", l.id)
	}()

	go func() {
		<-l.done
		cancel()
	}()

	log.Infof("log reader started for container: %s", l.id)
	return logCh
}

func (l *DockerLogs) Stop() { l.done <- true }

func (l *DockerLogs) parseTime(s string) time.Time {
	ts, err := time.Parse(time.RFC3339Nano, s)
	if err == nil {
		return ts
	}

	ts, err2 := time.Parse(time.RFC3339Nano, l.stripPfx(s))
	if err2 == nil {
		return ts
	}

	log.Errorf("failed to parse container log: %s", err)
	log.Errorf("failed to parse container log2: %s", err2)
	return time.Now()
}

// attempt to strip message header prefix from a given raw docker log string
func (l *DockerLogs) stripPfx(s string) string {
	b := []byte(s)
	if len(b) > 8 {
		return string(b[8:])
	}
	return s
}
<commit_msg>#254-handling-with-wrong-log-format<commit_after>package collector

import (
	"bufio"
	"context"
	"io"
	"strings"
	"time"

	"github.com/bcicen/ctop/models"
	api "github.com/fsouza/go-dockerclient"
)

type DockerLogs struct {
	id     string
	client *api.Client
	done   chan bool
}

func NewDockerLogs(id string, client *api.Client) *DockerLogs {
	return &DockerLogs{
		id:     id,
		client: client,
		done:   make(chan bool),
	}
}

func (l *DockerLogs) Stream() chan models.Log {
	r, w := io.Pipe()
	logCh := make(chan models.Log)
	ctx, cancel := context.WithCancel(context.Background())

	opts := api.LogsOptions{
		Context:      ctx,
		Container:    l.id,
		OutputStream: w,
		//ErrorStream:  w,
		Stdout:      true,
		Stderr:      true,
		Tail:        "20",
		Follow:      true,
		Timestamps:  true,
		RawTerminal: true,
	}

	// read io pipe into channel
	go func() {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			parts := strings.SplitN(scanner.Text(), " ", 2)
			if len(parts) == 0 {
				continue
			}
			if len(parts) < 2 {
				logCh <- models.Log{Timestamp: l.parseTime(""), Message: parts[0]}
			} else {
				logCh <- models.Log{Timestamp: l.parseTime(parts[0]), Message: parts[1]}
			}
		}
	}()

	// connect to container log stream
	go func() {
		err := l.client.Logs(opts)
		if err != nil {
			log.Errorf("error reading container logs: %s", err)
		}
		log.Infof("log reader stopped for container: %s", l.id)
	}()

	go func() {
		<-l.done
		cancel()
	}()

	log.Infof("log reader started for container: %s", l.id)
	return logCh
}

func (l *DockerLogs) Stop() { l.done <- true }

func (l *DockerLogs) parseTime(s string) time.Time {
	ts, err := time.Parse(time.RFC3339Nano, s)
	if err == nil {
		return ts
	}

	ts, err2 := time.Parse(time.RFC3339Nano, l.stripPfx(s))
	if err2 == nil {
		return ts
	}

	log.Errorf("failed to parse container log: %s", err)
	log.Errorf("failed to parse container log2: %s", err2)
	return time.Now()
}

// attempt to strip message header prefix from a given raw docker log string
func (l *DockerLogs) stripPfx(s string) string {
	b := []byte(s)
	if len(b) > 8 {
		return string(b[8:])
	}
	return s
}
<|endoftext|>


<commit_before>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.
package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"unicode/utf8"
)

type itemElement int

const (
	itemEOF itemElement = iota
	itemError
	itemTitle
	itemSectionAdornment
	itemParagraph
	itemBlockquote
	itemLiteralBlock
	itemSystemMessage
)

var elements = [...]string{
	"itemEOF",
	"itemError",
	"itemTitle",
	"itemSectionAdornment",
	"itemParagraph",
	"itemBlockquote",
	"itemLiteralBlock",
	"itemSystemMessage",
}

func (t itemElement) String() string { return elements[t] }

var sectionAdornments = []rune{'!', '"', '#', '$', '\'', '%', '&', '(', ')', '*',
	'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\',
	']', '^', '_', '`', '{', '|', '}', '~'}

func isSectionAdornment(r rune) bool {
	for _, a := range sectionAdornments {
		if a == r {
			return true
		}
	}
	return false
}

const eof = -1

type stateFn func(*lexer) stateFn

type item struct {
	ElementName string
	ElementType itemElement
	Position    Pos
	Line        int
	Value       interface{}
}

func (i item) String() string {
	switch {
	case i.ElementType == itemEOF:
		return "EOF"
	case i.ElementType == itemError:
		return i.Value.(string)
	}
	return fmt.Sprintf("%q", i.Value)
}

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string { return systemMessageLevels[s] }

type systemMessage struct {
	level  systemMessageLevel
	line   int
	source string
	items  []item
}

type lexer struct {
	name    string
	input   string
	state   stateFn
	pos     Pos
	start   Pos
	width   Pos
	lastPos Pos
	items   chan item
	line    int
}

func lex(name, input string) *lexer {
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
	}
	go l.run()
	return l
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemElement) {
	log.Debugf("\tEmit %s!\n", t)
	l.items <- item{ElementType: t, ElementName: fmt.Sprint(t),
		Position: l.start, Line: l.line, Value: l.input[l.start:l.pos]}
	l.start = l.pos

}

func (l *lexer) backup() {
	l.pos -= l.width
}

func (l *lexer) current() rune {
	r, _ := utf8.DecodeRuneInString(l.input[l.pos:])
	return r
}

func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

func (l *lexer) ignore() {
	l.pos += 1
	l.start = l.pos
}

// next returns the next rune in the input.
func (l *lexer) next() rune {
	if int(l.pos) >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	l.width = Pos(w)
	l.pos += l.width
	return r
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() item {
	item := <-l.items
	l.lastPos = item.Position
	return item

}

func (l *lexer) run() {
	l.line += 1
	for l.state = lexStart; l.state != nil; {
		l.state = l.state(l)
	}
}

// isSpace reports whether r is a space character.
func isSpace(r rune) bool {
	return r == ' ' || r == '\t'
}

// isEndOfLine reports whether r is an end-of-line character.
func isEndOfLine(r rune) bool {
	return r == '\r' || r == '\n'
}

func lexStart(l *lexer) stateFn {
	log.Debugln("\nTransition lexStart...")
	for {
		if len(l.input) == 0 {
			log.Debugln("\tEmit EOF!")
			l.emit(itemEOF)
			return nil
		}

		log.Debugf("\tlexStart: %q, Start: %d, Pos: %d, Line: %d\n",
			l.input[l.start:l.pos], l.start, l.pos, l.line)

		switch r := l.current(); {
		case isSectionAdornment(r) && isSectionAdornment(l.peek()) && l.pos == 1:
			log.Debugln("Transition lexSection...")
			return lexSection
		case isEndOfLine(r):
			log.Debugln("\tFound newline!")
			l.line += 1
			if isSectionAdornment(l.peek()) {
				log.Debugln("Transition lexSection...")
				return lexSection
			}
			if l.pos > l.start {
				l.emit(itemParagraph)
			}
			l.ignore()
		}

		if l.next() == eof {
			break
		}
	}

	// Correctly reached EOF.
	if l.pos > l.start {
		l.emit(itemParagraph)
	}

	l.emit(itemEOF)
	return nil
}

func lexSection(l *lexer) stateFn {
	if len(l.input) > 0 {
		log.Debugf("\tlexSection: %q, Pos: %d\n",
			l.input[l.start:l.pos], l.pos)
	}

	if isEndOfLine(l.peek()) {
		l.emit(itemTitle)
		l.ignore()
	}

Loop:
	for {
		switch r := l.next(); {
		case isSectionAdornment(r):
			if len(l.input) > 0 {
				log.Debugf("\tlexSection: %q, Pos: %d\n",
					l.input[l.start:l.pos], l.pos)
			}
		case isEndOfLine(r):
			l.backup()
			l.emit(itemSectionAdornment)
			l.line += 1
			l.ignore()
			break Loop
		}
	}
	return lexStart
}
<commit_msg>lex.go: Remove item.String()<commit_after>// go-rst - A reStructuredText parser for Go
// 2014 (c) The go-rst Authors
// MIT Licensed. See LICENSE for details.
package parse

import (
	"fmt"
	"github.com/demizer/go-elog"
	"unicode/utf8"
)

type itemElement int

const (
	itemEOF itemElement = iota
	itemError
	itemTitle
	itemSectionAdornment
	itemParagraph
	itemBlockquote
	itemLiteralBlock
	itemSystemMessage
)

var elements = [...]string{
	"itemEOF",
	"itemError",
	"itemTitle",
	"itemSectionAdornment",
	"itemParagraph",
	"itemBlockquote",
	"itemLiteralBlock",
	"itemSystemMessage",
}

func (t itemElement) String() string { return elements[t] }

var sectionAdornments = []rune{'!', '"', '#', '$', '\'', '%', '&', '(', ')', '*',
	'+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\',
	']', '^', '_', '`', '{', '|', '}', '~'}

func isSectionAdornment(r rune) bool {
	for _, a := range sectionAdornments {
		if a == r {
			return true
		}
	}
	return false
}

const eof = -1

type stateFn func(*lexer) stateFn

type item struct {
	ElementName string
	ElementType itemElement
	Position    Pos
	Line        int
	Value       interface{}
}

type systemMessageLevel int

const (
	levelInfo systemMessageLevel = iota
	levelWarning
	levelError
	levelSevere
)

var systemMessageLevels = [...]string{
	"INFO",
	"WARNING",
	"ERROR",
	"SEVERE",
}

func (s systemMessageLevel) String() string { return systemMessageLevels[s] }

type systemMessage struct {
	level  systemMessageLevel
	line   int
	source string
	items  []item
}

type lexer struct {
	name    string
	input   string
	state   stateFn
	pos     Pos
	start   Pos
	width   Pos
	lastPos Pos
	items   chan item
	line    int
}

func lex(name, input string) *lexer {
	l := &lexer{
		name:  name,
		input: input,
		items: make(chan item),
	}
	go l.run()
	return l
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemElement) {
	log.Debugf("\tEmit %s!\n", t)
	l.items <- item{ElementType: t, ElementName: fmt.Sprint(t),
		Position: l.start, Line: l.line, Value: l.input[l.start:l.pos]}
	l.start = l.pos

}

func (l *lexer) backup() {
	l.pos -= l.width
}

func (l *lexer) current() rune {
	r, _ := utf8.DecodeRuneInString(l.input[l.pos:])
	return r
}

func (l *lexer) peek() rune {
	r := l.next()
	l.backup()
	return r
}

func (l *lexer) ignore() {
	l.pos += 1
	l.start = l.pos
}

// next returns the next rune in the input.
func (l *lexer) next() rune {
	if int(l.pos) >= len(l.input) {
		l.width = 0
		return eof
	}
	r, w := utf8.DecodeRuneInString(l.input[l.pos:])
	l.width = Pos(w)
	l.pos += l.width
	return r
}

// nextItem returns the next item from the input.
func (l *lexer) nextItem() item {
	item := <-l.items
	l.lastPos = item.Position
	return item

}

func (l *lexer) run() {
	l.line += 1
	for l.state = lexStart; l.state != nil; {
		l.state = l.state(l)
	}
}

// isSpace reports whether r is a space character.
func isSpace(r rune) bool {
	return r == ' ' || r == '\t'
}

// isEndOfLine reports whether r is an end-of-line character.
func isEndOfLine(r rune) bool {
	return r == '\r' || r == '\n'
}

func lexStart(l *lexer) stateFn {
	log.Debugln("\nTransition lexStart...")
	for {
		if len(l.input) == 0 {
			log.Debugln("\tEmit EOF!")
			l.emit(itemEOF)
			return nil
		}

		log.Debugf("\tlexStart: %q, Start: %d, Pos: %d, Line: %d\n",
			l.input[l.start:l.pos], l.start, l.pos, l.line)

		switch r := l.current(); {
		case isSectionAdornment(r) && isSectionAdornment(l.peek()) && l.pos == 1:
			log.Debugln("Transition lexSection...")
			return lexSection
		case isEndOfLine(r):
			log.Debugln("\tFound newline!")
			l.line += 1
			if isSectionAdornment(l.peek()) {
				log.Debugln("Transition lexSection...")
				return lexSection
			}
			if l.pos > l.start {
				l.emit(itemParagraph)
			}
			l.ignore()
		}

		if l.next() == eof {
			break
		}
	}

	// Correctly reached EOF.
	if l.pos > l.start {
		l.emit(itemParagraph)
	}

	l.emit(itemEOF)
	return nil
}

func lexSection(l *lexer) stateFn {
	if len(l.input) > 0 {
		log.Debugf("\tlexSection: %q, Pos: %d\n",
			l.input[l.start:l.pos], l.pos)
	}

	if isEndOfLine(l.peek()) {
		l.emit(itemTitle)
		l.ignore()
	}

Loop:
	for {
		switch r := l.next(); {
		case isSectionAdornment(r):
			if len(l.input) > 0 {
				log.Debugf("\tlexSection: %q, Pos: %d\n",
					l.input[l.start:l.pos], l.pos)
			}
		case isEndOfLine(r):
			l.backup()
			l.emit(itemSectionAdornment)
			l.line += 1
			l.ignore()
			break Loop
		}
	}
	return lexStart
}
<|endoftext|>


<commit_before>// Copyright 2013 Julien Schmidt. All rights reserved.
// Based on the path package, Copyright 2009 The Go Authors.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.

package httprouter

import (
	"testing"
)

var cleanTests = []struct {
	path, result string
}{
	// Already clean
	{"/", "/"},
	{"/abc", "/abc"},
	{"/a/b/c", "/a/b/c"},
	{"/abc/", "/abc/"},
	{"/a/b/c/", "/a/b/c/"},

	// missing root
	{"", "/"},
	{"a/", "/a/"},
	{"abc", "/abc"},
	{"abc/def", "/abc/def"},
	{"a/b/c", "/a/b/c"},

	// Remove doubled slash
	{"//", "/"},
	{"/abc//", "/abc/"},
	{"/abc/def//", "/abc/def/"},
	{"/a/b/c//", "/a/b/c/"},
	{"/abc//def//ghi", "/abc/def/ghi"},
	{"//abc", "/abc"},
	{"///abc", "/abc"},
	{"//abc//", "/abc/"},

	// Remove . elements
	{".", "/"},
	{"./", "/"},
	{"/abc/./def", "/abc/def"},
	{"/./abc/def", "/abc/def"},
	{"/abc/.", "/abc/"},

	// Remove .. elements
	{"..", "/"},
	{"../", "/"},
	{"../../", "/"},
	{"../..", "/"},
	{"../../abc", "/abc"},
	{"/abc/def/ghi/../jkl", "/abc/def/jkl"},
	{"/abc/def/../ghi/../jkl", "/abc/jkl"},
	{"/abc/def/..", "/abc"},
	{"/abc/def/../..", "/"},
	{"/abc/def/../../..", "/"},
	{"/abc/def/../../..", "/"},
	{"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},

	// Combinations
	{"abc/./../def", "/def"},
	{"abc//./../def", "/def"},
	{"abc/../../././../def", "/def"},
}

func TestPathClean(t *testing.T) {
	for _, test := range cleanTests {
		if s := CleanPath(test.path); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
		}
		if s := CleanPath(test.result); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
		}
	}
}

func TestPathCleanMallocs(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping malloc count in short mode")
	}

	for _, test := range cleanTests {
		allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
		if allocs > 0 {
			t.Errorf("CleanPath(%q): %v allocs, want zero", test.result, allocs)
		}
	}
}

func BenchmarkPathClean(b *testing.B) {
	for i := 0; i < b.N; i++ {
		for _, test := range cleanTests {
			CleanPath(test.path)
		}
	}
}
<commit_msg>path: add test and benchmark for long CleanPath inputs<commit_after>// Copyright 2013 Julien Schmidt. All rights reserved.
// Based on the path package, Copyright 2009 The Go Authors.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.

package httprouter

import (
	"strings"
	"testing"
)

type cleanPathTest struct {
	path, result string
}

var cleanTests = []cleanPathTest{
	// Already clean
	{"/", "/"},
	{"/abc", "/abc"},
	{"/a/b/c", "/a/b/c"},
	{"/abc/", "/abc/"},
	{"/a/b/c/", "/a/b/c/"},

	// missing root
	{"", "/"},
	{"a/", "/a/"},
	{"abc", "/abc"},
	{"abc/def", "/abc/def"},
	{"a/b/c", "/a/b/c"},

	// Remove doubled slash
	{"//", "/"},
	{"/abc//", "/abc/"},
	{"/abc/def//", "/abc/def/"},
	{"/a/b/c//", "/a/b/c/"},
	{"/abc//def//ghi", "/abc/def/ghi"},
	{"//abc", "/abc"},
	{"///abc", "/abc"},
	{"//abc//", "/abc/"},

	// Remove . elements
	{".", "/"},
	{"./", "/"},
	{"/abc/./def", "/abc/def"},
	{"/./abc/def", "/abc/def"},
	{"/abc/.", "/abc/"},

	// Remove .. elements
	{"..", "/"},
	{"../", "/"},
	{"../../", "/"},
	{"../..", "/"},
	{"../../abc", "/abc"},
	{"/abc/def/ghi/../jkl", "/abc/def/jkl"},
	{"/abc/def/../ghi/../jkl", "/abc/jkl"},
	{"/abc/def/..", "/abc"},
	{"/abc/def/../..", "/"},
	{"/abc/def/../../..", "/"},
	{"/abc/def/../../..", "/"},
	{"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},

	// Combinations
	{"abc/./../def", "/def"},
	{"abc//./../def", "/def"},
	{"abc/../../././../def", "/def"},
}

func TestPathClean(t *testing.T) {
	for _, test := range cleanTests {
		if s := CleanPath(test.path); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
		}
		if s := CleanPath(test.result); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
		}
	}
}

func TestPathCleanMallocs(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping malloc count in short mode")
	}

	for _, test := range cleanTests {
		allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
		if allocs > 0 {
			t.Errorf("CleanPath(%q): %v allocs, want zero", test.result, allocs)
		}
	}
}

func BenchmarkPathClean(b *testing.B) {
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		for _, test := range cleanTests {
			CleanPath(test.path)
		}
	}
}

func genLongPaths() (testPaths []cleanPathTest) {
	for i := 1; i <= 1234; i++ {
		ss := strings.Repeat("a", i)

		correctPath := "/" + ss
		testPaths = append(testPaths, cleanPathTest{
			path:   correctPath,
			result: correctPath,
		}, cleanPathTest{
			path:   ss,
			result: correctPath,
		}, cleanPathTest{
			path:   "//" + ss,
			result: correctPath,
		}, cleanPathTest{
			path:   "/" + ss + "/b/..",
			result: correctPath,
		})
	}
	return
}

func TestPathCleanLong(t *testing.T) {
	cleanTests := genLongPaths()

	for _, test := range cleanTests {
		if s := CleanPath(test.path); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
		}
		if s := CleanPath(test.result); s != test.result {
			t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
		}
	}
}

func BenchmarkPathCleanLong(b *testing.B) {
	cleanTests := genLongPaths()
	b.ResetTimer()
	b.ReportAllocs()

	for i := 0; i < b.N; i++ {
		for _, test := range cleanTests {
			CleanPath(test.path)
		}
	}
}
<|endoftext|>


<commit_before>package config

import (
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"time"
)

type Config struct {
	// Top level options use an anonymous struct
	BaseConfig `mapstructure:",squash"`
	// Options for services
	P2P    *P2PConfig     `mapstructure:"p2p"`
	Wallet *WalletConfig  `mapstructure:"wallet"`
	Auth   *RPCAuthConfig `mapstructure:"auth"`
	Web    *WebConfig     `mapstructure:"web"`
}

// Default configurable parameters.
func DefaultConfig() *Config {
	return &Config{
		BaseConfig: DefaultBaseConfig(),
		P2P:        DefaultP2PConfig(),
		Wallet:     DefaultWalletConfig(),
		Auth:       DefaultRPCAuthConfig(),
		Web:        DefaultWebConfig(),
	}
}

// Set the RootDir for all Config structs
func (cfg *Config) SetRoot(root string) *Config {
	cfg.BaseConfig.RootDir = root
	cfg.P2P.RootDir = root
	return cfg
}

//-----------------------------------------------------------------------------
// BaseConfig
type BaseConfig struct {
	// The root directory for all data.
	// This should be set in viper so it can unmarshal into this struct
	RootDir string `mapstructure:"home"`

	//The ID of the network to json
	ChainID string `mapstructure:"chain_id"`

	// A JSON file containing the private key to use as a validator in the consensus protocol
	PrivateKey string `mapstructure:"private_key"`

	// A custom human readable name for this node
	Moniker string `mapstructure:"moniker"`

	// TCP or UNIX socket address for the profiling server to listen on
	ProfListenAddress string `mapstructure:"prof_laddr"`

	// If this node is many blocks behind the tip of the chain, FastSync
	// allows them to catchup quickly by downloading blocks in parallel
	// and verifying their commits
	FastSync bool `mapstructure:"fast_sync"`

	Mining bool `mapstructure:"mining"`

	FilterPeers bool `mapstructure:"filter_peers"` // false

	// What indexer to use for transactions
	TxIndex string `mapstructure:"tx_index"`

	// Database backend: leveldb | memdb
	DBBackend string `mapstructure:"db_backend"`

	// Database directory
	DBPath string `mapstructure:"db_dir"`

	// Keystore directory
	KeysPath string `mapstructure:"keys_dir"`

	// remote HSM url
	HsmUrl string `mapstructure:"hsm_url"`

	ApiAddress string `mapstructure:"api_addr"`

	VaultMode bool `mapstructure:"vault_mode"`

	Time time.Time

	// log file name
	LogName string `mapstructure:"log_name"`
}

// Default configurable base parameters.
func DefaultBaseConfig() BaseConfig {
	return BaseConfig{
		Moniker:           "anonymous",
		ProfListenAddress: "",
		FastSync:          true,
		FilterPeers:       false,
		Mining:            false,
		TxIndex:           "kv",
		DBBackend:         "leveldb",
		DBPath:            "data",
		KeysPath:          "keystore",
		HsmUrl:            "",
		LogName:           "bytom.log",
	}
}

func (b BaseConfig) DBDir() string {
	return rootify(b.DBPath, b.RootDir)
}

func (b BaseConfig) KeysDir() string {
	return rootify(b.KeysPath, b.RootDir)
}

// P2PConfig
type P2PConfig struct {
	RootDir          string `mapstructure:"home"`
	ListenAddress    string `mapstructure:"laddr"`
	Seeds            string `mapstructure:"seeds"`
	SkipUPNP         bool   `mapstructure:"skip_upnp"`
	AddrBook         string `mapstructure:"addr_book_file"`
	AddrBookStrict   bool   `mapstructure:"addr_book_strict"`
	PexReactor       bool   `mapstructure:"pex"`
	MaxNumPeers      int    `mapstructure:"max_num_peers"`
	HandshakeTimeout int    `mapstructure:"handshake_timeout"`
	DialTimeout      int    `mapstructure:"dial_timeout"`
}

// Default configurable p2p parameters.
func DefaultP2PConfig() *P2PConfig {
	return &P2PConfig{
		ListenAddress:    "tcp://0.0.0.0:46656",
		AddrBook:         "addrbook.json",
		AddrBookStrict:   true,
		SkipUPNP:         false,
		MaxNumPeers:      50,
		HandshakeTimeout: 30,
		DialTimeout:      3,
		PexReactor:       true,
	}
}

func (p *P2PConfig) AddrBookFile() string {
	return rootify(p.AddrBook, p.RootDir)
}

//-----------------------------------------------------------------------------
type WalletConfig struct {
	Disable bool `mapstructure:"disable"`
}

type RPCAuthConfig struct {
	Disable bool `mapstructure:"disable"`
}

type WebConfig struct {
	Closed bool `mapstructure:"closed"`
}

// Default configurable rpc's auth parameters.
func DefaultRPCAuthConfig() *RPCAuthConfig {
	return &RPCAuthConfig{
		Disable: false,
	}
}

// Default configurable web parameters.
func DefaultWebConfig() *WebConfig {
	return &WebConfig{
		Closed: false,
	}
}

// Default configurable wallet parameters.
func DefaultWalletConfig() *WalletConfig {
	return &WalletConfig{
		Disable: false,
	}
}

//-----------------------------------------------------------------------------
// Utils

// helper function to make config creation independent of root dir
func rootify(path, root string) string {
	if filepath.IsAbs(path) {
		return path
	}
	return filepath.Join(root, path)
}

// DefaultDataDir is the default data directory to use for the databases and other
// persistence requirements.
func DefaultDataDir() string {
	// Try to place the data folder in the user's home dir
	home := homeDir()
	dataDir := "./.bytom"
	if home != "" {
		switch runtime.GOOS {
		case "darwin":
			dataDir = filepath.Join(home, "Library", "Bytom")
		case "windows":
			dataDir = filepath.Join(home, "AppData", "Roaming", "Bytom")
		default:
			dataDir = filepath.Join(home, ".bytom")
		}
	}
	return dataDir
}

func homeDir() string {
	if home := os.Getenv("HOME"); home != "" {
		return home
	}
	if usr, err := user.Current(); err == nil {
		return usr.HomeDir
	}
	return ""
}
<commit_msg>refactor<commit_after>package config

import (
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"time"
)

type Config struct {
	// Top level options use an anonymous struct
	BaseConfig `mapstructure:",squash"`
	// Options for services
	P2P    *P2PConfig     `mapstructure:"p2p"`
	Wallet *WalletConfig  `mapstructure:"wallet"`
	Auth   *RPCAuthConfig `mapstructure:"auth"`
	Web    *WebConfig     `mapstructure:"web"`
}

// Default configurable parameters.
func DefaultConfig() *Config {
	return &Config{
		BaseConfig: DefaultBaseConfig(),
		P2P:        DefaultP2PConfig(),
		Wallet:     DefaultWalletConfig(),
		Auth:       DefaultRPCAuthConfig(),
		Web:        DefaultWebConfig(),
	}
}

// Set the RootDir for all Config structs
func (cfg *Config) SetRoot(root string) *Config {
	cfg.BaseConfig.RootDir = root
	cfg.P2P.RootDir = root
	return cfg
}

//-----------------------------------------------------------------------------
// BaseConfig
type BaseConfig struct {
	// The root directory for all data.
	// This should be set in viper so it can unmarshal into this struct
	RootDir string `mapstructure:"home"`

	//The ID of the network to json
	ChainID string `mapstructure:"chain_id"`

	// A JSON file containing the private key to use as a validator in the consensus protocol
	PrivateKey string `mapstructure:"private_key"`

	// A custom human readable name for this node
	Moniker string `mapstructure:"moniker"`

	// TCP or UNIX socket address for the profiling server to listen on
	ProfListenAddress string `mapstructure:"prof_laddr"`

	// If this node is many blocks behind the tip of the chain, FastSync
	// allows them to catchup quickly by downloading blocks in parallel
	// and verifying their commits
	FastSync bool `mapstructure:"fast_sync"`

	Mining bool `mapstructure:"mining"`

	FilterPeers bool `mapstructure:"filter_peers"` // false

	// What indexer to use for transactions
	TxIndex string `mapstructure:"tx_index"`

	// Database backend: leveldb | memdb
	DBBackend string `mapstructure:"db_backend"`

	// Database directory
	DBPath string `mapstructure:"db_dir"`

	// Keystore directory
	KeysPath string `mapstructure:"keys_dir"`

	// remote HSM url
	HsmUrl string `mapstructure:"hsm_url"`

	ApiAddress string `mapstructure:"api_addr"`

	VaultMode bool `mapstructure:"vault_mode"`

	Time time.Time

	// log file name
	LogName string `mapstructure:"log_name"`
}

// Default configurable base parameters.
func DefaultBaseConfig() BaseConfig {
	return BaseConfig{
		Moniker:           "anonymous",
		ProfListenAddress: "",
		FastSync:          true,
		FilterPeers:       false,
		Mining:            false,
		TxIndex:           "kv",
		DBBackend:         "leveldb",
		DBPath:            "data",
		KeysPath:          "keystore",
		HsmUrl:            "",
		LogName:           "bytom.log",
	}
}

func (b BaseConfig) DBDir() string {
	return rootify(b.DBPath, b.RootDir)
}

func (b BaseConfig) KeysDir() string {
	return rootify(b.KeysPath, b.RootDir)
}

// P2PConfig
type P2PConfig struct {
	RootDir          string `mapstructure:"home"`
	ListenAddress    string `mapstructure:"laddr"`
	Seeds            string `mapstructure:"seeds"`
	SkipUPNP         bool   `mapstructure:"skip_upnp"`
	AddrBook         string `mapstructure:"addr_book_file"`
	AddrBookStrict   bool   `mapstructure:"addr_book_strict"`
	PexReactor       bool   `mapstructure:"pex"`
	MaxNumPeers      int    `mapstructure:"max_num_peers"`
	HandshakeTimeout int    `mapstructure:"handshake_timeout"`
	DialTimeout      int    `mapstructure:"dial_timeout"`
}

// Default configurable p2p parameters.
func DefaultP2PConfig() *P2PConfig {
	return &P2PConfig{
		ListenAddress:    "tcp://0.0.0.0:46656",
		AddrBook:         "addrbook.json",
		AddrBookStrict:   true,
		SkipUPNP:         false,
		MaxNumPeers:      50,
		HandshakeTimeout: 30,
		DialTimeout:      3,
		PexReactor:       true,
	}
}

func (p *P2PConfig) AddrBookFile() string {
	return rootify(p.AddrBook, p.RootDir)
}

//-----------------------------------------------------------------------------
type WalletConfig struct {
	Disable bool `mapstructure:"disable"`
}

type RPCAuthConfig struct {
	Disable bool `mapstructure:"disable"`
}

type WebConfig struct {
	Closed bool `mapstructure:"closed"`
}

// Default configurable rpc's auth parameters.
func DefaultRPCAuthConfig() *RPCAuthConfig {
	return &RPCAuthConfig{
		Disable: false,
	}
}

// Default configurable web parameters.
func DefaultWebConfig() *WebConfig {
	return &WebConfig{
		Closed: false,
	}
}

// Default configurable wallet parameters.
func DefaultWalletConfig() *WalletConfig {
	return &WalletConfig{
		Disable: false,
	}
}

//-----------------------------------------------------------------------------
// Utils

// helper function to make config creation independent of root dir
func rootify(path, root string) string {
	if filepath.IsAbs(path) {
		return path
	}
	return filepath.Join(root, path)
}

// DefaultDataDir is the default data directory to use for the databases and other
// persistence requirements.
func DefaultDataDir() string {
	// Try to place the data folder in the user's home dir
	home := homeDir()
	if home == "" {
		return "./.bytom"
	}
	switch runtime.GOOS {
	case "darwin":
		return filepath.Join(home, "Library", "Bytom")
	case "windows":
		return filepath.Join(home, "AppData", "Roaming", "Bytom")
	default:
		return filepath.Join(home, ".bytom")
	}
}

func homeDir() string {
	if home := os.Getenv("HOME"); home != "" {
		return home
	}
	if usr, err := user.Current(); err == nil {
		return usr.HomeDir
	}
	return ""
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"reflect"

	"github.com/google/go-cmp/cmp"
)

type valueType int

const (
	stringType valueType = iota
	numberType
	booleanType
)

// Value may be either a string, float64 or boolean value.
// This is the Go equivalent of the C type "oconfig_value_t".
type Value struct {
	typ valueType
	s   string
	f   float64
	b   bool
}

// StringValue returns a new string Value.
func StringValue(v string) Value { return Value{typ: stringType, s: v} }

// Float64Value returns a new string Value.
func Float64Value(v float64) Value { return Value{typ: numberType, f: v} }

// BoolValue returns a new boolean Value.
func BoolValue(v bool) Value { return Value{typ: booleanType, b: v} }

// GoString returns a Go statement for creating cv.
func (cv Value) GoString() string {
	switch cv.typ {
	case stringType:
		return fmt.Sprintf("config.StringValue(%q)", cv.s)
	case numberType:
		return fmt.Sprintf("config.Float64Value(%v)", cv.f)
	case booleanType:
		return fmt.Sprintf("config.BoolValue(%v)", cv.b)
	}
	return "<invalid config.Value>"
}

// IsString returns true if cv is a string Value.
func (cv Value) IsString() bool {
	return cv.typ == stringType
}

// String returns Value as a string. Non-string values are formatted according to their default format.
func (cv Value) String() string {
	return fmt.Sprintf("%v", cv.Interface())
}

// Number returns the value of a number Value.
func (cv Value) Number() (float64, bool) {
	return cv.f, cv.typ == numberType
}

// Boolean returns the value of a bool Value.
func (cv Value) Boolean() (bool, bool) {
	return cv.b, cv.typ == booleanType
}

// Interface returns the specific value of Value without specifying its type, useful for functions like fmt.Printf
// which can use variables with unknown types.
func (cv Value) Interface() interface{} {
	switch cv.typ {
	case stringType:
		return cv.s
	case numberType:
		return cv.f
	case booleanType:
		return cv.b
	}
	return nil
}

func (cv Value) unmarshal(v reflect.Value) error {
	rvt := v.Type()
	var cvt reflect.Type
	var cvv reflect.Value

	switch cv.typ {
	case stringType:
		cvt = reflect.TypeOf(cv.s)
		cvv = reflect.ValueOf(cv.s)
	case booleanType:
		cvt = reflect.TypeOf(cv.b)
		cvv = reflect.ValueOf(cv.b)
	case numberType:
		cvt = reflect.TypeOf(cv.f)
		cvv = reflect.ValueOf(cv.f)
	default:
		return fmt.Errorf("unexpected Value type: %v", cv.typ)
	}

	if cvt.ConvertibleTo(rvt) {
		v.Set(cvv.Convert(rvt))
		return nil
	}
	if v.Kind() == reflect.Slice && cvt.ConvertibleTo(rvt.Elem()) {
		v.Set(reflect.Append(v, cvv.Convert(rvt.Elem())))
		return nil
	}
	return fmt.Errorf("cannot unmarshal a %T to a %s", cv.Interface(), v.Type())
}

// Block represents one configuration block, which may contain other configuration blocks.
type Block struct {
	Key      string
	Values   []Value
	Children []Block
}

// Merge appends other's Children to b's Children. If Key or Values differ, an
// error is returned.
func (b *Block) Merge(other Block) error {
	// If b is the zero value, we set it to other.
	if b.Key == "" && b.Values == nil && b.Children == nil {
		*b = other
		return nil
	}

	if b.Key != other.Key || !cmp.Equal(b.Values, other.Values, cmp.AllowUnexported(Value{})) {
		return fmt.Errorf("blocks differ: got {key:%v values:%v}, want {key:%v, values:%v}",
			other.Key, other.Values, b.Key, b.Values)
	}

	b.Children = append(b.Children, other.Children...)
	return nil
}

// Unmarshal applies the configuration from a Block to an arbitrary struct.
func (c *Block) Unmarshal(v interface{}) error {
	// If the target supports unmarshalling let it
	if u, ok := v.(Unmarshaler); ok {
		return u.UnmarshalConfig(v)
	}

	// Sanity check value of the interface
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return fmt.Errorf("can only unmarshal to a non-nil pointer") // TODO: better error message or nil if preferred
	}

	drv := rv.Elem() // get dereferenced value
	drvk := drv.Kind()

	// If config block has child blocks we can only unmarshal to a struct or slice of structs
	if len(c.Children) > 0 {
		if drvk != reflect.Struct && (drvk != reflect.Slice || drv.Type().Elem().Kind() != reflect.Struct) {
			return fmt.Errorf("cannot unmarshal a config with children except to a struct or slice of structs")
		}
	}

	switch drvk {
	case reflect.Struct:
		// Unmarshal values from config
		if err := storeStructConfigValues(c.Values, drv); err != nil {
			return fmt.Errorf("while unmarshalling config block values into %s: %s", drv.Type(), err)
		}
		for _, child := range c.Children {
			// If a config has children but the struct has no corresponding field, or the corresponding field is an
			// unexported struct field we throw an error.
			if field := drv.FieldByName(child.Key); field.IsValid() && field.CanInterface() {
				if err := child.Unmarshal(field.Addr().Interface()); err != nil {
					//	if err := child.Unmarshal(field.Interface()); err != nil {
					return fmt.Errorf("in child config block %s: %s", child.Key, err)
				}
			} else {
				return fmt.Errorf("found child config block with no corresponding field: %s", child.Key)
			}
		}
		return nil
	case reflect.Slice:
		switch drv.Type().Elem().Kind() {
		case reflect.Struct:
			// Create a temporary Value of the same type as dereferenced value, then get a Value of the same type as
			// its elements. Unmarshal into that Value and append the temporary Value to the original.
			tv := reflect.New(drv.Type().Elem()).Elem()
			if err := c.Unmarshal(tv.Addr().Interface()); err != nil {
				return fmt.Errorf("unmarshaling into temporary value failed: %s", err)
			}
			drv.Set(reflect.Append(drv, tv))
			return nil
		default:
			for _, cv := range c.Values {
				tv := reflect.New(drv.Type().Elem()).Elem()
				if err := cv.unmarshal(tv); err != nil {
					return fmt.Errorf("while unmarhalling values into %s: %s", drv.Type(), err)
				}
				drv.Set(reflect.Append(drv, tv))
			}
			return nil
		}
	case reflect.String, reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64:
		if len(c.Values) != 1 {
			return fmt.Errorf("cannot unmarshal config option with %d values into scalar type %s", len(c.Values), drv.Type())
		}
		return c.Values[0].unmarshal(drv)
	default:
		return fmt.Errorf("cannot unmarshal into type %s", drv.Type())
	}
}

func storeStructConfigValues(cvs []Value, v reflect.Value) error {
	if len(cvs) == 0 {
		return nil
	}
	args := v.FieldByName("Args")
	if !args.IsValid() {
		return fmt.Errorf("cannot unmarshal values to a struct without an Args field")
	}
	if len(cvs) > 1 && args.Kind() != reflect.Slice {
		return fmt.Errorf("cannot unmarshal config block with multiple values to a struct with non-slice Args field")
	}
	for _, cv := range cvs {
		if err := cv.unmarshal(args); err != nil {
			return fmt.Errorf("while attempting to unmarshal config value \"%v\" in Args: %s", cv.Interface(), err)
		}
	}
	return nil
}

// Unmarshaler is the interface implemented by types that can unmarshal a Block representation of themselves.
type Unmarshaler interface {
	UnmarshalConfig(v interface{}) error
}
<commit_msg>Package config: Unify Block's receiver name.<commit_after>package config

import (
	"fmt"
	"reflect"

	"github.com/google/go-cmp/cmp"
)

type valueType int

const (
	stringType valueType = iota
	numberType
	booleanType
)

// Value may be either a string, float64 or boolean value.
// This is the Go equivalent of the C type "oconfig_value_t".
type Value struct {
	typ valueType
	s   string
	f   float64
	b   bool
}

// StringValue returns a new string Value.
func StringValue(v string) Value { return Value{typ: stringType, s: v} }

// Float64Value returns a new string Value.
func Float64Value(v float64) Value { return Value{typ: numberType, f: v} }

// BoolValue returns a new boolean Value.
func BoolValue(v bool) Value { return Value{typ: booleanType, b: v} }

// GoString returns a Go statement for creating cv.
func (cv Value) GoString() string {
	switch cv.typ {
	case stringType:
		return fmt.Sprintf("config.StringValue(%q)", cv.s)
	case numberType:
		return fmt.Sprintf("config.Float64Value(%v)", cv.f)
	case booleanType:
		return fmt.Sprintf("config.BoolValue(%v)", cv.b)
	}
	return "<invalid config.Value>"
}

// IsString returns true if cv is a string Value.
func (cv Value) IsString() bool {
	return cv.typ == stringType
}

// String returns Value as a string. Non-string values are formatted according to their default format.
func (cv Value) String() string {
	return fmt.Sprintf("%v", cv.Interface())
}

// Number returns the value of a number Value.
func (cv Value) Number() (float64, bool) {
	return cv.f, cv.typ == numberType
}

// Boolean returns the value of a bool Value.
func (cv Value) Boolean() (bool, bool) {
	return cv.b, cv.typ == booleanType
}

// Interface returns the specific value of Value without specifying its type, useful for functions like fmt.Printf
// which can use variables with unknown types.
func (cv Value) Interface() interface{} {
	switch cv.typ {
	case stringType:
		return cv.s
	case numberType:
		return cv.f
	case booleanType:
		return cv.b
	}
	return nil
}

func (cv Value) unmarshal(v reflect.Value) error {
	rvt := v.Type()
	var cvt reflect.Type
	var cvv reflect.Value

	switch cv.typ {
	case stringType:
		cvt = reflect.TypeOf(cv.s)
		cvv = reflect.ValueOf(cv.s)
	case booleanType:
		cvt = reflect.TypeOf(cv.b)
		cvv = reflect.ValueOf(cv.b)
	case numberType:
		cvt = reflect.TypeOf(cv.f)
		cvv = reflect.ValueOf(cv.f)
	default:
		return fmt.Errorf("unexpected Value type: %v", cv.typ)
	}

	if cvt.ConvertibleTo(rvt) {
		v.Set(cvv.Convert(rvt))
		return nil
	}
	if v.Kind() == reflect.Slice && cvt.ConvertibleTo(rvt.Elem()) {
		v.Set(reflect.Append(v, cvv.Convert(rvt.Elem())))
		return nil
	}
	return fmt.Errorf("cannot unmarshal a %T to a %s", cv.Interface(), v.Type())
}

// Block represents one configuration block, which may contain other configuration blocks.
type Block struct {
	Key      string
	Values   []Value
	Children []Block
}

// Merge appends other's Children to b's Children. If Key or Values differ, an
// error is returned.
func (b *Block) Merge(other Block) error {
	// If b is the zero value, we set it to other.
	if b.Key == "" && b.Values == nil && b.Children == nil {
		*b = other
		return nil
	}

	if b.Key != other.Key || !cmp.Equal(b.Values, other.Values, cmp.AllowUnexported(Value{})) {
		return fmt.Errorf("blocks differ: got {key:%v values:%v}, want {key:%v, values:%v}",
			other.Key, other.Values, b.Key, b.Values)
	}

	b.Children = append(b.Children, other.Children...)
	return nil
}

// Unmarshal applies the configuration from a Block to an arbitrary struct.
func (b *Block) Unmarshal(v interface{}) error {
	// If the target supports unmarshalling let it
	if u, ok := v.(Unmarshaler); ok {
		return u.UnmarshalConfig(v)
	}

	// Sanity check value of the interface
	rv := reflect.ValueOf(v)
	if rv.Kind() != reflect.Ptr || rv.IsNil() {
		return fmt.Errorf("can only unmarshal to a non-nil pointer") // TODO: better error message or nil if preferred
	}

	drv := rv.Elem() // get dereferenced value
	drvk := drv.Kind()

	// If config block has child blocks we can only unmarshal to a struct or slice of structs
	if len(b.Children) > 0 {
		if drvk != reflect.Struct && (drvk != reflect.Slice || drv.Type().Elem().Kind() != reflect.Struct) {
			return fmt.Errorf("cannot unmarshal a config with children except to a struct or slice of structs")
		}
	}

	switch drvk {
	case reflect.Struct:
		// Unmarshal values from config
		if err := storeStructConfigValues(b.Values, drv); err != nil {
			return fmt.Errorf("while unmarshalling config block values into %s: %s", drv.Type(), err)
		}
		for _, child := range b.Children {
			// If a config has children but the struct has no corresponding field, or the corresponding field is an
			// unexported struct field we throw an error.
			if field := drv.FieldByName(child.Key); field.IsValid() && field.CanInterface() {
				if err := child.Unmarshal(field.Addr().Interface()); err != nil {
					//	if err := child.Unmarshal(field.Interface()); err != nil {
					return fmt.Errorf("in child config block %s: %s", child.Key, err)
				}
			} else {
				return fmt.Errorf("found child config block with no corresponding field: %s", child.Key)
			}
		}
		return nil
	case reflect.Slice:
		switch drv.Type().Elem().Kind() {
		case reflect.Struct:
			// Create a temporary Value of the same type as dereferenced value, then get a Value of the same type as
			// its elements. Unmarshal into that Value and append the temporary Value to the original.
			tv := reflect.New(drv.Type().Elem()).Elem()
			if err := b.Unmarshal(tv.Addr().Interface()); err != nil {
				return fmt.Errorf("unmarshaling into temporary value failed: %s", err)
			}
			drv.Set(reflect.Append(drv, tv))
			return nil
		default:
			for _, cv := range b.Values {
				tv := reflect.New(drv.Type().Elem()).Elem()
				if err := cv.unmarshal(tv); err != nil {
					return fmt.Errorf("while unmarhalling values into %s: %s", drv.Type(), err)
				}
				drv.Set(reflect.Append(drv, tv))
			}
			return nil
		}
	case reflect.String, reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64:
		if len(b.Values) != 1 {
			return fmt.Errorf("cannot unmarshal config option with %d values into scalar type %s", len(b.Values), drv.Type())
		}
		return b.Values[0].unmarshal(drv)
	default:
		return fmt.Errorf("cannot unmarshal into type %s", drv.Type())
	}
}

func storeStructConfigValues(cvs []Value, v reflect.Value) error {
	if len(cvs) == 0 {
		return nil
	}
	args := v.FieldByName("Args")
	if !args.IsValid() {
		return fmt.Errorf("cannot unmarshal values to a struct without an Args field")
	}
	if len(cvs) > 1 && args.Kind() != reflect.Slice {
		return fmt.Errorf("cannot unmarshal config block with multiple values to a struct with non-slice Args field")
	}
	for _, cv := range cvs {
		if err := cv.unmarshal(args); err != nil {
			return fmt.Errorf("while attempting to unmarshal config value \"%v\" in Args: %s", cv.Interface(), err)
		}
	}
	return nil
}

// Unmarshaler is the interface implemented by types that can unmarshal a Block representation of themselves.
type Unmarshaler interface {
	UnmarshalConfig(v interface{}) error
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"log"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"strings"

	"github.com/spf13/viper"
)

// TablesConf informations
type TablesConf struct {
	Name        string   `mapstructure:"name"`
	Permissions []string `mapstructure:"permissions"`
	Fields      []string `mapstructure:"fields"`
}

// AccessConf informations
type AccessConf struct {
	Restrict bool
	Tables   []TablesConf
}

// Prest basic config
type Prest struct {
	// HTTPPort Declare which http port the PREST used
	HTTPPort        int
	PGHost          string
	PGPort          int
	PGUser          string
	PGPass          string
	PGDatabase      string
	PGMaxIdleConn   int
	PGMAxOpenConn   int
	PGConnTimeout   int
	JWTKey          string
	MigrationsPath  string
	QueriesPath     string
	AccessConf      AccessConf
	CORSAllowOrigin []string
	Debug           bool
}

// PrestConf config variable
var PrestConf *Prest

func viperCfg() {
	filePath := os.Getenv("PREST_CONF")
	dir, file := path.Split(filePath)
	file = strings.TrimSuffix(file, filepath.Ext(file))
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvPrefix("PREST")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(replacer)
	viper.AddConfigPath(dir)
	viper.SetConfigName(file)
	viper.SetConfigType("toml")
	viper.SetDefault("http.port", 3000)
	viper.SetDefault("pg.host", "127.0.0.1")
	viper.SetDefault("pg.port", 5432)
	viper.SetDefault("pg.maxidleconn", 10)
	viper.SetDefault("pg.maxopenconn", 10)
	viper.SetDefault("pg.conntimeout", 10)
	viper.SetDefault("debug", false)

	user, err := user.Current()
	if err != nil {
		log.Println("{viperCfg}", err)
	}

	viper.SetDefault("queries.location", filepath.Join(user.HomeDir, "queries"))
}

// Parse pREST config
func Parse(cfg *Prest) (err error) {
	err = viper.ReadInConfig()
	if err != nil {
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			fmt.Println("Running without config file")
		default:
			return
		}
	}
	cfg.HTTPPort = viper.GetInt("http.port")
	cfg.PGHost = viper.GetString("pg.host")
	cfg.PGPort = viper.GetInt("pg.port")
	cfg.PGUser = viper.GetString("pg.user")
	cfg.PGPass = viper.GetString("pg.pass")
	cfg.PGDatabase = viper.GetString("pg.database")
	cfg.PGMaxIdleConn = viper.GetInt("pg.maxidleconn")
	cfg.PGMAxOpenConn = viper.GetInt("pg.maxopenconn")
	cfg.PGConnTimeout = viper.GetInt("pg.conntimeout")
	cfg.JWTKey = viper.GetString("jwt.key")
	cfg.MigrationsPath = viper.GetString("migrations")
	cfg.AccessConf.Restrict = viper.GetBool("access.restrict")
	cfg.QueriesPath = viper.GetString("queries.location")
	cfg.CORSAllowOrigin = viper.GetStringSlice("cors.alloworigin")
	cfg.Debug = viper.GetBool("debug")

	var t []TablesConf
	err = viper.UnmarshalKey("access.tables", &t)
	if err != nil {
		return err
	}

	cfg.AccessConf.Tables = t

	return
}

// Load configuration
func Load() {
	viperCfg()
	PrestConf = &Prest{}
	err := Parse(PrestConf)
	if err != nil {
		panic(err)
	}

	if !PrestConf.AccessConf.Restrict {
		fmt.Println("You are running pREST in public mode.")
	}

	if PrestConf.Debug {
		fmt.Println("You are running pREST in debug mode.")
	}

	if _, err = os.Stat(PrestConf.QueriesPath); os.IsNotExist(err) {
		if err = os.MkdirAll(PrestConf.QueriesPath, 0700); os.IsNotExist(err) {
			fmt.Printf("Queries directory %s is not created", PrestConf.QueriesPath)
		}
	}
}
<commit_msg>fix toml config file loading on windows (#180)<commit_after>package config

import (
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strings"
	"github.com/spf13/viper"
)

// TablesConf informations
type TablesConf struct {
	Name        string   `mapstructure:"name"`
	Permissions []string `mapstructure:"permissions"`
	Fields      []string `mapstructure:"fields"`
}

// AccessConf informations
type AccessConf struct {
	Restrict bool
	Tables   []TablesConf
}

// Prest basic config
type Prest struct {
	// HTTPPort Declare which http port the PREST used
	HTTPPort        int
	PGHost          string
	PGPort          int
	PGUser          string
	PGPass          string
	PGDatabase      string
	PGMaxIdleConn   int
	PGMAxOpenConn   int
	PGConnTimeout   int
	JWTKey          string
	MigrationsPath  string
	QueriesPath     string
	AccessConf      AccessConf
	CORSAllowOrigin []string
	Debug           bool
}

// PrestConf config variable
var PrestConf *Prest

func viperCfg() {
	filePath := os.Getenv("PREST_CONF")
	dir, file := filepath.Split(filePath)
	file = strings.TrimSuffix(file, filepath.Ext(file))
	replacer := strings.NewReplacer(".", "_")
	viper.SetEnvPrefix("PREST")
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(replacer)
	viper.AddConfigPath(dir)
	viper.SetConfigName(file)
	viper.SetConfigType("toml")
	viper.SetDefault("http.port", 3000)
	viper.SetDefault("pg.host", "127.0.0.1")
	viper.SetDefault("pg.port", 5432)
	viper.SetDefault("pg.maxidleconn", 10)
	viper.SetDefault("pg.maxopenconn", 10)
	viper.SetDefault("pg.conntimeout", 10)
	viper.SetDefault("debug", false)

	user, err := user.Current()
	if err != nil {
		log.Println("{viperCfg}", err)
	}

	viper.SetDefault("queries.location", filepath.Join(user.HomeDir, "queries"))
}

// Parse pREST config
func Parse(cfg *Prest) (err error) {
	err = viper.ReadInConfig()
	if err != nil {
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			fmt.Println("Running without config file")
		default:
			return
		}
	}
	cfg.HTTPPort = viper.GetInt("http.port")
	cfg.PGHost = viper.GetString("pg.host")
	cfg.PGPort = viper.GetInt("pg.port")
	cfg.PGUser = viper.GetString("pg.user")
	cfg.PGPass = viper.GetString("pg.pass")
	cfg.PGDatabase = viper.GetString("pg.database")
	cfg.PGMaxIdleConn = viper.GetInt("pg.maxidleconn")
	cfg.PGMAxOpenConn = viper.GetInt("pg.maxopenconn")
	cfg.PGConnTimeout = viper.GetInt("pg.conntimeout")
	cfg.JWTKey = viper.GetString("jwt.key")
	cfg.MigrationsPath = viper.GetString("migrations")
	cfg.AccessConf.Restrict = viper.GetBool("access.restrict")
	cfg.QueriesPath = viper.GetString("queries.location")
	cfg.CORSAllowOrigin = viper.GetStringSlice("cors.alloworigin")
	cfg.Debug = viper.GetBool("debug")

	var t []TablesConf
	err = viper.UnmarshalKey("access.tables", &t)
	if err != nil {
		return err
	}

	cfg.AccessConf.Tables = t

	return
}

// Load configuration
func Load() {
	viperCfg()
	PrestConf = &Prest{}
	err := Parse(PrestConf)
	if err != nil {
		panic(err)
	}

	if !PrestConf.AccessConf.Restrict {
		fmt.Println("You are running pREST in public mode.")
	}

	if PrestConf.Debug {
		fmt.Println("You are running pREST in debug mode.")
	}

	if _, err = os.Stat(PrestConf.QueriesPath); os.IsNotExist(err) {
		if err = os.MkdirAll(PrestConf.QueriesPath, 0700); os.IsNotExist(err) {
			fmt.Printf("Queries directory %s is not created", PrestConf.QueriesPath)
		}
	}
}
<|endoftext|>


<commit_before>package config

import (
	"time"

	"github.com/kelseyhightower/envconfig"
)

// Config represents the configuration required for florence
type Config struct {
	BindAddr                   string        `envconfig:"BIND_ADDR"`
	RouterURL                  string        `envconfig:"ROUTER_URL"`
	ZebedeeURL                 string        `envconfig:"ZEBEDEE_URL"`
	RecipeAPIURL               string        `envconfig:"RECIPE_API_URL"`
	ImportAPIURL               string        `envconfig:"IMPORT_API_URL"`
	DatasetAPIURL              string        `envconfig:"DATASET_API_URL"`
	DatasetControllerURL       string        `envconfig:"DATASET_CONTROLLER_URL"`
	AwsRegion                  string        `envconfig:"AWS_REGION"`
	UploadBucketName           string        `envconfig:"UPLOAD_BUCKET_NAME"`
	EncryptionDisabled         bool          `envconfig:"ENCRYPTION_DISABLED"`
	VaultAddr                  string        `envconfig:"VAULT_ADDR"`
	VaultToken                 string        `envconfig:"VAULT_TOKEN"                json:"-"`
	VaultPath                  string        `envconfig:"VAULT_PATH"`
	TableRendererURL           string        `envconfig:"TABLE_RENDERER_URL"`
	GracefulShutdownTimeout    time.Duration `envconfig:"GRACEFUL_SHUTDOWN_TIMEOUT"`
	HealthCheckInterval        time.Duration `envconfig:"HEALTHCHECK_INTERVAL"`
	HealthCheckCriticalTimeout time.Duration `envconfig:"HEALTHCHECK_CRITICAL_TIMEOUT"`
	SharedConfig               SharedConfig
}

// SharedConfig represents the configuration made available to the client-side application from the server
type SharedConfig struct {
	EnableDatasetImport      bool `envconfig:"ENABLE_DATASET_IMPORT" json:"enableDatasetImport"`
	EnableHomepagePublishing bool `envconfig:"ENABLE_HOMEPAGE_PUBLISHING" json:"enableHomepagePublishing"`
}

var cfg *Config

// Get retrieves the config from the environment for florence
func Get() (*Config, error) {
	if cfg != nil {
		return cfg, nil
	}

	cfg = &Config{
		BindAddr:                   ":8080",
		RouterURL:                  "http://localhost:20000",
		ZebedeeURL:                 "http://localhost:8082",
		RecipeAPIURL:               "http://localhost:22300",
		ImportAPIURL:               "http://localhost:21800",
		DatasetAPIURL:              "http://localhost:22000",
		DatasetControllerURL:       "http://localhost:24000",
		AwsRegion:                  "eu-west-1",
		UploadBucketName:           "dp-frontend-florence-file-uploads",
		SharedConfig:               SharedConfig{EnableDatasetImport: false, EnableHomepagePublishing: false},
		EncryptionDisabled:         false,
		TableRendererURL:           "http://localhost:23300",
		VaultAddr:                  "http://localhost:8200",
		VaultToken:                 "",
		VaultPath:                  "secret/shared/psk",
		GracefulShutdownTimeout:    10 * time.Second,
		HealthCheckInterval:        30 * time.Second,
		HealthCheckCriticalTimeout: 90 * time.Second,
	}

	return cfg, envconfig.Process("", cfg)
}
<commit_msg>Add image api url<commit_after>package config

import (
	"time"

	"github.com/kelseyhightower/envconfig"
)

// Config represents the configuration required for florence
type Config struct {
	BindAddr                   string        `envconfig:"BIND_ADDR"`
	RouterURL                  string        `envconfig:"ROUTER_URL"`
	ZebedeeURL                 string        `envconfig:"ZEBEDEE_URL"`
	RecipeAPIURL               string        `envconfig:"RECIPE_API_URL"`
	ImportAPIURL               string        `envconfig:"IMPORT_API_URL"`
	DatasetAPIURL              string        `envconfig:"DATASET_API_URL"`
	ImageAPIURL                string        `envconfig:"IMAGE_API_URL"`
	DatasetControllerURL       string        `envconfig:"DATASET_CONTROLLER_URL"`
	AwsRegion                  string        `envconfig:"AWS_REGION"`
	UploadBucketName           string        `envconfig:"UPLOAD_BUCKET_NAME"`
	EncryptionDisabled         bool          `envconfig:"ENCRYPTION_DISABLED"`
	VaultAddr                  string        `envconfig:"VAULT_ADDR"`
	VaultToken                 string        `envconfig:"VAULT_TOKEN"                json:"-"`
	VaultPath                  string        `envconfig:"VAULT_PATH"`
	TableRendererURL           string        `envconfig:"TABLE_RENDERER_URL"`
	GracefulShutdownTimeout    time.Duration `envconfig:"GRACEFUL_SHUTDOWN_TIMEOUT"`
	HealthCheckInterval        time.Duration `envconfig:"HEALTHCHECK_INTERVAL"`
	HealthCheckCriticalTimeout time.Duration `envconfig:"HEALTHCHECK_CRITICAL_TIMEOUT"`
	SharedConfig               SharedConfig
}

// SharedConfig represents the configuration made available to the client-side application from the server
type SharedConfig struct {
	EnableDatasetImport      bool `envconfig:"ENABLE_DATASET_IMPORT" json:"enableDatasetImport"`
	EnableHomepagePublishing bool `envconfig:"ENABLE_HOMEPAGE_PUBLISHING" json:"enableHomepagePublishing"`
}

var cfg *Config

// Get retrieves the config from the environment for florence
func Get() (*Config, error) {
	if cfg != nil {
		return cfg, nil
	}

	cfg = &Config{
		BindAddr:                   ":8080",
		RouterURL:                  "http://localhost:20000",
		ZebedeeURL:                 "http://localhost:8082",
		RecipeAPIURL:               "http://localhost:22300",
		ImportAPIURL:               "http://localhost:21800",
		DatasetAPIURL:              "http://localhost:22000",
		ImageAPIURL:                "localhost:24700",
		DatasetControllerURL:       "http://localhost:24000",
		AwsRegion:                  "eu-west-1",
		UploadBucketName:           "dp-frontend-florence-file-uploads",
		SharedConfig:               SharedConfig{EnableDatasetImport: false, EnableHomepagePublishing: false},
		EncryptionDisabled:         false,
		TableRendererURL:           "http://localhost:23300",
		VaultAddr:                  "http://localhost:8200",
		VaultToken:                 "",
		VaultPath:                  "secret/shared/psk",
		GracefulShutdownTimeout:    10 * time.Second,
		HealthCheckInterval:        30 * time.Second,
		HealthCheckCriticalTimeout: 90 * time.Second,
	}

	return cfg, envconfig.Process("", cfg)
}
<|endoftext|>