<commit_before>package commands

import (
	"errors"
	"io"
	"os"
	"os/exec"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/joyent/containerpilot/utils"
)

// Command wraps an os/exec.Cmd with a timeout, logging, and arg parsing.
type Command struct {
	Name            string // this gets used only in logs, defaults to Exec
	Cmd             *exec.Cmd
	Exec            string
	Args            []string
	Timeout         string
	TimeoutDuration time.Duration
	ticker          *time.Ticker
	logWriters      []io.WriteCloser
}

// NewCommand parses JSON config into a Command
func NewCommand(rawArgs interface{}, timeoutFmt string) (*Command, error) {
	exec, args, err := ParseArgs(rawArgs)
	if err != nil {
		return nil, err
	}
	timeout, err := getTimeout(timeoutFmt)
	if err != nil {
		return nil, err
	}
	cmd := &Command{
		Name:            exec, // override this in caller
		Exec:            exec,
		Args:            args,
		Timeout:         timeoutFmt,
		TimeoutDuration: timeout,
	} // cmd, ticker, logWriters all created at RunAndWait or RunWithTimeout
	return cmd, nil
}

func getTimeout(timeoutFmt string) (time.Duration, error) {
	if timeoutFmt != "" {
		timeout, err := utils.ParseDuration(timeoutFmt)
		if err != nil {
			return time.Duration(0), err
		}
		return timeout, nil
	}
	// support commands that don't have a timeout for backwards
	// compatibility
	return time.Duration(0), nil
}

// RunAndWait runs the given command and blocks until completed
func RunAndWait(c *Command, fields log.Fields) (int, error) {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return 1, errors.New("Command for RunAndWait was nil")
	}
	log.Debugf("%s.RunAndWait start", c.Name)
	c.setUpCmd(fields)
	log.Debugf("%s.Cmd.Run", c.Name)
	if err := c.Cmd.Run(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return status.ExitStatus(), err
			}
		}
		// Should only happen if we misconfigure or there's some more
		// serious problem with the underlying open/exec syscalls. But
		// we'll let the lack of heartbeat tell us if something has gone
		// wrong to that extent.
		log.Errorln(err)
		return 1, err
	}
	log.Debugf("%s.RunAndWait end", c.Name)
	return 0, nil
}

// RunAndWaitForOutput runs the given command and blocks until
// completed, then returns the stdout
func RunAndWaitForOutput(c *Command) (string, error) {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return "", errors.New("Command for RunAndWaitForOutput was nil")
	}
	log.Debugf("%s.RunAndWaitForOutput start", c.Name)
	c.setUpCmd(nil)

	// we'll pass stderr to the container's stderr, but stdout must
	// be "clean" and not have anything other than what we intend
	// to write to our collector.
	c.Cmd.Stderr = os.Stderr
	log.Debugf("%s.Cmd.Output", c.Name)
	out, err := c.Cmd.Output()
	if err != nil {
		return "", err
	}
	log.Debugf("%s.RunAndWaitForOutput end", c.Name)
	return string(out[:]), nil
}

// RunWithTimeout runs the given command and blocks until completed
// or until the timeout expires
func RunWithTimeout(c *Command, fields log.Fields) error {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return errors.New("Command for RunWithTimeout was nil")
	}
	log.Debugf("%s.RunWithTimeout start", c.Name)
	c.setUpCmd(fields)
	defer c.closeLogs()
	log.Debugf("%s.Cmd.Start", c.Name)
	if err := c.Cmd.Start(); err != nil {
		log.Errorf("Unable to start %s: %v", c.Name, err)
		return err
	}

	err := c.waitForTimeout()
	log.Debugf("%s.RunWithTimeout end", c.Name)
	return err
}

func (c *Command) setUpCmd(fields log.Fields) {
	cmd := ArgsToCmd(c.Exec, c.Args)
	if fields != nil {
		stdout := utils.NewLogWriter(fields, log.InfoLevel)
		stderr := utils.NewLogWriter(fields, log.DebugLevel)
		c.logWriters = []io.WriteCloser{stdout, stderr}
		cmd.Stdout = stdout
		cmd.Stderr = stderr
	}
	c.Cmd = cmd
}

// Kill sends a kill signal to the underlying process.
func (c *Command) Kill() error {
	log.Debugf("%s.kill", c.Name)
	if c.Cmd != nil && c.Cmd.Process != nil {
		log.Warnf("killing command at pid: %d", c.Cmd.Process.Pid)
		return c.Cmd.Process.Kill()
	}
	return nil
}

func (c *Command) waitForTimeout() error {

	quit := make(chan int)
	cmd := c.Cmd

	// for commands that don't have a timeout we just block forever;
	// this is required for backwards compat.
	doTimeout := c.TimeoutDuration != time.Duration(0)
	if doTimeout {
		// wrap a timer in a goroutine and kill the child process
		// if the timer expires
		ticker := time.NewTicker(c.TimeoutDuration)
		go func() {
			defer ticker.Stop()
			select {
			case <-ticker.C:
				log.Warnf("%s timeout after %s: '%s'", c.Name, c.Timeout, c.Args)
				if err := c.Kill(); err != nil {
					log.Errorf("error killing command: %v", err)
					return
				}
				log.Debugf("%s.run#gofunc swallow quit", c.Name)
				// Swallow quit signal
				<-quit
				log.Debugf("%s.run#gofunc swallow quit complete", c.Name)
				return
			case <-quit:
				log.Debugf("%s.run#gofunc received quit", c.Name)
				return
			}
		}()
	}
	log.Debugf("%s.run waiting for PID %d: ", c.Name, cmd.Process.Pid)
	if _, err := cmd.Process.Wait(); err != nil {
		log.Errorf("%s exited with error: %v", c.Name, err)
		return err
	}
	if doTimeout {
		// if we send on this when we haven't set up the receiver
		// we'll deadlock
		log.Debugf("%s.run sent timeout quit", c.Name)
		quit <- 0
	}
	log.Debugf("%s.run complete", c.Name)
	return nil
}

func (c *Command) closeLogs() {
	if c.logWriters == nil {
		return
	}
	for _, w := range c.logWriters {
		if err := w.Close(); err != nil {
			log.Errorf("unable to close log writer : %v", err)
		}
	}
}
<commit_msg>Attach stdout/stderr in RunAndWait (#209)<commit_after>package commands

import (
	"errors"
	"io"
	"os"
	"os/exec"
	"syscall"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/joyent/containerpilot/utils"
)

// Command wraps an os/exec.Cmd with a timeout, logging, and arg parsing.
type Command struct {
	Name            string // this gets used only in logs, defaults to Exec
	Cmd             *exec.Cmd
	Exec            string
	Args            []string
	Timeout         string
	TimeoutDuration time.Duration
	ticker          *time.Ticker
	logWriters      []io.WriteCloser
}

// NewCommand parses JSON config into a Command
func NewCommand(rawArgs interface{}, timeoutFmt string) (*Command, error) {
	exec, args, err := ParseArgs(rawArgs)
	if err != nil {
		return nil, err
	}
	timeout, err := getTimeout(timeoutFmt)
	if err != nil {
		return nil, err
	}
	cmd := &Command{
		Name:            exec, // override this in caller
		Exec:            exec,
		Args:            args,
		Timeout:         timeoutFmt,
		TimeoutDuration: timeout,
	} // cmd, ticker, logWriters all created at RunAndWait or RunWithTimeout
	return cmd, nil
}

func getTimeout(timeoutFmt string) (time.Duration, error) {
	if timeoutFmt != "" {
		timeout, err := utils.ParseDuration(timeoutFmt)
		if err != nil {
			return time.Duration(0), err
		}
		return timeout, nil
	}
	// support commands that don't have a timeout for backwards
	// compatibility
	return time.Duration(0), nil
}

// RunAndWait runs the given command and blocks until completed
func RunAndWait(c *Command, fields log.Fields) (int, error) {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return 1, errors.New("Command for RunAndWait was nil")
	}
	log.Debugf("%s.RunAndWait start", c.Name)
	c.setUpCmd(fields)
	if fields == nil {
		c.Cmd.Stdout = os.Stdout
		c.Cmd.Stderr = os.Stderr
	}
	log.Debugf("%s.Cmd.Run", c.Name)
	if err := c.Cmd.Run(); err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return status.ExitStatus(), err
			}
		}
		// Should only happen if we misconfigure or there's some more
		// serious problem with the underlying open/exec syscalls. But
		// we'll let the lack of heartbeat tell us if something has gone
		// wrong to that extent.
		log.Errorln(err)
		return 1, err
	}
	log.Debugf("%s.RunAndWait end", c.Name)
	return 0, nil
}

// RunAndWaitForOutput runs the given command and blocks until
// completed, then returns the stdout
func RunAndWaitForOutput(c *Command) (string, error) {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return "", errors.New("Command for RunAndWaitForOutput was nil")
	}
	log.Debugf("%s.RunAndWaitForOutput start", c.Name)
	c.setUpCmd(nil)

	// we'll pass stderr to the container's stderr, but stdout must
	// be "clean" and not have anything other than what we intend
	// to write to our collector.
	c.Cmd.Stderr = os.Stderr
	log.Debugf("%s.Cmd.Output", c.Name)
	out, err := c.Cmd.Output()
	if err != nil {
		return "", err
	}
	log.Debugf("%s.RunAndWaitForOutput end", c.Name)
	return string(out[:]), nil
}

// RunWithTimeout runs the given command and blocks until completed
// or until the timeout expires
func RunWithTimeout(c *Command, fields log.Fields) error {
	if c == nil {
		// sometimes this will be ok but we should return an error
		// anyway in case the caller cares
		return errors.New("Command for RunWithTimeout was nil")
	}
	log.Debugf("%s.RunWithTimeout start", c.Name)
	c.setUpCmd(fields)
	defer c.closeLogs()
	log.Debugf("%s.Cmd.Start", c.Name)
	if err := c.Cmd.Start(); err != nil {
		log.Errorf("Unable to start %s: %v", c.Name, err)
		return err
	}

	err := c.waitForTimeout()
	log.Debugf("%s.RunWithTimeout end", c.Name)
	return err
}

func (c *Command) setUpCmd(fields log.Fields) {
	cmd := ArgsToCmd(c.Exec, c.Args)
	if fields != nil {
		stdout := utils.NewLogWriter(fields, log.InfoLevel)
		stderr := utils.NewLogWriter(fields, log.DebugLevel)
		c.logWriters = []io.WriteCloser{stdout, stderr}
		cmd.Stdout = stdout
		cmd.Stderr = stderr
	}
	c.Cmd = cmd
}

// Kill sends a kill signal to the underlying process.
func (c *Command) Kill() error {
	log.Debugf("%s.kill", c.Name)
	if c.Cmd != nil && c.Cmd.Process != nil {
		log.Warnf("killing command at pid: %d", c.Cmd.Process.Pid)
		return c.Cmd.Process.Kill()
	}
	return nil
}

func (c *Command) waitForTimeout() error {

	quit := make(chan int)
	cmd := c.Cmd

	// for commands that don't have a timeout we just block forever;
	// this is required for backwards compat.
	doTimeout := c.TimeoutDuration != time.Duration(0)
	if doTimeout {
		// wrap a timer in a goroutine and kill the child process
		// if the timer expires
		ticker := time.NewTicker(c.TimeoutDuration)
		go func() {
			defer ticker.Stop()
			select {
			case <-ticker.C:
				log.Warnf("%s timeout after %s: '%s'", c.Name, c.Timeout, c.Args)
				if err := c.Kill(); err != nil {
					log.Errorf("error killing command: %v", err)
					return
				}
				log.Debugf("%s.run#gofunc swallow quit", c.Name)
				// Swallow quit signal
				<-quit
				log.Debugf("%s.run#gofunc swallow quit complete", c.Name)
				return
			case <-quit:
				log.Debugf("%s.run#gofunc received quit", c.Name)
				return
			}
		}()
	}
	log.Debugf("%s.run waiting for PID %d: ", c.Name, cmd.Process.Pid)
	if _, err := cmd.Process.Wait(); err != nil {
		log.Errorf("%s exited with error: %v", c.Name, err)
		return err
	}
	if doTimeout {
		// if we send on this when we haven't set up the receiver
		// we'll deadlock
		log.Debugf("%s.run sent timeout quit", c.Name)
		quit <- 0
	}
	log.Debugf("%s.run complete", c.Name)
	return nil
}

