<commit_before>package main

import (
	"bytes"
	"log"
	"regexp"

	"github.com/jangler/edit"
	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_ttf"
)

var (
	spaceRegexp = regexp.MustCompile(`\s`) // matches whitespace characters
	wordRegexp  = regexp.MustCompile(`\w`) // matches word characters
)

// focusedPane returns the focused pane index out of a slice of panes.
func focusedPane(panes []Pane) int {
	for i, pane := range panes {
		if pane.Focused {
			return i
		}
	}
	log.Fatal("No focused pane")
	return 0 // unreachable
}

// change pane focus based on mouse position
func refocus(panes []Pane, win *sdl.Window, font *ttf.Font, x, y int) {
	_, height := win.GetSize()
	ps := paneSpace(height, len(panes), font)
	i := y / ps
	if i < len(panes) {
		for j := range panes {
			panes[j].Focused = false
		}
		panes[i].Focused = true
	}
}

// singleClick processes a single left mouse click at the given coordinates.
func singleClick(panes []Pane, win *sdl.Window, font *ttf.Font, x, y int) {
	_, height := win.GetSize()
	ps := paneSpace(height, len(panes), font)
	i := y / ps                        // clicked pane index
	y = y%ps - font.Height() - padPx*3 // subtract pane header
	x -= padPx - fontWidth/2
	y /= font.Height()
	x /= fontWidth
	if i < len(panes) {
		panes[i].Mark(panes[i].IndexFromCoords(x, y), insertMark)
	}
}

// textInput inserts text into the focus, or performs another action depending
// on the contents of the string.
func textInput(buf *edit.Buffer, s string) {
	index, _ := buf.IndexFromMark(insertMark)
	buf.Insert(index, s)
}

// resize resizes the panes in the display and requests a render.
func resize(panes []Pane, font *ttf.Font, width, height int) {
	cols, rows := bufSize(width, height, len(panes), font)
	for i := range panes {
		panes[i].Cols, panes[i].Rows = cols, rows
		panes[i].SetSize(cols, rows)
	}
	render <- 1
}

// ShiftIndexByWord returns the given index shifted forward by n words. A
// negative value for n will shift backwards.
func (p *Pane) ShiftIndexByWord(index edit.Index, n int) edit.Index {
	for n > 0 {
		// TODO
		n--
	}
	for n < 0 {
		if index.Char == 0 {
			index = p.ShiftIndex(index, -1)
		} else {
			text := []rune(p.Get(edit.Index{index.Line, 0}, index))
			i := len(text) - 1
			for i >= 0 && spaceRegexp.MatchString(string(text[i])) {
				i--
			}
			if i >= 0 && wordRegexp.MatchString(string(text[i])) {
				for i >= 0 && wordRegexp.MatchString(string(text[i])) {
					i--
				}
			} else {
				for i >= 0 && !wordRegexp.MatchString(string(text[i])) &&
					!spaceRegexp.MatchString(string(text[i])) {
					i--
				}
			}
			index.Char = i + 1
		}
		n++
	}
	return index
}

// eventLoop handles SDL events until quit is requested.
func eventLoop(panes []Pane, font *ttf.Font, win *sdl.Window) {
	pane := panes[focusedPane(panes)]
	for {
		switch event := sdl.WaitEvent().(type) {
		case *sdl.KeyDownEvent:
			switch event.Keysym.Sym {
			case sdl.K_BACKSPACE:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Delete(pane.ShiftIndex(index, -1), index)
			case sdl.K_DELETE:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Delete(index, pane.ShiftIndex(index, 1))
			case sdl.K_DOWN:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row+1), insertMark)
			case sdl.K_END:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(edit.Index{index.Line, 0xffff}, insertMark)
			case sdl.K_LEFT:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(pane.ShiftIndex(index, -1), insertMark)
			case sdl.K_HOME:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(edit.Index{index.Line, 0}, insertMark)
			case sdl.K_PAGEDOWN:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row+pane.Rows), insertMark)
			case sdl.K_PAGEUP:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row-pane.Rows), insertMark)
			case sdl.K_RETURN:
				textInput(pane.Buffer, "\n")
			case sdl.K_RIGHT:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(pane.ShiftIndex(index, 1), insertMark)
			case sdl.K_TAB:
				textInput(pane.Buffer, "\t")
			case sdl.K_UP:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row-1), insertMark)
			case sdl.K_a:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Mark(edit.Index{index.Line, 0}, insertMark)
				}
			case sdl.K_e:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Mark(edit.Index{index.Line, 0xffff}, insertMark)
				}
			case sdl.K_h:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Delete(pane.ShiftIndex(index, -1), index)
				}
			case sdl.K_q:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					return
				}
			case sdl.K_u:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Delete(edit.Index{index.Line, 0}, index)
				}
			case sdl.K_w:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					end, _ := pane.IndexFromMark(insertMark)
					begin := pane.ShiftIndexByWord(end, -1)
					pane.Delete(begin, end)
				}
			}
			pane.See(insertMark)
			render <- 1
		case *sdl.MouseButtonEvent:
			if event.Type == sdl.MOUSEBUTTONDOWN &&
				event.Button == sdl.BUTTON_LEFT {
				singleClick(panes, win, font, int(event.X), int(event.Y))
				pane = panes[focusedPane(panes)]
				paneSet <- panes
			}
		case *sdl.MouseMotionEvent:
			refocus(panes, win, font, int(event.X), int(event.Y))
			pane = panes[focusedPane(panes)]
			paneSet <- panes
		case *sdl.MouseWheelEvent:
			pane.Scroll(int(event.Y) * -3)
			render <- 1
		case *sdl.QuitEvent:
			return
		case *sdl.TextInputEvent:
			if n := bytes.Index(event.Text[:], []byte{0}); n > 0 {
				textInput(pane.Buffer, string(event.Text[:n]))
				render <- 1
			}
		case *sdl.WindowEvent:
			switch event.Event {
			case sdl.WINDOWEVENT_EXPOSED:
				win.UpdateSurface()
			case sdl.WINDOWEVENT_RESIZED:
				resize(panes, font, int(event.Data1), int(event.Data2))
			}
		}
	}
}
<commit_msg>Implement autoindent<commit_after>package main

import (
	"bytes"
	"log"
	"regexp"

	"github.com/jangler/edit"
	"github.com/veandco/go-sdl2/sdl"
	"github.com/veandco/go-sdl2/sdl_ttf"
)

var (
	spaceRegexp = regexp.MustCompile(`\s`) // matches whitespace characters
	wordRegexp  = regexp.MustCompile(`\w`) // matches word characters
)

// focusedPane returns the focused pane index out of a slice of panes.
func focusedPane(panes []Pane) int {
	for i, pane := range panes {
		if pane.Focused {
			return i
		}
	}
	log.Fatal("No focused pane")
	return 0 // unreachable
}

// change pane focus based on mouse position
func refocus(panes []Pane, win *sdl.Window, font *ttf.Font, x, y int) {
	_, height := win.GetSize()
	ps := paneSpace(height, len(panes), font)
	i := y / ps
	if i < len(panes) {
		for j := range panes {
			panes[j].Focused = false
		}
		panes[i].Focused = true
	}
}

// singleClick processes a single left mouse click at the given coordinates.
func singleClick(panes []Pane, win *sdl.Window, font *ttf.Font, x, y int) {
	_, height := win.GetSize()
	ps := paneSpace(height, len(panes), font)
	i := y / ps                        // clicked pane index
	y = y%ps - font.Height() - padPx*3 // subtract pane header
	x -= padPx - fontWidth/2
	y /= font.Height()
	x /= fontWidth
	if i < len(panes) {
		panes[i].Mark(panes[i].IndexFromCoords(x, y), insertMark)
	}
}

// textInput inserts text into the focus, or performs another action depending
// on the contents of the string.
func textInput(buf *edit.Buffer, s string) {
	index, _ := buf.IndexFromMark(insertMark)
	if s == "\n" {
		// autoindent
		indent := buf.Get(edit.Index{index.Line, 0},
			edit.Index{index.Line, 0xffff})
		i := 0
		for i < len(indent) && (indent[i] == ' ' || indent[i] == '\t') {
			i++
		}
		if i <= index.Char {
			s += indent[:i]

			// delete lines containing only whitespace
			if i == len(indent) {
				buf.Delete(edit.Index{index.Line, 0}, index)
				index.Char = 0
			}
		}
	}
	buf.Insert(index, s)
}

// resize resizes the panes in the display and requests a render.
func resize(panes []Pane, font *ttf.Font, width, height int) {
	cols, rows := bufSize(width, height, len(panes), font)
	for i := range panes {
		panes[i].Cols, panes[i].Rows = cols, rows
		panes[i].SetSize(cols, rows)
	}
	render <- 1
}

// ShiftIndexByWord returns the given index shifted forward by n words. A
// negative value for n will shift backwards.
func (p *Pane) ShiftIndexByWord(index edit.Index, n int) edit.Index {
	for n > 0 {
		// TODO
		n--
	}
	for n < 0 {
		if index.Char == 0 {
			index = p.ShiftIndex(index, -1)
		} else {
			text := []rune(p.Get(edit.Index{index.Line, 0}, index))
			i := len(text) - 1
			for i >= 0 && spaceRegexp.MatchString(string(text[i])) {
				i--
			}
			if i >= 0 && wordRegexp.MatchString(string(text[i])) {
				for i >= 0 && wordRegexp.MatchString(string(text[i])) {
					i--
				}
			} else {
				for i >= 0 && !wordRegexp.MatchString(string(text[i])) &&
					!spaceRegexp.MatchString(string(text[i])) {
					i--
				}
			}
			index.Char = i + 1
		}
		n++
	}
	return index
}

