<commit_before>package native

import (
	"fmt"
	"go/ast"
	"runtime"
	"sync"

	"github.com/go-delve/delve/pkg/proc"
)

// Process represents all of the information the debugger
// is holding onto regarding the process we are debugging.
type Process struct {
	bi *proc.BinaryInfo

	pid int // Process Pid

	// Breakpoint table, holds information on breakpoints.
	// Maps instruction address to Breakpoint struct.
	breakpoints proc.BreakpointMap

	// List of threads mapped as such: pid -> *Thread
	threads map[int]*Thread

	// Active thread
	currentThread *Thread

	// Goroutine that will be used by default to set breakpoint, eval variables, etc...
	// Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
	selectedGoroutine *proc.G

	common              proc.CommonProcess
	os                  *OSProcessDetails
	firstStart          bool
	stopMu              sync.Mutex
	resumeChan          chan<- struct{}
	ptraceChan          chan func()
	ptraceDoneChan      chan interface{}
	childProcess        bool // this process was launched, not attached to
	manualStopRequested bool

	exited, detached bool
}

// New returns an initialized Process struct. Before returning,
// it will also launch a goroutine in order to handle ptrace(2)
// functions. For more information, see the documentation on
// `handlePtraceFuncs`.
func New(pid int) *Process {
	dbp := &Process{
		pid:            pid,
		threads:        make(map[int]*Thread),
		breakpoints:    proc.NewBreakpointMap(),
		firstStart:     true,
		os:             new(OSProcessDetails),
		ptraceChan:     make(chan func()),
		ptraceDoneChan: make(chan interface{}),
		bi:             proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH),
	}
	go dbp.handlePtraceFuncs()
	return dbp
}

// BinInfo will return the binary info struct associated with this process.
func (dbp *Process) BinInfo() *proc.BinaryInfo {
	return dbp.bi
}

// Recorded always returns false for the native proc backend.
func (dbp *Process) Recorded() (bool, string) { return false, "" }

// Restart will always return an error in the native proc backend, only for
// recorded traces.
func (dbp *Process) Restart(string) error { return proc.ErrNotRecorded }

// Direction will always return an error in the native proc backend, only for
// recorded traces.
func (dbp *Process) Direction(proc.Direction) error { return proc.ErrNotRecorded }

// When will always return an empty string and nil, not supported on native proc backend.
func (dbp *Process) When() (string, error) { return "", nil }

// Checkpoint will always return an error on the native proc backend,
// only supported for recorded traces.
func (dbp *Process) Checkpoint(string) (int, error) { return -1, proc.ErrNotRecorded }

// Checkpoints will always return an error on the native proc backend,
// only supported for recorded traces.
func (dbp *Process) Checkpoints() ([]proc.Checkpoint, error) { return nil, proc.ErrNotRecorded }

// ClearCheckpoint will always return an error on the native proc backend,
// only supported in recorded traces.
func (dbp *Process) ClearCheckpoint(int) error { return proc.ErrNotRecorded }

// Detach from the process being debugged, optionally killing it.
func (dbp *Process) Detach(kill bool) (err error) {
	if dbp.exited {
		return nil
	}
	if kill && dbp.childProcess {
		err := dbp.kill()
		if err != nil {
			return err
		}
		dbp.bi.Close()
		return nil
	}
	if !kill {
		// Clean up any breakpoints we've set.
		for _, bp := range dbp.breakpoints.M {
			if bp != nil {
				_, err := dbp.ClearBreakpoint(bp.Addr)
				if err != nil {
					return err
				}
			}
		}
	}
	dbp.execPtraceFunc(func() {
		err = dbp.detach(kill)
		if err != nil {
			return
		}
		if kill {
			err = killProcess(dbp.pid)
		}
	})
	dbp.detached = true
	dbp.postExit()
	return
}

// Valid returns whether the process is still attached to and
// has not exited.
func (dbp *Process) Valid() (bool, error) {
	if dbp.detached {
		return false, &proc.ProcessDetachedError{}
	}
	if dbp.exited {
		return false, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	return true, nil
}

// ResumeNotify specifies a channel that will be closed the next time
// ContinueOnce finishes resuming the target.
func (dbp *Process) ResumeNotify(ch chan<- struct{}) {
	dbp.resumeChan = ch
}

// Pid returns the process ID.
func (dbp *Process) Pid() int {
	return dbp.pid
}

// SelectedGoroutine returns the current selected,
// active goroutine.
func (dbp *Process) SelectedGoroutine() *proc.G {
	return dbp.selectedGoroutine
}

// ThreadList returns a list of threads in the process.
func (dbp *Process) ThreadList() []proc.Thread {
	r := make([]proc.Thread, 0, len(dbp.threads))
	for _, v := range dbp.threads {
		r = append(r, v)
	}
	return r
}

// FindThread attempts to find the thread with the specified ID.
func (dbp *Process) FindThread(threadID int) (proc.Thread, bool) {
	th, ok := dbp.threads[threadID]
	return th, ok
}

// CurrentThread returns the current selected, active thread.
func (dbp *Process) CurrentThread() proc.Thread {
	return dbp.currentThread
}

// Breakpoints returns a list of breakpoints currently set.
func (dbp *Process) Breakpoints() *proc.BreakpointMap {
	return &dbp.breakpoints
}

// RequestManualStop sets the `halt` flag and
// sends SIGSTOP to all threads.
func (dbp *Process) RequestManualStop() error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	dbp.stopMu.Lock()
	defer dbp.stopMu.Unlock()
	dbp.manualStopRequested = true
	return dbp.requestManualStop()
}

// CheckAndClearManualStopRequest checks if a manual stop has
// been requested, and then clears that state.
func (dbp *Process) CheckAndClearManualStopRequest() bool {
	dbp.stopMu.Lock()
	defer dbp.stopMu.Unlock()

	msr := dbp.manualStopRequested
	dbp.manualStopRequested = false

	return msr
}

func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
	f, l, fn := dbp.bi.PCToLine(uint64(addr))

	originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
	_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
	if err != nil {
		return "", 0, nil, nil, err
	}
	if err := dbp.writeSoftwareBreakpoint(dbp.currentThread, addr); err != nil {
		return "", 0, nil, nil, err
	}

	return f, l, fn, originalData, nil
}

// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
// break point table.
func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
	return dbp.breakpoints.Set(addr, kind, cond, dbp.writeBreakpoint)
}

// ClearBreakpoint clears the breakpoint at addr.
func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
	if dbp.exited {
		return nil, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	return dbp.breakpoints.Clear(addr, dbp.currentThread.ClearBreakpoint)
}

// ContinueOnce will continue the target until it stops.
// This could be the result of a breakpoint or signal.
func (dbp *Process) ContinueOnce() (proc.Thread, error) {
	if dbp.exited {
		return nil, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}

	if err := dbp.resume(); err != nil {
		return nil, err
	}

	dbp.common.ClearAllGCache()
	for _, th := range dbp.threads {
		th.CurrentBreakpoint.Clear()
	}

	if dbp.resumeChan != nil {
		close(dbp.resumeChan)
		dbp.resumeChan = nil
	}

	trapthread, err := dbp.trapWait(-1)
	if err != nil {
		return nil, err
	}
	if err := dbp.stop(trapthread); err != nil {
		return nil, err
	}
	return trapthread, err
}

// StepInstruction will continue the current thread for exactly
// one instruction. This method affects only the thread
// associated with the selected goroutine. All other
// threads will remain stopped.
func (dbp *Process) StepInstruction() (err error) {
	thread := dbp.currentThread
	if dbp.selectedGoroutine != nil {
		if dbp.selectedGoroutine.Thread == nil {
			// Step called on parked goroutine
			if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
				return err
			}
			return proc.Continue(dbp)
		}
		thread = dbp.selectedGoroutine.Thread.(*Thread)
	}
	dbp.common.ClearAllGCache()
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	thread.CurrentBreakpoint.Clear()
	err = thread.StepInstruction()
	if err != nil {
		return err
	}
	err = thread.SetCurrentBreakpoint(true)
	if err != nil {
		return err
	}
	if g, _ := proc.GetG(thread); g != nil {
		dbp.selectedGoroutine = g
	}
	return nil
}

// SwitchThread changes from current thread to the thread specified by `tid`.
func (dbp *Process) SwitchThread(tid int) error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	if th, ok := dbp.threads[tid]; ok {
		dbp.currentThread = th
		dbp.selectedGoroutine, _ = proc.GetG(dbp.currentThread)
		return nil
	}
	return fmt.Errorf("thread %d does not exist", tid)
}

// SwitchGoroutine changes from current thread to the thread
// running the specified goroutine.
func (dbp *Process) SwitchGoroutine(gid int) error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	g, err := proc.FindGoroutine(dbp, gid)
	if err != nil {
		return err
	}
	if g == nil {
		// user specified -1 and selectedGoroutine is nil
		return nil
	}
	if g.Thread != nil {
		return dbp.SwitchThread(g.Thread.ThreadID())
	}
	dbp.selectedGoroutine = g
	return nil
}

// FindBreakpoint finds the breakpoint for the given pc.
func (dbp *Process) FindBreakpoint(pc uint64, adjustPC bool) (*proc.Breakpoint, bool) {
	if adjustPC {
		// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
		if bp, ok := dbp.breakpoints.M[pc-uint64(dbp.bi.Arch.BreakpointSize())]; ok {
			return bp, true
		}
	}
	// Directly use addr to lookup breakpoint.
	if bp, ok := dbp.breakpoints.M[pc]; ok {
		return bp, true
	}
	return nil, false
}

// initialize will ensure that all relevant information is loaded
// so the process is ready to be debugged.
func (dbp *Process) initialize(path string, debugInfoDirs []string) error {
	if err := initialize(dbp); err != nil {
		return err
	}
	if err := dbp.updateThreadList(); err != nil {
		return err
	}
	return proc.PostInitializationSetup(dbp, path, debugInfoDirs, dbp.writeBreakpoint)
}

// SetSelectedGoroutine will set internally the goroutine that should be
// the default for any command executed, the goroutine being actively
// followed.
func (dbp *Process) SetSelectedGoroutine(g *proc.G) {
	dbp.selectedGoroutine = g
}

// ClearInternalBreakpoints will clear all non-user set breakpoints. These
// breakpoints are set for internal operations such as 'next'.
func (dbp *Process) ClearInternalBreakpoints() error {
	return dbp.breakpoints.ClearInternalBreakpoints(func(bp *proc.Breakpoint) error {
		if err := dbp.currentThread.ClearBreakpoint(bp); err != nil {
			return err
		}
		for _, thread := range dbp.threads {
			if thread.CurrentBreakpoint.Breakpoint == bp {
				thread.CurrentBreakpoint.Clear()
			}
		}
		return nil
	})
}

func (dbp *Process) handlePtraceFuncs() {
	// We must ensure here that we are running on the same thread during
	// while invoking the ptrace(2) syscall. This is due to the fact that ptrace(2) expects
	// all commands after PTRACE_ATTACH to come from the same thread.
	runtime.LockOSThread()

	for fn := range dbp.ptraceChan {
		fn()
		dbp.ptraceDoneChan <- nil
	}
}

func (dbp *Process) execPtraceFunc(fn func()) {
	dbp.ptraceChan <- fn
	<-dbp.ptraceDoneChan
}

func (dbp *Process) postExit() {
	dbp.exited = true
	close(dbp.ptraceChan)
	close(dbp.ptraceDoneChan)
	dbp.bi.Close()
}

func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error {
	_, err := thread.WriteMemory(uintptr(addr), dbp.bi.Arch.BreakpointInstruction())
	return err
}

// Common returns common information across Process
// implementations
func (dbp *Process) Common() *proc.CommonProcess {
	return &dbp.common
}
<commit_msg>proc/native: always remove breakpoints when detaching (#1771) (#1772)<commit_after>package native

import (
	"fmt"
	"go/ast"
	"runtime"
	"sync"

	"github.com/go-delve/delve/pkg/proc"
)

// Process represents all of the information the debugger
// is holding onto regarding the process we are debugging.
type Process struct {
	bi *proc.BinaryInfo

	pid int // Process Pid

	// Breakpoint table, holds information on breakpoints.
	// Maps instruction address to Breakpoint struct.
	breakpoints proc.BreakpointMap

	// List of threads mapped as such: pid -> *Thread
	threads map[int]*Thread

	// Active thread
	currentThread *Thread

	// Goroutine that will be used by default to set breakpoint, eval variables, etc...
	// Normally selectedGoroutine is currentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
	selectedGoroutine *proc.G

	common              proc.CommonProcess
	os                  *OSProcessDetails
	firstStart          bool
	stopMu              sync.Mutex
	resumeChan          chan<- struct{}
	ptraceChan          chan func()
	ptraceDoneChan      chan interface{}
	childProcess        bool // this process was launched, not attached to
	manualStopRequested bool

	exited, detached bool
}

// New returns an initialized Process struct. Before returning,
// it will also launch a goroutine in order to handle ptrace(2)
// functions. For more information, see the documentation on
// `handlePtraceFuncs`.
func New(pid int) *Process {
	dbp := &Process{
		pid:            pid,
		threads:        make(map[int]*Thread),
		breakpoints:    proc.NewBreakpointMap(),
		firstStart:     true,
		os:             new(OSProcessDetails),
		ptraceChan:     make(chan func()),
		ptraceDoneChan: make(chan interface{}),
		bi:             proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH),
	}
	go dbp.handlePtraceFuncs()
	return dbp
}

// BinInfo will return the binary info struct associated with this process.
func (dbp *Process) BinInfo() *proc.BinaryInfo {
	return dbp.bi
}

// Recorded always returns false for the native proc backend.
func (dbp *Process) Recorded() (bool, string) { return false, "" }

// Restart will always return an error in the native proc backend, only for
// recorded traces.
func (dbp *Process) Restart(string) error { return proc.ErrNotRecorded }