func (c *Command) closeLogs() {
	if c.logWriters == nil {
		return
	}
	for _, w := range c.logWriters {
		if err := w.Close(); err != nil {
			log.Errorf("unable to close log writer : %v", err)
		}
	}
}
<|endoftext|>


<commit_before>package windowsipam

import (
	"net"

	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/ipamapi"
	"github.com/docker/libnetwork/netlabel"
	"github.com/docker/libnetwork/types"
	"github.com/sirupsen/logrus"
)

const (
	localAddressSpace  = "LocalDefault"
	globalAddressSpace = "GlobalDefault"
)

// DefaultIPAM defines the default ipam-driver for local-scoped windows networks
const DefaultIPAM = "windows"

var (
	defaultPool, _ = types.ParseCIDR("0.0.0.0/0")
)

type allocator struct {
}

// GetInit registers the built-in ipam service with libnetwork
func GetInit(ipamName string) func(ic ipamapi.Callback, l, g interface{}) error {
	return func(ic ipamapi.Callback, l, g interface{}) error {
		return ic.RegisterIpamDriver(ipamName, &allocator{})
	}
}

func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
	return localAddressSpace, globalAddressSpace, nil
}

// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the
// subnet user asked and does not validate anything. Doesn't support subpool allocation
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
	logrus.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
	if subPool != "" || v6 {
		return "", nil, nil, types.InternalErrorf("This request is not supported by null ipam driver")
	}

	var ipNet *net.IPNet
	var err error

	if pool != "" {
		_, ipNet, err = net.ParseCIDR(pool)
		if err != nil {
			return "", nil, nil, err
		}
	} else {
		ipNet = defaultPool
	}

	return ipNet.String(), ipNet, nil, nil
}

// ReleasePool releases the address pool - always succeeds
func (a *allocator) ReleasePool(poolID string) error {
	logrus.Debugf("ReleasePool(%s)", poolID)
	return nil
}

// RequestAddress returns an address from the specified pool ID.
// Always allocate the 0.0.0.0/32 ip if no preferred address was specified
func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
	logrus.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
	_, ipNet, err := net.ParseCIDR(poolID)

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

	// TODO Windows: Remove this once the bug in docker daemon is fixed
	// that causes it to throw an exception on nil gateway
	if prefAddress != nil {
		return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil
	} else if opts[ipamapi.RequestAddressType] == netlabel.Gateway {
		return ipNet, nil, nil
	} else {
		return nil, nil, nil
	}
}

// ReleaseAddress releases the address - always succeeds
func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
	logrus.Debugf("ReleaseAddress(%s, %v)", poolID, address)
	return nil
}

// DiscoverNew informs the allocator about a new global scope datastore
func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	return nil
}

// DiscoverDelete is a notification of no interest for the allocator
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
	return nil
}

func (a *allocator) IsBuiltIn() bool {
	return true
}
<commit_msg>Docker deamon doesn't work with --fixed-cidr on windows<commit_after>package windowsipam

import (
	"net"

	"github.com/docker/libnetwork/discoverapi"
	"github.com/docker/libnetwork/ipamapi"
	"github.com/docker/libnetwork/types"
	"github.com/sirupsen/logrus"
)

const (
	localAddressSpace  = "LocalDefault"
	globalAddressSpace = "GlobalDefault"
)

// DefaultIPAM defines the default ipam-driver for local-scoped windows networks
const DefaultIPAM = "windows"

var (
	defaultPool, _ = types.ParseCIDR("0.0.0.0/0")
)

type allocator struct {
}

// GetInit registers the built-in ipam service with libnetwork
func GetInit(ipamName string) func(ic ipamapi.Callback, l, g interface{}) error {
	return func(ic ipamapi.Callback, l, g interface{}) error {
		return ic.RegisterIpamDriver(ipamName, &allocator{})
	}
}

func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
	return localAddressSpace, globalAddressSpace, nil
}

// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the
// subnet user asked and does not validate anything. Doesn't support subpool allocation
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
	logrus.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
	if subPool != "" || v6 {
		return "", nil, nil, types.InternalErrorf("This request is not supported by null ipam driver")
	}

	var ipNet *net.IPNet
	var err error

	if pool != "" {
		_, ipNet, err = net.ParseCIDR(pool)
		if err != nil {
			return "", nil, nil, err
		}
	} else {
		ipNet = defaultPool
	}

	return ipNet.String(), ipNet, nil, nil
}

// ReleasePool releases the address pool - always succeeds
func (a *allocator) ReleasePool(poolID string) error {
	logrus.Debugf("ReleasePool(%s)", poolID)
	return nil
}

// RequestAddress returns an address from the specified pool ID.
// Always allocate the 0.0.0.0/32 ip if no preferred address was specified
func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
	logrus.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
	_, ipNet, err := net.ParseCIDR(poolID)

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

	if prefAddress != nil {
		return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil
	}

	return nil, nil, nil
}

// ReleaseAddress releases the address - always succeeds
func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
	logrus.Debugf("ReleaseAddress(%s, %v)", poolID, address)
	return nil
}

// DiscoverNew informs the allocator about a new global scope datastore
func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
	return nil
}

// DiscoverDelete is a notification of no interest for the allocator
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
	return nil
}

func (a *allocator) IsBuiltIn() bool {
	return true
}
<|endoftext|>


<commit_before>package components

import (
	"github.com/erroneousboat/termui"
	runewidth "github.com/mattn/go-runewidth"
)

// Input is the definition of an Input component
type Input struct {
	Par                  *termui.Par
	Text                 []rune
	CursorPositionScreen int
	CursorPositionText   int
	Offset               int
}

// CreateInput is the constructor of the Input struct
func CreateInputComponent() *Input {
	input := &Input{
		Par:                  termui.NewPar(""),
		Text:                 make([]rune, 0),
		CursorPositionScreen: 0,
		CursorPositionText:   0,
		Offset:               0,
	}

	input.Par.Height = 3

	return input
}

// Buffer implements interface termui.Bufferer
func (i *Input) Buffer() termui.Buffer {
	buf := i.Par.Buffer()

	// Set visible cursor, get char at screen cursor position
	char := buf.At(i.Par.InnerX()+i.CursorPositionScreen, i.Par.Block.InnerY())

	buf.Set(
		i.Par.InnerX()+i.CursorPositionScreen,
		i.Par.Block.InnerY(),
		termui.Cell{
			Ch: char.Ch,
			Fg: i.Par.TextBgColor,
			Bg: i.Par.TextFgColor,
		},
	)

	return buf
}

// GetHeight implements interface termui.GridBufferer
func (i *Input) GetHeight() int {
	return i.Par.Block.GetHeight()
}

// SetWidth implements interface termui.GridBufferer
func (i *Input) SetWidth(w int) {
	i.Par.SetWidth(w)
}

// SetX implements interface termui.GridBufferer
func (i *Input) SetX(x int) {
	i.Par.SetX(x)
}

// SetY implements interface termui.GridBufferer
func (i *Input) SetY(y int) {
	i.Par.SetY(y)
}

// Insert will insert a given key at the place of the current CursorPositionText
func (i *Input) Insert(key rune) {
	// Append key to the left side
	left := make([]rune, len(i.Text[0:i.CursorPositionText]))
	copy(left, i.Text[0:i.CursorPositionText])
	left = append(left, key)

	// Combine left and right side
	i.Text = append(left, i.Text[i.CursorPositionText:]...)

	i.MoveCursorRight()
}

// Backspace will remove a character in front of the CursorPositionText
func (i *Input) Backspace() {
	if i.CursorPositionText > 0 {
		i.MoveCursorLeft()
		i.Text = append(i.Text[0:i.CursorPositionText], i.Text[i.CursorPositionText+1:]...)
		i.Par.Text = string(i.Text[i.Offset:])
	}
}

// Delete will remove a character at the CursorPositionText
func (i *Input) Delete() {
	if i.CursorPositionText < len(i.Text) {
		i.Text = append(i.Text[0:i.CursorPositionText], i.Text[i.CursorPositionText+1:]...)
		i.Par.Text = string(i.Text[i.Offset:])
	}
}

// MoveCursorRight will increase the current CursorPositionText with 1
func (i *Input) MoveCursorRight() {
	if i.CursorPositionText < len(i.Text) {
		i.CursorPositionText++
		i.ScrollRight()
	}

	i.Par.Text = string(i.Text[i.Offset:])
}

// MoveCursorLeft will decrease the current CursorPositionText with 1
func (i *Input) MoveCursorLeft() {
	if i.CursorPositionText > 0 {
		i.CursorPositionText--
		i.ScrollLeft()
	}

	i.Par.Text = string(i.Text[i.Offset:])
}

func (i *Input) ScrollLeft() {
	// Is the cursor at the far left of the Input component?
	if i.CursorPositionScreen == 0 {

		// Decrease offset to show what is on the left side
		if i.Offset > 0 {
			i.Offset--
		}
	} else {
		i.CursorPositionScreen -= i.GetRuneWidthRight()
	}
}

func (i *Input) ScrollRight() {
	// Is the cursor at the far right of the Input component, cursor
	// isn't at the end of the text
	if (i.CursorPositionScreen + i.GetRuneWidthLeft()) > i.Par.InnerBounds().Dx()-1 {

		// Increase offset to show what is on the right side
		if i.Offset < len(i.Text) {
			i.Offset = i.CalculateOffset()
			i.CursorPositionScreen = i.GetRuneWidthOffsetToCursor()
		}
	} else {
		i.CursorPositionScreen += i.GetRuneWidthLeft()
	}
}

// CalculateOffset will, based on the width of the runes on the
// left of the text cursor, calculate the offset that needs to
// be used by the Inpute Component
func (i *Input) CalculateOffset() int {
	var offset int

	var currentRuneWidth int
	for j := (i.CursorPositionText - 1); currentRuneWidth < i.GetMaxWidth()-1; j-- {
		currentRuneWidth += runewidth.RuneWidth(i.Text[j])
		offset = j
	}

	return offset
}

// GetRunWidthOffsetToCursor will get the rune width of all
// the runes from the offset until the text cursor
func (i *Input) GetRuneWidthOffsetToCursor() int {
	return runewidth.StringWidth(string(i.Text[i.Offset:i.CursorPositionText]))
}

// GetRuneWidthLeft will get the width of a rune on the left side
// of the CursorPositionText
func (i *Input) GetRuneWidthLeft() int {
	return runewidth.RuneWidth(i.Text[i.CursorPositionText-1])
}

// GetRuneWidthLeft will get the width of a rune on the right side
// of the CursorPositionText
func (i *Input) GetRuneWidthRight() int {
	return runewidth.RuneWidth(i.Text[i.CursorPositionText])
}

// IsEmpty will return true when the input is empty
func (i *Input) IsEmpty() bool {
	if i.Par.Text == "" {
		return true
	}
	return false
}

// Clear will empty the input and move the cursor to the start position
func (i *Input) Clear() {
	i.Text = make([]rune, 0)
	i.Par.Text = ""
	i.CursorPositionScreen = 0
	i.CursorPositionText = 0
	i.Offset = 0
}

// GetText returns the text currently in the input
func (i *Input) GetText() string {
	return i.Par.Text
}