// eventLoop handles SDL events until quit is requested.
func eventLoop(panes []Pane, font *ttf.Font, win *sdl.Window) {
	pane := panes[focusedPane(panes)]
	for {
		switch event := sdl.WaitEvent().(type) {
		case *sdl.KeyDownEvent:
			switch event.Keysym.Sym {
			case sdl.K_BACKSPACE:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Delete(pane.ShiftIndex(index, -1), index)
			case sdl.K_DELETE:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Delete(index, pane.ShiftIndex(index, 1))
			case sdl.K_DOWN:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row+1), insertMark)
			case sdl.K_END:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(edit.Index{index.Line, 0xffff}, insertMark)
			case sdl.K_LEFT:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(pane.ShiftIndex(index, -1), insertMark)
			case sdl.K_HOME:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(edit.Index{index.Line, 0}, insertMark)
			case sdl.K_PAGEDOWN:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row+pane.Rows), insertMark)
			case sdl.K_PAGEUP:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row-pane.Rows), insertMark)
			case sdl.K_RETURN:
				textInput(pane.Buffer, "\n")
			case sdl.K_RIGHT:
				index, _ := pane.IndexFromMark(insertMark)
				pane.Mark(pane.ShiftIndex(index, 1), insertMark)
			case sdl.K_TAB:
				textInput(pane.Buffer, "\t")
			case sdl.K_UP:
				index, _ := pane.IndexFromMark(insertMark)
				col, row := pane.CoordsFromIndex(index)
				pane.Mark(pane.IndexFromCoords(col, row-1), insertMark)
			case sdl.K_a:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Mark(edit.Index{index.Line, 0}, insertMark)
				}
			case sdl.K_e:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Mark(edit.Index{index.Line, 0xffff}, insertMark)
				}
			case sdl.K_h:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Delete(pane.ShiftIndex(index, -1), index)
				}
			case sdl.K_q:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					return
				}
			case sdl.K_u:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					index, _ := pane.IndexFromMark(insertMark)
					pane.Delete(edit.Index{index.Line, 0}, index)
				}
			case sdl.K_w:
				if event.Keysym.Mod&sdl.KMOD_CTRL != 0 {
					end, _ := pane.IndexFromMark(insertMark)
					begin := pane.ShiftIndexByWord(end, -1)
					pane.Delete(begin, end)
				}
			}
			pane.See(insertMark)
			render <- 1
		case *sdl.MouseButtonEvent:
			if event.Type == sdl.MOUSEBUTTONDOWN &&
				event.Button == sdl.BUTTON_LEFT {
				singleClick(panes, win, font, int(event.X), int(event.Y))
				pane = panes[focusedPane(panes)]
				paneSet <- panes
			}
		case *sdl.MouseMotionEvent:
			refocus(panes, win, font, int(event.X), int(event.Y))
			pane = panes[focusedPane(panes)]
			paneSet <- panes
		case *sdl.MouseWheelEvent:
			pane.Scroll(int(event.Y) * -3)
			render <- 1
		case *sdl.QuitEvent:
			return
		case *sdl.TextInputEvent:
			if n := bytes.Index(event.Text[:], []byte{0}); n > 0 {
				textInput(pane.Buffer, string(event.Text[:n]))
				render <- 1
			}
		case *sdl.WindowEvent:
			switch event.Event {
			case sdl.WINDOWEVENT_EXPOSED:
				win.UpdateSurface()
			case sdl.WINDOWEVENT_RESIZED:
				resize(panes, font, int(event.Data1), int(event.Data2))
			}
		}
	}
}
<|endoftext|>


<commit_before>package kocha

import (
	"os"
	"reflect"
	"strconv"

	"github.com/naoina/kocha/event"
)

// EventHandlerMap represents a map of event handlers.
type EventHandlerMap map[event.Queue]map[string]func(app *Application, args ...interface{}) error

// Evevnt represents the event.
type Event struct {
	// HandlerMap is a map of queue/handlers.
	HandlerMap EventHandlerMap

	// WorkersPerQueue is a number of workers per queue.
	// The default value is taken from GOMAXPROCS.
	// If value of GOMAXPROCS is invalid, set to 1.
	WorkersPerQueue int

	// ErrorHandler is the handler for error.
	// If you want to use your own error handler, please set to ErrorHandler.
	ErrorHandler func(err interface{})

	e   *event.Event
	app *Application
}

// Trigger emits the event.
// The name is an event name that is defined in e.HandlerMap.
// If args given, they will be passed to event handler that is defined in e.HandlerMap.
func (e *Event) Trigger(name string, args ...interface{}) error {
	return e.e.Trigger(name, args...)
}

func (e *Event) addHandler(name string, queueName string, handler func(app *Application, args ...interface{}) error) error {
	return e.e.AddHandler(name, queueName, func(args ...interface{}) error {
		return handler(e.app, args...)
	})
}

func (e *Event) build(app *Application) (*Event, error) {
	if e == nil {
		e = &Event{}
	}
	e.e = event.New()
	for queue, handlerMap := range e.HandlerMap {
		queueName := reflect.TypeOf(queue).Name()
		if err := e.e.RegisterQueue(queueName, queue); err != nil {
			return nil, err
		}
		for name, handler := range handlerMap {
			if err := e.addHandler(name, queueName, handler); err != nil {
				return nil, err
			}
		}
	}
	n := e.WorkersPerQueue
	if n < 1 {
		if n, _ = strconv.Atoi(os.Getenv("GOMAXPROCS")); n < 1 {
			n = 1
		}
	}
	e.e.SetWorkersPerQueue(n)
	e.e.ErrorHandler = e.ErrorHandler
	return e, nil
}

func (e *Event) start() {
	e.e.Start()
}

func (e *Event) stop() {
	e.e.Stop()
}
<commit_msg>event: Fix the issue that a queue name is always empty string<commit_after>package kocha

import (
	"os"
	"reflect"
	"strconv"

	"github.com/naoina/kocha/event"
)

// EventHandlerMap represents a map of event handlers.
type EventHandlerMap map[event.Queue]map[string]func(app *Application, args ...interface{}) error

// Evevnt represents the event.
type Event struct {
	// HandlerMap is a map of queue/handlers.
	HandlerMap EventHandlerMap

	// WorkersPerQueue is a number of workers per queue.
	// The default value is taken from GOMAXPROCS.
	// If value of GOMAXPROCS is invalid, set to 1.
	WorkersPerQueue int

	// ErrorHandler is the handler for error.
	// If you want to use your own error handler, please set to ErrorHandler.
	ErrorHandler func(err interface{})

	e   *event.Event
	app *Application
}

// Trigger emits the event.
// The name is an event name that is defined in e.HandlerMap.
// If args given, they will be passed to event handler that is defined in e.HandlerMap.
func (e *Event) Trigger(name string, args ...interface{}) error {
	return e.e.Trigger(name, args...)
}

func (e *Event) addHandler(name string, queueName string, handler func(app *Application, args ...interface{}) error) error {
	return e.e.AddHandler(name, queueName, func(args ...interface{}) error {
		return handler(e.app, args...)
	})
}

func (e *Event) build(app *Application) (*Event, error) {
	if e == nil {
		e = &Event{}
	}
	e.e = event.New()
	for queue, handlerMap := range e.HandlerMap {
		queueName := reflect.TypeOf(queue).String()
		if err := e.e.RegisterQueue(queueName, queue); err != nil {
			return nil, err
		}
		for name, handler := range handlerMap {
			if err := e.addHandler(name, queueName, handler); err != nil {
				return nil, err
			}
		}
	}
	n := e.WorkersPerQueue
	if n < 1 {
		if n, _ = strconv.Atoi(os.Getenv("GOMAXPROCS")); n < 1 {
			n = 1
		}
	}
	e.e.SetWorkersPerQueue(n)
	e.e.ErrorHandler = e.ErrorHandler
	return e, nil
}

func (e *Event) start() {
	e.e.Start()
}

func (e *Event) stop() {
	e.e.Stop()
}
<|endoftext|>


<commit_before>package filu

import "time"

// An Event is an immutable fact that happened at a single moment in time.
type Event interface {
	HappenedAt() time.Time
}

// A Time is a single moment in time. It is used by Implementors
// of the Event interface to avoid reimplementation of the HappenedAt()
// method.
type Time struct {
	moment time.Time
}

func (e Time) HappenedAt() time.Time {
	return e.moment
}
<commit_msg>[filu] Add function to produce time.Now() as filu.Time<commit_after>package filu

import "time"

// An Event is an immutable fact that happened at a single moment in time.
type Event interface {
	HappenedAt() time.Time
}

// A Time is a single moment in time. It is used by Implementors
// of the Event interface to avoid reimplementation of the HappenedAt()
// method.
type Time struct {
	moment time.Time
}

func Now() Time {
	return Time{time.Now()}
}

func (e Time) HappenedAt() time.Time {
	return e.moment
}
<|endoftext|>


<commit_before>// History: Oct 07 14 tcolar Creation

package main

import "github.com/tcolar/termbox-go"

func (e *Editor) EventLoop() {

	termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)

	for {
		ev := termbox.PollEvent()
		switch ev.Type {
		case termbox.EventResize:
			e.Render()
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				return
			default:
				if e.CurView != nil {
					e.CurView.Event(&ev)
				}
			}
		case termbox.EventMouse:
			w := e.WidgetAt(ev.MouseX, ev.MouseY)
			if w != nil {
				w.Event(&ev)
			}
		}
		e.Render()
	}
}

// Event handler for Menubar
func (m *Menubar) Event(ev *termbox.Event) {
	// TBD
}

// Event handler for Statusbar
func (s *Statusbar) Event(ev *termbox.Event) {
	// TBD
}

// Event handler for View
func (v *View) Event(ev *termbox.Event) {
	switch ev.Type {
	case termbox.EventKey:
		switch ev.Key {
		case termbox.KeyArrowRight:
			v.MoveCursor(1, 0)
		case termbox.KeyArrowLeft:
			v.MoveCursor(-1, 0)
		case termbox.KeyArrowUp:
			v.MoveCursor(0, -1)
		case termbox.KeyArrowDown:
			v.MoveCursor(0, 1)
		case termbox.KeyPgdn:
			dist := v.LastViewLine() + 1
			if len(v.Buffer)-v.CurLine() < dist {
				dist = len(v.Buffer) - v.CurLine() - 1
			}
			v.MoveCursor(0, dist)
		case termbox.KeyPgup:
			dist := v.LastViewLine() + 1
			if dist > v.CurLine() {
				dist = v.CurLine()
			}
			v.MoveCursor(0, -dist)
		case termbox.KeyEsc:
			return
		}
	case termbox.EventMouse:
		switch ev.Key {
		case termbox.MouseLeft:
			// MoveCursor use text coordinates which starts at offset 2,2
			v.MoveCursor(ev.MouseX-v.x1-2-v.CursorX, ev.MouseY-v.y1-2-v.CursorY)
			// Make the clicked view active
			Ed.CurView = v
		}
	}
}
<commit_msg>Home/End keys.<commit_after>// History: Oct 07 14 tcolar Creation

package main

import "github.com/tcolar/termbox-go"

func (e *Editor) EventLoop() {

	termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)

	for {
		ev := termbox.PollEvent()
		switch ev.Type {
		case termbox.EventResize:
			e.Render()
		case termbox.EventKey:
			switch ev.Key {
			case termbox.KeyEsc:
				return
			default:
				if e.CurView != nil {
					e.CurView.Event(&ev)
				}
			}
		case termbox.EventMouse:
			w := e.WidgetAt(ev.MouseX, ev.MouseY)
			if w != nil {
				w.Event(&ev)
			}
		}
		e.Render()
	}
}

// Event handler for Menubar
func (m *Menubar) Event(ev *termbox.Event) {
	// TBD
}

// Event handler for Statusbar
func (s *Statusbar) Event(ev *termbox.Event) {
	// TBD
}