// Direction will always return an error in the native proc backend, only for
// recorded traces.
func (dbp *Process) Direction(proc.Direction) error { return proc.ErrNotRecorded }

// When will always return an empty string and nil, not supported on native proc backend.
func (dbp *Process) When() (string, error) { return "", nil }

// Checkpoint will always return an error on the native proc backend,
// only supported for recorded traces.
func (dbp *Process) Checkpoint(string) (int, error) { return -1, proc.ErrNotRecorded }

// Checkpoints will always return an error on the native proc backend,
// only supported for recorded traces.
func (dbp *Process) Checkpoints() ([]proc.Checkpoint, error) { return nil, proc.ErrNotRecorded }

// ClearCheckpoint will always return an error on the native proc backend,
// only supported in recorded traces.
func (dbp *Process) ClearCheckpoint(int) error { return proc.ErrNotRecorded }

// Detach from the process being debugged, optionally killing it.
func (dbp *Process) Detach(kill bool) (err error) {
	if dbp.exited {
		return nil
	}
	if kill && dbp.childProcess {
		err := dbp.kill()
		if err != nil {
			return err
		}
		dbp.bi.Close()
		return nil
	}
	// Clean up any breakpoints we've set.
	for _, bp := range dbp.breakpoints.M {
		if bp != nil {
			_, err := dbp.ClearBreakpoint(bp.Addr)
			if err != nil {
				return err
			}
		}
	}
	dbp.execPtraceFunc(func() {
		err = dbp.detach(kill)
		if err != nil {
			return
		}
		if kill {
			err = killProcess(dbp.pid)
		}
	})
	dbp.detached = true
	dbp.postExit()
	return
}

// Valid returns whether the process is still attached to and
// has not exited.
func (dbp *Process) Valid() (bool, error) {
	if dbp.detached {
		return false, &proc.ProcessDetachedError{}
	}
	if dbp.exited {
		return false, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	return true, nil
}

// ResumeNotify specifies a channel that will be closed the next time
// ContinueOnce finishes resuming the target.
func (dbp *Process) ResumeNotify(ch chan<- struct{}) {
	dbp.resumeChan = ch
}

// Pid returns the process ID.
func (dbp *Process) Pid() int {
	return dbp.pid
}

// SelectedGoroutine returns the current selected,
// active goroutine.
func (dbp *Process) SelectedGoroutine() *proc.G {
	return dbp.selectedGoroutine
}

// ThreadList returns a list of threads in the process.
func (dbp *Process) ThreadList() []proc.Thread {
	r := make([]proc.Thread, 0, len(dbp.threads))
	for _, v := range dbp.threads {
		r = append(r, v)
	}
	return r
}

// FindThread attempts to find the thread with the specified ID.
func (dbp *Process) FindThread(threadID int) (proc.Thread, bool) {
	th, ok := dbp.threads[threadID]
	return th, ok
}

// CurrentThread returns the current selected, active thread.
func (dbp *Process) CurrentThread() proc.Thread {
	return dbp.currentThread
}

// Breakpoints returns a list of breakpoints currently set.
func (dbp *Process) Breakpoints() *proc.BreakpointMap {
	return &dbp.breakpoints
}

// RequestManualStop sets the `halt` flag and
// sends SIGSTOP to all threads.
func (dbp *Process) RequestManualStop() error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	dbp.stopMu.Lock()
	defer dbp.stopMu.Unlock()
	dbp.manualStopRequested = true
	return dbp.requestManualStop()
}

// CheckAndClearManualStopRequest checks if a manual stop has
// been requested, and then clears that state.
func (dbp *Process) CheckAndClearManualStopRequest() bool {
	dbp.stopMu.Lock()
	defer dbp.stopMu.Unlock()

	msr := dbp.manualStopRequested
	dbp.manualStopRequested = false

	return msr
}

func (dbp *Process) writeBreakpoint(addr uint64) (string, int, *proc.Function, []byte, error) {
	f, l, fn := dbp.bi.PCToLine(uint64(addr))

	originalData := make([]byte, dbp.bi.Arch.BreakpointSize())
	_, err := dbp.currentThread.ReadMemory(originalData, uintptr(addr))
	if err != nil {
		return "", 0, nil, nil, err
	}
	if err := dbp.writeSoftwareBreakpoint(dbp.currentThread, addr); err != nil {
		return "", 0, nil, nil, err
	}

	return f, l, fn, originalData, nil
}

// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
// break point table.
func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond ast.Expr) (*proc.Breakpoint, error) {
	return dbp.breakpoints.Set(addr, kind, cond, dbp.writeBreakpoint)
}

// ClearBreakpoint clears the breakpoint at addr.
func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
	if dbp.exited {
		return nil, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	return dbp.breakpoints.Clear(addr, dbp.currentThread.ClearBreakpoint)
}

// ContinueOnce will continue the target until it stops.
// This could be the result of a breakpoint or signal.
func (dbp *Process) ContinueOnce() (proc.Thread, error) {
	if dbp.exited {
		return nil, &proc.ErrProcessExited{Pid: dbp.Pid()}
	}

	if err := dbp.resume(); err != nil {
		return nil, err
	}

	dbp.common.ClearAllGCache()
	for _, th := range dbp.threads {
		th.CurrentBreakpoint.Clear()
	}

	if dbp.resumeChan != nil {
		close(dbp.resumeChan)
		dbp.resumeChan = nil
	}

	trapthread, err := dbp.trapWait(-1)
	if err != nil {
		return nil, err
	}
	if err := dbp.stop(trapthread); err != nil {
		return nil, err
	}
	return trapthread, err
}

// StepInstruction will continue the current thread for exactly
// one instruction. This method affects only the thread
// associated with the selected goroutine. All other
// threads will remain stopped.
func (dbp *Process) StepInstruction() (err error) {
	thread := dbp.currentThread
	if dbp.selectedGoroutine != nil {
		if dbp.selectedGoroutine.Thread == nil {
			// Step called on parked goroutine
			if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
				return err
			}
			return proc.Continue(dbp)
		}
		thread = dbp.selectedGoroutine.Thread.(*Thread)
	}
	dbp.common.ClearAllGCache()
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	thread.CurrentBreakpoint.Clear()
	err = thread.StepInstruction()
	if err != nil {
		return err
	}
	err = thread.SetCurrentBreakpoint(true)
	if err != nil {
		return err
	}
	if g, _ := proc.GetG(thread); g != nil {
		dbp.selectedGoroutine = g
	}
	return nil
}

// SwitchThread changes from current thread to the thread specified by `tid`.
func (dbp *Process) SwitchThread(tid int) error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	if th, ok := dbp.threads[tid]; ok {
		dbp.currentThread = th
		dbp.selectedGoroutine, _ = proc.GetG(dbp.currentThread)
		return nil
	}
	return fmt.Errorf("thread %d does not exist", tid)
}

// SwitchGoroutine changes from current thread to the thread
// running the specified goroutine.
func (dbp *Process) SwitchGoroutine(gid int) error {
	if dbp.exited {
		return &proc.ErrProcessExited{Pid: dbp.Pid()}
	}
	g, err := proc.FindGoroutine(dbp, gid)
	if err != nil {
		return err
	}
	if g == nil {
		// user specified -1 and selectedGoroutine is nil
		return nil
	}
	if g.Thread != nil {
		return dbp.SwitchThread(g.Thread.ThreadID())
	}
	dbp.selectedGoroutine = g
	return nil
}

// FindBreakpoint finds the breakpoint for the given pc.
func (dbp *Process) FindBreakpoint(pc uint64, adjustPC bool) (*proc.Breakpoint, bool) {
	if adjustPC {
		// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
		if bp, ok := dbp.breakpoints.M[pc-uint64(dbp.bi.Arch.BreakpointSize())]; ok {
			return bp, true
		}
	}
	// Directly use addr to lookup breakpoint.
	if bp, ok := dbp.breakpoints.M[pc]; ok {
		return bp, true
	}
	return nil, false
}

// initialize will ensure that all relevant information is loaded
// so the process is ready to be debugged.
func (dbp *Process) initialize(path string, debugInfoDirs []string) error {
	if err := initialize(dbp); err != nil {
		return err
	}
	if err := dbp.updateThreadList(); err != nil {
		return err
	}
	return proc.PostInitializationSetup(dbp, path, debugInfoDirs, dbp.writeBreakpoint)
}

// SetSelectedGoroutine will set internally the goroutine that should be
// the default for any command executed, the goroutine being actively
// followed.
func (dbp *Process) SetSelectedGoroutine(g *proc.G) {
	dbp.selectedGoroutine = g
}

// ClearInternalBreakpoints will clear all non-user set breakpoints. These
// breakpoints are set for internal operations such as 'next'.
func (dbp *Process) ClearInternalBreakpoints() error {
	return dbp.breakpoints.ClearInternalBreakpoints(func(bp *proc.Breakpoint) error {
		if err := dbp.currentThread.ClearBreakpoint(bp); err != nil {
			return err
		}
		for _, thread := range dbp.threads {
			if thread.CurrentBreakpoint.Breakpoint == bp {
				thread.CurrentBreakpoint.Clear()
			}
		}
		return nil
	})
}

func (dbp *Process) handlePtraceFuncs() {
	// We must ensure here that we are running on the same thread during
	// while invoking the ptrace(2) syscall. This is due to the fact that ptrace(2) expects
	// all commands after PTRACE_ATTACH to come from the same thread.
	runtime.LockOSThread()

	for fn := range dbp.ptraceChan {
		fn()
		dbp.ptraceDoneChan <- nil
	}
}

func (dbp *Process) execPtraceFunc(fn func()) {
	dbp.ptraceChan <- fn
	<-dbp.ptraceDoneChan
}

func (dbp *Process) postExit() {
	dbp.exited = true
	close(dbp.ptraceChan)
	close(dbp.ptraceDoneChan)
	dbp.bi.Close()
}

func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error {
	_, err := thread.WriteMemory(uintptr(addr), dbp.bi.Arch.BreakpointInstruction())
	return err
}

// Common returns common information across Process
// implementations
func (dbp *Process) Common() *proc.CommonProcess {
	return &dbp.common
}
<|endoftext|>


<commit_before>package gce

import (
	"errors"
	"fmt"

	"github.com/jetstack/kube-lego/pkg/kubelego_const"
	"github.com/jetstack/kube-lego/pkg/service"

	"github.com/Sirupsen/logrus"
	k8sExtensions "k8s.io/kubernetes/pkg/apis/extensions"
)

const ClassName = "gce"

var ErrorClassNotMatching = errors.New("Ingress class not matching")

var challengePath = fmt.Sprintf("%s/*", kubelego.AcmeHttpChallengePath)

var _ kubelego.IngressProvider = &Gce{}

func getHostMap(ing kubelego.Ingress) map[string]bool {
	hostMap := map[string]bool{}
	for _, tls := range ing.Tls() {
		for _, host := range tls.Hosts() {
			hostMap[host] = true
		}
	}
	return hostMap
}

type Gce struct {
	kubelego        kubelego.KubeLego
	service         kubelego.Service
	usedByNamespace map[string]bool
}

func New(kl kubelego.KubeLego) *Gce {
	return &Gce{
		kubelego:        kl,
		usedByNamespace: map[string]bool{},
	}
}

func (p *Gce) Log() (log *logrus.Entry) {
	return p.kubelego.Log().WithField("context", "provider").WithField("provider", "gce")
}

func (p *Gce) Reset() (err error) {
	p.Log().Debug("reset")
	p.usedByNamespace = map[string]bool{}
	p.service = nil
	return nil
}

func (p *Gce) Finalize() (err error) {
	p.Log().Debug("finialize")

	err = p.updateServices()
	if err != nil {
		return err
	}

	err = p.removeServices()
	return
}

func (p *Gce) removeServices() (err error) {
	// TODO implement me
	return nil
}