// GetMaxWidth returns the maximum number of positions
// the Input component can display
func (i *Input) GetMaxWidth() int {
	return i.Par.InnerBounds().Dx() - 1
}
<commit_msg>Fix GetText to return actual text not representation<commit_after>package components

import (
	"github.com/erroneousboat/termui"
	runewidth "github.com/mattn/go-runewidth"
)

// Input is the definition of an Input component
type Input struct {
	Par                  *termui.Par
	Text                 []rune
	CursorPositionScreen int
	CursorPositionText   int
	Offset               int
}

// CreateInput is the constructor of the Input struct
func CreateInputComponent() *Input {
	input := &Input{
		Par:                  termui.NewPar(""),
		Text:                 make([]rune, 0),
		CursorPositionScreen: 0,
		CursorPositionText:   0,
		Offset:               0,
	}

	input.Par.Height = 3

	return input
}

// Buffer implements interface termui.Bufferer
func (i *Input) Buffer() termui.Buffer {
	buf := i.Par.Buffer()

	// Set visible cursor, get char at screen cursor position
	char := buf.At(i.Par.InnerX()+i.CursorPositionScreen, i.Par.Block.InnerY())

	buf.Set(
		i.Par.InnerX()+i.CursorPositionScreen,
		i.Par.Block.InnerY(),
		termui.Cell{
			Ch: char.Ch,
			Fg: i.Par.TextBgColor,
			Bg: i.Par.TextFgColor,
		},
	)

	return buf
}

// GetHeight implements interface termui.GridBufferer
func (i *Input) GetHeight() int {
	return i.Par.Block.GetHeight()
}

// SetWidth implements interface termui.GridBufferer
func (i *Input) SetWidth(w int) {
	i.Par.SetWidth(w)
}

// SetX implements interface termui.GridBufferer
func (i *Input) SetX(x int) {
	i.Par.SetX(x)
}

// SetY implements interface termui.GridBufferer
func (i *Input) SetY(y int) {
	i.Par.SetY(y)
}

// Insert will insert a given key at the place of the current CursorPositionText
func (i *Input) Insert(key rune) {
	// Append key to the left side
	left := make([]rune, len(i.Text[0:i.CursorPositionText]))
	copy(left, i.Text[0:i.CursorPositionText])
	left = append(left, key)

	// Combine left and right side
	i.Text = append(left, i.Text[i.CursorPositionText:]...)

	i.MoveCursorRight()
}

// Backspace will remove a character in front of the CursorPositionText
func (i *Input) Backspace() {
	if i.CursorPositionText > 0 {
		i.MoveCursorLeft()
		i.Text = append(i.Text[0:i.CursorPositionText], i.Text[i.CursorPositionText+1:]...)
		i.Par.Text = string(i.Text[i.Offset:])
	}
}

// Delete will remove a character at the CursorPositionText
func (i *Input) Delete() {
	if i.CursorPositionText < len(i.Text) {
		i.Text = append(i.Text[0:i.CursorPositionText], i.Text[i.CursorPositionText+1:]...)
		i.Par.Text = string(i.Text[i.Offset:])
	}
}

// MoveCursorRight will increase the current CursorPositionText with 1
func (i *Input) MoveCursorRight() {
	if i.CursorPositionText < len(i.Text) {
		i.CursorPositionText++
		i.ScrollRight()
	}

	i.Par.Text = string(i.Text[i.Offset:])
}

// MoveCursorLeft will decrease the current CursorPositionText with 1
func (i *Input) MoveCursorLeft() {
	if i.CursorPositionText > 0 {
		i.CursorPositionText--
		i.ScrollLeft()
	}

	i.Par.Text = string(i.Text[i.Offset:])
}

func (i *Input) ScrollLeft() {
	// Is the cursor at the far left of the Input component?
	if i.CursorPositionScreen == 0 {

		// Decrease offset to show what is on the left side
		if i.Offset > 0 {
			i.Offset--
		}
	} else {
		i.CursorPositionScreen -= i.GetRuneWidthRight()
	}
}

func (i *Input) ScrollRight() {
	// Is the cursor at the far right of the Input component, cursor
	// isn't at the end of the text
	if (i.CursorPositionScreen + i.GetRuneWidthLeft()) > i.Par.InnerBounds().Dx()-1 {

		// Increase offset to show what is on the right side
		if i.Offset < len(i.Text) {
			i.Offset = i.CalculateOffset()
			i.CursorPositionScreen = i.GetRuneWidthOffsetToCursor()
		}
	} else {
		i.CursorPositionScreen += i.GetRuneWidthLeft()
	}
}

// CalculateOffset will, based on the width of the runes on the
// left of the text cursor, calculate the offset that needs to
// be used by the Inpute Component
func (i *Input) CalculateOffset() int {
	var offset int

	var currentRuneWidth int
	for j := (i.CursorPositionText - 1); currentRuneWidth < i.GetMaxWidth()-1; j-- {
		currentRuneWidth += runewidth.RuneWidth(i.Text[j])
		offset = j
	}

	return offset
}

// GetRunWidthOffsetToCursor will get the rune width of all
// the runes from the offset until the text cursor
func (i *Input) GetRuneWidthOffsetToCursor() int {
	return runewidth.StringWidth(string(i.Text[i.Offset:i.CursorPositionText]))
}

// GetRuneWidthLeft will get the width of a rune on the left side
// of the CursorPositionText
func (i *Input) GetRuneWidthLeft() int {
	return runewidth.RuneWidth(i.Text[i.CursorPositionText-1])
}

// GetRuneWidthLeft will get the width of a rune on the right side
// of the CursorPositionText
func (i *Input) GetRuneWidthRight() int {
	return runewidth.RuneWidth(i.Text[i.CursorPositionText])
}

// IsEmpty will return true when the input is empty
func (i *Input) IsEmpty() bool {
	if i.Par.Text == "" {
		return true
	}
	return false
}

// Clear will empty the input and move the cursor to the start position
func (i *Input) Clear() {
	i.Text = make([]rune, 0)
	i.Par.Text = ""
	i.CursorPositionScreen = 0
	i.CursorPositionText = 0
	i.Offset = 0
}

// GetText returns the text currently in the input
func (i *Input) GetText() string {
	return string(i.Text)
}

// GetMaxWidth returns the maximum number of positions
// the Input component can display
func (i *Input) GetMaxWidth() int {
	return i.Par.InnerBounds().Dx() - 1
}
<|endoftext|>


<commit_before>package logging

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"

	"github.com/dogenzaka/rotator"

	"github.com/getlantern/appdir"
	"github.com/getlantern/flashlight/config"
	"github.com/getlantern/flashlight/globals"
	"github.com/getlantern/flashlight/util"
	"github.com/getlantern/go-loggly"
	"github.com/getlantern/golog"
	"github.com/getlantern/jibber_jabber"
	"github.com/getlantern/waitforserver"
	"github.com/getlantern/wfilter"
)

var (
	log = golog.LoggerFor("flashlight")

	LogTimestampFormat = "Jan 02 15:04:05.000"
	lang               string
	tz                 string
	versionToLoggly    string
	cfgMutex           sync.RWMutex
	httpClient         *http.Client

	// logglyToken is populated at build time by crosscompile.bash. During
	// development time, logglyToken will be empty and we won't log to Loggly.
	logglyToken string
)

func init() {
	lang, _ = jibber_jabber.DetectLanguage()
	tz = time.Local.String()
}

func Setup(version string, buildDate string) *rotator.SizeRotator {

	if version == "" {
		panic("You can't use an empty version.")
	}

	if buildDate == "" {
		panic("You can't use an empty build date.")
	}

	versionToLoggly = fmt.Sprintf("%v (%v)", version, buildDate)

	logdir := appdir.Logs("Lantern")
	log.Debugf("Placing logs in %v", logdir)
	if _, err := os.Stat(logdir); err != nil {
		if os.IsNotExist(err) {
			// Create log dir
			if err := os.MkdirAll(logdir, 0755); err != nil {
				log.Fatalf("Unable to create logdir at %s: %s", logdir, err)
			}
		}
	}
	file := rotator.NewSizeRotator(filepath.Join(logdir, "lantern.log"))
	// Set log files to 1 MB
	file.RotationSize = 1 * 1024 * 1024
	// Keep up to 20 log files
	file.MaxRotation = 20

	// Loggly has its own timestamp so don't bother adding it in message,
	// moreover, golog always write each line in whole, so we need not to care about line breaks.
	errorOut := timestamped(NonStopWriter(os.Stderr, file))

	if logglyToken == "" {
		log.Debugf("No logglyToken, not sending error logs to Loggly")
	} else {
		log.Debugf("Sending error logs to Loggly")
		remoteWriter := logglyErrorWriter{loggly.New(logglyToken)}
		errorOut = NonStopWriter(errorOut, remoteWriter)
	}
	debugOut := timestamped(NonStopWriter(os.Stdout, file))
	golog.SetOutputs(errorOut, debugOut)
	return file
}

func Configure(cfg *config.Config) (err error) {
	if cfg.Addr == "" {
		return fmt.Errorf("No proxy address provided.")
	}

	if err = waitforserver.WaitForServer("tcp", cfg.Addr, 10*time.Second); err != nil {
		return fmt.Errorf("Proxy never came online at %s: %q", cfg.Addr, err)
	}

	var cli *http.Client
	if cli, err = util.HTTPClient(cfg.CloudConfigCA, cfg.Addr); err != nil {
		return fmt.Errorf("Could not create proxy HTTP client %q.", err)
	}

	loggly.SetHTTPClient(cli)

	return nil
}

// timestamped adds a timestamp to the beginning of log lines
func timestamped(orig io.Writer) io.Writer {
	return wfilter.LinePrepender(orig, func(w io.Writer) (int, error) {
		return fmt.Fprintf(w, "%s - ", time.Now().In(time.UTC).Format(LogTimestampFormat))
	})
}

type logglyErrorWriter struct {
	l *loggly.Client
}

func (w logglyErrorWriter) Write(b []byte) (int, error) {
	return writeToLoggly(w.l, "ERROR", string(b))
}

func writeToLoggly(l *loggly.Client, level string, msg string) (int, error) {
	extra := map[string]string{
		"logLevel":  level,
		"osName":    runtime.GOOS,
		"osArch":    runtime.GOARCH,
		"osVersion": "",
		"language":  lang,
		"country":   globals.GetCountry(),
		"timeZone":  tz,
		"version":   versionToLoggly,
	}

	m := loggly.Message{
		"extra":   extra,
		"message": msg,
	}
	err := l.Send(m)
	if err != nil {
		return 0, err
	}
	return len(msg), nil
}

type nonStopWriter struct {
	writers []io.Writer
}

func (t *nonStopWriter) Write(p []byte) (n int, err error) {
	for _, w := range t.writers {
		n, _ = w.Write(p)
	}
	return len(p), nil
}

// NonStopWriter creates a writer that duplicates its writes to all the
// provided writers, even if errors encountered while writting.
func NonStopWriter(writers ...io.Writer) io.Writer {
	w := make([]io.Writer, len(writers))
	copy(w, writers)
	return &nonStopWriter{w}
}
<commit_msg>Adding mutex to protect Configure and removing unused httpClient.<commit_after>package logging

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"

	"github.com/dogenzaka/rotator"

	"github.com/getlantern/appdir"
	"github.com/getlantern/flashlight/config"
	"github.com/getlantern/flashlight/globals"
	"github.com/getlantern/flashlight/util"
	"github.com/getlantern/go-loggly"
	"github.com/getlantern/golog"
	"github.com/getlantern/jibber_jabber"
	"github.com/getlantern/waitforserver"
	"github.com/getlantern/wfilter"
)

var (
	log = golog.LoggerFor("flashlight")

	LogTimestampFormat = "Jan 02 15:04:05.000"
	lang               string
	tz                 string
	versionToLoggly    string
	cfgMutex           sync.RWMutex

	// logglyToken is populated at build time by crosscompile.bash. During
	// development time, logglyToken will be empty and we won't log to Loggly.
	logglyToken string
)