// Event handler for View
func (v *View) Event(ev *termbox.Event) {
	switch ev.Type {
	case termbox.EventKey:
		switch ev.Key {
		case termbox.KeyArrowRight:
			v.MoveCursor(1, 0)
		case termbox.KeyArrowLeft:
			v.MoveCursor(-1, 0)
		case termbox.KeyArrowUp:
			v.MoveCursor(0, -1)
		case termbox.KeyArrowDown:
			v.MoveCursor(0, 1)
		case termbox.KeyPgdn:
			dist := v.LastViewLine() + 1
			if len(v.Buffer)-v.CurLine() < dist {
				dist = len(v.Buffer) - v.CurLine() - 1
			}
			v.MoveCursor(0, dist)
		case termbox.KeyPgup:
			dist := v.LastViewLine() + 1
			if dist > v.CurLine() {
				dist = v.CurLine()
			}
			v.MoveCursor(0, -dist)
		case termbox.KeyEnd:
			v.MoveCursor(v.lineLn(v.CurLine())-v.CurCol(), 0)
		case termbox.KeyHome:
			v.MoveCursor(-v.CurCol(), 0)
		case termbox.KeyEsc:
			return
		}
	case termbox.EventMouse:
		switch ev.Key {
		case termbox.MouseLeft:
			// MoveCursor use text coordinates which starts at offset 2,2
			v.MoveCursor(ev.MouseX-v.x1-2-v.CursorX, ev.MouseY-v.y1-2-v.CursorY)
			// Make the clicked view active
			Ed.CurView = v
		}
	}
}
<|endoftext|>


<commit_before>package grpc_opentracing

import (
	"strings"

	grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
	opentracing "github.com/opentracing/opentracing-go"
	"google.golang.org/grpc/grpclog"
)

const (
	TagTraceId           = "trace.traceid"
	TagSpanId            = "trace.spanid"
	TagSampled           = "trace.sampled"
	jaegerNotSampledFlag = "0"
)

// injectOpentracingIdsToTags writes trace data to ctxtags.
// This is done in an incredibly hacky way, because the public-facing interface of opentracing doesn't give access to
// the TraceId and SpanId of the SpanContext. Only the Tracer's Inject/Extract methods know what these are.
// Most tracers have them encoded as keys with 'traceid' and 'spanid':
// https://github.com/openzipkin/zipkin-go-opentracing/blob/594640b9ef7e5c994e8d9499359d693c032d738c/propagation_ot.go#L29
// https://github.com/opentracing/basictracer-go/blob/1b32af207119a14b1b231d451df3ed04a72efebf/propagation_ot.go#L26
// Jaeger from Uber use one-key schema with next format '{trace-id}:{span-id}:{parent-span-id}:{flags}'
// https://www.jaegertracing.io/docs/client-libraries/#trace-span-identity
func injectOpentracingIdsToTags(span opentracing.Span, tags grpc_ctxtags.Tags) {
	if err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, &tagsCarrier{tags}); err != nil {
		grpclog.Infof("grpc_opentracing: failed extracting trace info into ctx %v", err)
	}
}

// tagsCarrier is a really hacky way of
type tagsCarrier struct {
	grpc_ctxtags.Tags
}

func (t *tagsCarrier) Set(key, val string) {
	key = strings.ToLower(key)
	if strings.Contains(key, "traceid") {
		t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded
	}

	if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") {
		t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded
	}

	if strings.Contains(key, "sampled") {
		switch val {
		case "true", "false":
			t.Tags.Set(TagSampled, val)
		}
	}

	if key == "uber-trace-id" {
		parts := strings.Split(val, ":")
		if len(parts) == 4 {
			t.Tags.Set(TagTraceId, parts[0])
			t.Tags.Set(TagSpanId, parts[1])

			if parts[3] != jaegerNotSampledFlag {
				t.Tags.Set(TagSampled, "true")
			} else {
				t.Tags.Set(TagSampled, "false")
			}
		}
	}
}
<commit_msg>feature(tracing): Add datadog support to injectOpenTracingIdsToTags<commit_after>package grpc_opentracing

import (
	"strings"

	grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
	opentracing "github.com/opentracing/opentracing-go"
	"google.golang.org/grpc/grpclog"
)

const (
	TagTraceId           = "trace.traceid"
	TagSpanId            = "trace.spanid"
	TagSampled           = "trace.sampled"
	jaegerNotSampledFlag = "0"
)

// injectOpentracingIdsToTags writes trace data to ctxtags.
// This is done in an incredibly hacky way, because the public-facing interface of opentracing doesn't give access to
// the TraceId and SpanId of the SpanContext. Only the Tracer's Inject/Extract methods know what these are.
// Most tracers have them encoded as keys with 'traceid' and 'spanid':
// https://github.com/openzipkin/zipkin-go-opentracing/blob/594640b9ef7e5c994e8d9499359d693c032d738c/propagation_ot.go#L29
// https://github.com/opentracing/basictracer-go/blob/1b32af207119a14b1b231d451df3ed04a72efebf/propagation_ot.go#L26
// Jaeger from Uber use one-key schema with next format '{trace-id}:{span-id}:{parent-span-id}:{flags}'
// https://www.jaegertracing.io/docs/client-libraries/#trace-span-identity
// Datadog uses keys ending with 'trace-id' and 'parent-id' (for span) by default:
// https://github.com/DataDog/dd-trace-go/blob/v1/ddtrace/tracer/textmap.go#L77
func injectOpentracingIdsToTags(span opentracing.Span, tags grpc_ctxtags.Tags) {
	if err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, &tagsCarrier{tags}); err != nil {
		grpclog.Infof("grpc_opentracing: failed extracting trace info into ctx %v", err)
	}
}

// tagsCarrier is a really hacky way of
type tagsCarrier struct {
	grpc_ctxtags.Tags
}

func (t *tagsCarrier) Set(key, val string) {
	key = strings.ToLower(key)
	if strings.Contains(key, "traceid") {
		t.Tags.Set(TagTraceId, val) // this will most likely be base-16 (hex) encoded
	}

	if strings.Contains(key, "spanid") && !strings.Contains(strings.ToLower(key), "parent") {
		t.Tags.Set(TagSpanId, val) // this will most likely be base-16 (hex) encoded
	}

	if strings.Contains(key, "sampled") {
		switch val {
		case "true", "false":
			t.Tags.Set(TagSampled, val)
		}
	}

	if key == "uber-trace-id" {
		parts := strings.Split(val, ":")
		if len(parts) == 4 {
			t.Tags.Set(TagTraceId, parts[0])
			t.Tags.Set(TagSpanId, parts[1])

			if parts[3] != jaegerNotSampledFlag {
				t.Tags.Set(TagSampled, "true")
			} else {
				t.Tags.Set(TagSampled, "false")
			}
		}
	}

	if strings.HasSuffix(key, "trace-id") {
		t.Tags.Set(TagTraceId, val)
	}

	if strings.HasSuffix(key, "parent-id") {
		t.Tags.Set(TagSpanId, val)
	}
}
<|endoftext|>


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

// The vector package implements an efficient container for managing
// linear arrays of elements.  Unlike arrays, vectors can change size dynamically.
package vector

// Element is an empty-interface object representing the contents of
// a cell in the vector.
type Element interface {}

// Vector is the container itself.
type Vector struct {
	a []Element
}

func copy(dst, src []Element) {
	for i := 0; i < len(src); i++ {
		dst[i] = src[i]
	}
}

// Insert n elements at position i.
func expand(a []Element, i, n int) []Element {
	// make sure we have enough space
	len0 := len(a);
	len1 := len0 + n;
	if len1 < cap(a) {
		// enough space - just expand
		a = a[0 : len1]
	} else {
		// not enough space - double capacity
		capb := cap(a)*2;
		if capb < len1 {
			// still not enough - use required length
			capb = len1
		}
		// capb >= len1
		b := make([]Element, len1, capb);
		copy(b, a);
		a = b
	}

	// make a hole
	for j := len0-1; j >= i ; j-- {
		a[j+n] = a[j]
	}
	return a
}

// Init initializes a new or resized vector.  The initial_len may be <= 0 to
// request a default length.  If initial_len is shorter than the current
// length of the Vector, trailing elements of the Vector will be cleared.
func (p *Vector) Init(initial_len int) *Vector {
	a := p.a;

	if cap(a) == 0 || cap(a) < initial_len {
		n := 8;  // initial capacity
		if initial_len > n {
			n = initial_len
		}
		a = make([]Element, n);
	} else {
		// nil out entries
		for j := len(a) - 1; j >= 0; j-- {
			a[j] = nil
		}
	}

	p.a = a[0 : initial_len];
	return p
}

// New returns an initialized new Vector with length at least len.
func New(len int) *Vector {
	return new(Vector).Init(len)
}

// Len returns the number of elements in the vector.
func (p *Vector) Len() int {
	return len(p.a)
}

// At returns the i'th element of the vector.
func (p *Vector) At(i int) Element {
	return p.a[i]
}

// Set sets the i'th element of the vector to value x.
func (p *Vector) Set(i int, x Element) {
	p.a[i] = x
}

// Last returns the element in the vector of highest index.
func (p *Vector) Last() Element {
	return p.a[len(p.a) - 1]
}

// Insert inserts into the vector an element of value x before
// the current element at index i.
func (p *Vector) Insert(i int, x Element) {
	p.a = expand(p.a, i, 1);
	p.a[i] = x;
}

// Delete deletes the i'th element of the vector.  The gap is closed so the old
// element at index i+1 has index i afterwards.
func (p *Vector) Delete(i int) Element {
	a := p.a;
	n := len(a);

	x := a[i];
	copy(a[i : n-1], a[i+1 : n]);
	a[n-1] = nil;  // support GC, nil out entry
	p.a = a[0 : n-1];

	return x
}

// InsertVector inserts into the vector the contents of the Vector
// x such that the 0th element of x appears at index i after insertion.
func (p *Vector) InsertVector(i int, x *Vector) {
	p.a = expand(p.a, i, len(x.a));
	copy(p.a[i : i + len(x.a)], x.a);
}

// Cut deletes elements i through j-1, inclusive.
func (p *Vector) Cut(i, j int) {
	a := p.a;
	n := len(a);
	m := n - (j - i);

	copy(a[i : m], a[j : n]);
	for k := m; k < n; k++ {
		a[k] = nil  // support GC, nil out entries
	}

	p.a = a[0 : m];
}

// Slice returns a new Vector by slicing the old one to extract slice [i:j].
// The elements are copied. The original vector is unchanged.
func (p *Vector) Slice(i, j int) *Vector {
	s := New(j - i);  // will fail in Init() if j < j
	copy(s.a, p.a[i : j]);
	return s;
}

// Do calls function f for each element of the vector, in order.
// The function should not change the indexing of the vector underfoot.
func (p *Vector) Do(f func(elem Element)) {
	for i := 0; i < len(p.a); i++ {
		f(p.a[i])	// not too safe if f changes the Vector
	}
}

// Convenience wrappers

// Push appends x to the end of the vector.
func (p *Vector) Push(x Element) {
	p.Insert(len(p.a), x)
}

// Push deletes the last element of the vector.
func (p *Vector) Pop() Element {
	return p.Delete(len(p.a) - 1)
}

// AppendVector appends the entire Vector x to the end of this vector.
func (p *Vector) AppendVector(x *Vector) {
	p.InsertVector(len(p.a), x);
}

// Partial SortInterface support

// LessInterface provides partial support of the SortInterface.
type LessInterface interface {
	Less(y Element) bool
}