func (p *Gce) updateServices() (err error) {
	for namespace, enabled := range p.usedByNamespace {
		if enabled {
			err = p.updateService(namespace)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (p *Gce) updateService(namespace string) (err error) {
	var svc kubelego.Service = service.New(p.kubelego, namespace, p.kubelego.LegoServiceNameGce())

	svc.SetKubeLegoSpec()
	svc.Object().Spec.Type = "NodePort"

	err = svc.SetEndpoints([]string{"1.2.3.4:8080"})
	if err != nil{
		return err
	}

	return svc.Save()
}

func (p *Gce) Process(ingObj kubelego.Ingress) (err error) {
	ingApi := ingObj.Object()
	hostsEnabled := getHostMap(ingObj)
	hostsNotConfigured := getHostMap(ingObj)

	var rulesNew []k8sExtensions.IngressRule
	for _, rule := range ingApi.Spec.Rules {

		pathsNew := []k8sExtensions.HTTPIngressPath{}

		// add challenge endpoints first, if needed
		if _, hostEnabled := hostsEnabled[rule.Host]; hostEnabled {
			delete(hostsNotConfigured, rule.Host)
			pathsNew = []k8sExtensions.HTTPIngressPath{
				p.getHTTPIngressPath(),
			}
		}

		// remove existing challenge paths
		for _, path := range rule.HTTP.Paths {
			if path.Path == challengePath {
				continue
			}
			pathsNew = append(pathsNew, path)
		}

		// add rule if it contains at least one path
		if len(pathsNew) > 0 {
			rule.HTTP.Paths = pathsNew
			rulesNew = append(rulesNew, rule)
		}
	}

	// add missing hosts
	for host, _ := range hostsNotConfigured {
		rulesNew = append(rulesNew, k8sExtensions.IngressRule{
			Host: host,
			IngressRuleValue: k8sExtensions.IngressRuleValue{
				HTTP: &k8sExtensions.HTTPIngressRuleValue{
					Paths: []k8sExtensions.HTTPIngressPath{
						p.getHTTPIngressPath(),
					},
				},
			},
		})
	}

	ingApi.Spec.Rules = rulesNew

	if len(hostsEnabled) > 0 {
		p.usedByNamespace[ingApi.Namespace] = true
	}

	return ingObj.Save()
}

func (p *Gce) getHTTPIngressPath() k8sExtensions.HTTPIngressPath {
	return k8sExtensions.HTTPIngressPath{
		Path: challengePath,
		Backend: k8sExtensions.IngressBackend{
			ServiceName: p.kubelego.LegoServiceNameGce(),
			ServicePort: p.kubelego.LegoHTTPPort(),
		},
	}
}
<commit_msg>Use correct pod IP for setting up endpoints for service<commit_after>package gce

import (
	"errors"
	"fmt"

	"github.com/jetstack/kube-lego/pkg/kubelego_const"
	"github.com/jetstack/kube-lego/pkg/service"

	"github.com/Sirupsen/logrus"
	k8sExtensions "k8s.io/kubernetes/pkg/apis/extensions"
)

const ClassName = "gce"

var ErrorClassNotMatching = errors.New("Ingress class not matching")

var challengePath = fmt.Sprintf("%s/*", kubelego.AcmeHttpChallengePath)

var _ kubelego.IngressProvider = &Gce{}

func getHostMap(ing kubelego.Ingress) map[string]bool {
	hostMap := map[string]bool{}
	for _, tls := range ing.Tls() {
		for _, host := range tls.Hosts() {
			hostMap[host] = true
		}
	}
	return hostMap
}

type Gce struct {
	kubelego        kubelego.KubeLego
	service         kubelego.Service
	usedByNamespace map[string]bool
}

func New(kl kubelego.KubeLego) *Gce {
	return &Gce{
		kubelego:        kl,
		usedByNamespace: map[string]bool{},
	}
}

func (p *Gce) Log() (log *logrus.Entry) {
	return p.kubelego.Log().WithField("context", "provider").WithField("provider", "gce")
}

func (p *Gce) Reset() (err error) {
	p.Log().Debug("reset")
	p.usedByNamespace = map[string]bool{}
	p.service = nil
	return nil
}

func (p *Gce) Finalize() (err error) {
	p.Log().Debug("finialize")

	err = p.updateServices()
	if err != nil {
		return err
	}

	err = p.removeServices()
	return
}

func (p *Gce) removeServices() (err error) {
	// TODO implement me
	return nil
}

func (p *Gce) updateServices() (err error) {
	for namespace, enabled := range p.usedByNamespace {
		if enabled {
			err = p.updateService(namespace)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (p *Gce) updateService(namespace string) (err error) {
	var svc kubelego.Service = service.New(p.kubelego, namespace, p.kubelego.LegoServiceNameGce())

	svc.SetKubeLegoSpec()
	svc.Object().Spec.Type = "NodePort"

	podIP := p.kubelego.LegoPodIP().String()
	p.Log().WithField("pod_ip", podIP).WithField("namespace", namespace).Debug("setting up svc endpoint")
	err = svc.SetEndpoints([]string{podIP})
	if err != nil {
		return err
	}

	return svc.Save()
}

func (p *Gce) Process(ingObj kubelego.Ingress) (err error) {
	ingApi := ingObj.Object()
	hostsEnabled := getHostMap(ingObj)
	hostsNotConfigured := getHostMap(ingObj)

	var rulesNew []k8sExtensions.IngressRule
	for _, rule := range ingApi.Spec.Rules {

		pathsNew := []k8sExtensions.HTTPIngressPath{}

		// add challenge endpoints first, if needed
		if _, hostEnabled := hostsEnabled[rule.Host]; hostEnabled {
			delete(hostsNotConfigured, rule.Host)
			pathsNew = []k8sExtensions.HTTPIngressPath{
				p.getHTTPIngressPath(),
			}
		}

		// remove existing challenge paths
		for _, path := range rule.HTTP.Paths {
			if path.Path == challengePath {
				continue
			}
			pathsNew = append(pathsNew, path)
		}

		// add rule if it contains at least one path
		if len(pathsNew) > 0 {
			rule.HTTP.Paths = pathsNew
			rulesNew = append(rulesNew, rule)
		}
	}

	// add missing hosts
	for host, _ := range hostsNotConfigured {
		rulesNew = append(rulesNew, k8sExtensions.IngressRule{
			Host: host,
			IngressRuleValue: k8sExtensions.IngressRuleValue{
				HTTP: &k8sExtensions.HTTPIngressRuleValue{
					Paths: []k8sExtensions.HTTPIngressPath{
						p.getHTTPIngressPath(),
					},
				},
			},
		})
	}

	ingApi.Spec.Rules = rulesNew

	if len(hostsEnabled) > 0 {
		p.usedByNamespace[ingApi.Namespace] = true
	}

	return ingObj.Save()
}

func (p *Gce) getHTTPIngressPath() k8sExtensions.HTTPIngressPath {
	return k8sExtensions.HTTPIngressPath{
		Path: challengePath,
		Backend: k8sExtensions.IngressBackend{
			ServiceName: p.kubelego.LegoServiceNameGce(),
			ServicePort: p.kubelego.LegoHTTPPort(),
		},
	}
}
<|endoftext|>


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

package service

import (
	"fmt"

	"github.com/cilium/cilium/pkg/loadbalancer"
	"github.com/cilium/cilium/pkg/lock"
)

// IDAllocator contains an internal state of the ID allocator.
type IDAllocator struct {
	// Protects entitiesID, entities, nextID and maxID
	lock.RWMutex

	// entitiesID is a map of all entities indexed by service or backend ID
	entitiesID map[uint32]*loadbalancer.L3n4AddrID

	// entities is a map of all entities indexed by L3n4Addr.StringID()
	entities map[string]uint32

	// nextID is the next ID to attempt to allocate
	nextID uint32

	// maxID is the maximum ID available for allocation
	maxID uint32

	// initNextID is the initial nextID
	initNextID uint32

	// initMaxID is the initial maxID
	initMaxID uint32
}

var (
	serviceIDAlloc = NewIDAllocator(FirstFreeServiceID, MaxSetOfServiceID)
	backendIDAlloc = NewIDAllocator(FirstFreeBackendID, MaxSetOfBackendID)
)

// NewIDAllocator creates a new ID allocator instance.
func NewIDAllocator(nextID uint32, maxID uint32) *IDAllocator {
	return &IDAllocator{
		entitiesID: map[uint32]*loadbalancer.L3n4AddrID{},
		entities:   map[string]uint32{},
		nextID:     nextID,
		maxID:      maxID,
		initNextID: nextID,
		initMaxID:  maxID,
	}
}

func (alloc *IDAllocator) addID(svc loadbalancer.L3n4Addr, id uint32) *loadbalancer.L3n4AddrID {
	svcID := newID(svc, id)
	alloc.entitiesID[id] = svcID
	alloc.entities[svc.StringID()] = id

	return svcID
}

func (alloc *IDAllocator) acquireLocalID(svc loadbalancer.L3n4Addr, desiredID uint32) (*loadbalancer.L3n4AddrID, error) {
	alloc.Lock()
	defer alloc.Unlock()

	if svcID, ok := alloc.entities[svc.StringID()]; ok {
		if svc, ok := alloc.entitiesID[svcID]; ok {
			return svc, nil
		}
	}

	if desiredID != 0 {
		foundSVC, ok := alloc.entitiesID[desiredID]
		if !ok {
			return alloc.addID(svc, desiredID), nil
		}
		return nil, fmt.Errorf("Service ID %d is already registered to %q",
			desiredID, foundSVC)
	}

	startingID := alloc.nextID
	rollover := false
	for {
		if alloc.nextID == startingID && rollover {
			break
		} else if alloc.nextID == alloc.maxID {
			alloc.nextID = FirstFreeServiceID
			rollover = true
		}

		if _, ok := alloc.entitiesID[alloc.nextID]; !ok {
			svcID := alloc.addID(svc, alloc.nextID)
			alloc.nextID++
			return svcID, nil
		}

		alloc.nextID++
	}

	return nil, fmt.Errorf("no service ID available")
}

func (alloc *IDAllocator) getLocalID(id uint32) (*loadbalancer.L3n4AddrID, error) {
	alloc.RLock()
	defer alloc.RUnlock()

	if svc, ok := alloc.entitiesID[id]; ok {
		return svc, nil
	}

	return nil, nil
}

func (alloc *IDAllocator) deleteLocalID(id uint32) error {
	alloc.Lock()
	defer alloc.Unlock()

	if svc, ok := alloc.entitiesID[id]; ok {
		delete(alloc.entitiesID, id)
		delete(alloc.entities, svc.StringID())
	}

	return nil
}

func (alloc *IDAllocator) lookupLocalID(svc loadbalancer.L3n4Addr) (uint32, error) {
	alloc.RLock()
	defer alloc.RUnlock()

	if svcID, ok := alloc.entities[svc.StringID()]; ok {
		return svcID, nil
	}

	return 0, fmt.Errorf("ID not found")
}

func (alloc *IDAllocator) setLocalIDSpace(next, max uint32) error {
	alloc.Lock()
	alloc.nextID = next
	alloc.maxID = max
	alloc.Unlock()

	return nil
}

func (alloc *IDAllocator) getLocalMaxID() (uint32, error) {
	alloc.RLock()
	defer alloc.RUnlock()
	return alloc.nextID, nil
}

func (alloc *IDAllocator) resetLocalID() {
	alloc.Lock()
	alloc.entitiesID = map[uint32]*loadbalancer.L3n4AddrID{}
	alloc.entities = map[string]uint32{}
	alloc.nextID = alloc.initNextID
	alloc.maxID = alloc.initMaxID
	alloc.Unlock()
}

func newID(svc loadbalancer.L3n4Addr, id uint32) *loadbalancer.L3n4AddrID {
	return &loadbalancer.L3n4AddrID{
		L3n4Addr: svc,
		ID:       loadbalancer.ID(id),
	}
}
<commit_msg>service: Use initNextID in acquireLocalID()<commit_after>// Copyright 2018 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package service

import (
	"fmt"

	"github.com/cilium/cilium/pkg/loadbalancer"
	"github.com/cilium/cilium/pkg/lock"
)

// IDAllocator contains an internal state of the ID allocator.
type IDAllocator struct {
	// Protects entitiesID, entities, nextID and maxID
	lock.RWMutex

	// entitiesID is a map of all entities indexed by service or backend ID
	entitiesID map[uint32]*loadbalancer.L3n4AddrID

	// entities is a map of all entities indexed by L3n4Addr.StringID()
	entities map[string]uint32

	// nextID is the next ID to attempt to allocate
	nextID uint32

	// maxID is the maximum ID available for allocation
	maxID uint32

	// initNextID is the initial nextID
	initNextID uint32

	// initMaxID is the initial maxID
	initMaxID uint32
}

var (
	serviceIDAlloc = NewIDAllocator(FirstFreeServiceID, MaxSetOfServiceID)
	backendIDAlloc = NewIDAllocator(FirstFreeBackendID, MaxSetOfBackendID)
)

// NewIDAllocator creates a new ID allocator instance.
func NewIDAllocator(nextID uint32, maxID uint32) *IDAllocator {
	return &IDAllocator{
		entitiesID: map[uint32]*loadbalancer.L3n4AddrID{},
		entities:   map[string]uint32{},
		nextID:     nextID,
		maxID:      maxID,
		initNextID: nextID,
		initMaxID:  maxID,
	}
}

func (alloc *IDAllocator) addID(svc loadbalancer.L3n4Addr, id uint32) *loadbalancer.L3n4AddrID {
	svcID := newID(svc, id)
	alloc.entitiesID[id] = svcID
	alloc.entities[svc.StringID()] = id

	return svcID
}

func (alloc *IDAllocator) acquireLocalID(svc loadbalancer.L3n4Addr, desiredID uint32) (*loadbalancer.L3n4AddrID, error) {
	alloc.Lock()
	defer alloc.Unlock()

	if svcID, ok := alloc.entities[svc.StringID()]; ok {
		if svc, ok := alloc.entitiesID[svcID]; ok {
			return svc, nil
		}
	}

	if desiredID != 0 {
		foundSVC, ok := alloc.entitiesID[desiredID]
		if !ok {
			return alloc.addID(svc, desiredID), nil
		}
		return nil, fmt.Errorf("Service ID %d is already registered to %q",
			desiredID, foundSVC)
	}

	startingID := alloc.nextID
	rollover := false
	for {
		if alloc.nextID == startingID && rollover {
			break
		} else if alloc.nextID == alloc.maxID {
			alloc.nextID = alloc.initNextID
			rollover = true
		}

		if _, ok := alloc.entitiesID[alloc.nextID]; !ok {
			svcID := alloc.addID(svc, alloc.nextID)
			alloc.nextID++
			return svcID, nil
		}

		alloc.nextID++
	}

	return nil, fmt.Errorf("no service ID available")
}

func (alloc *IDAllocator) getLocalID(id uint32) (*loadbalancer.L3n4AddrID, error) {
	alloc.RLock()
	defer alloc.RUnlock()

	if svc, ok := alloc.entitiesID[id]; ok {
		return svc, nil
	}

	return nil, nil
}

func (alloc *IDAllocator) deleteLocalID(id uint32) error {
	alloc.Lock()
	defer alloc.Unlock()

	if svc, ok := alloc.entitiesID[id]; ok {
		delete(alloc.entitiesID, id)
		delete(alloc.entities, svc.StringID())
	}

	return nil
}

func (alloc *IDAllocator) lookupLocalID(svc loadbalancer.L3n4Addr) (uint32, error) {
	alloc.RLock()
	defer alloc.RUnlock()

	if svcID, ok := alloc.entities[svc.StringID()]; ok {
		return svcID, nil
	}

	return 0, fmt.Errorf("ID not found")
}

func (alloc *IDAllocator) setLocalIDSpace(next, max uint32) error {
	alloc.Lock()
	alloc.nextID = next
	alloc.maxID = max
	alloc.Unlock()

	return nil
}

func (alloc *IDAllocator) getLocalMaxID() (uint32, error) {
	alloc.RLock()
	defer alloc.RUnlock()
	return alloc.nextID, nil
}

func (alloc *IDAllocator) resetLocalID() {
	alloc.Lock()
	alloc.entitiesID = map[uint32]*loadbalancer.L3n4AddrID{}
	alloc.entities = map[string]uint32{}
	alloc.nextID = alloc.initNextID
	alloc.maxID = alloc.initMaxID
	alloc.Unlock()
}

func newID(svc loadbalancer.L3n4Addr, id uint32) *loadbalancer.L3n4AddrID {
	return &loadbalancer.L3n4AddrID{
		L3n4Addr: svc,
		ID:       loadbalancer.ID(id),
	}
}
<|endoftext|>


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

// +build windows

// Package mgr can be used to manage Windows service programs.
// It can be used to install and remove them. It can also start,
// stop and pause them. The package can query / change current
// service state and config parameters.
//
package mgr

import (
	"syscall"
	"unicode/utf16"

	"golang.org/x/sys/windows"
)

// Mgr is used to manage Windows service.
type Mgr struct {
	Handle windows.Handle
}

// Connect establishes a connection to the service control manager.
func Connect() (*Mgr, error) {
	return ConnectRemote("")
}

// ConnectRemote establishes a connection to the
// service control manager on computer named host.
func ConnectRemote(host string) (*Mgr, error) {
	var s *uint16
	if host != "" {
		s = syscall.StringToUTF16Ptr(host)
	}
	h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
	if err != nil {
		return nil, err
	}
	return &Mgr{Handle: h}, nil
}

// Disconnect closes connection to the service control manager m.
func (m *Mgr) Disconnect() error {
	return windows.CloseServiceHandle(m.Handle)
}

func toPtr(s string) *uint16 {
	if len(s) == 0 {
		return nil
	}
	return syscall.StringToUTF16Ptr(s)
}

// toStringBlock terminates strings in ss with 0, and then
// concatenates them together. It also adds extra 0 at the end.
func toStringBlock(ss []string) *uint16 {
	if len(ss) == 0 {
		return nil
	}
	t := ""
	for _, s := range ss {
		if s != "" {
			t += s + "\x00"
		}
	}
	if t == "" {
		return nil
	}
	t += "\x00"
	return &utf16.Encode([]rune(t))[0]
}

// CreateService installs new service name on the system.
// The service will be executed by running exepath binary.
// Use config c to specify service parameters.
// If service StartType is set to StartAutomatic,
// args will be passed to svc.Handle.Execute.
func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) {
	if c.StartType == 0 {
		c.StartType = StartManual
	}
	if c.ErrorControl == 0 {
		c.ErrorControl = ErrorNormal
	}
	if c.ServiceType == 0 {
		c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
	}
	s := syscall.EscapeArg(exepath)
	for _, v := range args {
		s += " " + syscall.EscapeArg(v)
	}
	h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
		windows.SERVICE_ALL_ACCESS, c.ServiceType,
		c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
		nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
	if err != nil {
		return nil, err
	}
	if c.Description != "" {
		err = updateDescription(h, c.Description)
		if err != nil {
			return nil, err
		}
	}
	return &Service{Name: name, Handle: h}, nil
}

// OpenService retrieves access to service name, so it can
// be interrogated and controlled.
func (m *Mgr) OpenService(name string) (*Service, error) {
	h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
	if err != nil {
		return nil, err
	}
	return &Service{Name: name, Handle: h}, nil
}
<commit_msg>windows/svc/mgr: correct documentation for args parameter of Mgr.CreateService<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows

// Package mgr can be used to manage Windows service programs.
// It can be used to install and remove them. It can also start,
// stop and pause them. The package can query / change current
// service state and config parameters.
//
package mgr

import (
	"syscall"
	"unicode/utf16"

	"golang.org/x/sys/windows"
)

// Mgr is used to manage Windows service.
type Mgr struct {
	Handle windows.Handle
}

// Connect establishes a connection to the service control manager.
func Connect() (*Mgr, error) {
	return ConnectRemote("")
}

// ConnectRemote establishes a connection to the
// service control manager on computer named host.
func ConnectRemote(host string) (*Mgr, error) {
	var s *uint16
	if host != "" {
		s = syscall.StringToUTF16Ptr(host)
	}
	h, err := windows.OpenSCManager(s, nil, windows.SC_MANAGER_ALL_ACCESS)
	if err != nil {
		return nil, err
	}
	return &Mgr{Handle: h}, nil
}

// Disconnect closes connection to the service control manager m.
func (m *Mgr) Disconnect() error {
	return windows.CloseServiceHandle(m.Handle)
}

func toPtr(s string) *uint16 {
	if len(s) == 0 {
		return nil
	}
	return syscall.StringToUTF16Ptr(s)
}

// toStringBlock terminates strings in ss with 0, and then
// concatenates them together. It also adds extra 0 at the end.
func toStringBlock(ss []string) *uint16 {
	if len(ss) == 0 {
		return nil
	}
	t := ""
	for _, s := range ss {
		if s != "" {
			t += s + "\x00"
		}
	}
	if t == "" {
		return nil
	}
	t += "\x00"
	return &utf16.Encode([]rune(t))[0]
}

// CreateService installs new service name on the system.
// The service will be executed by running exepath binary.
// Use config c to specify service parameters.
// Any args will be passed as command-line arguments when
// the service is started; these arguments are distinct from
// the arguments passed to Service.Start or via the "Start
// parameters" field in the service's Properties dialog box.
func (m *Mgr) CreateService(name, exepath string, c Config, args ...string) (*Service, error) {
	if c.StartType == 0 {
		c.StartType = StartManual
	}
	if c.ErrorControl == 0 {
		c.ErrorControl = ErrorNormal
	}
	if c.ServiceType == 0 {
		c.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
	}
	s := syscall.EscapeArg(exepath)
	for _, v := range args {
		s += " " + syscall.EscapeArg(v)
	}
	h, err := windows.CreateService(m.Handle, toPtr(name), toPtr(c.DisplayName),
		windows.SERVICE_ALL_ACCESS, c.ServiceType,
		c.StartType, c.ErrorControl, toPtr(s), toPtr(c.LoadOrderGroup),
		nil, toStringBlock(c.Dependencies), toPtr(c.ServiceStartName), toPtr(c.Password))
	if err != nil {
		return nil, err
	}
	if c.Description != "" {
		err = updateDescription(h, c.Description)
		if err != nil {
			return nil, err
		}
	}
	return &Service{Name: name, Handle: h}, nil
}

// OpenService retrieves access to service name, so it can
// be interrogated and controlled.
func (m *Mgr) OpenService(name string) (*Service, error) {
	h, err := windows.OpenService(m.Handle, syscall.StringToUTF16Ptr(name), windows.SERVICE_ALL_ACCESS)
	if err != nil {
		return nil, err
	}
	return &Service{Name: name, Handle: h}, nil
}
<|endoftext|>


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

package wordlist

var DefaultWordlist = `
.git
.htaccess
.htpasswd
Admin
Administration
CVS
Log
Logs
Pages
Servlet
Servlets
SiteServer
Sources
Statistics
Stats
W3SVC
W3SVC1
W3SVC2
W3SVC3
WEB-INF
a
aa
aaa
abc
about
academic
access
accessgranted
account
accounting
action
actions
active
adm
admin
admin_login
admin_logon
administration
administrator
adminlogin
adminlogon
adminsql
adsl
agent
agents
alias
aliases
all
alpha
analog
analyse
announcements
answer
any
apache
api
app
applet
applets
appliance
application
applications
apps
archive
archives
arrow
asp
aspadmin
assets
attach
attachments
audit
auth
auto
automatic
b
back
back-up
backdoor
backend
backoffice
backup
backups
bak
bak-up
bakup
bank
banks
banner
banners
base
basic
bass
batch
bd
bdata
bea
bean
beans
beta
bill
billing
bin
binaries
biz
blog
blow
board
boards
body
boot
bot
bots
box
boxes
broken
bsd
bug
bugs
build
builder
bulk
buttons
c
cache
cachemgr
cad
can
captcha
car
card
cardinal
cards
carpet
cart
cas
cat
catalog
catalogs
catch
cc
ccs
cd
cdrom
cert
certenroll
certificate
certificates
certs
cfdocs
cfg
cgi
cgi-bin/
cgi-win
cgibin
chan
change
changepw
channel
chart
chat
class
classes
classic
classified
classifieds
client
clients
cluster
cm
cmd
code
coffee
command
commerce
commercial
common
component
compose
composer
compressed
comunicator
con
config
configs
configuration
configure
connect
connections
console
constant
constants
contact
contacts
content
contents
control
controller
controlpanel
controls
corba
core
corporate
count
counter
cpanel
create
creation
credit
creditcards
cron
crs
css
customer
customers
cv
cvs
d
daemon
dat
data
database
databases
dav
db
dba
dbase
dbm
dbms
debug
default
delete
deletion
demo
demos
deny
deploy
deployment
design
details
dev
dev60cgi
devel
develop
developement
developers
development
device
devices
devs
diag
dial
dig
dir
directory
discovery
disk
dispatch
dispatcher
dms
dns
doc
docs
document
documents
down
download
downloads
draft
dragon
dratfs
driver
dump
dumpenv
e
easy
ebriefs
echannel
ecommerce
edit
editor
element
elements
email
employees
en
eng
engine
english
enterprise
env
environ
environment
error
errors
es
esales
esp
established
esupport
etc
event
events
example
examples
exchange
exe
exec
executable
executables
explorer
export
external
extra
Extranet
extranet
fail
failed
fcgi-bin
feedback
field
file
files
filter
firewall
first
flash
folder
foo
forget
forgot
forgotten
form
format
formhandler
formsend
formupdate
fortune
forum
forums
frame
framework
ftp
fun
function
functions
games
gate
generic
gest
get
global
globalnav
globals
gone
gp
gpapp
granted
graphics
group
groups
guest
guestbook
guests
hack
hacker
handler
hanlder
happening
head
header
headers
hello
helloworld
help
hidden
hide
history
hits
home
homepage
homes
homework
host
hosts
htdocs
htm
html
htmls
ibm
icons
idbc
iis
images
img
import
inbox
inc
include
includes
incoming
incs
index
index2
index_adm
index_admin
indexes
info
information
ingres
ingress
ini
init
input
install
installation
interactive
internal
internet
intranet
intro
inventory
invitation
invite
ipp
ips
j
java
java-sys
javascript
jdbc
job
join
jrun
js
jsp
jsps
jsr
keep
kept
kernel
key
lab
labs
launch
launchpage
ldap
left
level
lib
libraries
library
libs
link
links
linux
list
load
loader
lock
lockout
log
logfile
logfiles
logger
logging
login
logo
logon
logout
logs
lost+found
ls
magic
mail
mailbox
maillist
main
maint
makefile
man
manage
management
manager
manual
map
market
marketing
master
mbo
mdb
me
member
members
memory
menu
message
messages
messaging
meta
metabase
mgr
mine
minimum
mirror
mirrors
misc
mkstats
model
modem
module
modules
monitor
mount
mp3
mp3s
mqseries
mrtg
ms
ms-sql
msql
mssql
music
my
my-sql
mysql
names
navigation
ne
net
netscape
netstat
network
new
news
next
nl
nobody
notes
novell
nul
null
number
object
objects
odbc
of
off
office
ogl
old
on
online
open
openapp
openfile
operator
oracle
oradata
order
orders
outgoing
output
pad
page
pages
pam
panel
paper
papers
pass
passes
passw
passwd
passwor
password
passwords
path
pdf
perl
perl5
personal
personals
pgsql
phone
php
phpMyAdmin
phpmyadmin
pics
ping
pix
pl
pls
plx
pol
policy
poll
pop
portal
portlet
portlets
post
postgres
power
press
preview
print
printenv
priv
private
privs
process
processform
prod
production
products
professor
profile
program
project
proof
properties
protect
protected
proxy
ps
pub
public
publish
publisher
purchase
purchases
put
pw
pwd
python
query
queue
quote
ramon
random
rank
rcs
readme
redir
redirect
reference
references
reg
reginternal
regional
register
registered
release
remind
reminder
remote
removed
report
reports
requisite
research
reseller
resource
resources
responder
restricted
retail
right
robot
robots.txt
robotics
root
route
router
rpc
rss
rules
run
sales
sample
samples
save
saved
schema
scr
scratc
script
scripts
sdk
search
secret
secrets
section
sections
secure
secured
security
select
sell
send
sendmail
sensepost
sensor
sent
server
server_stats
servers
service
services
servlet
servlets
session
sessions
set
setting
settings
setup
share
shared
shell
shit
shop
shopper
show
showcode
shtml
sign
signature
signin
simple
single
site
sitemap
sites
small
snoop
soap
soapdocs
software
solaris
solutions
somebody
source
sources
spain
spanish
sql
sqladmin
src
srchad
srv
ssi
ssl
staff
start
startpage
stat
static
statistic
statistics
stats
status
stop
store
story
string
student
stuff
style
stylesheet
stylesheets
submit
submitter
sun
super
support
supported
survey
svc
svn
svr
sys
sysadmin
system
table
tag
tape
tar
target
tech
temp
template
templates
temporal
temps
terminal
test
testing
tests
text
texts
ticket
tmp
today
tool
toolbar
tools
top
topics
tour
trace
traffic
transactions
transfer
transport
trap
trash
tree
trees
tsql
tutorial
uddi
uninstall
unix
up
update
updates
upload
uploader
uploads
usage
user
users
usr
ustats
util
utilities
utility
utils
validation
validatior
vap
var
vb
vbs
vbscript
vbscripts
vfs
view
viewer
views
virtual
visitor
vpn
w
w3
w3c
warez
wdav
web
webaccess
webadmin
webapp
webboard
webcart
webdata
webdav
webdist
webhits
weblog
weblogic
weblogs
webmail
webmaster
websearch
website
webstat
webstats
webvpn
welcome
wellcome
whatever
whatnot
whois
will
win
windows
word
work
workplace
workshop
wstats
wusage
www
wwwboard
wwwjoin
wwwlog
wwwstats
xcache
xfer
xml
xmlrpc
xsl
xyz
zip
zipfiles
zips
`
<commit_msg>Expand wordlist.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package wordlist

var DefaultWordlist = `
.git
.htaccess
.htpasswd
Admin
Administration
CVS
LICENSE
Log
Logs
Pages
Servlet
Servlets
SiteServer
Sources
Statistics
Stats
W3SVC
W3SVC1
W3SVC2
W3SVC3
WEB-INF
a
aa
aaa
abc
about
academic
access
accessgranted
account
accounting
action
actions
active
adm
admin
admin_login
admin_logon
administration
administrator
adminlogin
adminlogon
adminsql
adsl
agent
agents
alias
aliases
all
alpha
analog
analyse
announcements
answer
any
apache
api
app
applet
applets
appliance
application
applications
apps
archive
archives
arrow
asp
aspadmin
assets
attach
attachments
audit
auth
auto
automatic
b
back
back-up
backdoor
backend
backoffice
backup
backups
bak
bak-up
bakup
bank
banks
banner
banners
base
basic
bass
batch
bd
bdata
bea
bean
beans
beta
bill
billing
bin
binaries
biz
blog
blow
board
boards
body
boot
bot
bots
box
boxes
broken
bsd
bug
bugs
build
builder
bulk
buttons
c
cache
cachemgr
cad
can
captcha
car
card
cardinal
cards
carpet
cart
cas
cat
catalog
catalogs
catch
cc
ccs
cd
cdrom
cert
certenroll
certificate
certificates
certs
cfdocs
cfg
cgi
cgi-bin/
cgi-win
cgibin
chan
change
changepw
channel
chart
chat
class
classes
classic
classified
classifieds
client
clients
cluster
cm
cmd
code
coffee
command
commerce
commercial
common
component
compose
composer
compressed
comunicator
con
config
configs
configuration
configure
connect
connections
console
constant
constants
contact
contacts
content
contents
control
controller
controlpanel
controls
corba
core
corporate
count
counter
cpanel
create
creation
credit
creditcards
cron
crs
css
customer
customers
cv
cvs
d
daemon
dat
data
database
databases
dav
db
dba
dbase
dbm
dbms
debug
default
delete
deletion
demo
demos
deny
deploy
deployment
design
details
dev
dev60cgi
devel
develop
developement
developers
development
device
devices
devs
diag
dial
dig
dir
directory
discovery
disk
dispatch
dispatcher
dms
dns
doc
docs
document
documents
down
download
downloads
draft
dragon
dratfs
driver
dump
dumpenv
e
easy
ebriefs
echannel
ecommerce
edit
editor
element
elements
email
employees
en
eng
engine
english
enterprise
env
environ
environment
error
errors
es
esales
esp
established
esupport
etc
event
events
example
examples
exchange
exe
exec
executable
executables
explorer
export
external
extra
Extranet
extranet
fail
failed
fcgi-bin
feedback
field
file
files
filter
firewall
first
flash
folder
foo
forget
forgot
forgotten
form
format
formhandler
formsend
formupdate
fortune
forum
forums
frame
framework
ftp
fun
function
functions
games
gate
generic
gest
get
global
globalnav
globals
gone
gp
gpapp
granted
graphics
group
groups
guest
guestbook
guests
hack
hacker
handler
hanlder
happening
head
header
headers
hello
helloworld
help
hidden
hide
history
hits
home
homepage
homes
homework
host
hosts
htdocs
htm
html
htmls
ibm
icons
idbc
iis
images
img
import
inbox
inc
include
includes
incoming
incs
index
index2
index_adm
index_admin
indexes
info
information
ingres
ingress
ini
init
input
install
installation
interactive
internal
internet
intranet
intro
inventory
invitation
invite
ipp
ips
j
java
java-sys
javascript
jdbc
job
join
jrun
js
jsp
jsps
jsr
keep
kept
kernel
key
lab
labs
launch
launchpage
ldap
left
level
lib
libraries
library
libs
link
links
linux
list
load
loader
lock
lockout
log
logfile
logfiles
logger
logging
login
logo
logon
logout
logs
lost+found
ls
magic
mail
mailbox
maillist
main
maint
makefile
man
manage
management
manager
manual
map
market
marketing
master
mbo
mdb
me
member
members
memory
menu
message
messages
messaging
meta
metabase
mgr
mine
minimum
mirror
mirrors
misc
mkstats
model
modem
module
modules
monitor
mount
mp3
mp3s
mqseries
mrtg
ms
ms-sql
msql
mssql
music
my
my-sql
mysql
names
navigation
ne
net
netscape
netstat
network
new
news
next
nl
nobody
notes
novell
nul
null
number
object
objects
odbc
of
off
office
ogl
old
on
online
open
openapp
openfile
operator
oracle
oradata
order
orders
outgoing
output
pad
page
pages
pam
panel
paper
papers
pass
passes
passw
passwd
passwor
password
passwords
path
pdf
perl
perl5
personal
personals
pgsql
phone
php
phpMyAdmin
phpmyadmin
pics
ping
pix
pl
pls
plx
pol
policy
poll
pop
portal
portlet
portlets
post
postgres
power
press
preview
print
printenv
priv
private
privs
process
processform
prod
production
products
professor
profile
program
project
proof
properties
protect
protected
proxy
ps
pub
public
publish
publisher
purchase
purchases
put
pw
pwd
python
query
queue
quote
ramon
random
rank
rcs
readme
redir
redirect
reference
references
reg
reginternal
regional
register
registered
release
remind
reminder
remote
removed
report
reports
requisite
research
reseller
resource
resources
responder
restricted
retail
right
robot
robots.txt
robotics
root
route
router
rpc
rss
rules
run
sales
sample
samples
save
saved
schema
scr
scratc
script
scripts
sdk
search
secret
secrets
section
sections
secure
secured
security
select
sell
send
sendmail
sensepost
sensor
sent
server
server_stats
servers
service
services
servlet
servlets
session
sessions
set
setting
settings
setup
share
shared
shell
shit
shop
shopper
show
showcode
shtml
sign
signature
signin
simple
single
site
sitemap
sites
small
snoop
soap
soapdocs
software
solaris
solutions
somebody
source
sources
spain
spanish
sql
sqladmin
src
srchad
srv
ssi
ssl
staff
start
startpage
stat
static
statistic
statistics
stats
status
stop
store
story
string
student
stuff
style
stylesheet
stylesheets
submit
submitter
sun
super
support
supported
survey
svc
svn
svr
sys
sysadmin
system
table
tag
tape
tar
target
tech
temp
template
templates
temporal
temps
terminal
test
testing
tests
text
texts
ticket
tmp
today
tool
toolbar
tools
top
topics
tour
trace
traffic
transactions
transfer
transport
trap
trash
tree
trees
tsql
tutorial
uddi
uninstall
unix
up
update
updates
upload
uploader
uploads
usage
user
users
usr
ustats
util
utilities
utility
utils
validation
validatior
vap
var
vb
vbs
vbscript
vbscripts
vfs
view
viewer
views
virtual
visitor
vpn
w
w3
w3c
warez
wdav
web
webaccess
webadmin
webapp
webboard
webcart
webdata
webdav
webdist
webhits
weblog
weblogic
weblogs
webmail
webmaster
websearch
website
webstat
webstats
webvpn
welcome
wellcome
whatever
whatnot
whois
will
win
windows
word
work
workplace
workshop
wstats
wusage
www
wwwboard
wwwjoin
wwwlog
wwwstats
xcache
xfer
xml
xmlrpc
xsl
xyz
zip
zipfiles
zips
`
<|endoftext|>


<commit_before>package workflows

import (
	"errors"
	"fmt"

	"github.com/stelligent/mu/common"
)

type databaseWorkflow struct {
	serviceName           string
	codeRevision          string
	appRevisionBucket     string
	databaseName          string
	repoName              string
	cloudFormationRoleArn string
	databaseKeyArn        string
<<<<<<< HEAD
=======
	ssmParamName          string
	ssmParamIsManaged     bool
>>>>>>> fix 345 - delete SSM param when deleting db stack
}

func (workflow *databaseWorkflow) databaseInput(ctx *common.Context, serviceName string, environmentName string) Executor {
	return func() error {
		// Repo Name
		if serviceName != "" {
			workflow.serviceName = serviceName
		} else if ctx.Config.Service.Name != "" {
			workflow.serviceName = ctx.Config.Service.Name
		} else if ctx.Config.Repo.Name != "" {
			workflow.serviceName = ctx.Config.Repo.Name
		} else {
			return errors.New("Service name must be provided")
		}

		workflow.appRevisionBucket = ctx.Config.Service.Pipeline.Build.Bucket
		workflow.databaseName = ctx.Config.Service.Database.Name
		workflow.ssmParamName = ctx.Config.Service.Database.MasterPasswordSSMParam
		if workflow.ssmParamName == "" {
			dbStackName := common.CreateStackName(ctx.Config.Namespace, common.StackTypeDatabase, workflow.serviceName, environmentName)
			workflow.ssmParamName = fmt.Sprintf("%s-%s", dbStackName, "DatabaseMasterPassword")
			workflow.ssmParamIsManaged = true
		}

		return nil
	}
}

func (workflow *databaseWorkflow) hasDatabase() Conditional {
	return func() bool {
		return workflow.databaseName != ""
	}
}
<commit_msg>remove conflict<commit_after>package workflows

import (
	"errors"
	"fmt"

	"github.com/stelligent/mu/common"
)

type databaseWorkflow struct {
	serviceName           string
	codeRevision          string
	appRevisionBucket     string
	databaseName          string
	repoName              string
	cloudFormationRoleArn string
	databaseKeyArn        string
	ssmParamName          string
	ssmParamIsManaged     bool
}

func (workflow *databaseWorkflow) databaseInput(ctx *common.Context, serviceName string, environmentName string) Executor {
	return func() error {
		// Repo Name
		if serviceName != "" {
			workflow.serviceName = serviceName
		} else if ctx.Config.Service.Name != "" {
			workflow.serviceName = ctx.Config.Service.Name
		} else if ctx.Config.Repo.Name != "" {
			workflow.serviceName = ctx.Config.Repo.Name
		} else {
			return errors.New("Service name must be provided")
		}

		workflow.appRevisionBucket = ctx.Config.Service.Pipeline.Build.Bucket
		workflow.databaseName = ctx.Config.Service.Database.Name
		workflow.ssmParamName = ctx.Config.Service.Database.MasterPasswordSSMParam
		if workflow.ssmParamName == "" {
			dbStackName := common.CreateStackName(ctx.Config.Namespace, common.StackTypeDatabase, workflow.serviceName, environmentName)
			workflow.ssmParamName = fmt.Sprintf("%s-%s", dbStackName, "DatabaseMasterPassword")
			workflow.ssmParamIsManaged = true
		}

		return nil
	}
}

func (workflow *databaseWorkflow) hasDatabase() Conditional {
	return func() bool {
		return workflow.databaseName != ""
	}
}
<|endoftext|>


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

package types

import (
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

// Default parameter values.
const (
	DclMaxMemoCharacters          uint64  = authtypes.DefaultMaxMemoCharacters
	DclTxSigLimit                 uint64  = authtypes.DefaultTxSigLimit
	DclTxSizeCostPerByte          uint64  = 0 // gas is not needed in DCL
	DclSigVerifyCostED25519       uint64  = 0 // gas is not needed in DCL
	DclSigVerifyCostSecp256k1     uint64  = 0 // gas is not needed in DCL
	AccountApprovalsPercent       float64 = 0.66
	AccountRejectApprovalsPercent float64 = 0.33
)
<commit_msg>Remove unused variable<commit_after>// Copyright 2020 DSR Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
)

// Default parameter values.
const (
	DclMaxMemoCharacters      uint64  = authtypes.DefaultMaxMemoCharacters
	DclTxSigLimit             uint64  = authtypes.DefaultTxSigLimit
	DclTxSizeCostPerByte      uint64  = 0 // gas is not needed in DCL
	DclSigVerifyCostED25519   uint64  = 0 // gas is not needed in DCL
	DclSigVerifyCostSecp256k1 uint64  = 0 // gas is not needed in DCL
	AccountApprovalsPercent   float64 = 0.66
)
<|endoftext|>


<commit_before>package main

type bash int

var BASH bash

const BASH_HOOK = `
_direnv_hook() {
  eval "$(direnv export bash)";
};
if ! [[ "$PROMPT_COMMAND" =~ _direnv_hook ]]; then
  PROMPT_COMMAND="_direnv_hook;$PROMPT_COMMAND";
fi
`

func (b bash) Hook() string {
	return BASH_HOOK
}

func (b bash) Escape(str string) string {
	return ShellEscape(str)
}

func (b bash) Export(key, value string) string {
	return "export " + b.Escape(key) + "=" + b.Escape(value) + ";"
}

func (b bash) Unset(key string) string {
	return "unset " + b.Escape(key) + ";"
}
<commit_msg>Preserve previous BASH status code<commit_after>package main

type bash int

var BASH bash

const BASH_HOOK = `
_direnv_hook() {
  local previous_exit_status=$?;
  eval "$(direnv export bash)";
  return $previous_exit_status;
};
if ! [[ "$PROMPT_COMMAND" =~ _direnv_hook ]]; then
  PROMPT_COMMAND="_direnv_hook;$PROMPT_COMMAND";
fi
`

func (b bash) Hook() string {
	return BASH_HOOK
}

func (b bash) Escape(str string) string {
	return ShellEscape(str)
}

func (b bash) Export(key, value string) string {
	return "export " + b.Escape(key) + "=" + b.Escape(value) + ";"
}

func (b bash) Unset(key string) string {
	return "unset " + b.Escape(key) + ";"
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
)

type fish struct{}

var FISH Shell = fish{}

const FISH_HOOK = `
function __direnv_export_eval --on-event fish_preexec;
	"{{.SelfPath}}" export fish | source;
end
`

func (sh fish) Hook() (string, error) {
	return FISH_HOOK, nil
}

func (sh fish) Export(e ShellExport) (out string) {
	for key, value := range e {
		if value == nil {
			out += sh.unset(key)
		} else {
			out += sh.export(key, *value)
		}
	}
	return out
}

func (sh fish) Dump(env Env) (out string) {
	for key, value := range env {
		out += sh.export(key, value)
	}
	return out
}

func (sh fish) export(key, value string) string {
	if key == "PATH" {
		command := "set -x -g PATH"
		for _, path := range strings.Split(value, ":") {
			command += " " + sh.escape(path)
		}
		return command + ";"
	}
	return "set -x -g " + sh.escape(key) + " " + sh.escape(value) + ";"
}

func (sh fish) unset(key string) string {
	return "set -e -g " + sh.escape(key) + ";"
}

func (sh fish) escape(str string) string {
	in := []byte(str)
	out := "'"
	i := 0
	l := len(in)

	hex := func(char byte) {
		out += fmt.Sprintf("'\\x%02x'", char)
	}

	backslash := func(char byte) {
		out += string([]byte{BACKSLASH, char})
	}

	escaped := func(str string) {
		out += "'" + str + "'"
	}

	literal := func(char byte) {
		out += string([]byte{char})
	}

	for i < l {
		char := in[i]
		switch {
		case char == TAB:
			escaped(`\t`)
		case char == LF:
			escaped(`\n`)
		case char == CR:
			escaped(`\r`)
		case char <= US:
			hex(char)
		case char == SINGLE_QUOTE:
			backslash(char)
		case char == BACKSLASH:
			backslash(char)
		case char <= TILDA:
			literal(char)
		case char == DEL:
			hex(char)
		default:
			hex(char)
		}
		i += 1
	}

	out += "'"

	return out
}
<commit_msg>Use `fish_postexec` to make sure direnv hook executed 'after' the directory has changed when using `cd`.<commit_after>package main

import (
	"fmt"
	"strings"
)

type fish struct{}

var FISH Shell = fish{}

const FISH_HOOK = `
function __direnv_export_eval --on-event fish_postexec;
	"{{.SelfPath}}" export fish | source;
end
`

func (sh fish) Hook() (string, error) {
	return FISH_HOOK, nil
}

func (sh fish) Export(e ShellExport) (out string) {
	for key, value := range e {
		if value == nil {
			out += sh.unset(key)
		} else {
			out += sh.export(key, *value)
		}
	}
	return out
}

func (sh fish) Dump(env Env) (out string) {
	for key, value := range env {
		out += sh.export(key, value)
	}
	return out
}

func (sh fish) export(key, value string) string {
	if key == "PATH" {
		command := "set -x -g PATH"
		for _, path := range strings.Split(value, ":") {
			command += " " + sh.escape(path)
		}
		return command + ";"
	}
	return "set -x -g " + sh.escape(key) + " " + sh.escape(value) + ";"
}

func (sh fish) unset(key string) string {
	return "set -e -g " + sh.escape(key) + ";"
}

func (sh fish) escape(str string) string {
	in := []byte(str)
	out := "'"
	i := 0
	l := len(in)

	hex := func(char byte) {
		out += fmt.Sprintf("'\\x%02x'", char)
	}

	backslash := func(char byte) {
		out += string([]byte{BACKSLASH, char})
	}

	escaped := func(str string) {
		out += "'" + str + "'"
	}

	literal := func(char byte) {
		out += string([]byte{char})
	}

	for i < l {
		char := in[i]
		switch {
		case char == TAB:
			escaped(`\t`)
		case char == LF:
			escaped(`\n`)
		case char == CR:
			escaped(`\r`)
		case char <= US:
			hex(char)
		case char == SINGLE_QUOTE:
			backslash(char)
		case char == BACKSLASH:
			backslash(char)
		case char <= TILDA:
			literal(char)
		case char == DEL:
			hex(char)
		default:
			hex(char)
		}
		i += 1
	}

	out += "'"

	return out
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import "testing"

func TestWebURL(t *testing.T) {
	for _, c := range [...]struct {
		in   string
		want interface{}
	}{
		{``, nil},
		{` `, nil},
		{`:`, nil},
		{`::`, nil},
		{`:::`, nil},
		{`::::`, nil},
		{`://`, nil},
		{`foo`, nil},

		// Web links
		{`foo.a`, nil},
		{`foo.com`, `foo.com`},
		{`foo.com bar.com`, `foo.com`},
		{`foo.com-foo`, `foo.com`},
		{`foo.onion`, `foo.onion`},
		{`foo.i2p`, `foo.i2p`},
		{`中国.中国`, `中国.中国`},
		{`中国.中国/foo中国`, `中国.中国/foo中国`},
		{`foo.com/`, `foo.com/`},
		{`1.1.1.1`, `1.1.1.1`},
		{`121.1.1.1`, `121.1.1.1`},
		{`255.1.1.1`, `255.1.1.1`},
		{`300.1.1.1`, nil},
		{`1.1.1`, nil},
		{`1.1..1`, nil},
		{`1080:0:0:0:8:800:200C:4171`, `1080:0:0:0:8:800:200C:4171`},
		{`3ffe:2a00:100:7031::1`, `3ffe:2a00:100:7031::1`},
		{`1080::8:800:200c:417a`, `1080::8:800:200c:417a`},
		{`1:1`, nil},
		{`:2:`, nil},
		{`1:2:3`, nil},
		{`foo.com:8080`, `foo.com:8080`},
		{`foo.com:8080/path`, `foo.com:8080/path`},
		{`test.foo.com`, `test.foo.com`},
		{`test.foo.com/path`, `test.foo.com/path`},
		{`test.foo.com/path/more/`, `test.foo.com/path/more/`},
		{`TEST.FOO.COM/PATH`, `TEST.FOO.COM/PATH`},
		{`foo.com/a.,:;-+_()?@&=$~!*%'"a`, `foo.com/a.,:;-+_()?@&=$~!*%'"a`},
		{`foo.com/path_(more)`, `foo.com/path_(more)`},
		{`foo.com/path_(even)_(more)`, `foo.com/path_(even)_(more)`},
		{`foo.com/path_(more)/more`, `foo.com/path_(more)/more`},
		{`foo.com/path_(more)/end)`, `foo.com/path_(more)/end)`},
		{`www.foo.com`, `www.foo.com`},
		{` foo.com/bar `, `foo.com/bar`},
		{` foo.com/bar more`, `foo.com/bar`},
		{`<foo.com/bar>`, `foo.com/bar`},
		{`<foo.com/bar>more`, `foo.com/bar`},
		{`,foo.com/bar.`, `foo.com/bar`},
		{`,foo.com/bar.more`, `foo.com/bar.more`},
		{`,foo.com/bar,`, `foo.com/bar`},
		{`,foo.com/bar,more`, `foo.com/bar,more`},
		{`(foo.com/bar)`, `foo.com/bar`},
		{`(foo.com/bar)more`, `foo.com/bar)more`},
		{`"foo.com/bar'`, `foo.com/bar`},
		{`"foo.com/bar'more`, `foo.com/bar'more`},
		{`"foo.com/bar"`, `foo.com/bar`},
		{`"foo.com/bar"more`, `foo.com/bar"more`},
		{`what is foo.com?`, `foo.com`},
		{`the foo.com!`, `foo.com`},

		// Email addresses
		{`foo@bar`, nil},
		{`foo@bar.a`, nil},
		{`foo@bar.com`, `foo@bar.com`},
		{`foo@bar.com bar@bar.com`, `foo@bar.com`},
		{`foo@bar.onion`, `foo@bar.onion`},
		{`foo@中国.中国`, `foo@中国.中国`},
		{`mailto:foo@bar.com`, `foo@bar.com`},
		{`foo@test.bar.com`, `foo@test.bar.com`},
		{`FOO@TEST.BAR.COM`, `FOO@TEST.BAR.COM`},
		{`foo@bar.com/path`, `foo@bar.com`},
		{`foo+test@bar.com`, `foo+test@bar.com`},
		{`foo+._%-@bar.com`, `foo+._%-@bar.com`},

		{`http://foo.com`, `http://foo.com`},
		{`http://foo.random`, `http://foo.random`},
		{` http://foo.com/bar `, `http://foo.com/bar`},
		{` http://foo.com/bar more`, `http://foo.com/bar`},
		{`<http://foo.com/bar>`, `http://foo.com/bar`},
		{`<http://foo.com/bar>more`, `http://foo.com/bar`},
		{`,http://foo.com/bar.`, `http://foo.com/bar`},
		{`,http://foo.com/bar.more`, `http://foo.com/bar.more`},
		{`,http://foo.com/bar,`, `http://foo.com/bar`},
		{`,http://foo.com/bar,more`, `http://foo.com/bar,more`},
		{`(http://foo.com/bar)`, `http://foo.com/bar`},
		{`(http://foo.com/bar)more`, `http://foo.com/bar)more`},
		{`"http://foo.com/bar'`, `http://foo.com/bar`},
		{`"http://foo.com/bar'more`, `http://foo.com/bar'more`},
		{`"http://foo.com/bar"`, `http://foo.com/bar`},
		{`"http://foo.com/bar"more`, `http://foo.com/bar"more`},
		{`http://foo.com/path_(more)`, `http://foo.com/path_(more)`},
		{`http://test.foo.com/`, `http://test.foo.com/`},
		{`http://foo.com/path`, `http://foo.com/path`},
		{`http://foo.com:8080/path`, `http://foo.com:8080/path`},
		{`http://1.1.1.1/path`, `http://1.1.1.1/path`},
		{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
		{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
		{`what is http://foo.com?`, `http://foo.com`},
		{`the http://foo.com!`, `http://foo.com`},
		{`https://test.foo.bar/path?a=b`, `https://test.foo.bar/path?a=b`},
		{`ftp://user@foo.bar`, `ftp://user@foo.bar`},
	} {
		got := All.FindString(c.in)
		var want string
		switch x := c.want.(type) {
		case string:
			want = x
		}
		if got != want {
			t.Errorf(`xurls.All.FindString("%s") got "%s", want "%s"`, c.in, got, want)
		}
	}
}
<commit_msg>Add some more tests<commit_after>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import "testing"

func TestWebURL(t *testing.T) {
	for _, c := range [...]struct {
		in   string
		want interface{}
	}{
		{``, nil},
		{` `, nil},
		{`:`, nil},
		{`::`, nil},
		{`:::`, nil},
		{`::::`, nil},
		{`.`, nil},
		{`..`, nil},
		{`...`, nil},
		{`://`, nil},
		{`foo`, nil},
		{`foo:`, nil},
		{`foo://`, nil},
		{`:foo`, nil},
		{`://foo`, nil},
		{`foo:bar`, nil},
		{`/some/path`, nil},

		// Web links
		{`foo.a`, nil},
		{`foo.com`, `foo.com`},
		{`foo.com bar.com`, `foo.com`},
		{`foo.com-foo`, `foo.com`},
		{`foo.onion`, `foo.onion`},
		{`foo.i2p`, `foo.i2p`},
		{`中国.中国`, `中国.中国`},
		{`中国.中国/foo中国`, `中国.中国/foo中国`},
		{`foo.com/`, `foo.com/`},
		{`1.1.1.1`, `1.1.1.1`},
		{`121.1.1.1`, `121.1.1.1`},
		{`255.1.1.1`, `255.1.1.1`},
		{`300.1.1.1`, nil},
		{`1.1.1`, nil},
		{`1.1..1`, nil},
		{`1080:0:0:0:8:800:200C:4171`, `1080:0:0:0:8:800:200C:4171`},
		{`3ffe:2a00:100:7031::1`, `3ffe:2a00:100:7031::1`},
		{`1080::8:800:200c:417a`, `1080::8:800:200c:417a`},
		{`1:1`, nil},
		{`:2:`, nil},
		{`1:2:3`, nil},
		{`foo.com:8080`, `foo.com:8080`},
		{`foo.com:8080/path`, `foo.com:8080/path`},
		{`test.foo.com`, `test.foo.com`},
		{`test.foo.com/path`, `test.foo.com/path`},
		{`test.foo.com/path/more/`, `test.foo.com/path/more/`},
		{`TEST.FOO.COM/PATH`, `TEST.FOO.COM/PATH`},
		{`foo.com/a.,:;-+_()?@&=$~!*%'"a`, `foo.com/a.,:;-+_()?@&=$~!*%'"a`},
		{`foo.com/path_(more)`, `foo.com/path_(more)`},
		{`foo.com/path_(even)_(more)`, `foo.com/path_(even)_(more)`},
		{`foo.com/path_(more)/more`, `foo.com/path_(more)/more`},
		{`foo.com/path_(more)/end)`, `foo.com/path_(more)/end)`},
		{`www.foo.com`, `www.foo.com`},
		{` foo.com/bar `, `foo.com/bar`},
		{` foo.com/bar more`, `foo.com/bar`},
		{`<foo.com/bar>`, `foo.com/bar`},
		{`<foo.com/bar>more`, `foo.com/bar`},
		{`,foo.com/bar.`, `foo.com/bar`},
		{`,foo.com/bar.more`, `foo.com/bar.more`},
		{`,foo.com/bar,`, `foo.com/bar`},
		{`,foo.com/bar,more`, `foo.com/bar,more`},
		{`(foo.com/bar)`, `foo.com/bar`},
		{`(foo.com/bar)more`, `foo.com/bar)more`},
		{`"foo.com/bar'`, `foo.com/bar`},
		{`"foo.com/bar'more`, `foo.com/bar'more`},
		{`"foo.com/bar"`, `foo.com/bar`},
		{`"foo.com/bar"more`, `foo.com/bar"more`},
		{`what is foo.com?`, `foo.com`},
		{`the foo.com!`, `foo.com`},

		// Email addresses
		{`foo@bar`, nil},
		{`foo@bar.a`, nil},
		{`foo@bar.com`, `foo@bar.com`},
		{`foo@bar.com bar@bar.com`, `foo@bar.com`},
		{`foo@bar.onion`, `foo@bar.onion`},
		{`foo@中国.中国`, `foo@中国.中国`},
		{`mailto:foo@bar.com`, `foo@bar.com`},
		{`foo@test.bar.com`, `foo@test.bar.com`},
		{`FOO@TEST.BAR.COM`, `FOO@TEST.BAR.COM`},
		{`foo@bar.com/path`, `foo@bar.com`},
		{`foo+test@bar.com`, `foo+test@bar.com`},
		{`foo+._%-@bar.com`, `foo+._%-@bar.com`},

		// Urls with scheme and ://
		{`http://foo.com`, `http://foo.com`},
		{`http://foo.random`, `http://foo.random`},
		{` http://foo.com/bar `, `http://foo.com/bar`},
		{` http://foo.com/bar more`, `http://foo.com/bar`},
		{`<http://foo.com/bar>`, `http://foo.com/bar`},
		{`<http://foo.com/bar>more`, `http://foo.com/bar`},
		{`,http://foo.com/bar.`, `http://foo.com/bar`},
		{`,http://foo.com/bar.more`, `http://foo.com/bar.more`},
		{`,http://foo.com/bar,`, `http://foo.com/bar`},
		{`,http://foo.com/bar,more`, `http://foo.com/bar,more`},
		{`(http://foo.com/bar)`, `http://foo.com/bar`},
		{`(http://foo.com/bar)more`, `http://foo.com/bar)more`},
		{`"http://foo.com/bar'`, `http://foo.com/bar`},
		{`"http://foo.com/bar'more`, `http://foo.com/bar'more`},
		{`"http://foo.com/bar"`, `http://foo.com/bar`},
		{`"http://foo.com/bar"more`, `http://foo.com/bar"more`},
		{`http://a.b/a.,:;-+_()?@&=$~!*%'"a`, `http://a.b/a.,:;-+_()?@&=$~!*%'"a`},
		{`http://foo.com/path_(more)`, `http://foo.com/path_(more)`},
		{`http://test.foo.com/`, `http://test.foo.com/`},
		{`http://foo.com/path`, `http://foo.com/path`},
		{`http://foo.com:8080/path`, `http://foo.com:8080/path`},
		{`http://1.1.1.1/path`, `http://1.1.1.1/path`},
		{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
		{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
		{`what is http://foo.com?`, `http://foo.com`},
		{`the http://foo.com!`, `http://foo.com`},
		{`https://test.foo.bar/path?a=b`, `https://test.foo.bar/path?a=b`},
		{`ftp://user@foo.bar`, `ftp://user@foo.bar`},
	} {
		got := All.FindString(c.in)
		var want string
		switch x := c.want.(type) {
		case string:
			want = x
		}
		if got != want {
			t.Errorf(`xurls.All.FindString("%s") got "%s", want "%s"`, c.in, got, want)
		}
	}
}
<|endoftext|>


<commit_before>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import (
	"regexp"
	"testing"
)

type regexTestCase struct {
	in   string
	want interface{}
}

func doTest(t *testing.T, name string, re *regexp.Regexp, cases []regexTestCase) {
	for _, c := range cases {
		got := re.FindString(c.in)
		want, _ := c.want.(string)
		if got != want {
			t.Errorf(`%s.FindString("%s") got "%s", want "%s"`, name, c.in, got, want)
		}
	}
}

var constantTestCases = []regexTestCase{
	{``, nil},
	{` `, nil},
	{`:`, nil},
	{`::`, nil},
	{`:::`, nil},
	{`::::`, nil},
	{`.`, nil},
	{`..`, nil},
	{`...`, nil},
	{`1.1`, nil},
	{`.1.`, nil},
	{`1.1.1`, nil},
	{`1:1`, nil},
	{`:1:`, nil},
	{`1:1:1`, nil},
	{`://`, nil},
	{`foo`, nil},
	{`foo:`, nil},
	{`mailto:`, nil},
	{`randomxmpp:foo`, nil},
	{`foo://`, nil},
	{`http://`, nil},
	{`:foo`, nil},
	{`://foo`, nil},
	{`foo:bar`, nil},
	{`zzz.`, nil},
	{`.zzz`, nil},
	{`zzz.zzz`, nil},
	{`/some/path`, nil},
	{`localhost`, nil},
	{`com`, nil},
	{`.com`, nil},
	{`http`, nil},

	{`http://foo`, `http://foo`},
	{`http://FOO`, `http://FOO`},
	{`http://FAÀ`, `http://FAÀ`},
	{`https://localhost`, `https://localhost`},
	{`git+https://localhost`, `git+https://localhost`},
	{`foo.bar://localhost`, `foo.bar://localhost`},
	{`foo-bar://localhost`, `foo-bar://localhost`},
	{`mailto:foo`, `mailto:foo`},
	{`MAILTO:foo`, `MAILTO:foo`},
	{`sms:123`, `sms:123`},
	{`xmpp:foo@bar`, `xmpp:foo@bar`},
	{`bitcoin:Addr23?amount=1&message=foo`, `bitcoin:Addr23?amount=1&message=foo`},
	{`http://foo.com`, `http://foo.com`},
	{`http://foo.co.uk`, `http://foo.co.uk`},
	{`http://foo.random`, `http://foo.random`},
	{` http://foo.com/bar `, `http://foo.com/bar`},
	{` http://foo.com/bar more`, `http://foo.com/bar`},
	{`<http://foo.com/bar>`, `http://foo.com/bar`},
	{`<http://foo.com/bar>more`, `http://foo.com/bar`},
	{`.http://foo.com/bar.`, `http://foo.com/bar`},
	{`.http://foo.com/bar.more`, `http://foo.com/bar.more`},
	{`,http://foo.com/bar,`, `http://foo.com/bar`},
	{`,http://foo.com/bar,more`, `http://foo.com/bar,more`},
	{`(http://foo.com/bar)`, `http://foo.com/bar`},
	{`"http://foo.com/bar'`, `http://foo.com/bar`},
	{`"http://foo.com/bar'more`, `http://foo.com/bar'more`},
	{`"http://foo.com/bar"`, `http://foo.com/bar`},
	{`http://a.b/a.,:;-+_()?@&=#$~!*%'a`, `http://a.b/a.,:;-+_()?@&=#$~!*%'a`},
	{`http://foo.com/path_(more)`, `http://foo.com/path_(more)`},
	{`(http://foo.com/path_(more))`, `http://foo.com/path_(more)`},
	{`http://foo.com/path_(even)-(more)`, `http://foo.com/path_(even)-(more)`},
	{`http://foo.com/path_(even)(more)`, `http://foo.com/path_(even)(more)`},
	{`http://foo.com/path_(even_(nested))`, `http://foo.com/path_(even_(nested))`},
	{`(http://foo.com/path_(even_(nested)))`, `http://foo.com/path_(even_(nested))`},
	{`http://foo.com/path#fragment`, `http://foo.com/path#fragment`},
	{`http://test.foo.com/`, `http://test.foo.com/`},
	{`http://foo.com/path`, `http://foo.com/path`},
	{`http://foo.com:8080/path`, `http://foo.com:8080/path`},
	{`http://1.1.1.1/path`, `http://1.1.1.1/path`},
	{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
	{`http://中国.中国/foo中国`, `http://中国.中国/foo中国`},
	{`http://✪foo.bar/pa✪th`, `http://✪foo.bar/pa✪th`},
	{`✪http://✪foo.bar/pa✪th✪`, `http://✪foo.bar/pa✪th`},
	{`what is http://foo.com?`, `http://foo.com`},
	{`the http://foo.com!`, `http://foo.com`},
	{`https://test.foo.bar/path?a=b`, `https://test.foo.bar/path?a=b`},
	{`ftp://user@foo.bar`, `ftp://user@foo.bar`},
}

func TestRegexes(t *testing.T) {
	doTest(t, "Relaxed", Relaxed, constantTestCases)
	doTest(t, "Strict", Strict, constantTestCases)
	doTest(t, "Relaxed", Relaxed, []regexTestCase{
		{`foo.a`, nil},
		{`foo.com`, `foo.com`},
		{`foo.com bar.com`, `foo.com`},
		{`foo.com-foo`, `foo.com`},
		{`foo.company`, `foo.company`},
		{`foo.comrandom`, nil},
		{`foo.onion`, `foo.onion`},
		{`foo.i2p`, `foo.i2p`},
		{`中国.中国`, `中国.中国`},
		{`中国.中国/foo中国`, `中国.中国/foo中国`},
		{`foo.com/`, `foo.com/`},
		{`1.1.1.1`, `1.1.1.1`},
		{`10.50.23.250`, `10.50.23.250`},
		{`121.1.1.1`, `121.1.1.1`},
		{`255.1.1.1`, `255.1.1.1`},
		{`300.1.1.1`, nil},
		{`1.1.1.300`, nil},
		{`1080:0:0:0:8:800:200C:4171`, `1080:0:0:0:8:800:200C:4171`},
		{`3ffe:2a00:100:7031::1`, `3ffe:2a00:100:7031::1`},
		{`1080::8:800:200c:417a`, `1080::8:800:200c:417a`},
		{`foo.com:8080`, `foo.com:8080`},
		{`foo.com:8080/path`, `foo.com:8080/path`},
		{`test.foo.com`, `test.foo.com`},
		{`test.foo.com/path`, `test.foo.com/path`},
		{`test.foo.com/path/more/`, `test.foo.com/path/more/`},
		{`TEST.FOO.COM/PATH`, `TEST.FOO.COM/PATH`},
		{`TEST.FÓO.COM/PÁTH`, `TEST.FÓO.COM/PÁTH`},
		{`foo.com/path_(more)`, `foo.com/path_(more)`},
		{`foo.com/path_(even)_(more)`, `foo.com/path_(even)_(more)`},
		{`foo.com/path_(more)/more`, `foo.com/path_(more)/more`},
		{`foo.com/path_(more)/end)`, `foo.com/path_(more)/end`},
		{`www.foo.com`, `www.foo.com`},
		{` foo.com/bar `, `foo.com/bar`},
		{` foo.com/bar more`, `foo.com/bar`},
		{`<foo.com/bar>`, `foo.com/bar`},
		{`<foo.com/bar>more`, `foo.com/bar`},
		{`,foo.com/bar.`, `foo.com/bar`},
		{`,foo.com/bar.more`, `foo.com/bar.more`},
		{`,foo.com/bar,`, `foo.com/bar`},
		{`,foo.com/bar,more`, `foo.com/bar,more`},
		{`(foo.com/bar)`, `foo.com/bar`},
		{`"foo.com/bar'`, `foo.com/bar`},
		{`"foo.com/bar'more`, `foo.com/bar'more`},
		{`"foo.com/bar"`, `foo.com/bar`},
		{`what is foo.com?`, `foo.com`},
		{`the foo.com!`, `foo.com`},

		{`foo@bar`, nil},
		{`foo@bar.a`, nil},
		{`foo@bar.com`, `foo@bar.com`},
		{`foo@bar.com bar@bar.com`, `foo@bar.com`},
		{`foo@bar.onion`, `foo@bar.onion`},
		{`foo@中国.中国`, `foo@中国.中国`},
		{`foo@test.bar.com`, `foo@test.bar.com`},
		{`FOO@TEST.BAR.COM`, `FOO@TEST.BAR.COM`},
		{`foo@bar.com/path`, `foo@bar.com`},
		{`foo+test@bar.com`, `foo+test@bar.com`},
		{`foo+._%-@bar.com`, `foo+._%-@bar.com`},
	})
	doTest(t, "Strict", Strict, []regexTestCase{
		{`http:// foo.com`, nil},
		{`http:// foo.com`, nil},
		{`foo.a`, nil},
		{`foo.com`, nil},
		{`foo.com/`, nil},
		{`1.1.1.1`, nil},
		{`3ffe:2a00:100:7031::1`, nil},
		{`test.foo.com:8080/path`, nil},
		{`foo@bar.com`, nil},
	})
}

func TestStrictMatchingError(t *testing.T) {
	for _, c := range []struct {
		exp     string
		wantErr bool
	}{
		{`http://`, false},
		{`https?://`, false},
		{`http://|mailto:`, false},
		{`http://(`, true},
	} {
		_, err := StrictMatching(c.exp)
		if c.wantErr && err == nil {
			t.Errorf(`StrictMatching("%s") did not error as expected`, c.exp)
		} else if !c.wantErr && err != nil {
			t.Errorf(`StrictMatching("%s") unexpectedly errored`, c.exp)
		}
	}
}

func TestStrictMatching(t *testing.T) {
	strictMatching, _ := StrictMatching("http://|ftps?://|mailto:")
	doTest(t, "StrictMatching", strictMatching, []regexTestCase{
		{`foo.com`, nil},
		{`foo@bar.com`, nil},
		{`http://foo`, `http://foo`},
		{`https://foo`, nil},
		{`ftp://foo`, `ftp://foo`},
		{`ftps://foo`, `ftps://foo`},
		{`mailto:foo`, `mailto:foo`},
		{`sms:123`, nil},
	})
}

func bench(b *testing.B, re *regexp.Regexp, str string) {
	for i := 0; i < b.N; i++ {
		re.FindAllString(str, -1)
	}
}

func BenchmarkStrictEmpty(b *testing.B) {
	bench(b, Strict, "foo")
}

func BenchmarkStrictSingle(b *testing.B) {
	bench(b, Strict, "http://foo.foo foo.com")
}

func BenchmarkStrictMany(b *testing.B) {
	bench(b, Strict, ` foo bar http://foo.foo
	foo.com bitcoin:address ftp://
	xmpp:foo@bar.com`)
}

func BenchmarkRelaxedEmpty(b *testing.B) {
	bench(b, Relaxed, "foo")
}

func BenchmarkRelaxedSingle(b *testing.B) {
	bench(b, Relaxed, "http://foo.foo foo.com")
}

func BenchmarkRelaxedMany(b *testing.B) {
	bench(b, Relaxed, ` foo bar http://foo.foo
	foo.com bitcoin:address ftp://
	xmpp:foo@bar.com`)
}
<commit_msg>No need for regex var name redundancy<commit_after>/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */

package xurls

import (
	"regexp"
	"testing"
)

type testCase struct {
	in   string
	want interface{}
}

func doTest(t *testing.T, name string, re *regexp.Regexp, cases []testCase) {
	for _, c := range cases {
		got := re.FindString(c.in)
		want, _ := c.want.(string)
		if got != want {
			t.Errorf(`%s.FindString("%s") got "%s", want "%s"`, name, c.in, got, want)
		}
	}
}

var constantTestCases = []testCase{
	{``, nil},
	{` `, nil},
	{`:`, nil},
	{`::`, nil},
	{`:::`, nil},
	{`::::`, nil},
	{`.`, nil},
	{`..`, nil},
	{`...`, nil},
	{`1.1`, nil},
	{`.1.`, nil},
	{`1.1.1`, nil},
	{`1:1`, nil},
	{`:1:`, nil},
	{`1:1:1`, nil},
	{`://`, nil},
	{`foo`, nil},
	{`foo:`, nil},
	{`mailto:`, nil},
	{`randomxmpp:foo`, nil},
	{`foo://`, nil},
	{`http://`, nil},
	{`:foo`, nil},
	{`://foo`, nil},
	{`foo:bar`, nil},
	{`zzz.`, nil},
	{`.zzz`, nil},
	{`zzz.zzz`, nil},
	{`/some/path`, nil},
	{`localhost`, nil},
	{`com`, nil},
	{`.com`, nil},
	{`http`, nil},

	{`http://foo`, `http://foo`},
	{`http://FOO`, `http://FOO`},
	{`http://FAÀ`, `http://FAÀ`},
	{`https://localhost`, `https://localhost`},
	{`git+https://localhost`, `git+https://localhost`},
	{`foo.bar://localhost`, `foo.bar://localhost`},
	{`foo-bar://localhost`, `foo-bar://localhost`},
	{`mailto:foo`, `mailto:foo`},
	{`MAILTO:foo`, `MAILTO:foo`},
	{`sms:123`, `sms:123`},
	{`xmpp:foo@bar`, `xmpp:foo@bar`},
	{`bitcoin:Addr23?amount=1&message=foo`, `bitcoin:Addr23?amount=1&message=foo`},
	{`http://foo.com`, `http://foo.com`},
	{`http://foo.co.uk`, `http://foo.co.uk`},
	{`http://foo.random`, `http://foo.random`},
	{` http://foo.com/bar `, `http://foo.com/bar`},
	{` http://foo.com/bar more`, `http://foo.com/bar`},
	{`<http://foo.com/bar>`, `http://foo.com/bar`},
	{`<http://foo.com/bar>more`, `http://foo.com/bar`},
	{`.http://foo.com/bar.`, `http://foo.com/bar`},
	{`.http://foo.com/bar.more`, `http://foo.com/bar.more`},
	{`,http://foo.com/bar,`, `http://foo.com/bar`},
	{`,http://foo.com/bar,more`, `http://foo.com/bar,more`},
	{`(http://foo.com/bar)`, `http://foo.com/bar`},
	{`"http://foo.com/bar'`, `http://foo.com/bar`},
	{`"http://foo.com/bar'more`, `http://foo.com/bar'more`},
	{`"http://foo.com/bar"`, `http://foo.com/bar`},
	{`http://a.b/a.,:;-+_()?@&=#$~!*%'a`, `http://a.b/a.,:;-+_()?@&=#$~!*%'a`},
	{`http://foo.com/path_(more)`, `http://foo.com/path_(more)`},
	{`(http://foo.com/path_(more))`, `http://foo.com/path_(more)`},
	{`http://foo.com/path_(even)-(more)`, `http://foo.com/path_(even)-(more)`},
	{`http://foo.com/path_(even)(more)`, `http://foo.com/path_(even)(more)`},
	{`http://foo.com/path_(even_(nested))`, `http://foo.com/path_(even_(nested))`},
	{`(http://foo.com/path_(even_(nested)))`, `http://foo.com/path_(even_(nested))`},
	{`http://foo.com/path#fragment`, `http://foo.com/path#fragment`},
	{`http://test.foo.com/`, `http://test.foo.com/`},
	{`http://foo.com/path`, `http://foo.com/path`},
	{`http://foo.com:8080/path`, `http://foo.com:8080/path`},
	{`http://1.1.1.1/path`, `http://1.1.1.1/path`},
	{`http://1080::8:800:200c:417a/path`, `http://1080::8:800:200c:417a/path`},
	{`http://中国.中国/foo中国`, `http://中国.中国/foo中国`},
	{`http://✪foo.bar/pa✪th`, `http://✪foo.bar/pa✪th`},
	{`✪http://✪foo.bar/pa✪th✪`, `http://✪foo.bar/pa✪th`},
	{`what is http://foo.com?`, `http://foo.com`},
	{`the http://foo.com!`, `http://foo.com`},
	{`https://test.foo.bar/path?a=b`, `https://test.foo.bar/path?a=b`},
	{`ftp://user@foo.bar`, `ftp://user@foo.bar`},
}

func TestRegexes(t *testing.T) {
	doTest(t, "Relaxed", Relaxed, constantTestCases)
	doTest(t, "Strict", Strict, constantTestCases)
	doTest(t, "Relaxed", Relaxed, []testCase{
		{`foo.a`, nil},
		{`foo.com`, `foo.com`},
		{`foo.com bar.com`, `foo.com`},
		{`foo.com-foo`, `foo.com`},
		{`foo.company`, `foo.company`},
		{`foo.comrandom`, nil},
		{`foo.onion`, `foo.onion`},
		{`foo.i2p`, `foo.i2p`},
		{`中国.中国`, `中国.中国`},
		{`中国.中国/foo中国`, `中国.中国/foo中国`},
		{`foo.com/`, `foo.com/`},
		{`1.1.1.1`, `1.1.1.1`},
		{`10.50.23.250`, `10.50.23.250`},
		{`121.1.1.1`, `121.1.1.1`},
		{`255.1.1.1`, `255.1.1.1`},
		{`300.1.1.1`, nil},
		{`1.1.1.300`, nil},
		{`1080:0:0:0:8:800:200C:4171`, `1080:0:0:0:8:800:200C:4171`},
		{`3ffe:2a00:100:7031::1`, `3ffe:2a00:100:7031::1`},
		{`1080::8:800:200c:417a`, `1080::8:800:200c:417a`},
		{`foo.com:8080`, `foo.com:8080`},
		{`foo.com:8080/path`, `foo.com:8080/path`},
		{`test.foo.com`, `test.foo.com`},
		{`test.foo.com/path`, `test.foo.com/path`},
		{`test.foo.com/path/more/`, `test.foo.com/path/more/`},
		{`TEST.FOO.COM/PATH`, `TEST.FOO.COM/PATH`},
		{`TEST.FÓO.COM/PÁTH`, `TEST.FÓO.COM/PÁTH`},
		{`foo.com/path_(more)`, `foo.com/path_(more)`},
		{`foo.com/path_(even)_(more)`, `foo.com/path_(even)_(more)`},
		{`foo.com/path_(more)/more`, `foo.com/path_(more)/more`},
		{`foo.com/path_(more)/end)`, `foo.com/path_(more)/end`},
		{`www.foo.com`, `www.foo.com`},
		{` foo.com/bar `, `foo.com/bar`},
		{` foo.com/bar more`, `foo.com/bar`},
		{`<foo.com/bar>`, `foo.com/bar`},
		{`<foo.com/bar>more`, `foo.com/bar`},
		{`,foo.com/bar.`, `foo.com/bar`},
		{`,foo.com/bar.more`, `foo.com/bar.more`},
		{`,foo.com/bar,`, `foo.com/bar`},
		{`,foo.com/bar,more`, `foo.com/bar,more`},
		{`(foo.com/bar)`, `foo.com/bar`},
		{`"foo.com/bar'`, `foo.com/bar`},
		{`"foo.com/bar'more`, `foo.com/bar'more`},
		{`"foo.com/bar"`, `foo.com/bar`},
		{`what is foo.com?`, `foo.com`},
		{`the foo.com!`, `foo.com`},

		{`foo@bar`, nil},
		{`foo@bar.a`, nil},
		{`foo@bar.com`, `foo@bar.com`},
		{`foo@bar.com bar@bar.com`, `foo@bar.com`},
		{`foo@bar.onion`, `foo@bar.onion`},
		{`foo@中国.中国`, `foo@中国.中国`},
		{`foo@test.bar.com`, `foo@test.bar.com`},
		{`FOO@TEST.BAR.COM`, `FOO@TEST.BAR.COM`},
		{`foo@bar.com/path`, `foo@bar.com`},
		{`foo+test@bar.com`, `foo+test@bar.com`},
		{`foo+._%-@bar.com`, `foo+._%-@bar.com`},
	})
	doTest(t, "Strict", Strict, []testCase{
		{`http:// foo.com`, nil},
		{`http:// foo.com`, nil},
		{`foo.a`, nil},
		{`foo.com`, nil},
		{`foo.com/`, nil},
		{`1.1.1.1`, nil},
		{`3ffe:2a00:100:7031::1`, nil},
		{`test.foo.com:8080/path`, nil},
		{`foo@bar.com`, nil},
	})
}

func TestStrictMatchingError(t *testing.T) {
	for _, c := range []struct {
		exp     string
		wantErr bool
	}{
		{`http://`, false},
		{`https?://`, false},
		{`http://|mailto:`, false},
		{`http://(`, true},
	} {
		_, err := StrictMatching(c.exp)
		if c.wantErr && err == nil {
			t.Errorf(`StrictMatching("%s") did not error as expected`, c.exp)
		} else if !c.wantErr && err != nil {
			t.Errorf(`StrictMatching("%s") unexpectedly errored`, c.exp)
		}
	}
}

func TestStrictMatching(t *testing.T) {
	strictMatching, _ := StrictMatching("http://|ftps?://|mailto:")
	doTest(t, "StrictMatching", strictMatching, []testCase{
		{`foo.com`, nil},
		{`foo@bar.com`, nil},
		{`http://foo`, `http://foo`},
		{`https://foo`, nil},
		{`ftp://foo`, `ftp://foo`},
		{`ftps://foo`, `ftps://foo`},
		{`mailto:foo`, `mailto:foo`},
		{`sms:123`, nil},
	})
}

func bench(b *testing.B, re *regexp.Regexp, str string) {
	for i := 0; i < b.N; i++ {
		re.FindAllString(str, -1)
	}
}

func BenchmarkStrictEmpty(b *testing.B) {
	bench(b, Strict, "foo")
}

func BenchmarkStrictSingle(b *testing.B) {
	bench(b, Strict, "http://foo.foo foo.com")
}

func BenchmarkStrictMany(b *testing.B) {
	bench(b, Strict, ` foo bar http://foo.foo
	foo.com bitcoin:address ftp://
	xmpp:foo@bar.com`)
}

func BenchmarkRelaxedEmpty(b *testing.B) {
	bench(b, Relaxed, "foo")
}

func BenchmarkRelaxedSingle(b *testing.B) {
	bench(b, Relaxed, "http://foo.foo foo.com")
}

func BenchmarkRelaxedMany(b *testing.B) {
	bench(b, Relaxed, ` foo bar http://foo.foo
	foo.com bitcoin:address ftp://
	xmpp:foo@bar.com`)
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// Version is the current version of the buffalo binary
const Version = "v0.9.2"

func init() {
	decorate("version", versionCmd)
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number of buffalo",
	Long:  `All software has versions.  This is buffalo's.`,
	Run: func(c *cobra.Command, args []string) {
		fmt.Printf("Buffalo version is: %s\n", Version)
	},
	// needed to override the root level pre-run func
	PersistentPreRunE: func(c *cobra.Command, args []string) error {
		return nil
	},
}
<commit_msg>reset to development version<commit_after>package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// Version is the current version of the buffalo binary
const Version = "development"

func init() {
	decorate("version", versionCmd)
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number of buffalo",
	Long:  `All software has versions.  This is buffalo's.`,
	Run: func(c *cobra.Command, args []string) {
		fmt.Printf("Buffalo version is: %s\n", Version)
	},
	// needed to override the root level pre-run func
	PersistentPreRunE: func(c *cobra.Command, args []string) error {
		return nil
	},
}
<|endoftext|>


<commit_before>package cmd

// Version is the current version of the buffalo binary
var Version = "0.7.1"
<commit_msg>convert version to constant<commit_after>package cmd

// Version is the current version of the buffalo binary
const Version = "0.7.1"
<|endoftext|>