func init() {
	lang, _ = jibber_jabber.DetectLanguage()
	tz = time.Local.String()
}

func Setup(version string, buildDate string) *rotator.SizeRotator {

	if version == "" {
		panic("You can't use an empty version.")
	}

	if buildDate == "" {
		panic("You can't use an empty build date.")
	}

	versionToLoggly = fmt.Sprintf("%v (%v)", version, buildDate)

	logdir := appdir.Logs("Lantern")
	log.Debugf("Placing logs in %v", logdir)
	if _, err := os.Stat(logdir); err != nil {
		if os.IsNotExist(err) {
			// Create log dir
			if err := os.MkdirAll(logdir, 0755); err != nil {
				log.Fatalf("Unable to create logdir at %s: %s", logdir, err)
			}
		}
	}
	file := rotator.NewSizeRotator(filepath.Join(logdir, "lantern.log"))
	// Set log files to 1 MB
	file.RotationSize = 1 * 1024 * 1024
	// Keep up to 20 log files
	file.MaxRotation = 20

	// Loggly has its own timestamp so don't bother adding it in message,
	// moreover, golog always write each line in whole, so we need not to care about line breaks.
	errorOut := timestamped(NonStopWriter(os.Stderr, file))

	if logglyToken == "" {
		log.Debugf("No logglyToken, not sending error logs to Loggly")
	} else {
		log.Debugf("Sending error logs to Loggly")
		remoteWriter := logglyErrorWriter{loggly.New(logglyToken)}
		errorOut = NonStopWriter(errorOut, remoteWriter)
	}
	debugOut := timestamped(NonStopWriter(os.Stdout, file))
	golog.SetOutputs(errorOut, debugOut)
	return file
}

func Configure(cfg *config.Config) (err error) {
	cfgMutex.Lock()
	defer cfgMutex.Unlock()

	if cfg.Addr == "" {
		return fmt.Errorf("No proxy address provided.")
	}

	if err = waitforserver.WaitForServer("tcp", cfg.Addr, 10*time.Second); err != nil {
		return fmt.Errorf("Proxy never came online at %s: %q", cfg.Addr, err)
	}

	var cli *http.Client
	if cli, err = util.HTTPClient(cfg.CloudConfigCA, cfg.Addr); err != nil {
		return fmt.Errorf("Could not create proxy HTTP client %q.", err)
	}

	loggly.SetHTTPClient(cli)

	return nil
}

// timestamped adds a timestamp to the beginning of log lines
func timestamped(orig io.Writer) io.Writer {
	return wfilter.LinePrepender(orig, func(w io.Writer) (int, error) {
		return fmt.Fprintf(w, "%s - ", time.Now().In(time.UTC).Format(LogTimestampFormat))
	})
}

type logglyErrorWriter struct {
	l *loggly.Client
}

func (w logglyErrorWriter) Write(b []byte) (int, error) {
	return writeToLoggly(w.l, "ERROR", string(b))
}

func writeToLoggly(l *loggly.Client, level string, msg string) (int, error) {
	extra := map[string]string{
		"logLevel":  level,
		"osName":    runtime.GOOS,
		"osArch":    runtime.GOARCH,
		"osVersion": "",
		"language":  lang,
		"country":   globals.GetCountry(),
		"timeZone":  tz,
		"version":   versionToLoggly,
	}

	m := loggly.Message{
		"extra":   extra,
		"message": msg,
	}
	err := l.Send(m)
	if err != nil {
		return 0, err
	}
	return len(msg), nil
}

type nonStopWriter struct {
	writers []io.Writer
}

func (t *nonStopWriter) Write(p []byte) (n int, err error) {
	for _, w := range t.writers {
		n, _ = w.Write(p)
	}
	return len(p), nil
}

// NonStopWriter creates a writer that duplicates its writes to all the
// provided writers, even if errors encountered while writting.
func NonStopWriter(writers ...io.Writer) io.Writer {
	w := make([]io.Writer, len(writers))
	copy(w, writers)
	return &nonStopWriter{w}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/t3rm1n4l/go-mega"
	"html"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
)

const CACHEDIR = "cache"
var megaSession *mega.Mega

func handle(w http.ResponseWriter, r *http.Request) {
	var node *mega.Node

	trimmedPath := strings.Trim(r.URL.Path, "/")
	path := strings.Split(trimmedPath, "/")
	root := megaSession.FS.GetRoot()
	// Root path is an empty array.
	if path[0] == "" {
		node = root
	} else {
		paths, err := megaSession.FS.PathLookup(root, path)
		if err != nil {
			// XXX should be 404
			fmt.Fprintf(w, "invalid path: %s\n", r.URL.Path)
			return
		}
		// We only care about the last path.
		node = paths[len(paths)-1]
	}

	switch r.Method {
	case "GET":
		switch node.GetType() {
		case mega.FOLDER, mega.ROOT:
			list(w, r, node)
		default:
			get(w, r, node)
		}

	case "PUT":
		put(w, r, node)
	}
}