// Less returns a boolean denoting whether the i'th element is less than the j'th element.
func (p *Vector) Less(i, j int) bool {
	return p.a[i].(LessInterface).Less(p.a[j])
}

// Swap exchanges the elements at indexes i and j.
func (p *Vector) Swap(i, j int) {
	a := p.a;
	a[i], a[j] = a[j], a[i]
}

// Iterate over all elements; driver for range
func (p *Vector) iterate(c chan Element) {
	for i := 0; i < len(p.a); i++ {
		c <- p.a[i]
	}
	close(c);
}

// Channel iterator for range.
func (p *Vector) Iter() chan Element {
	c := make(chan Element);
	go p.iterate(c);
	return c;
}
<commit_msg>use range in vector iterator<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The vector package implements an efficient container for managing
// linear arrays of elements.  Unlike arrays, vectors can change size dynamically.
package vector

// Element is an empty-interface object representing the contents of
// a cell in the vector.
type Element interface {}

// Vector is the container itself.
type Vector struct {
	a []Element
}

func copy(dst, src []Element) {
	for i := 0; i < len(src); i++ {
		dst[i] = src[i]
	}
}

// Insert n elements at position i.
func expand(a []Element, i, n int) []Element {
	// make sure we have enough space
	len0 := len(a);
	len1 := len0 + n;
	if len1 < cap(a) {
		// enough space - just expand
		a = a[0 : len1]
	} else {
		// not enough space - double capacity
		capb := cap(a)*2;
		if capb < len1 {
			// still not enough - use required length
			capb = len1
		}
		// capb >= len1
		b := make([]Element, len1, capb);
		copy(b, a);
		a = b
	}

	// make a hole
	for j := len0-1; j >= i ; j-- {
		a[j+n] = a[j]
	}
	return a
}

// Init initializes a new or resized vector.  The initial_len may be <= 0 to
// request a default length.  If initial_len is shorter than the current
// length of the Vector, trailing elements of the Vector will be cleared.
func (p *Vector) Init(initial_len int) *Vector {
	a := p.a;

	if cap(a) == 0 || cap(a) < initial_len {
		n := 8;  // initial capacity
		if initial_len > n {
			n = initial_len
		}
		a = make([]Element, n);
	} else {
		// nil out entries
		for j := len(a) - 1; j >= 0; j-- {
			a[j] = nil
		}
	}

	p.a = a[0 : initial_len];
	return p
}

// New returns an initialized new Vector with length at least len.
func New(len int) *Vector {
	return new(Vector).Init(len)
}

// Len returns the number of elements in the vector.
func (p *Vector) Len() int {
	return len(p.a)
}

// At returns the i'th element of the vector.
func (p *Vector) At(i int) Element {
	return p.a[i]
}

// Set sets the i'th element of the vector to value x.
func (p *Vector) Set(i int, x Element) {
	p.a[i] = x
}

// Last returns the element in the vector of highest index.
func (p *Vector) Last() Element {
	return p.a[len(p.a) - 1]
}

// Insert inserts into the vector an element of value x before
// the current element at index i.
func (p *Vector) Insert(i int, x Element) {
	p.a = expand(p.a, i, 1);
	p.a[i] = x;
}

// Delete deletes the i'th element of the vector.  The gap is closed so the old
// element at index i+1 has index i afterwards.
func (p *Vector) Delete(i int) Element {
	a := p.a;
	n := len(a);

	x := a[i];
	copy(a[i : n-1], a[i+1 : n]);
	a[n-1] = nil;  // support GC, nil out entry
	p.a = a[0 : n-1];

	return x
}

// InsertVector inserts into the vector the contents of the Vector
// x such that the 0th element of x appears at index i after insertion.
func (p *Vector) InsertVector(i int, x *Vector) {
	p.a = expand(p.a, i, len(x.a));
	copy(p.a[i : i + len(x.a)], x.a);
}

// Cut deletes elements i through j-1, inclusive.
func (p *Vector) Cut(i, j int) {
	a := p.a;
	n := len(a);
	m := n - (j - i);

	copy(a[i : m], a[j : n]);
	for k := m; k < n; k++ {
		a[k] = nil  // support GC, nil out entries
	}

	p.a = a[0 : m];
}

// Slice returns a new Vector by slicing the old one to extract slice [i:j].
// The elements are copied. The original vector is unchanged.
func (p *Vector) Slice(i, j int) *Vector {
	s := New(j - i);  // will fail in Init() if j < j
	copy(s.a, p.a[i : j]);
	return s;
}

// Do calls function f for each element of the vector, in order.
// The function should not change the indexing of the vector underfoot.
func (p *Vector) Do(f func(elem Element)) {
	for i := 0; i < len(p.a); i++ {
		f(p.a[i])	// not too safe if f changes the Vector
	}
}

// Convenience wrappers

// Push appends x to the end of the vector.
func (p *Vector) Push(x Element) {
	p.Insert(len(p.a), x)
}

// Push deletes the last element of the vector.
func (p *Vector) Pop() Element {
	return p.Delete(len(p.a) - 1)
}

// AppendVector appends the entire Vector x to the end of this vector.
func (p *Vector) AppendVector(x *Vector) {
	p.InsertVector(len(p.a), x);
}

// Partial SortInterface support

// LessInterface provides partial support of the SortInterface.
type LessInterface interface {
	Less(y Element) bool
}

// Less returns a boolean denoting whether the i'th element is less than the j'th element.
func (p *Vector) Less(i, j int) bool {
	return p.a[i].(LessInterface).Less(p.a[j])
}

// Swap exchanges the elements at indexes i and j.
func (p *Vector) Swap(i, j int) {
	a := p.a;
	a[i], a[j] = a[j], a[i]
}

// Iterate over all elements; driver for range
func (p *Vector) iterate(c chan Element) {
	for i, v := range p.a {
		c <- v
	}
	close(c);
}

// Channel iterator for range.
func (p *Vector) Iter() chan Element {
	c := make(chan Element);
	go p.iterate(c);
	return c;
}
<|endoftext|>


<commit_before>package controller

import (
	"sort"
	"strings"
)

// StringsUnique returns true if all strings in the list are unique,
// false otherwise.
func StringsUnique(s []string) bool {
	sort.Strings(s)

	for i := 0; i < len(s)-1; i++ {
		if s[i] == s[i+1] {
			return false
		}
	}

	return true
}

// StringsHasPrefix returns true if all of the strings have the given prefix,
// false otherwise.
func StringsHasPrefix(s []string, p string) bool {
	for _, x := range s {
		if !strings.HasPrefix(x, p) {
			return false
		}
	}

	return true
}

// StringsSharePrefix returns true if any of the strings are prefixes of another,
// false otherwise.
func StringsSharePrefix(s []string) bool {
	sort.Strings(s)

	for i := 0; i < len(s)-1; i++ {
		if strings.HasPrefix(s[i+1], s[i]) {
			return true
		}
	}

	return false
}

// StringsCountMoreThan returns true if any of the strings in s
// contain more than n occurences of c, false otherwise.
func StringsCountMoreThan(s []string, c string, n int) bool {
	for _, x := range s {
		if strings.Count(x, c) > n {
			return true
		}
	}

	return false
}

// StringsHaveOrNot returns true if all strings in s either have an occurence of c,
// or do not have any occurence of c.
// In another way, it returns false if only some strings in s have an occurence of c.
func StringsHaveOrNot(s []string, c string) bool {
	numStringsWithOccurence := 0

	for _, x := range s {
		if strings.Contains(x, c) {
			numStringsWithOccurence++
		}
	}

	return !(numStringsWithOccurence > 0 && numStringsWithOccurence < len(s))
}

// ValidateSubmitRequest validates that the given request contains no SliceIDs.
// Otherwise it is identical to ValidateRequest().
func ValidateSubmitRequest(request Request) (bool, error) {
	if len(request.SliceIDs) != 0 {
		return false, maskAny(invalidSubmitRequestSlicesGivenError)
	}

	return ValidateRequest(request)
}

// ValidateRequest takes a Request, and returns whether it is valid or not.
// If the request is not valid, the error provides more details.
func ValidateRequest(request Request) (bool, error) {
	var error ValidationError
	// Check there are units in the group.
	if len(request.Units) == 0 {
		error.causingErrors = append(error.causingErrors, noUnitsInGroupError)
	}

	// Check that there are not any @ symbols in the group name.
	if strings.Contains(request.Group, "@") {
		error.causingErrors = append(error.causingErrors, atInGroupNameError)
	}

	unitNames := []string{}
	for _, unit := range request.Units {
		unitNames = append(unitNames, unit.Name)
	}

	// Check that we're not mixing units with @ and units without @.
	if !StringsHaveOrNot(unitNames, "@.") {
		error.causingErrors = append(error.causingErrors, mixedSliceInstanceError)
	}

	// Check that all unit names are prefixed by the group name.
	if !StringsHasPrefix(unitNames, request.Group) {
		error.causingErrors = append(error.causingErrors, badUnitPrefixError)
	}

	// Check that @ only occurences at most once per unit name.
	if StringsCountMoreThan(unitNames, "@", 1) {
		error.causingErrors = append(error.causingErrors, multipleAtInUnitNameError)
	}

	// Check that all unit names are unique.
	if !StringsUnique(unitNames) {
		error.causingErrors = append(error.causingErrors, unitsSameNameError)
	}

	if len(error.causingErrors) != 0 {
		return false, error
	}
	return true, nil
}

// ValidateMultipleRequest takes a list of Requests, and returns whether
// they are valid together or not.
// If the requests are not valid, the error returned provides more details.
func ValidateMultipleRequest(requests []Request) (bool, error) {
	groupNames := []string{}
	var error ValidationError

	for _, request := range requests {
		groupNames = append(groupNames, request.Group)
	}

	// Check that all group names are unique.
	if !StringsUnique(groupNames) {
		error.causingErrors = append(error.causingErrors, groupsSameNameError)
	}

	// Check that group names are not prefixes of each other.
	if StringsSharePrefix(groupNames) {
		error.causingErrors = append(error.causingErrors, groupsArePrefixError)
	}

	if len(error.causingErrors) != 0 {
		return false, error
	}
	return true, nil
}
<commit_msg>rename error to ValidationError<commit_after>package controller

import (
	"sort"
	"strings"
)

// StringsUnique returns true if all strings in the list are unique,
// false otherwise.
func StringsUnique(s []string) bool {
	sort.Strings(s)

	for i := 0; i < len(s)-1; i++ {
		if s[i] == s[i+1] {
			return false
		}
	}

	return true
}

// StringsHasPrefix returns true if all of the strings have the given prefix,
// false otherwise.
func StringsHasPrefix(s []string, p string) bool {
	for _, x := range s {
		if !strings.HasPrefix(x, p) {
			return false
		}
	}

	return true
}

// StringsSharePrefix returns true if any of the strings are prefixes of another,
// false otherwise.
func StringsSharePrefix(s []string) bool {
	sort.Strings(s)

	for i := 0; i < len(s)-1; i++ {
		if strings.HasPrefix(s[i+1], s[i]) {
			return true
		}
	}

	return false
}

// StringsCountMoreThan returns true if any of the strings in s
// contain more than n occurences of c, false otherwise.
func StringsCountMoreThan(s []string, c string, n int) bool {
	for _, x := range s {
		if strings.Count(x, c) > n {
			return true
		}
	}

	return false
}

// StringsHaveOrNot returns true if all strings in s either have an occurence of c,
// or do not have any occurence of c.
// In another way, it returns false if only some strings in s have an occurence of c.
func StringsHaveOrNot(s []string, c string) bool {
	numStringsWithOccurence := 0

	for _, x := range s {
		if strings.Contains(x, c) {
			numStringsWithOccurence++
		}
	}

	return !(numStringsWithOccurence > 0 && numStringsWithOccurence < len(s))
}

// ValidateSubmitRequest validates that the given request contains no SliceIDs.
// Otherwise it is identical to ValidateRequest().
func ValidateSubmitRequest(request Request) (bool, error) {
	if len(request.SliceIDs) != 0 {
		return false, maskAny(invalidSubmitRequestSlicesGivenError)
	}

	return ValidateRequest(request)
}

// ValidateRequest takes a Request, and returns whether it is valid or not.
// If the request is not valid, the error provides more details.
func ValidateRequest(request Request) (bool, error) {
	var validationError ValidationError
	// Check there are units in the group.
	if len(request.Units) == 0 {
		validationError.causingErrors = append(validationError.causingErrors, noUnitsInGroupError)
	}

	// Check that there are not any @ symbols in the group name.
	if strings.Contains(request.Group, "@") {
		validationError.causingErrors = append(validationError.causingErrors, atInGroupNameError)
	}

	unitNames := []string{}
	for _, unit := range request.Units {
		unitNames = append(unitNames, unit.Name)
	}

	// Check that we're not mixing units with @ and units without @.
	if !StringsHaveOrNot(unitNames, "@.") {
		validationError.causingErrors = append(validationError.causingErrors, mixedSliceInstanceError)
	}

	// Check that all unit names are prefixed by the group name.
	if !StringsHasPrefix(unitNames, request.Group) {
		validationError.causingErrors = append(validationError.causingErrors, badUnitPrefixError)
	}

	// Check that @ only occurences at most once per unit name.
	if StringsCountMoreThan(unitNames, "@", 1) {
		validationError.causingErrors = append(validationError.causingErrors, multipleAtInUnitNameError)
	}

	// Check that all unit names are unique.
	if !StringsUnique(unitNames) {
		validationError.causingErrors = append(validationError.causingErrors, unitsSameNameError)
	}

	if len(validationError.causingErrors) != 0 {
		return false, validationError
	}
	return true, nil
}

// ValidateMultipleRequest takes a list of Requests, and returns whether
// they are valid together or not.
// If the requests are not valid, the error returned provides more details.
func ValidateMultipleRequest(requests []Request) (bool, error) {
	groupNames := []string{}
	var validationError ValidationError

	for _, request := range requests {
		groupNames = append(groupNames, request.Group)
	}

	// Check that all group names are unique.
	if !StringsUnique(groupNames) {
		validationError.causingErrors = append(validationError.causingErrors, groupsSameNameError)
	}

	// Check that group names are not prefixes of each other.
	if StringsSharePrefix(groupNames) {
		validationError.causingErrors = append(validationError.causingErrors, groupsArePrefixError)
	}

	if len(validationError.causingErrors) != 0 {
		return false, validationError
	}
	return true, nil
}
<|endoftext|>


<commit_before>// Copyright 2014, Surul Software Labs GmbH
// All rights reserved.

/*
Package fault provides utilities to help with package internal error handling.

It supports a simple idiom for reducing the amount of package internal error
handling. It allows you to panic with a Fault instance in package internal code.
This is then recovered using a defer for a all exported methods, which then return
an error extracted from the fault. As an example, if you were to be reading data
from a file and then writing it you could use

	import (
		"github.com/surullabs/fault"
	)

	var check = fault.NewChecker()

	func ExportedMethod() (err error) {
		// Set up the recovery. err will be automatically populated and all
		// non-fault panics will be propogated.
		defer check.Recover(&err)

		// If there is an error in ReadFile the method will automatically return
		// the error.
		data := check.Return(ioutil.ReadFile("filename")).([]byte)
		// If yourFn returns false the function will return an error
		// formatted as "condition is not true: yourData"
		check.Truef(yourFn(data), "condition is not true: %s", string(data))
	}

It also provides access to an ErrorChain class which can be used to chain errors together.
Errors can be transparently checked for existence in a chain by calling the Contains method.

Please look at the tests for more sample usage.
*/
package fault

import (
	"errors"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
)

// ErrorChain is a list of errors and can be used to chain errors together.
type ErrorChain struct {
	chain []error
}

// AsError returns an error if any are present in the chain or nil if not
func (c *ErrorChain) AsError() error {
	if c == nil || len(c.chain) == 0 {
		return nil
	}
	return c
}

// String returns the same value as Error()
func (c *ErrorChain) String() string { return c.Error() }

// Errors returns all errors in the chain
func (c *ErrorChain) Errors() []error { return c.chain }

// Error will return a string representation of all errors.
func (c *ErrorChain) Error() string {
	errors := make([]string, len(c.chain))
	for i, err := range c.chain {
		errors[i] = err.Error()
	}
	return strings.Join(errors, "; ")
}

// Chain appends the error provided to the current chain. If the
// err is a chain then all errors in the chain are appended.
func (c *ErrorChain) Chain(err error) {
	if err == nil {
		return
	}

	if c.chain == nil {
		c.chain = make([]error, 0)
	}

	switch e := err.(type) {
	case *ErrorChain:
		if e.chain != nil {
			c.chain = append(c.chain, e.chain...)
		}
	default:
		c.chain = append(c.chain, e)
	}
}

// Chain will chain a list of errors passed in. The errors can
// be of type *ErrorChain in which case their chains will be appended.
func Chain(errs ...error) error {
	chain := &ErrorChain{}
	for _, err := range errs {
		chain.Chain(err)
	}
	return chain.AsError()
}

// Contains will return true in the following cases:
//
// 	* chain.Error() == target.Error()
// 	* chain is an ErrorChain and one of the errors is target
// 	* Contains(target, chain) returns true
func Contains(chain, target error) bool {
	if chain == nil || target == nil {
		return false
	}
	if chain.Error() == target.Error() {
		return true
	}
	if chainErr, isChain := chain.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == target.Error() {
				return true
			}
		}
	}
	if chainErr, isChain := target.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == chain.Error() {
				return true
			}
		}
	}
	return false
}

// Fault is an interface for representing a package internal fault.
type Fault interface {
	// Fault returns the error tied to this fault
	Fault() error
}

// Faulter is an interface used to generate faults from errors
type Faulter interface {
	New(err error) Fault
}

// FaultCheck is an interface providing functionality to check for faults and recover from them.
type FaultCheck interface {
	// Recover is used to recover from faults that were expressed through panics.
	// It will call recover() internally and the error variable pointed to by the argument will be populated with the fault information.
	Recover(*error)
	// RecoverPanic works exactly like recover with the exception that the second argument
	// must be the result of a call to recover()
	RecoverPanic(*error, interface{})
	// True will panic with a fault if the condition provided is false
	// The fault error string will be the second argument
	True(bool, string)
	// Truef behaves like Check with the error string as the result of a call to fmt.Errorf(format, args...)
	Truef(bool, string, ...interface{})
	// Return will panic if the error provided is not nil. It will return the first argument if not
	Return(interface{}, error) interface{}
	// Error is equivalent to a call to Return(nil, err)
	Error(error)
	// Output functions exactly as Return, with the only difference being that the output is included in the error message.
	// If the output is a byte array it is converted to a string.
	// This can be useful when debugging use of os/exec package for instance.
	Output(interface{}, error) interface{}
}

// Checker provides a default implementation of FaultCheck
type Checker struct {
	faulter Faulter
}

func NewChecker() *Checker { return &Checker{faulter: ErrorFaulter{}} }

func (c *Checker) SetFaulter(f Faulter) *Checker {
	c.faulter = f
	return c
}

// RecoverPanic implements FaultCheck.RecoverPanic
func (c *Checker) RecoverPanic(errPtr *error, panicked interface{}) {
	if panicked == nil {
		return
	} else if fault, faulty := panicked.(Fault); faulty {
		*errPtr = Chain(fault.Fault(), *errPtr)
		return
	} else {
		panic(panicked)
	}
}

// Recover implements FaultCheck.Recover
func (c *Checker) Recover(errPtr *error) {
	c.RecoverPanic(errPtr, recover())
}

type ErrorFaulter struct{}

func (ErrorFaulter) New(err error) Fault { return &errorFault{err: err} }

type errorFault struct {
	err error
}

func (e *errorFault) Fault() error { return e.err }

func (e *errorFault) String() string {
	if e.err == nil {
		return ""
	}
	return e.err.Error()

}

func (c *Checker) True(condition bool, errStr string) {
	if !condition {
		panic(c.faulter.New(errors.New(errStr)))
	}
}

// True implements FaultCheck.True
func (c *Checker) Truef(condition bool, format string, args ...interface{}) {
	if !condition {
		panic(c.faulter.New(fmt.Errorf(format, args...)))
	}
}

// Return implements FaultCheck.Return
func (c *Checker) Return(i interface{}, err error) interface{} {
	if err != nil {
		panic(c.faulter.New(err))
	}
	return i
}

// Error implements FaultCheck.Error
func (c *Checker) Error(err error) {
	if err != nil {
		panic(c.faulter.New(err))
	}
}

// Output implements FaultCheck.Output
func (c *Checker) Output(i interface{}, err error) interface{} {
	if err != nil {
		var out string
		if bytes, isByteArray := i.([]byte); isByteArray {
			out = string(bytes)
		} else {
			out = fmt.Sprintf("%v", i)
		}
		panic(c.faulter.New(&ErrorChain{chain: []error{err, fmt.Errorf("output: %s", out)}}))
	}
	return i
}

// Call provides information about a function call.
type Call struct {
	File string // File provides the file of the caller
	Line int    // Line provides the line number
	Name string // Name is the name of the calling function
}

func (c *Call) String() string { return fmt.Sprintf("%s:%d:%s", filepath.Base(c.File), c.Line, c.Name) }

func (c *Call) Equal(c2 *Call) bool {
	if c == nil {
		return c2 == nil
	} else if c2 == nil {
		return false
	}
	return c.File == c2.File && c.Line == c2.Line && c.Name == c2.Name
}

type debugFault struct {
	err   error
	trace []Call
}

func GetTrace(err error) (trace []Call) {
	if chain, isChain := err.(*ErrorChain); isChain {
		if fault, isFault := chain.Errors()[0].(*debugFault); isFault {
			return fault.trace
		}
	}
	return nil
}

func StartSite(trace []Call) (call *Call) {
	if len(trace) == 0 {
		call = &Call{"?", -1, "?"}
	} else {
		call = &trace[0]
	}
	return
}