func list(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	children, err := megaSession.FS.GetChildren(node)
	if err != nil {
		fmt.Fprintf(w, "error getting children: %s", err)
		// XXX 500
		return
	}

	fmt.Fprint(w, "")
	fmt.Fprintf(w, "
%s
", html.EscapeString(r.URL.Path))
	fmt.Fprint(w, "
")
	if node != megaSession.FS.GetRoot() {
		fmt.Fprintf(w, "
..")
	}
	for _, child := range children {
		var folder string
		if child.GetType() == mega.FOLDER {
			folder = "/"
		}
		fmt.Fprintf(w, "
%s%s",
			html.EscapeString(child.GetName()), folder,
			html.EscapeString(child.GetName()), folder)
	}
	fmt.Fprint(w, "
")
}

func get(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	hash := node.GetHash()
	tempfile := fmt.Sprintf("%s/%s", CACHEDIR, hash)
	err := megaSession.DownloadFile(node, tempfile, nil)
	if err != nil {
		log.Printf("download failed: %s", err)
		os.Remove(tempfile)
		return
	}
	file, err := os.Open(tempfile) // For read access.
	if err != nil {
		log.Printf("error opening %s: %s", tempfile, err)
	}
	defer file.Close()
	data := make([]byte, 1024*1024)
	for {
		nr, err := file.Read(data)
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Printf("error reading %s: %s", tempfile, err)
		}
		for nr != 0 {
			nw, err := w.Write(data[:nr])
			if err != nil {
				log.Printf("error sending data: %s", err)
				return
			}
			nr -= nw
		}
	}
}

func put(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	//func (m *Mega) CreateDir(name string, parent *Node) (*Node, error)
	/*
		tmpfile = ok.MkTemp()
		defer os.Remove(tmpfile)
		write(tmpfile, r.Data)
		name := path[len(path)-1]
		megaSession.UploadFile(tmpfile, node, name, nil) (*Node, error)
	*/
}

func main() {
	user := os.Getenv("MEGA_USER")
	pass := os.Getenv("MEGA_PASSWD")
	megaSession = mega.New()
	if err := megaSession.Login(user, pass); err != nil {
		log.Fatal(err)
	}
	if err := os.Mkdir(CACHEDIR, 0700); err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}
	http.HandleFunc("/", handle)
	log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
<commit_msg>Simplify error message, don't print to client.<commit_after>package main

import (
	"fmt"
	"github.com/t3rm1n4l/go-mega"
	"html"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
)

const CACHEDIR = "cache"
var megaSession *mega.Mega

func handle(w http.ResponseWriter, r *http.Request) {
	var node *mega.Node

	trimmedPath := strings.Trim(r.URL.Path, "/")
	path := strings.Split(trimmedPath, "/")
	root := megaSession.FS.GetRoot()
	// Root path is an empty array.
	if path[0] == "" {
		node = root
	} else {
		paths, err := megaSession.FS.PathLookup(root, path)
		if err != nil {
			// XXX should be 404
			fmt.Fprintf(w, "invalid path: %s\n", r.URL.Path)
			return
		}
		// We only care about the last path.
		node = paths[len(paths)-1]
	}

	switch r.Method {
	case "GET":
		switch node.GetType() {
		case mega.FOLDER, mega.ROOT:
			list(w, r, node)
		default:
			get(w, r, node)
		}

	case "PUT":
		put(w, r, node)
	}
}

func list(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	children, err := megaSession.FS.GetChildren(node)
	if err != nil {
		fmt.Print(err)
		// XXX 500
		return
	}

	fmt.Fprint(w, "")
	fmt.Fprintf(w, "
%s
", html.EscapeString(r.URL.Path))
	fmt.Fprint(w, "
")
	if node != megaSession.FS.GetRoot() {
		fmt.Fprintf(w, "
..")
	}
	for _, child := range children {
		var folder string
		if child.GetType() == mega.FOLDER {
			folder = "/"
		}
		fmt.Fprintf(w, "
%s%s",
			html.EscapeString(child.GetName()), folder,
			html.EscapeString(child.GetName()), folder)
	}
	fmt.Fprint(w, "
")
}

func get(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	hash := node.GetHash()
	tempfile := fmt.Sprintf("%s/%s", CACHEDIR, hash)
	err := megaSession.DownloadFile(node, tempfile, nil)
	if err != nil {
		log.Printf("download failed: %s", err)
		os.Remove(tempfile)
		return
	}
	file, err := os.Open(tempfile) // For read access.
	if err != nil {
		log.Printf("error opening %s: %s", tempfile, err)
	}
	defer file.Close()
	data := make([]byte, 1024*1024)
	for {
		nr, err := file.Read(data)
		if err == io.EOF {
			return
		}
		if err != nil {
			log.Printf("error reading %s: %s", tempfile, err)
		}
		for nr != 0 {
			nw, err := w.Write(data[:nr])
			if err != nil {
				log.Printf("error sending data: %s", err)
				return
			}
			nr -= nw
		}
	}
}

func put(w http.ResponseWriter, r *http.Request, node *mega.Node) {
	//func (m *Mega) CreateDir(name string, parent *Node) (*Node, error)
	/*
		tmpfile = ok.MkTemp()
		defer os.Remove(tmpfile)
		write(tmpfile, r.Data)
		name := path[len(path)-1]
		megaSession.UploadFile(tmpfile, node, name, nil) (*Node, error)
	*/
}

func main() {
	user := os.Getenv("MEGA_USER")
	pass := os.Getenv("MEGA_PASSWD")
	megaSession = mega.New()
	if err := megaSession.Login(user, pass); err != nil {
		log.Fatal(err)
	}
	if err := os.Mkdir(CACHEDIR, 0700); err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}
	http.HandleFunc("/", handle)
	log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
<|endoftext|>


<commit_before>package lib

import (
	// Any non-release package imports are not allowed to make
	// sure the repository can be downloaded using "go get".
	// rps "veyron.io/examples/rockpaperscissors"
	// "veyron.io/store/veyron2/services/store"
	// roadmap_watchtypes "veyron.io/store/veyron2/services/watch/types"
	// "veyron.io/store/veyron2/storage"

	mttypes "veyron.io/veyron/veyron2/services/mounttable/types"
	watchtypes "veyron.io/veyron/veyron2/services/watch/types"
	"veyron.io/veyron/veyron2/vom"
)

func init() {
	vom.Register(mttypes.MountEntry{})
	vom.Register(watchtypes.GlobRequest{})
	vom.Register(watchtypes.Change{})
	// vom.Register(storage.Entry{})
	// vom.Register(storage.Stat{})
	// vom.Register(store.NestedResult(0))
	// vom.Register(store.QueryResult{})
	// vom.Register(roadmap_watchtypes.QueryRequest{})
	// vom.Register(rps.GameOptions{})
	// vom.Register(rps.GameID{})
	// vom.Register(rps.PlayResult{})
	// vom.Register(rps.PlayerAction{})
	// vom.Register(rps.JudgeAction{})
}
<commit_msg>wspr: Mounttable types has moved to naming: go/vcl/6713<commit_after>package lib

import (
	// Any non-release package imports are not allowed to make
	// sure the repository can be downloaded using "go get".
	// rps "veyron.io/examples/rockpaperscissors"
	// "veyron.io/store/veyron2/services/store"
	// roadmap_watchtypes "veyron.io/store/veyron2/services/watch/types"
	// "veyron.io/store/veyron2/storage"

	"veyron.io/veyron/veyron2/naming"
	watchtypes "veyron.io/veyron/veyron2/services/watch/types"
	"veyron.io/veyron/veyron2/vom"
)

func init() {
	vom.Register(naming.VDLMountEntry{})
	vom.Register(watchtypes.GlobRequest{})
	vom.Register(watchtypes.Change{})
	// vom.Register(storage.Entry{})
	// vom.Register(storage.Stat{})
	// vom.Register(store.NestedResult(0))
	// vom.Register(store.QueryResult{})
	// vom.Register(roadmap_watchtypes.QueryRequest{})
	// vom.Register(rps.GameOptions{})
	// vom.Register(rps.GameID{})
	// vom.Register(rps.PlayResult{})
	// vom.Register(rps.PlayerAction{})
	// vom.Register(rps.JudgeAction{})
}
<|endoftext|>


<commit_before>package sender

// CODE GENERATED AUTOMATICALLY
// THIS FILE MUST NOT BE EDITED BY HAND

const (
	// ourUserAgent is the User-Agent of this underlying library package.
	ourUserAgent = "xenolf-acme/3.3.0"

	// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
	// values: detach|release
	// NOTE: Update this with each tagged release.
	ourUserAgentComment = "release"
)
<commit_msg>detach v3.3.0<commit_after>package sender

// CODE GENERATED AUTOMATICALLY
// THIS FILE MUST NOT BE EDITED BY HAND

const (
	// ourUserAgent is the User-Agent of this underlying library package.
	ourUserAgent = "xenolf-acme/3.3.0"

	// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
	// values: detach|release
	// NOTE: Update this with each tagged release.
	ourUserAgentComment = "detach"
)
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

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 v1

const (
	LabelHostname = "kubernetes.io/hostname"

	LabelZoneFailureDomain       = "failure-domain.beta.kubernetes.io/zone"
	LabelZoneRegion              = "failure-domain.beta.kubernetes.io/region"
	LabelZoneFailureDomainStable = "topology.kubernetes.io/zone"
	LabelZoneRegionStable        = "topology.kubernetes.io/region"

	LabelInstanceType       = "beta.kubernetes.io/instance-type"
	LabelInstanceTypeStable = "node.kubernetes.io/instance-type"

	LabelOSStable   = "kubernetes.io/os"
	LabelArchStable = "kubernetes.io/arch"

	// LabelWindowsBuild is used on Windows nodes to specify the Windows build number starting with v1.17.0.
	// It's in the format MajorVersion.MinorVersion.BuildNumber (for ex: 10.0.17763)
	LabelWindowsBuild = "node.kubernetes.io/windows-build"

	// LabelNamespaceSuffixKubelet is an allowed label namespace suffix kubelets can self-set ([*.]kubelet.kubernetes.io/*)
	LabelNamespaceSuffixKubelet = "kubelet.kubernetes.io"
	// LabelNamespaceSuffixNode is an allowed label namespace suffix kubelets can self-set ([*.]node.kubernetes.io/*)
	LabelNamespaceSuffixNode = "node.kubernetes.io"

	// LabelNamespaceNodeRestriction is a forbidden label namespace that kubelets may not self-set when the NodeRestriction admission plugin is enabled
	LabelNamespaceNodeRestriction = "node-restriction.kubernetes.io"

	// IsHeadlessService is added by Controller to an Endpoint denoting if its parent
	// Service is Headless. The existence of this label can be used further by other
	// controllers and kube-proxy to check if the Endpoint objects should be replicated when
	// using Headless Services
	IsHeadlessService = "service.kubernetes.io/headless"
)
<commit_msg>Use topology labels instead of old beta names (#96033)<commit_after>/*
Copyright 2019 The Kubernetes Authors.

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 v1

const (
	LabelHostname = "kubernetes.io/hostname"

	LabelFailureDomainBetaZone   = "failure-domain.beta.kubernetes.io/zone"
	LabelFailureDomainBetaRegion = "failure-domain.beta.kubernetes.io/region"
	LabelTopologyZone            = "topology.kubernetes.io/zone"
	LabelTopologyRegion          = "topology.kubernetes.io/region"

	// Legacy names for compat.
	LabelZoneFailureDomain       = LabelFailureDomainBetaZone   // deprecated, remove after 1.20
	LabelZoneRegion              = LabelFailureDomainBetaRegion // deprecated, remove after 1.20
	LabelZoneFailureDomainStable = LabelTopologyZone
	LabelZoneRegionStable        = LabelTopologyRegion

	LabelInstanceType       = "beta.kubernetes.io/instance-type"
	LabelInstanceTypeStable = "node.kubernetes.io/instance-type"

	LabelOSStable   = "kubernetes.io/os"
	LabelArchStable = "kubernetes.io/arch"

	// LabelWindowsBuild is used on Windows nodes to specify the Windows build number starting with v1.17.0.
	// It's in the format MajorVersion.MinorVersion.BuildNumber (for ex: 10.0.17763)
	LabelWindowsBuild = "node.kubernetes.io/windows-build"

	// LabelNamespaceSuffixKubelet is an allowed label namespace suffix kubelets can self-set ([*.]kubelet.kubernetes.io/*)
	LabelNamespaceSuffixKubelet = "kubelet.kubernetes.io"
	// LabelNamespaceSuffixNode is an allowed label namespace suffix kubelets can self-set ([*.]node.kubernetes.io/*)
	LabelNamespaceSuffixNode = "node.kubernetes.io"

	// LabelNamespaceNodeRestriction is a forbidden label namespace that kubelets may not self-set when the NodeRestriction admission plugin is enabled
	LabelNamespaceNodeRestriction = "node-restriction.kubernetes.io"

	// IsHeadlessService is added by Controller to an Endpoint denoting if its parent
	// Service is Headless. The existence of this label can be used further by other
	// controllers and kube-proxy to check if the Endpoint objects should be replicated when
	// using Headless Services
	IsHeadlessService = "service.kubernetes.io/headless"
)
<|endoftext|>


<commit_before>package permutations

func permute(nums []int) [][]int {
	if len(nums) == 0 {
		return [][]int{}
	}
	result := make([][]int, 0, 2*len(nums))
	permuteRecursive(nums, 0, &result)
	return result
}

func permuteRecursive(nums []int, pos int, result *[][]int) {
	if pos >= len(nums) {
		num := make([]int, len(nums))
		for i, n := range nums {
			num[i] = n
		}
		*result = append(*result, num) // append to result
		return
	}
	for i := pos; i < len(nums); i++ {
		nums[pos], nums[i] = nums[i], nums[pos] // swap
		permuteRecursive(nums, pos+1, result)   // recursive
		nums[pos], nums[i] = nums[i], nums[pos] // reset
	}
}
<commit_msg>fix(algorithms): permutations<commit_after>package permutations

func permute(nums []int) [][]int {
	if len(nums) == 0 {
		return [][]int{}
	}
	result := make([][]int, 0, 2*len(nums))
	permuteRecursive(nums, 0, &result)
	return result
}

func permuteRecursive(nums []int, pos int, result *[][]int) {
	if pos >= len(nums) {
		num := make([]int, len(nums))
		copy(num, nums)
		*result = append(*result, num) // append to result
		return
	}
	for i := pos; i < len(nums); i++ {
		nums[pos], nums[i] = nums[i], nums[pos] // swap
		permuteRecursive(nums, pos+1, result)   // recursive
		nums[pos], nums[i] = nums[i], nums[pos] // reset
	}
}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"log"
	"regexp"

	"github.com/Azure/azure-sdk-for-go/arm/containerregistry"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmContainerRegistry() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmContainerRegistryCreate,
		Read:   resourceArmContainerRegistryRead,
		Update: resourceArmContainerRegistryUpdate,
		Delete: resourceArmContainerRegistryDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		MigrateState:  resourceAzureRMContainerRegistryMigrateState,
		SchemaVersion: 2,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateAzureRMContainerRegistryName,
			},

			"resource_group_name": resourceGroupNameSchema(),

			"location": locationSchema(),

			"sku": {
				Type:             schema.TypeString,
				Optional:         true,
				ForceNew:         true,
				Default:          string(containerregistry.Classic),
				DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
				ValidateFunc: validation.StringInSlice([]string{
					string(containerregistry.Classic),
					string(containerregistry.ManagedBasic),
					string(containerregistry.ManagedStandard),
					string(containerregistry.ManagedPremium),
				}, true),
			},

			"admin_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"storage_account_id": {
				Type:     schema.TypeString,
				Required: true,
			},

			"storage_account": {
				Type:       schema.TypeList,
				Optional:   true,
				Deprecated: "`storage_account` has been replaced by `storage_account_id`.",
				MaxItems:   1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},

						"access_key": {
							Type:      schema.TypeString,
							Required:  true,
							Sensitive: true,
						},
					},
				},
			},

			"login_server": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"admin_username": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"admin_password": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceArmContainerRegistryCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient
	log.Printf("[INFO] preparing arguments for AzureRM Container Registry creation.")

	resourceGroup := d.Get("resource_group_name").(string)
	name := d.Get("name").(string)
	location := d.Get("location").(string)
	sku := d.Get("sku").(string)
	storageAccountId := d.Get("storage_account_id").(string)
	adminUserEnabled := d.Get("admin_enabled").(bool)
	tags := d.Get("tags").(map[string]interface{})

	parameters := containerregistry.Registry{
		Location: &location,
		Sku: &containerregistry.Sku{
			Name: containerregistry.SkuName(sku),
			Tier: containerregistry.SkuTier(sku),
		},
		RegistryProperties: &containerregistry.RegistryProperties{
			AdminUserEnabled: utils.Bool(adminUserEnabled),
			StorageAccount: &containerregistry.StorageAccountProperties{
				ID: utils.String(storageAccountId),
			},
		},
		Tags: expandTags(tags),
	}

	_, createErr := client.Create(resourceGroup, name, parameters, make(<-chan struct{}))
	err := <-createErr
	if err != nil {
		return err
	}

	read, err := client.Get(resourceGroup, name)
	if err != nil {
		return err
	}

	if read.ID == nil {
		return fmt.Errorf("Cannot read Container Registry %s (resource group %s) ID", name, resourceGroup)
	}

	d.SetId(*read.ID)

	return resourceArmContainerRegistryRead(d, meta)
}

func resourceArmContainerRegistryUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient
	log.Printf("[INFO] preparing arguments for AzureRM Container Registry update.")

	resourceGroup := d.Get("resource_group_name").(string)
	name := d.Get("name").(string)

	storageAccountId := d.Get("storage_account_id").(string)
	adminUserEnabled := d.Get("admin_enabled").(bool)
	tags := d.Get("tags").(map[string]interface{})

	parameters := containerregistry.RegistryUpdateParameters{
		RegistryPropertiesUpdateParameters: &containerregistry.RegistryPropertiesUpdateParameters{
			AdminUserEnabled: utils.Bool(adminUserEnabled),
			StorageAccount: &containerregistry.StorageAccountProperties{
				ID: utils.String(storageAccountId),
			},
		},
		Tags: expandTags(tags),
	}

	_, updateErr := client.Update(resourceGroup, name, parameters, make(chan struct{}))
	err := <-updateErr
	if err != nil {
		return err
	}

	read, err := client.Get(resourceGroup, name)
	if err != nil {
		return err
	}

	if read.ID == nil {
		return fmt.Errorf("Cannot read Container Registry %q (resource group %q) ID", name, resourceGroup)
	}

	d.SetId(*read.ID)

	return resourceArmContainerRegistryRead(d, meta)
}

func resourceArmContainerRegistryRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resourceGroup := id.ResourceGroup
	name := id.Path["registries"]

	resp, err := client.Get(resourceGroup, name)
	if err != nil {
		if utils.ResponseWasNotFound(resp.Response) {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error making Read request on Azure Container Registry %q: %+v", name, err)
	}

	d.Set("name", resp.Name)
	d.Set("resource_group_name", resourceGroup)
	d.Set("location", azureRMNormalizeLocation(*resp.Location))
	d.Set("admin_enabled", resp.AdminUserEnabled)
	d.Set("login_server", resp.LoginServer)

	if sku := resp.Sku; sku != nil {
		d.Set("sku", string(sku.Tier))
	}

	if account := resp.StorageAccount; account != nil {
		d.Set("storage_account_id", account.ID)
	}

	if *resp.AdminUserEnabled {
		credsResp, err := client.ListCredentials(resourceGroup, name)
		if err != nil {
			return fmt.Errorf("Error making Read request on Azure Container Registry %s for Credentials: %s", name, err)
		}

		d.Set("admin_username", credsResp.Username)
		for _, v := range *credsResp.Passwords {
			d.Set("admin_password", v.Value)
			break
		}
	} else {
		d.Set("admin_username", "")
		d.Set("admin_password", "")
	}

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmContainerRegistryDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resourceGroup := id.ResourceGroup
	name := id.Path["registries"]

	deleteResp, deleteErr := client.Delete(resourceGroup, name, make(chan struct{}))
	resp := <-deleteResp
	err = <-deleteErr

	if err != nil {
		if utils.ResponseWasNotFound(resp) {
			return nil
		}

		return fmt.Errorf("Error issuing Azure ARM delete request of Container Registry '%s': %+v", name, err)
	}

	return nil
}

func validateAzureRMContainerRegistryName(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)
	if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(value) {
		errors = append(errors, fmt.Errorf(
			"alpha numeric characters only are allowed in %q: %q", k, value))
	}

	if 5 > len(value) {
		errors = append(errors, fmt.Errorf("%q cannot be less than 5 characters: %q", k, value))
	}

	if len(value) >= 50 {
		errors = append(errors, fmt.Errorf("%q cannot be longer than 50 characters: %q %d", k, value, len(value)))
	}

	return
}
<commit_msg>Updating to the new enum values<commit_after>package azurerm