func (d *debugFault) Error() string {
	return fmt.Sprintf("%v: %s", StartSite(d.trace), d.err.Error())
}

func (d *debugFault) Fault() error { return d }

type DebugFaulter struct{}

var checkerPrefix = TypePrefix(&Checker{})

func TypePrefix(i interface{}) string {
	val := reflect.ValueOf(i)
	if val.Kind() == reflect.Ptr {
		typeVal := val.Elem().Type()
		return fmt.Sprintf("%s.(*%s)", typeVal.PkgPath(), typeVal.Name())
	} else {
		return fmt.Sprintf("%s.(%s)", val.Type().PkgPath(), val.Type().Name())
	}
}

// ReadStack reads returns the stack after ignoring all calls up to the
// function which has the first parameter as a prefix . An empty string returns
// the entire stack.
func ReadStack(prefix string) (trace []Call) {
	trace = make([]Call, 0)
	var (
		pc uintptr
		fn *runtime.Func
	)
	appendTo := false
	for skip, ok := 0, true; ok; skip++ {
		call := Call{Name: "?"}
		if pc, call.File, call.Line, ok = runtime.Caller(skip); !ok {
			break
		}
		if fn = runtime.FuncForPC(pc); fn != nil {
			call.Name = fn.Name()
		}

		if appendTo {
			trace = append(trace, call)
		}
		if strings.HasPrefix(call.Name, prefix) {
			appendTo = true
		}
	}
	return
}

func (DebugFaulter) New(err error) Fault {
	return &debugFault{err: err, trace: ReadStack(checkerPrefix)}
}
<commit_msg>Utilities to add stacktraces to errors.<commit_after>// Copyright 2014, Surul Software Labs GmbH
// All rights reserved.

/*
Package fault provides utilities to help with package internal error handling.

It supports a simple idiom for reducing the amount of package internal error
handling. It allows you to panic with a Fault instance in package internal code.
This is then recovered using a defer for a all exported methods, which then return
an error extracted from the fault. As an example, if you were to be reading data
from a file and then writing it you could use

	import (
		"github.com/surullabs/fault"
	)

	var check = fault.NewChecker()

	func ExportedMethod() (err error) {
		// Set up the recovery. err will be automatically populated and all
		// non-fault panics will be propogated.
		defer check.Recover(&err)

		// If there is an error in ReadFile the method will automatically return
		// the error.
		data := check.Return(ioutil.ReadFile("filename")).([]byte)
		// If yourFn returns false the function will return an error
		// formatted as "condition is not true: yourData"
		check.Truef(yourFn(data), "condition is not true: %s", string(data))
	}

It also provides access to an ErrorChain class which can be used to chain errors together.
Errors can be transparently checked for existence in a chain by calling the Contains method.

Please look at the tests for more sample usage.
*/
package fault

import (
	"errors"
	"fmt"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
)

// ErrorChain is a list of errors and can be used to chain errors together.
type ErrorChain struct {
	chain []error
}

// AsError returns an error if any are present in the chain or nil if not
func (c *ErrorChain) AsError() error {
	if c == nil || len(c.chain) == 0 {
		return nil
	}
	return c
}

// String returns the same value as Error()
func (c *ErrorChain) String() string { return c.Error() }

// Errors returns all errors in the chain
func (c *ErrorChain) Errors() []error { return c.chain }

// Error will return a string representation of all errors.
func (c *ErrorChain) Error() string {
	errors := make([]string, len(c.chain))
	for i, err := range c.chain {
		errors[i] = err.Error()
	}
	return strings.Join(errors, "; ")
}

// Chain appends the error provided to the current chain. If the
// err is a chain then all errors in the chain are appended.
func (c *ErrorChain) Chain(err error) {
	if err == nil {
		return
	}

	if c.chain == nil {
		c.chain = make([]error, 0)
	}

	switch e := err.(type) {
	case *ErrorChain:
		if e.chain != nil {
			c.chain = append(c.chain, e.chain...)
		}
	default:
		c.chain = append(c.chain, e)
	}
}

// Chain will chain a list of errors passed in. The errors can
// be of type *ErrorChain in which case their chains will be appended.
func Chain(errs ...error) error {
	chain := &ErrorChain{}
	for _, err := range errs {
		chain.Chain(err)
	}
	return chain.AsError()
}

// Contains will return true in the following cases:
//
// 	* chain.Error() == target.Error()
// 	* chain is an ErrorChain and one of the errors is target
// 	* Contains(target, chain) returns true
func Contains(chain, target error) bool {
	if chain == nil || target == nil {
		return false
	}
	if chain.Error() == target.Error() {
		return true
	}
	if chainErr, isChain := chain.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == target.Error() {
				return true
			}
		}
	}
	if chainErr, isChain := target.(*ErrorChain); isChain {
		for _, err := range chainErr.chain {
			if err.Error() == chain.Error() {
				return true
			}
		}
	}
	return false
}

// Fault is an interface for representing a package internal fault.
type Fault interface {
	// Cause returns the error tied to this fault
	Cause() error
	// Error returns the result of a call to Cause().Error()
	Error() string
}

// Faulter is an interface used to generate faults from errors
type Faulter interface {
	New(err error) Fault
}

// FaultCheck is an interface providing functionality to check for faults and recover from them.
type FaultCheck interface {
	// Recover is used to recover from faults that were expressed through panics.
	// It will call recover() internally and the error variable pointed to by the argument will be populated with the fault information.
	Recover(*error)
	// RecoverPanic works exactly like recover with the exception that the second argument
	// must be the result of a call to recover()
	RecoverPanic(*error, interface{})
	// True will panic with a fault if the condition provided is false
	// The fault error string will be the second argument
	True(bool, string)
	// Truef behaves like Check with the error string as the result of a call to fmt.Errorf(format, args...)
	Truef(bool, string, ...interface{})
	// Return will panic if the error provided is not nil. It will return the first argument if not
	Return(interface{}, error) interface{}
	// Error is equivalent to a call to Return(nil, err)
	Error(error)
	// Output functions exactly as Return, with the only difference being that the output is included in the error message.
	// If the output is a byte array it is converted to a string.
	// This can be useful when debugging use of os/exec package for instance.
	Output(interface{}, error) interface{}
}

// Checker provides a default implementation of FaultCheck
type Checker struct {
	faulter Faulter
}

func NewChecker() *Checker { return &Checker{faulter: ErrorFaulter{}} }

func (c *Checker) SetFaulter(f Faulter) *Checker {
	c.faulter = f
	return c
}

// RecoverPanic implements FaultCheck.RecoverPanic
func (c *Checker) RecoverPanic(errPtr *error, panicked interface{}) {
	if panicked == nil {
		return
	} else if fault, faulty := panicked.(Fault); faulty {
		*errPtr = Chain(fault.Cause(), *errPtr)
		return
	} else {
		panic(panicked)
	}
}

// Recover implements FaultCheck.Recover
func (c *Checker) Recover(errPtr *error) {
	c.RecoverPanic(errPtr, recover())
}

type ErrorFaulter struct{}

func (ErrorFaulter) New(err error) Fault { return &errorFault{err: err} }

type errorFault struct {
	err error
}

func (e *errorFault) Error() string { return e.err.Error() }
func (e *errorFault) Cause() error  { return e.err }

func (e *errorFault) String() string {
	if e.err == nil {
		return ""
	}
	return e.err.Error()

}

func (c *Checker) True(condition bool, errStr string) {
	if !condition {
		panic(c.faulter.New(errors.New(errStr)))
	}
}

// True implements FaultCheck.True
func (c *Checker) Truef(condition bool, format string, args ...interface{}) {
	if !condition {
		panic(c.faulter.New(fmt.Errorf(format, args...)))
	}
}

// Return implements FaultCheck.Return
func (c *Checker) Return(i interface{}, err error) interface{} {
	if err != nil {
		panic(c.faulter.New(err))
	}
	return i
}

// Error implements FaultCheck.Error
func (c *Checker) Error(err error) {
	if err != nil {
		panic(c.faulter.New(err))
	}
}

// Output implements FaultCheck.Output
func (c *Checker) Output(i interface{}, err error) interface{} {
	if err != nil {
		var out string
		if bytes, isByteArray := i.([]byte); isByteArray {
			out = string(bytes)
		} else {
			out = fmt.Sprintf("%v", i)
		}
		panic(c.faulter.New(&ErrorChain{chain: []error{err, fmt.Errorf("output: %s", out)}}))
	}
	return i
}

// Call provides information about a function call.
type Call struct {
	File string // File provides the file of the caller
	Line int    // Line provides the line number
	Name string // Name is the name of the calling function
}

func (c *Call) String() string { return fmt.Sprintf("%s:%d:%s", filepath.Base(c.File), c.Line, c.Name) }

func (c *Call) Equal(c2 *Call) bool {
	if c == nil {
		return c2 == nil
	} else if c2 == nil {
		return false
	}
	return c.File == c2.File && c.Line == c2.Line && c.Name == c2.Name
}

type debugFault struct {
	err   error
	trace []Call
}

func GetTrace(err error) (trace []Call) {
	if chain, isChain := err.(*ErrorChain); isChain && len(chain.Errors()) == 1 {
		err = chain.Errors()[0]
	}
	if fault, isFault := err.(*debugFault); isFault {
		return fault.trace
	}
	return nil
}

func StartSite(trace []Call) (call *Call) {
	if len(trace) == 0 {
		call = &Call{"?", -1, "?"}
	} else {
		call = &trace[0]
	}
	return
}

func (d *debugFault) Error() string {
	return fmt.Sprintf("%v: %s", StartSite(d.trace), d.err.Error())
}

func (d *debugFault) Cause() error { return d }

type DebugFaulter struct{}

var checkerPrefix = TypePrefix(&Checker{})

func TypePrefix(i interface{}) string {
	val := reflect.ValueOf(i)
	if val.Kind() == reflect.Ptr {
		typeVal := val.Elem().Type()
		return fmt.Sprintf("%s.(*%s)", typeVal.PkgPath(), typeVal.Name())
	} else {
		return fmt.Sprintf("%s.(%s)", val.Type().PkgPath(), val.Type().Name())
	}
}

// ReadStack reads returns the stack after ignoring all calls up to the
// function which has the first parameter as a prefix . An empty string returns
// the entire stack.
func ReadStack(prefix string) (trace []Call) {
	trace = make([]Call, 0)
	var (
		pc uintptr
		fn *runtime.Func
	)
	appendTo := false
	for skip, ok := 0, true; ok; skip++ {
		call := Call{Name: "?"}
		if pc, call.File, call.Line, ok = runtime.Caller(skip); !ok {
			break
		}
		if fn = runtime.FuncForPC(pc); fn != nil {
			call.Name = fn.Name()
		}

		if appendTo {
			trace = append(trace, call)
		}
		if strings.HasPrefix(call.Name, prefix) {
			appendTo = true
		}
	}
	return
}

func (DebugFaulter) New(err error) Fault {
	return &debugFault{err: err, trace: ReadStack(checkerPrefix)}
}

// Traced returns an error with the entire stack trace
func Traced(err error) error {
	if chain, isChain := err.(*ErrorChain); isChain && len(chain.Errors()) == 1 {
		err = chain.Errors()[0]
	}
	if _, ok := err.(*debugFault); ok {
		return err
	}
	trace := ReadStack("")
	return &debugFault{err: err, trace: trace[1:]}
}

func VerboseTrace(err error) string {
	trace := GetTrace(err)
	if trace == nil {
		return err.Error()
	}

	parts := make([]string, len(trace))
	for i := range trace {
		parts[i] = trace[i].String()
	}
	parts[0] = err.Error()
	return strings.Join(parts, "\n")
}
<|endoftext|>


<commit_before>package userstored

import (
	"context"
	"net/http"

	"github.com/rancher/norman/store/subtype"
	"github.com/rancher/norman/types"
	namespacecustom "github.com/rancher/rancher/pkg/api/customization/namespace"
	"github.com/rancher/rancher/pkg/api/customization/yaml"
	"github.com/rancher/rancher/pkg/api/store/cert"
	"github.com/rancher/rancher/pkg/api/store/ingress"
	"github.com/rancher/rancher/pkg/api/store/namespace"
	"github.com/rancher/rancher/pkg/api/store/pod"
	"github.com/rancher/rancher/pkg/api/store/projectsetter"
	"github.com/rancher/rancher/pkg/api/store/secret"
	"github.com/rancher/rancher/pkg/api/store/service"
	"github.com/rancher/rancher/pkg/api/store/workload"
	"github.com/rancher/rancher/pkg/clustermanager"
	clusterschema "github.com/rancher/types/apis/cluster.cattle.io/v3/schema"
	"github.com/rancher/types/apis/project.cattle.io/v3/schema"
	clusterClient "github.com/rancher/types/client/cluster/v3"
	"github.com/rancher/types/client/project/v3"
	"github.com/rancher/types/config"
)