import (
	"fmt"
	"log"
	"regexp"

	"github.com/Azure/azure-sdk-for-go/arm/containerregistry"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/helper/validation"
	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmContainerRegistry() *schema.Resource {
	return &schema.Resource{
		Create: resourceArmContainerRegistryCreate,
		Read:   resourceArmContainerRegistryRead,
		Update: resourceArmContainerRegistryUpdate,
		Delete: resourceArmContainerRegistryDelete,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		MigrateState:  resourceAzureRMContainerRegistryMigrateState,
		SchemaVersion: 2,

		Schema: map[string]*schema.Schema{
			"name": {
				Type:         schema.TypeString,
				Required:     true,
				ForceNew:     true,
				ValidateFunc: validateAzureRMContainerRegistryName,
			},

			"resource_group_name": resourceGroupNameSchema(),

			"location": locationSchema(),

			"sku": {
				Type:             schema.TypeString,
				Optional:         true,
				ForceNew:         true,
				Default:          string(containerregistry.Classic),
				DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
				ValidateFunc: validation.StringInSlice([]string{
					string(containerregistry.Classic),
					string(containerregistry.Basic),
					string(containerregistry.Standard),
					string(containerregistry.Premium),
				}, true),
			},

			"admin_enabled": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},

			"storage_account_id": {
				Type:     schema.TypeString,
				Required: true,
			},

			"storage_account": {
				Type:       schema.TypeList,
				Optional:   true,
				Deprecated: "`storage_account` has been replaced by `storage_account_id`.",
				MaxItems:   1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"name": {
							Type:     schema.TypeString,
							Required: true,
						},

						"access_key": {
							Type:      schema.TypeString,
							Required:  true,
							Sensitive: true,
						},
					},
				},
			},

			"login_server": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"admin_username": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"admin_password": {
				Type:     schema.TypeString,
				Computed: true,
			},

			"tags": tagsSchema(),
		},
	}
}

func resourceArmContainerRegistryCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient
	log.Printf("[INFO] preparing arguments for AzureRM Container Registry creation.")

	resourceGroup := d.Get("resource_group_name").(string)
	name := d.Get("name").(string)
	location := d.Get("location").(string)
	sku := d.Get("sku").(string)
	storageAccountId := d.Get("storage_account_id").(string)
	adminUserEnabled := d.Get("admin_enabled").(bool)
	tags := d.Get("tags").(map[string]interface{})

	parameters := containerregistry.Registry{
		Location: &location,
		Sku: &containerregistry.Sku{
			Name: containerregistry.SkuName(sku),
			Tier: containerregistry.SkuTier(sku),
		},
		RegistryProperties: &containerregistry.RegistryProperties{
			AdminUserEnabled: utils.Bool(adminUserEnabled),
			StorageAccount: &containerregistry.StorageAccountProperties{
				ID: utils.String(storageAccountId),
			},
		},
		Tags: expandTags(tags),
	}

	_, createErr := client.Create(resourceGroup, name, parameters, make(<-chan struct{}))
	err := <-createErr
	if err != nil {
		return err
	}

	read, err := client.Get(resourceGroup, name)
	if err != nil {
		return err
	}

	if read.ID == nil {
		return fmt.Errorf("Cannot read Container Registry %s (resource group %s) ID", name, resourceGroup)
	}

	d.SetId(*read.ID)

	return resourceArmContainerRegistryRead(d, meta)
}

func resourceArmContainerRegistryUpdate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient
	log.Printf("[INFO] preparing arguments for AzureRM Container Registry update.")

	resourceGroup := d.Get("resource_group_name").(string)
	name := d.Get("name").(string)

	storageAccountId := d.Get("storage_account_id").(string)
	adminUserEnabled := d.Get("admin_enabled").(bool)
	tags := d.Get("tags").(map[string]interface{})

	parameters := containerregistry.RegistryUpdateParameters{
		RegistryPropertiesUpdateParameters: &containerregistry.RegistryPropertiesUpdateParameters{
			AdminUserEnabled: utils.Bool(adminUserEnabled),
			StorageAccount: &containerregistry.StorageAccountProperties{
				ID: utils.String(storageAccountId),
			},
		},
		Tags: expandTags(tags),
	}

	_, updateErr := client.Update(resourceGroup, name, parameters, make(chan struct{}))
	err := <-updateErr
	if err != nil {
		return err
	}

	read, err := client.Get(resourceGroup, name)
	if err != nil {
		return err
	}

	if read.ID == nil {
		return fmt.Errorf("Cannot read Container Registry %q (resource group %q) ID", name, resourceGroup)
	}

	d.SetId(*read.ID)

	return resourceArmContainerRegistryRead(d, meta)
}

func resourceArmContainerRegistryRead(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resourceGroup := id.ResourceGroup
	name := id.Path["registries"]

	resp, err := client.Get(resourceGroup, name)
	if err != nil {
		if utils.ResponseWasNotFound(resp.Response) {
			d.SetId("")
			return nil
		}

		return fmt.Errorf("Error making Read request on Azure Container Registry %q: %+v", name, err)
	}

	d.Set("name", resp.Name)
	d.Set("resource_group_name", resourceGroup)
	d.Set("location", azureRMNormalizeLocation(*resp.Location))
	d.Set("admin_enabled", resp.AdminUserEnabled)
	d.Set("login_server", resp.LoginServer)

	if sku := resp.Sku; sku != nil {
		d.Set("sku", string(sku.Tier))
	}

	if account := resp.StorageAccount; account != nil {
		d.Set("storage_account_id", account.ID)
	}

	if *resp.AdminUserEnabled {
		credsResp, err := client.ListCredentials(resourceGroup, name)
		if err != nil {
			return fmt.Errorf("Error making Read request on Azure Container Registry %s for Credentials: %s", name, err)
		}

		d.Set("admin_username", credsResp.Username)
		for _, v := range *credsResp.Passwords {
			d.Set("admin_password", v.Value)
			break
		}
	} else {
		d.Set("admin_username", "")
		d.Set("admin_password", "")
	}

	flattenAndSetTags(d, resp.Tags)

	return nil
}

func resourceArmContainerRegistryDelete(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*ArmClient).containerRegistryClient

	id, err := parseAzureResourceID(d.Id())
	if err != nil {
		return err
	}
	resourceGroup := id.ResourceGroup
	name := id.Path["registries"]

	deleteResp, deleteErr := client.Delete(resourceGroup, name, make(chan struct{}))
	resp := <-deleteResp
	err = <-deleteErr

	if err != nil {
		if utils.ResponseWasNotFound(resp) {
			return nil
		}

		return fmt.Errorf("Error issuing Azure ARM delete request of Container Registry '%s': %+v", name, err)
	}

	return nil
}

func validateAzureRMContainerRegistryName(v interface{}, k string) (ws []string, errors []error) {
	value := v.(string)
	if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(value) {
		errors = append(errors, fmt.Errorf(
			"alpha numeric characters only are allowed in %q: %q", k, value))
	}

	if 5 > len(value) {
		errors = append(errors, fmt.Errorf("%q cannot be less than 5 characters: %q", k, value))
	}

	if len(value) >= 50 {
		errors = append(errors, fmt.Errorf("%q cannot be longer than 50 characters: %q %d", k, value, len(value)))
	}

	return
}
<|endoftext|>


<commit_before>package moderatorController

import (
	"fmt"
	"html"
	"net/http"
	"strconv"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/activities"
	"github.com/NyaaPantsu/nyaa/models/reports"
	"github.com/NyaaPantsu/nyaa/models/torrents"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/log"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/search"
	"github.com/NyaaPantsu/nyaa/utils/upload"
	"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
	"github.com/gin-gonic/gin"
)

// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
func TorrentsListPanel(c *gin.Context) {
	page := c.Param("page")
	messages := msg.GetMessages(c)
	deleted := c.Request.URL.Query()["deleted"]
	unblocked := c.Request.URL.Query()["unblocked"]
	blocked := c.Request.URL.Query()["blocked"]
	if deleted != nil {
		messages.AddInfoTf("infos", "torrent_deleted", "")
	}
	if blocked != nil {
		messages.AddInfoT("infos", "torrent_blocked")
	}
	if unblocked != nil {
		messages.AddInfoT("infos", "torrent_unblocked")
	}

	var err error
	pagenum := 1
	if page != "" {
		pagenum, err = strconv.Atoi(html.EscapeString(page))
		if !log.CheckError(err) {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}
	}

	searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
	if err != nil {
		messages.Error(err)
	}
	category := ""
	if len(searchParam.Category) > 0 {
		category = searchParam.Category[0].String()
	}
	searchForm := templates.SearchForm{
		TorrentParam:     searchParam,
		Category:         category,
		ShowItemsPerPage: true,
	}

	nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}

	templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
}

// TorrentEditModPanel : Controller for editing a torrent after GET request
func TorrentEditModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()

	torrentJSON := torrent.ToJSON()
	uploadForm := upload.NewTorrentRequest()
	uploadForm.ID = torrentJSON.ID
	uploadForm.Name = torrentJSON.Name
	uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
	uploadForm.Status = torrentJSON.Status
	uploadForm.Hidden = torrent.Hidden
	uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
	uploadForm.Description = string(torrentJSON.Description)
	uploadForm.Languages = torrent.Languages
	uploadForm.Tags.Bind(&torrent)

	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
}