func Setup(ctx context.Context, mgmt *config.ScaledContext, clusterManager *clustermanager.Manager, k8sProxy http.Handler) error {
	// Here we setup all types that will be stored in the User cluster

	schemas := mgmt.Schemas

	addProxyStore(ctx, schemas, mgmt, client.ConfigMapType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, client.CronJobType, "batch/v1beta1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.DaemonSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.DeploymentType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.IngressType, "extensions/v1beta1", ingress.Wrap)
	addProxyStore(ctx, schemas, mgmt, client.JobType, "batch/v1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.PersistentVolumeClaimType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, client.PodType, "v1", func(store types.Store) types.Store {
		return pod.New(store, clusterManager, mgmt)
	})
	addProxyStore(ctx, schemas, mgmt, client.ReplicaSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.ReplicationControllerType, "v1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.ServiceType, "v1", service.New)
	addProxyStore(ctx, schemas, mgmt, client.StatefulSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, clusterClient.NamespaceType, "v1", namespace.New)
	addProxyStore(ctx, schemas, mgmt, clusterClient.PersistentVolumeType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, clusterClient.StorageClassType, "storage.k8s.io/v1", nil)

	Secret(ctx, mgmt, schemas)
	Service(schemas)
	Workload(schemas, clusterManager)
	Namespace(schemas, clusterManager)

	SetProjectID(schemas, clusterManager, k8sProxy)

	return nil
}

func SetProjectID(schemas *types.Schemas, clusterManager *clustermanager.Manager, k8sProxy http.Handler) {
	for _, schema := range schemas.SchemasForVersion(schema.Version) {
		if schema.Store == nil || schema.Store.Context() != config.UserStorageContext {
			continue
		}

		if schema.CanList(nil) != nil {
			continue
		}

		if _, ok := schema.ResourceFields["namespaceId"]; !ok {
			panic(schema.ID + " does not have namespaceId")
		}

		if _, ok := schema.ResourceFields["projectId"]; !ok {
			panic(schema.ID + " does not have projectId")
		}

		schema.Store = projectsetter.New(schema.Store, clusterManager)
		schema.Formatter = yaml.NewFormatter(schema.Formatter)
		schema.LinkHandler = yaml.NewLinkHandler(k8sProxy, clusterManager, schema.LinkHandler)
	}
}

func Namespace(schemas *types.Schemas, manager *clustermanager.Manager) {
	namespaceSchema := schemas.Schema(&clusterschema.Version, "namespace")
	namespaceSchema.LinkHandler = namespacecustom.NewLinkHandler(namespaceSchema.LinkHandler, manager)
	namespaceSchema.Formatter = yaml.NewFormatter(namespaceSchema.Formatter)
}

func Workload(schemas *types.Schemas, clusterManager *clustermanager.Manager) {
	workload.NewWorkloadAggregateStore(schemas, clusterManager)
}

func Service(schemas *types.Schemas) {
	serviceSchema := schemas.Schema(&schema.Version, "service")
	dnsSchema := schemas.Schema(&schema.Version, "dnsRecord")
	dnsSchema.Store = struct {
		types.Store
	}{
		serviceSchema.Store,
	}
}

func Secret(ctx context.Context, management *config.ScaledContext, schemas *types.Schemas) {
	schema := schemas.Schema(&schema.Version, "namespacedSecret")
	schema.Store = secret.NewNamespacedSecretStore(ctx, management.ClientGetter)

	for _, subSchema := range schemas.Schemas() {
		if subSchema.BaseType == schema.ID && subSchema.ID != schema.ID {
			subSchema.Store = subtype.NewSubTypeStore(subSchema.ID, schema.Store)
		}
	}

	schema = schemas.Schema(&schema.Version, "namespacedCertificate")
	schema.Store = cert.Wrap(schema.Store)
}
<commit_msg>Should Not Use the Same Store Instance for DNSRecord and Service<commit_after>package userstored

import (
	"context"
	"net/http"

	"github.com/rancher/norman/store/subtype"
	"github.com/rancher/norman/types"
	namespacecustom "github.com/rancher/rancher/pkg/api/customization/namespace"
	"github.com/rancher/rancher/pkg/api/customization/yaml"
	"github.com/rancher/rancher/pkg/api/store/cert"
	"github.com/rancher/rancher/pkg/api/store/ingress"
	"github.com/rancher/rancher/pkg/api/store/namespace"
	"github.com/rancher/rancher/pkg/api/store/pod"
	"github.com/rancher/rancher/pkg/api/store/projectsetter"
	"github.com/rancher/rancher/pkg/api/store/secret"
	"github.com/rancher/rancher/pkg/api/store/service"
	"github.com/rancher/rancher/pkg/api/store/workload"
	"github.com/rancher/rancher/pkg/clustermanager"
	clusterschema "github.com/rancher/types/apis/cluster.cattle.io/v3/schema"
	"github.com/rancher/types/apis/project.cattle.io/v3/schema"
	clusterClient "github.com/rancher/types/client/cluster/v3"
	"github.com/rancher/types/client/project/v3"
	"github.com/rancher/types/config"
)

func Setup(ctx context.Context, mgmt *config.ScaledContext, clusterManager *clustermanager.Manager, k8sProxy http.Handler) error {
	// Here we setup all types that will be stored in the User cluster

	schemas := mgmt.Schemas

	addProxyStore(ctx, schemas, mgmt, client.ConfigMapType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, client.CronJobType, "batch/v1beta1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.DaemonSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.DeploymentType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.IngressType, "extensions/v1beta1", ingress.Wrap)
	addProxyStore(ctx, schemas, mgmt, client.JobType, "batch/v1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.PersistentVolumeClaimType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, client.PodType, "v1", func(store types.Store) types.Store {
		return pod.New(store, clusterManager, mgmt)
	})
	addProxyStore(ctx, schemas, mgmt, client.ReplicaSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.ReplicationControllerType, "v1", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, client.ServiceType, "v1", service.New)
	addProxyStore(ctx, schemas, mgmt, client.StatefulSetType, "apps/v1beta2", workload.NewCustomizeStore)
	addProxyStore(ctx, schemas, mgmt, clusterClient.NamespaceType, "v1", namespace.New)
	addProxyStore(ctx, schemas, mgmt, clusterClient.PersistentVolumeType, "v1", nil)
	addProxyStore(ctx, schemas, mgmt, clusterClient.StorageClassType, "storage.k8s.io/v1", nil)

	Secret(ctx, mgmt, schemas)
	Service(ctx, schemas, mgmt)
	Workload(schemas, clusterManager)
	Namespace(schemas, clusterManager)

	SetProjectID(schemas, clusterManager, k8sProxy)

	return nil
}

func SetProjectID(schemas *types.Schemas, clusterManager *clustermanager.Manager, k8sProxy http.Handler) {
	for _, schema := range schemas.SchemasForVersion(schema.Version) {
		if schema.Store == nil || schema.Store.Context() != config.UserStorageContext {
			continue
		}

		if schema.CanList(nil) != nil {
			continue
		}

		if _, ok := schema.ResourceFields["namespaceId"]; !ok {
			panic(schema.ID + " does not have namespaceId")
		}

		if _, ok := schema.ResourceFields["projectId"]; !ok {
			panic(schema.ID + " does not have projectId")
		}

		schema.Store = projectsetter.New(schema.Store, clusterManager)
		schema.Formatter = yaml.NewFormatter(schema.Formatter)
		schema.LinkHandler = yaml.NewLinkHandler(k8sProxy, clusterManager, schema.LinkHandler)
	}
}

func Namespace(schemas *types.Schemas, manager *clustermanager.Manager) {
	namespaceSchema := schemas.Schema(&clusterschema.Version, "namespace")
	namespaceSchema.LinkHandler = namespacecustom.NewLinkHandler(namespaceSchema.LinkHandler, manager)
	namespaceSchema.Formatter = yaml.NewFormatter(namespaceSchema.Formatter)
}

func Workload(schemas *types.Schemas, clusterManager *clustermanager.Manager) {
	workload.NewWorkloadAggregateStore(schemas, clusterManager)
}

func Service(ctx context.Context, schemas *types.Schemas, mgmt *config.ScaledContext) {
	serviceSchema := schemas.Schema(&schema.Version, "service")
	dnsSchema := schemas.Schema(&schema.Version, "dnsRecord")
	// Move service store to DNSRecord and create new store on service, so they are then
	// same store but two different instances
	dnsSchema.Store = serviceSchema.Store
	addProxyStore(ctx, schemas, mgmt, client.ServiceType, "v1", service.New)
}

func Secret(ctx context.Context, management *config.ScaledContext, schemas *types.Schemas) {
	schema := schemas.Schema(&schema.Version, "namespacedSecret")
	schema.Store = secret.NewNamespacedSecretStore(ctx, management.ClientGetter)

	for _, subSchema := range schemas.Schemas() {
		if subSchema.BaseType == schema.ID && subSchema.ID != schema.ID {
			subSchema.Store = subtype.NewSubTypeStore(subSchema.ID, schema.Store)
		}
	}

	schema = schemas.Schema(&schema.Version, "namespacedCertificate")
	schema.Store = cert.Wrap(schema.Store)
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative 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 config

import (
	"context"

	"knative.dev/pkg/configmap"
)

type channelCfgKey struct{}

// Config holds the collection of configurations that we attach to contexts.
// +k8s:deepcopy-gen=false
type Config struct {
	ChannelDefaults *ChannelDefaults
}

// FromContext extracts a Config from the provided context.
func FromContext(ctx context.Context) *Config {
	x, ok := ctx.Value(channelCfgKey{}).(*Config)
	if ok {
		return x
	}
	return nil
}

// FromContextOrDefaults is like FromContext, but when no Config is attached it
// returns a Config populated with the defaults for each of the Config fields.
func FromContextOrDefaults(ctx context.Context) *Config {
	if cfg := FromContext(ctx); cfg != nil {
		return cfg
	}
	channelDefaults, _ := NewChannelDefaultsConfigFromMap(map[string]string{})
	return &Config{
		ChannelDefaults: channelDefaults,
	}
}

// ToContext attaches the provided Config to the provided context, returning the
// new context with the Config attached.
func ToContext(ctx context.Context, c *Config) context.Context {
	return context.WithValue(ctx, channelCfgKey{}, c)
}

// Store is a typed wrapper around configmap.Untyped store to handle our configmaps.
// +k8s:deepcopy-gen=false
type Store struct {
	*configmap.UntypedStore
}

// NewStore creates a new store of Configs and optionally calls functions when ConfigMaps are updated.
func NewStore(logger configmap.Logger, onAfterStore ...func(name string, value interface{})) *Store {
	store := &Store{
		UntypedStore: configmap.NewUntypedStore(
			"chnaneldefaults",
			logger,
			configmap.Constructors{
				ChannelDefaultsConfigName: NewChannelDefaultsConfigFromConfigMap,
			},
			onAfterStore...,
		),
	}

	return store
}

// ToContext attaches the current Config state to the provided context.
func (s *Store) ToContext(ctx context.Context) context.Context {
	return ToContext(ctx, s.Load())
}

// Load creates a Config from the current config state of the Store.
func (s *Store) Load() *Config {
	return &Config{
		ChannelDefaults: s.UntypedLoad(ChannelDefaultsConfigName).(*ChannelDefaults).DeepCopy(),
	}
}
<commit_msg>Fix typo 'chnanel' -> 'channel'. (#3237)<commit_after>/*
Copyright 2020 The Knative 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 config

import (
	"context"

	"knative.dev/pkg/configmap"
)

type channelCfgKey struct{}

// Config holds the collection of configurations that we attach to contexts.
// +k8s:deepcopy-gen=false
type Config struct {
	ChannelDefaults *ChannelDefaults
}

// FromContext extracts a Config from the provided context.
func FromContext(ctx context.Context) *Config {
	x, ok := ctx.Value(channelCfgKey{}).(*Config)
	if ok {
		return x
	}
	return nil
}

// FromContextOrDefaults is like FromContext, but when no Config is attached it
// returns a Config populated with the defaults for each of the Config fields.
func FromContextOrDefaults(ctx context.Context) *Config {
	if cfg := FromContext(ctx); cfg != nil {
		return cfg
	}
	channelDefaults, _ := NewChannelDefaultsConfigFromMap(map[string]string{})
	return &Config{
		ChannelDefaults: channelDefaults,
	}
}

// ToContext attaches the provided Config to the provided context, returning the
// new context with the Config attached.
func ToContext(ctx context.Context, c *Config) context.Context {
	return context.WithValue(ctx, channelCfgKey{}, c)
}

// Store is a typed wrapper around configmap.Untyped store to handle our configmaps.
// +k8s:deepcopy-gen=false
type Store struct {
	*configmap.UntypedStore
}

// NewStore creates a new store of Configs and optionally calls functions when ConfigMaps are updated.
func NewStore(logger configmap.Logger, onAfterStore ...func(name string, value interface{})) *Store {
	store := &Store{
		UntypedStore: configmap.NewUntypedStore(
			"channeldefaults",
			logger,
			configmap.Constructors{
				ChannelDefaultsConfigName: NewChannelDefaultsConfigFromConfigMap,
			},
			onAfterStore...,
		),
	}

	return store
}

// ToContext attaches the current Config state to the provided context.
func (s *Store) ToContext(ctx context.Context) context.Context {
	return ToContext(ctx, s.Load())
}

// Load creates a Config from the current config state of the Store.
func (s *Store) Load() *Config {
	return &Config{
		ChannelDefaults: s.UntypedLoad(ChannelDefaultsConfigName).(*ChannelDefaults).DeepCopy(),
	}
}
<|endoftext|>


<commit_before>package metricsstore

import (
	"io"
	"sync"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/types"
)

// FamilyStringer represents a metric family that can be converted to its string
// representation.
type FamilyStringer interface {
	String() string
}

// MetricsStore implements the k8s.io/kubernetes/client-go/tools/cache.Store
// interface. Instead of storing entire Kubernetes objects, it stores metrics
// generated based on those objects.
type MetricsStore struct {
	// Protects metrics
	mutex sync.RWMutex
	// metrics is a map indexed by Kubernetes object id, containing a slice of
	// metric families, containing a slice of metrics. We need to keep metrics
	// grouped by metric families in order to zip families with their help text in
	// MetricsStore.WriteAll().
	metrics map[types.UID][]string
	// headers contains the header (TYPE and HELP) of each metric family. It is
	// later on zipped with with their corresponding metric families in
	// MetricStore.WriteAll().
	headers []string

	// generateMetricsFunc generates metrics based on a given Kubernetes object
	// and returns them grouped by metric family.
	generateMetricsFunc func(interface{}) []FamilyStringer
}

// NewMetricsStore returns a new MetricsStore
func NewMetricsStore(headers []string, generateFunc func(interface{}) []FamilyStringer) *MetricsStore {
	return &MetricsStore{
		generateMetricsFunc: generateFunc,
		headers:             headers,
		metrics:             map[types.UID][]string{},
	}
}

// Implementing k8s.io/kubernetes/client-go/tools/cache.Store interface

// TODO: Proper comments on all functions below.
func (s *MetricsStore) Add(obj interface{}) error {
	o, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()

	families := s.generateMetricsFunc(obj)
	familyStrings := make([]string, len(families))

	for i, f := range families {
		familyStrings[i] = f.String()
	}

	s.metrics[o.GetUID()] = familyStrings

	return nil
}

func (s *MetricsStore) Update(obj interface{}) error {
	// For now, just call Add, in the future one could check if the resource
	// version changed?
	return s.Add(obj)
}

func (s *MetricsStore) Delete(obj interface{}) error {

	o, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()

	delete(s.metrics, o.GetUID())

	return nil
}

func (s *MetricsStore) List() []interface{} {
	return nil
}

func (s *MetricsStore) ListKeys() []string {
	return nil
}

func (s *MetricsStore) Get(obj interface{}) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

func (s *MetricsStore) GetByKey(key string) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

// Replace will delete the contents of the store, using instead the
// given list.
func (s *MetricsStore) Replace(list []interface{}, _ string) error {
	s.mutex.Lock()
	s.metrics = map[types.UID][]string{}
	s.mutex.Unlock()

	for _, o := range list {
		err := s.Add(o)
		if err != nil {
			return err
		}
	}

	return nil
}

func (s *MetricsStore) Resync() error {
	return nil
}

// WriteAll writes all metrics of the store into the given writer, zipped with the
// help text of each metric family.
func (s *MetricsStore) WriteAll(w io.Writer) {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	for i, help := range s.headers {
		w.Write([]byte(help))
		w.Write([]byte{'\n'})
		for _, metricFamilies := range s.metrics {
			w.Write([]byte(metricFamilies[i]))
		}
	}
}
<commit_msg>clarify the import location of Store interface in comments<commit_after>package metricsstore

import (
	"io"
	"sync"

	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/types"
)

// FamilyStringer represents a metric family that can be converted to its string
// representation.
type FamilyStringer interface {
	String() string
}

// MetricsStore implements the k8s.io/client-go/tools/cache.Store
// interface. Instead of storing entire Kubernetes objects, it stores metrics
// generated based on those objects.
type MetricsStore struct {
	// Protects metrics
	mutex sync.RWMutex
	// metrics is a map indexed by Kubernetes object id, containing a slice of
	// metric families, containing a slice of metrics. We need to keep metrics
	// grouped by metric families in order to zip families with their help text in
	// MetricsStore.WriteAll().
	metrics map[types.UID][]string
	// headers contains the header (TYPE and HELP) of each metric family. It is
	// later on zipped with with their corresponding metric families in
	// MetricStore.WriteAll().
	headers []string

	// generateMetricsFunc generates metrics based on a given Kubernetes object
	// and returns them grouped by metric family.
	generateMetricsFunc func(interface{}) []FamilyStringer
}

// NewMetricsStore returns a new MetricsStore
func NewMetricsStore(headers []string, generateFunc func(interface{}) []FamilyStringer) *MetricsStore {
	return &MetricsStore{
		generateMetricsFunc: generateFunc,
		headers:             headers,
		metrics:             map[types.UID][]string{},
	}
}

// Implementing k8s.io/client-go/tools/cache.Store interface

// TODO: Proper comments on all functions below.
func (s *MetricsStore) Add(obj interface{}) error {
	o, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()

	families := s.generateMetricsFunc(obj)
	familyStrings := make([]string, len(families))

	for i, f := range families {
		familyStrings[i] = f.String()
	}

	s.metrics[o.GetUID()] = familyStrings

	return nil
}

func (s *MetricsStore) Update(obj interface{}) error {
	// For now, just call Add, in the future one could check if the resource
	// version changed?
	return s.Add(obj)
}

func (s *MetricsStore) Delete(obj interface{}) error {

	o, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	s.mutex.Lock()
	defer s.mutex.Unlock()

	delete(s.metrics, o.GetUID())

	return nil
}

func (s *MetricsStore) List() []interface{} {
	return nil
}

func (s *MetricsStore) ListKeys() []string {
	return nil
}

func (s *MetricsStore) Get(obj interface{}) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

func (s *MetricsStore) GetByKey(key string) (item interface{}, exists bool, err error) {
	return nil, false, nil
}

// Replace will delete the contents of the store, using instead the
// given list.
func (s *MetricsStore) Replace(list []interface{}, _ string) error {
	s.mutex.Lock()
	s.metrics = map[types.UID][]string{}
	s.mutex.Unlock()

	for _, o := range list {
		err := s.Add(o)
		if err != nil {
			return err
		}
	}

	return nil
}

func (s *MetricsStore) Resync() error {
	return nil
}

// WriteAll writes all metrics of the store into the given writer, zipped with the
// help text of each metric family.
func (s *MetricsStore) WriteAll(w io.Writer) {
	s.mutex.RLock()
	defer s.mutex.RUnlock()

	for i, help := range s.headers {
		w.Write([]byte(help))
		w.Write([]byte{'\n'})
		for _, metricFamilies := range s.metrics {
			w.Write([]byte(metricFamilies[i]))
		}
	}
}
<|endoftext|>