// TorrentPostEditModPanel : Controller for editing a torrent after POST request
func TorrentPostEditModPanel(c *gin.Context) {
	var uploadForm torrentValidator.UpdateRequest
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	messages := msg.GetMessages(c)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()
	currentUser := router.GetUser(c)
	if torrent.ID > 0 {
		errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
		uploadForm.ID = torrent.ID
		uploadForm.Update.ID = torrent.ID

		if errUp != nil {
			messages.AddErrorT("errors", "fail_torrent_update")
		}
		if !messages.HasErrors() {
			_, err := upload.UpdateUnscopeTorrent(&uploadForm, &torrent, currentUser).UpdateUnscope()
			messages.AddInfoT("infos", "torrent_updated")
			if err == nil { // We only log edit torrent for admins
				if torrent.Uploader == nil {
					torrent.Uploader = &models.User{}
				}
				_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
				activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
			}
		}
	}
	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm.Update)
}

// TorrentDeleteModPanel : Controller for deleting a torrent
func TorrentDeleteModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
	definitely := c.Request.URL.Query()["definitely"]

	var returnRoute = "/mod/torrents"
	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		var err error
		if definitely != nil {
			_, _, err = torrent.DefinitelyDelete()
			returnRoute = "/mod/torrents/deleted"
		} else {
			_, _, err = torrent.Delete(false)
		}

		//delete reports of torrent
		query := &search.Query{}
		query.Append("torrent_id", id)
		reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
		for _, report := range reports {
			report.Delete()
		}

		if err == nil {
			if torrent.Uploader == nil {
				torrent.Uploader = &models.User{}
			}
			_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
			activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
		}
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
}

// DeleteTagsModPanel : Controller for deleting all torrent tags
func DeleteTagsModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)

	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		// delete all tags
		torrent.DeleteTags()
	}
	// redirect to edit form
	c.Redirect(http.StatusSeeOther, fmt.Sprintf("/mod/torrent?id=%d", id))
}

// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
func TorrentBlockModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _, err := torrents.ToggleBlock(uint(id))
	var returnRoute, action string
	if torrent.IsDeleted() {
		returnRoute = "/mod/torrents/deleted"
	} else {
		returnRoute = "/mod/torrents"
	}
	if torrent.IsBlocked() {
		action = "blocked"
	} else {
		action = "unblocked"
	}
	if err == nil {
		if torrent.Uploader == nil {
			torrent.Uploader = &models.User{}
		}
		_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
		activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
}

// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
func TorrentsPostListPanel(c *gin.Context) {
	torrentManyAction(c)
	TorrentsListPanel(c)
}
<commit_msg>Update torrents.go<commit_after>package moderatorController

import (
	"fmt"
	"html"
	"net/http"
	"strconv"

	"github.com/NyaaPantsu/nyaa/controllers/router"
	"github.com/NyaaPantsu/nyaa/models"
	"github.com/NyaaPantsu/nyaa/models/activities"
	"github.com/NyaaPantsu/nyaa/models/reports"
	"github.com/NyaaPantsu/nyaa/models/torrents"
	"github.com/NyaaPantsu/nyaa/templates"
	"github.com/NyaaPantsu/nyaa/utils/log"
	msg "github.com/NyaaPantsu/nyaa/utils/messages"
	"github.com/NyaaPantsu/nyaa/utils/search"
	"github.com/NyaaPantsu/nyaa/utils/upload"
	"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
	"github.com/gin-gonic/gin"
)

// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
func TorrentsListPanel(c *gin.Context) {
	page := c.Param("page")
	messages := msg.GetMessages(c)
	deleted := c.Request.URL.Query()["deleted"]
	unblocked := c.Request.URL.Query()["unblocked"]
	blocked := c.Request.URL.Query()["blocked"]
	if deleted != nil {
		messages.AddInfoTf("infos", "torrent_deleted", "")
	}
	if blocked != nil {
		messages.AddInfoT("infos", "torrent_blocked")
	}
	if unblocked != nil {
		messages.AddInfoT("infos", "torrent_unblocked")
	}

	var err error
	pagenum := 1
	if page != "" {
		pagenum, err = strconv.Atoi(html.EscapeString(page))
		if !log.CheckError(err) {
			c.AbortWithError(http.StatusInternalServerError, err)
			return
		}
	}

	searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
	if err != nil {
		messages.Error(err)
	}
	category := ""
	if len(searchParam.Category) > 0 {
		category = searchParam.Category[0].String()
	}
	searchForm := templates.SearchForm{
		TorrentParam:     searchParam,
		Category:         category,
		ShowItemsPerPage: true,
	}

	nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}

	templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
}

// TorrentEditModPanel : Controller for editing a torrent after GET request
func TorrentEditModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()

	torrentJSON := torrent.ToJSON()
	uploadForm := upload.NewTorrentRequest()
	uploadForm.ID = torrentJSON.ID
	uploadForm.Name = torrentJSON.Name
	uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
	uploadForm.Status = torrentJSON.Status
	uploadForm.Hidden = torrent.Hidden
	uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
	uploadForm.Description = string(torrentJSON.Description)
	uploadForm.Languages = torrent.Languages
	uploadForm.Tags.Bind(&torrent)

	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
}

// TorrentPostEditModPanel : Controller for editing a torrent after POST request
func TorrentPostEditModPanel(c *gin.Context) {
	var uploadForm torrentValidator.UpdateRequest
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
	messages := msg.GetMessages(c)
	torrent, _ := torrents.FindUnscopeByID(uint(id))
	torrent.LoadTags()
	currentUser := router.GetUser(c)
	if torrent.ID > 0 {
		errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
		uploadForm.ID = torrent.ID
		uploadForm.Update.ID = torrent.ID

		if errUp != nil {
			messages.AddErrorT("errors", "fail_torrent_update")
		}
		if !messages.HasErrors() {
			_, err := upload.UpdateUnscopeTorrent(&uploadForm, &torrent, currentUser).UpdateUnscope()
			messages.AddInfoT("infos", "torrent_updated")
			if err == nil { // We only log edit torrent for admins
				if torrent.Uploader == nil {
					torrent.Uploader = &models.User{}
				}
				_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
				activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
			}
		}
	}
	templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm.Update)
}

// TorrentDeleteModPanel : Controller for deleting a torrent
func TorrentDeleteModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
	definitely := c.Request.URL.Query()["definitely"]

	var returnRoute = "/mod/torrents"
	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		var err error
		if definitely != nil {
			_, _, err = torrent.DefinitelyDelete()
			returnRoute = "/mod/torrents/deleted"
		} else {
			_, _, err = torrent.Delete(false)
		}

		//delete reports of torrent
		query := &search.Query{}
		query.Append("torrent_id", id)
		reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
		for _, report := range reports {
			report.Delete()
		}

		if err == nil {
			if torrent.Uploader == nil {
				torrent.Uploader = &models.User{}
			}
			_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
			activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
		}
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
}

// DeleteTagsModPanel : Controller for deleting all torrent tags
func DeleteTagsModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.Query("id"), 10, 32)

	torrent, errFind := torrents.FindByID(uint(id))
	if errFind == nil {
		// delete all tags
		torrent.DeleteTags()
	}
	// redirect to edit form
	c.Redirect(http.StatusSeeOther, fmt.Sprintf("/mod/torrent?id=%d", id))
}

// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
func TorrentBlockModPanel(c *gin.Context) {
	id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
	torrent, _, err := torrents.ToggleBlock(uint(id))
	var returnRoute, action string
	if torrent.IsDeleted() {
		returnRoute = "/mod/torrents/deleted"
	} else {
		returnRoute = "/mod/torrents"
	}
	if torrent.IsBlocked() {
		action = "blocked"
	} else {
		action = "unblocked"
	}
	if err == nil {
		if torrent.Uploader == nil {
			torrent.Uploader = &models.User{}
		}
		_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
		activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
	}

	c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
}

// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
func TorrentsPostListPanel(c *gin.Context) {
	torrentManyAction(c)
	TorrentsListPanel(c)
}
<|endoftext|>


<commit_before><commit_msg>Fix help text for note commands<commit_after><|endoftext|>


<commit_before>package main

import (
	"regexp"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	return KEYS_LIST.FindAllString(list, -1)
}
<commit_msg>Unescape escaped comma<commit_after>package main

import (
	"regexp"
	"strings"
)

var KEYS_LIST = regexp.MustCompile(`(?:[^,\\]|\\.)*`)

func ParseKeysList(list string) []string {
	keys := KEYS_LIST.FindAllString(list, -1)
	for i := 0; i < len(keys); i++ {
		keys[i] = strings.Replace(keys[i], `\,`, `,`, -1)
	}
	return keys
}
<|endoftext|>


<commit_before><commit_msg>Remove hard to disambiguate characters from random string<commit_after><|endoftext|>


<commit_before>package versions

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/node"
	"github.com/MG-RAST/golib/mgo"
	"github.com/MG-RAST/golib/mgo/bson"
	"io/ioutil"
	"os"
	"strconv"
	"time"
)

type Version struct {
	Name    string `bson:"name" json:"name"`
	Version int    `bson:"version" json:"version"`
}

type Versions []Version

var VersionMap = make(map[string]int)

func Initialize() (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	c.EnsureIndex(mgo.Index{Key: []string{"name"}, Unique: true})
	var versions = new(Versions)
	err = c.Find(bson.M{}).All(versions)
	for _, v := range *versions {
		VersionMap[v.Name] = v.Version
	}
	return
}

func Print() (err error) {
	fmt.Printf("##### Versions ####\n")
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	var versions = new(Versions)
	if err = c.Find(bson.M{}).All(versions); err != nil {
		return err
	}
	for _, v := range *versions {
		fmt.Printf("name: %v\tversion number: %v\n", v.Name, v.Version)
	}
	fmt.Println("")
	return
}

func PushVersionsToDatabase() (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	for k, v := range conf.VERSIONS {
		if _, err = c.Upsert(bson.M{"name": k}, bson.M{"$set": bson.M{"name": k, "version": v}}); err != nil {
			return err
		}
	}
	return
}

func RunVersionUpdates() (err error) {
	// get ACL versions
	confVersionACL, ok1 := conf.VERSIONS["ACL"]
	dbVersionACL, ok2 := VersionMap["ACL"]

	// Upgrading databases with ACL schema before version 2
	if (ok1 && confVersionACL >= 2) && (!ok2 || (ok2 && dbVersionACL < 2)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The ACL schema version in your database needs updating to version 2.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			// Checking database to see if "public" already exists in a Node's ACL's somewhere.
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			nCount, err := c.Find(bson.M{}).Count()
			if err != nil {
				return err
			}
			oCount, err := c.Find(bson.M{"acl.owner": "public"}).Count()
			if err != nil {
				return err
			}
			rCount, err := c.Find(bson.M{"acl.read": "public"}).Count()
			if err != nil {
				return err
			}
			wCount, err := c.Find(bson.M{"acl.write": "public"}).Count()
			if err != nil {
				return err
			}
			dCount, err := c.Find(bson.M{"acl.delete": "public"}).Count()
			if err != nil {
				return err
			}
			if oCount > 0 || rCount > 0 || wCount > 0 || dCount > 0 {
				fmt.Println("There are \"public\" strings already present in some of your Node ACL's:")
				fmt.Println("Total number of nodes: " + strconv.Itoa(nCount))
				fmt.Println("Number of nodes with \"public\" in owner ACL: " + strconv.Itoa(oCount))
				fmt.Println("Number of nodes with \"public\" in read ACL: " + strconv.Itoa(rCount))
				fmt.Println("Number of nodes with \"public\" in write ACL: " + strconv.Itoa(wCount))
				fmt.Println("Number of nodes with \"public\" in delete ACL: " + strconv.Itoa(dCount))
				fmt.Print("Your database may be in a mixed state, would you like to run the update anyway? (y/n): ")
				text, _ = consoleReader.ReadString('\n')
			}
			if text[0] == 'y' {
				fmt.Println("Updating ACL's to version 2")
				if _, err = c.UpdateAll(bson.M{"acl.owner": ""}, bson.M{"$set": bson.M{"acl.owner": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.read": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.read": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.write": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.write": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.delete": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.delete": "public"}}); err != nil {
					return err
				}
				session := db.Connection.Session.Copy()
				defer session.Close()
				c := session.DB(conf.MONGODB_DATABASE).C("Versions")
				if _, err = c.Upsert(bson.M{"name": "ACL"}, bson.M{"$set": bson.M{"name": "ACL", "version": 2}}); err != nil {
					return err
				}
				fmt.Println("ACL schema version 2 update complete.")
			} else {
				os.Exit(0)
			}
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// get Node versions
	confVersionNode, ok1 := conf.VERSIONS["Node"]
	dbVersionNode, ok2 := VersionMap["Node"]

	// Updating databases with Node schema before version 2
	// removing 'public' field
	if (ok1 && confVersionNode >= 2) && (!ok2 || (ok2 && dbVersionNode < 2)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 2.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			fmt.Println("Updating Nodes to version 2")
			if _, err = c.UpdateAll(bson.M{}, bson.M{"$unset": bson.M{"public": 1}}); err != nil {
				return err
			}
			fmt.Println("Node schema version 2 update complete.")
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// Updating databases with Node schema before version 3
	// move parts info from file in node dir to part of node document
	if (ok1 && confVersionNode >= 3) && (!ok2 || (ok2 && dbVersionNode < 3)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 3.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			// get node iter
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			n := node.Node{}
			iter := c.Find(bson.M{"type": "parts"}).Iter()
			defer iter.Close()
			for iter.Next(n) {
				pfile, perr := ioutil.ReadFile(n.Path() + "/parts/parts.json")
				// have file and no parts in node document - fix it
				if (perr == nil) && (n.Parts == nil) {
					fmt.Println("Updating parts node: " + n.Id)
					pl := &node.PartsList{}
					if err = json.Unmarshal(pfile, &pl); err != nil {
						return err
					}
					if err = os.RemoveAll(n.Path() + "/parts/parts.json"); err != nil {
						return err
					}
					n.Parts = pl
					n.Save()
				}
			}
			fmt.Println("Node schema version 3 update complete.")
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// Updating databases with Node schema before version 4
	// add timestamp for file info and each index info
	if (ok1 && confVersionNode >= 4) && (!ok2 || (ok2 && dbVersionNode < 4)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 4.  Would you like the update to run? (y/n): ")
		utext, _ := consoleReader.ReadString('\n')
		if utext[0] == 'y' {
			fmt.Print("Would you like to update node file info with timestamp from disk (otherwise current time is used)? (y/n): ")
			ftext, _ := consoleReader.ReadString('\n')
			// get node iter
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			n := node.Node{}
			iter := c.Find(bson.M{"file.checksum.md5": bson.M{"$ne": ""}}).Iter()
			defer iter.Close()
			for iter.Next(n) {
				if ftext[0] == 'y' {
					// update file info from disk
					if fileStat, ferr := os.Stat(n.FilePath()); ferr == nil {
						n.File.CreatedOn = fileStat.ModTime()
					} else {
						n.File.CreatedOn = time.Now()
					}
				} else {
					// update file info with current
					n.File.CreatedOn = time.Now()
				}
				// update index time
				for idxtype, idxinfo := range n.Indexes {
					idxinfo.CreatedOn = time.Now()
					n.Indexes[idxtype] = idxinfo
				}
				n.Save()
			}
			fmt.Println("Node schema version 4 update complete.")
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	return
}
<commit_msg>updated update message<commit_after>package versions

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/MG-RAST/Shock/shock-server/conf"
	"github.com/MG-RAST/Shock/shock-server/db"
	"github.com/MG-RAST/Shock/shock-server/node"
	"github.com/MG-RAST/golib/mgo"
	"github.com/MG-RAST/golib/mgo/bson"
	"io/ioutil"
	"os"
	"strconv"
	"time"
)

type Version struct {
	Name    string `bson:"name" json:"name"`
	Version int    `bson:"version" json:"version"`
}

type Versions []Version

var VersionMap = make(map[string]int)

func Initialize() (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	c.EnsureIndex(mgo.Index{Key: []string{"name"}, Unique: true})
	var versions = new(Versions)
	err = c.Find(bson.M{}).All(versions)
	for _, v := range *versions {
		VersionMap[v.Name] = v.Version
	}
	return
}

func Print() (err error) {
	fmt.Printf("##### Versions ####\n")
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	var versions = new(Versions)
	if err = c.Find(bson.M{}).All(versions); err != nil {
		return err
	}
	for _, v := range *versions {
		fmt.Printf("name: %v\tversion number: %v\n", v.Name, v.Version)
	}
	fmt.Println("")
	return
}

func PushVersionsToDatabase() (err error) {
	session := db.Connection.Session.Copy()
	defer session.Close()
	c := session.DB(conf.MONGODB_DATABASE).C("Versions")
	for k, v := range conf.VERSIONS {
		if _, err = c.Upsert(bson.M{"name": k}, bson.M{"$set": bson.M{"name": k, "version": v}}); err != nil {
			return err
		}
	}
	return
}

func RunVersionUpdates() (err error) {
	// get ACL versions
	confVersionACL, ok1 := conf.VERSIONS["ACL"]
	dbVersionACL, ok2 := VersionMap["ACL"]

	// Upgrading databases with ACL schema before version 2
	if (ok1 && confVersionACL >= 2) && (!ok2 || (ok2 && dbVersionACL < 2)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The ACL schema version in your database needs updating to version 2.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			// Checking database to see if "public" already exists in a Node's ACL's somewhere.
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			nCount, err := c.Find(bson.M{}).Count()
			if err != nil {
				return err
			}
			oCount, err := c.Find(bson.M{"acl.owner": "public"}).Count()
			if err != nil {
				return err
			}
			rCount, err := c.Find(bson.M{"acl.read": "public"}).Count()
			if err != nil {
				return err
			}
			wCount, err := c.Find(bson.M{"acl.write": "public"}).Count()
			if err != nil {
				return err
			}
			dCount, err := c.Find(bson.M{"acl.delete": "public"}).Count()
			if err != nil {
				return err
			}
			if oCount > 0 || rCount > 0 || wCount > 0 || dCount > 0 {
				fmt.Println("There are \"public\" strings already present in some of your Node ACL's:")
				fmt.Println("Total number of nodes: " + strconv.Itoa(nCount))
				fmt.Println("Number of nodes with \"public\" in owner ACL: " + strconv.Itoa(oCount))
				fmt.Println("Number of nodes with \"public\" in read ACL: " + strconv.Itoa(rCount))
				fmt.Println("Number of nodes with \"public\" in write ACL: " + strconv.Itoa(wCount))
				fmt.Println("Number of nodes with \"public\" in delete ACL: " + strconv.Itoa(dCount))
				fmt.Print("Your database may be in a mixed state, would you like to run the update anyway? (y/n): ")
				text, _ = consoleReader.ReadString('\n')
			}
			if text[0] == 'y' {
				fmt.Println("Updating ACL's to version 2")
				if _, err = c.UpdateAll(bson.M{"acl.owner": ""}, bson.M{"$set": bson.M{"acl.owner": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.read": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.read": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.write": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.write": "public"}}); err != nil {
					return err
				}
				if _, err = c.UpdateAll(bson.M{"acl.delete": bson.M{"$size": 0}}, bson.M{"$push": bson.M{"acl.delete": "public"}}); err != nil {
					return err
				}
				session := db.Connection.Session.Copy()
				defer session.Close()
				c := session.DB(conf.MONGODB_DATABASE).C("Versions")
				if _, err = c.Upsert(bson.M{"name": "ACL"}, bson.M{"$set": bson.M{"name": "ACL", "version": 2}}); err != nil {
					return err
				}
				fmt.Println("ACL schema version 2 update complete.")
			} else {
				os.Exit(0)
			}
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// get Node versions
	confVersionNode, ok1 := conf.VERSIONS["Node"]
	dbVersionNode, ok2 := VersionMap["Node"]

	// Updating databases with Node schema before version 2
	// removing 'public' field
	if (ok1 && confVersionNode >= 2) && (!ok2 || (ok2 && dbVersionNode < 2)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 2.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			fmt.Println("Updating Nodes to version 2")
			if _, err = c.UpdateAll(bson.M{}, bson.M{"$unset": bson.M{"public": 1}}); err != nil {
				return err
			}
			fmt.Println("Node schema version 2 update complete.")
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// Updating databases with Node schema before version 3
	// move parts info from file in node dir to part of node document
	if (ok1 && confVersionNode >= 3) && (!ok2 || (ok2 && dbVersionNode < 3)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 3.  Would you like the update to run? (y/n): ")
		text, _ := consoleReader.ReadString('\n')
		if text[0] == 'y' {
			// get node iter
			updated := 0
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			n := node.Node{}
			iter := c.Find(bson.M{"type": "parts"}).Iter()
			defer iter.Close()
			for iter.Next(n) {
				pfile, perr := ioutil.ReadFile(n.Path() + "/parts/parts.json")
				// have file and no parts in node document - fix it
				if (perr == nil) && (n.Parts == nil) {
					fmt.Println("Updating parts node: " + n.Id)
					pl := &node.PartsList{}
					if err = json.Unmarshal(pfile, &pl); err != nil {
						return err
					}
					if err = os.RemoveAll(n.Path() + "/parts/parts.json"); err != nil {
						return err
					}
					n.Parts = pl
					n.Save()
					updated += 1
				}
			}
			fmt.Println(fmt.Sprintf("Node schema version 3 update complete, updated %d nodes.", updated))
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	// Updating databases with Node schema before version 4
	// add timestamp for file info and each index info
	if (ok1 && confVersionNode >= 4) && (!ok2 || (ok2 && dbVersionNode < 4)) {
		consoleReader := bufio.NewReader(os.Stdin)
		fmt.Print("The Node schema version in your database needs updating to version 4.  Would you like the update to run? (y/n): ")
		utext, _ := consoleReader.ReadString('\n')
		if utext[0] == 'y' {
			fmt.Print("Would you like to update node file info with timestamp from disk (otherwise current time is used)? (y/n): ")
			ftext, _ := consoleReader.ReadString('\n')
			// get node iter
			updated := 0
			session := db.Connection.Session.Copy()
			defer session.Close()
			c := session.DB(conf.MONGODB_DATABASE).C("Nodes")
			n := node.Node{}
			iter := c.Find(bson.M{"file.checksum.md5": bson.M{"$ne": ""}}).Iter()
			defer iter.Close()
			for iter.Next(n) {
				if ftext[0] == 'y' {
					// update file info from disk
					if fileStat, ferr := os.Stat(n.FilePath()); ferr == nil {
						n.File.CreatedOn = fileStat.ModTime()
					} else {
						n.File.CreatedOn = time.Now()
					}
				} else {
					// update file info with current
					n.File.CreatedOn = time.Now()
				}
				// update index time
				for idxtype, idxinfo := range n.Indexes {
					idxinfo.CreatedOn = time.Now()
					n.Indexes[idxtype] = idxinfo
				}
				n.Save()
				updated += 1
			}
			fmt.Println(fmt.Sprintf("Node schema version 4 update complete, updated %d nodes.", updated))
		} else {
			fmt.Println("Exiting.")
			os.Exit(0)
		}
	}

	return
}
<|endoftext|>