<commit_before>package main

import "github.com/nsf/termbox-go"
import "fmt"
import "os"
import "io/ioutil"
import "path/filepath"

type Editor struct {
	screen     *Screen
	file       *File
	files      []*File
	fileIdx    int
	keyboard   *Keyboard
	flushChan  chan struct{}
	msg        string
	copyBuffer Buffer
	copyContig int
}

func NewEditor() *Editor {
	return &Editor{
		flushChan:  make(chan struct{}, 1),
		screen:     NewScreen(),
		copyBuffer: MakeBuffer([]string{}),
		copyContig: 0,
	}
}

func (editor *Editor) OpenNewFile() {
	dir, _ := os.Getwd()
	dir += "/"
	names := []string{}
	idx := 0
	files := []os.FileInfo{}
	for {
		files, _ = ioutil.ReadDir(dir)
		dotdot, err := os.Stat("../")
		if err == nil {
			files = append([]os.FileInfo{dotdot}, files...)
		}
		names = []string{}
		for _, file := range files {
			if file.IsDir() {
				names = append(names, file.Name()+"/")
			} else {
				names = append(names, file.Name())
			}
		}
		menu := NewMenu(editor.screen)
		idx = menu.Choose(names)
		editor.Flush()
		if idx < 0 {
			return
		}
		chosenFile := files[idx]
		if chosenFile.IsDir() {
			dir = filepath.Clean(dir+chosenFile.Name()) + "/"
		} else {
			break
		}
	}
	editor.OpenFile(names[idx])
	editor.fileIdx = len(editor.files) - 1
	editor.file = editor.files[editor.fileIdx]
}

func (editor *Editor) OpenFile(name string) {
	file := NewFile(name, editor.flushChan, editor.screen)
	file.syntaxRules = NewSyntaxRules(name)
	editor.files = append(editor.files, file)
}

func (editor *Editor) OpenFiles(fileNames []string) {
	for _, name := range fileNames {
		editor.OpenFile(name)
	}
	if len(editor.files) == 0 {
		editor.files = append(editor.files, NewFile("", editor.flushChan, editor.screen))
	}
	editor.fileIdx = 0
	editor.file = editor.files[0]
}

func (editor *Editor) Quit() {
	for _, _ = range editor.files {
		if !editor.CloseFile() {
			editor.NextFile()
		}
	}
}

func (editor *Editor) CloseFile() bool {
	editor.Flush()
	idx := editor.fileIdx
	if !editor.files[idx].Close() {
		return false
	}
	editor.files = append(editor.files[:idx], editor.files[idx+1:]...)
	if len(editor.files) == 0 {
		editor.screen.Close()
		os.Exit(0)
	}
	editor.NextFile()
	return true
}

func (editor *Editor) Listen() {

	keyboard := NewKeyboard()
	for {
		cmd, r := keyboard.GetKey()
		editor.msg = ""
		switch cmd {
		case "backspace":
			editor.file.Backspace()
		case "delete":
			editor.file.Delete()
		case "space":
			editor.file.InsertChar(' ')
		case "tab":
			editor.file.InsertChar('\t')
		case "enter":
			editor.file.Newline()
		case "arrowLeft", "ctrlO":
			editor.file.CursorLeft()
		case "arrowRight", "ctrlL":
			editor.file.CursorRight()
		case "arrowUp", "ctrlK":
			editor.file.CursorUp(1)
		case "arrowDown", "ctrlJ":
			editor.file.CursorDown(1)
		case "ctrlU":
			editor.file.ScrollUp()
		case "ctrlP":
			editor.file.ScrollDown()
		case "altP":
			editor.file.ScrollRight()
		case "altU":
			editor.file.ScrollLeft()
		case "pageDown", "ctrlN":
			editor.file.CursorDown(10)
		case "pageUp", "ctrlB":
			editor.file.CursorUp(10)
		case "altL":
			editor.file.Refresh()
		case "altO":
			editor.OpenNewFile()
		case "altQ":
			editor.Quit()
		case "altW":
			editor.CloseFile()
		case "altN":
			editor.NextFile()
		case "altB":
			editor.PrevFile()
		case "altM":
			editor.SelectFile()
		case "ctrlX":
			editor.file.AddCursor()
		case "altC":
			editor.file.AddCursorCol()
		case "altX":
			editor.file.ClearCursors()
		case "ctrlZ":
			editor.Undo()
		case "ctrlY":
			editor.Redo()
		case "ctrlS":
			editor.Save()
		case "ctrlA":
			editor.file.StartOfLine()
		case "ctrlE":
			editor.file.EndOfLine()
		case "ctrlW":
			editor.file.NextWord()
		case "ctrlQ":
			editor.file.PrevWord()
		case "ctrlF":
			editor.Search()
		case "altF":
			editor.SearchAndReplace()
		case "ctrlC":
			editor.Cut()
		case "ctrlV":
			editor.Paste()
		case "altG":
			editor.file.GoFmt()
		case "altJ":
			editor.file.Justify()
		case "unknown":
			editor.msg = "Unknown keypress"
		case "char":
			editor.file.InsertChar(r)
		default:
			editor.msg = "Unknown keypress"
		}
		editor.copyContig--
		editor.RequestFlush()
	}

}

func (editor *Editor) Cut() {
	if editor.copyContig > 0 {
		editor.copyBuffer = append(editor.copyBuffer, editor.file.Cut()...)
	} else {
		editor.copyBuffer = editor.file.Cut()
	}
	editor.copyContig = 2
}

func (editor *Editor) Search() {
	editor.file.Search()
}

func (editor *Editor) SearchAndReplace() {
	editor.file.SearchAndReplace()
}

func (editor *Editor) Paste() {
	editor.file.Paste(editor.copyBuffer)
}

func (editor *Editor) Undo() {
	editor.file.Undo()
}

func (editor *Editor) Redo() {
	editor.file.Redo()
}

func (editor *Editor) NextFile() {
	editor.SwitchFile(editor.fileIdx + 1)
}

func (editor *Editor) PrevFile() {
	editor.SwitchFile(editor.fileIdx - 1)
}

func (editor *Editor) SelectFile() {
	names := []string{}
	for _, file := range editor.files {
		names = append(names, file.name)
	}
	menu := NewMenu(editor.screen)
	idx := menu.Choose(names)
	if idx > 0 {
		editor.SwitchFile(idx)
	}
}

func (editor *Editor) Save() {
	editor.msg = editor.file.Save()
}

func intMod(a, n int) int {
	if a >= 0 {
		return a - n*(a/n)
	} else {
		return a - n*((a-n+1)/n)
	}
}

func (editor *Editor) SwitchFile(n int) {
	n = intMod(n, len(editor.files))
	editor.fileIdx = n
	editor.file = editor.files[n]
}

func (editor *Editor) HighlightCursors() {
	cells := termbox.CellBuffer()
	cols, _ := termbox.Size()
	for k, _ := range editor.file.multiCursor[1:] {
		r, c := editor.file.GetCursor(k + 1)
		j := r*cols + c
		if j < 0 || j >= len(cells) {
			continue
		}
		cell := cells[j]
		cells[j].Bg, cells[j].Fg = cell.Fg, cell.Bg
	}
}

func (editor *Editor) Flush() {
	editor.file.Flush()
	editor.HighlightCursors()
	editor.UpdateStatus()
	editor.screen.WriteMessage(editor.msg)
	editor.screen.Flush()
}

func (editor *Editor) KeepFlushed() {
	go func() {
		for {
			<-editor.flushChan
			editor.Flush()
		}
	}()
}

func (editor *Editor) RequestFlush() {
	select {
	case editor.flushChan <- struct{}{}:
	default:
	}
}

func (editor *Editor) UpdateStatus() {
	cols, rows := termbox.Size()
	message := fmt.Sprintf("%s (%d/%d)   %d/%d,%d",
		editor.file.name,
		editor.fileIdx,
		len(editor.files),
		editor.file.multiCursor[0].row,
		len(editor.file.buffer)-1,
		editor.file.multiCursor[0].col,
	)
	col := cols - len(message)
	editor.screen.WriteString(rows-1, col, message)
	editor.screen.WriteString(rows-1, 0, "[ Sith ]")
	editor.screen.DecorateStatusLine()
	editor.file.WriteStatus(rows-1, col)
	editor.screen.SetCursor(editor.file.GetCursor(0))
}

<commit_msg>bugfix: allow menu index to zero so can switch to any buffer<commit_after>package main

import "github.com/nsf/termbox-go"
import "fmt"
import "os"
import "io/ioutil"
import "path/filepath"

type Editor struct {
	screen     *Screen
	file       *File
	files      []*File
	fileIdx    int
	keyboard   *Keyboard
	flushChan  chan struct{}
	msg        string
	copyBuffer Buffer
	copyContig int
}

func NewEditor() *Editor {
	return &Editor{
		flushChan:  make(chan struct{}, 1),
		screen:     NewScreen(),
		copyBuffer: MakeBuffer([]string{}),
		copyContig: 0,
	}
}

func (editor *Editor) OpenNewFile() {
	dir, _ := os.Getwd()
	dir += "/"
	names := []string{}
	idx := 0
	files := []os.FileInfo{}
	for {
		files, _ = ioutil.ReadDir(dir)
		dotdot, err := os.Stat("../")
		if err == nil {
			files = append([]os.FileInfo{dotdot}, files...)
		}
		names = []string{}
		for _, file := range files {
			if file.IsDir() {
				names = append(names, file.Name()+"/")
			} else {
				names = append(names, file.Name())
			}
		}
		menu := NewMenu(editor.screen)
		idx = menu.Choose(names)
		editor.Flush()
		if idx < 0 {
			return
		}
		chosenFile := files[idx]
		if chosenFile.IsDir() {
			dir = filepath.Clean(dir+chosenFile.Name()) + "/"
		} else {
			break
		}
	}
	editor.OpenFile(names[idx])
	editor.fileIdx = len(editor.files) - 1
	editor.file = editor.files[editor.fileIdx]
}

func (editor *Editor) OpenFile(name string) {
	file := NewFile(name, editor.flushChan, editor.screen)
	file.syntaxRules = NewSyntaxRules(name)
	editor.files = append(editor.files, file)
}

func (editor *Editor) OpenFiles(fileNames []string) {
	for _, name := range fileNames {
		editor.OpenFile(name)
	}
	if len(editor.files) == 0 {
		editor.files = append(editor.files, NewFile("", editor.flushChan, editor.screen))
	}
	editor.fileIdx = 0
	editor.file = editor.files[0]
}

func (editor *Editor) Quit() {
	for _, _ = range editor.files {
		if !editor.CloseFile() {
			editor.NextFile()
		}
	}
}

func (editor *Editor) CloseFile() bool {
	editor.Flush()
	idx := editor.fileIdx
	if !editor.files[idx].Close() {
		return false
	}
	editor.files = append(editor.files[:idx], editor.files[idx+1:]...)
	if len(editor.files) == 0 {
		editor.screen.Close()
		os.Exit(0)
	}
	editor.NextFile()
	return true
}

func (editor *Editor) Listen() {

	keyboard := NewKeyboard()
	for {
		cmd, r := keyboard.GetKey()
		editor.msg = ""
		switch cmd {
		case "backspace":
			editor.file.Backspace()
		case "delete":
			editor.file.Delete()
		case "space":
			editor.file.InsertChar(' ')
		case "tab":
			editor.file.InsertChar('\t')
		case "enter":
			editor.file.Newline()
		case "arrowLeft", "ctrlO":
			editor.file.CursorLeft()
		case "arrowRight", "ctrlL":
			editor.file.CursorRight()
		case "arrowUp", "ctrlK":
			editor.file.CursorUp(1)
		case "arrowDown", "ctrlJ":
			editor.file.CursorDown(1)
		case "ctrlU":
			editor.file.ScrollUp()
		case "ctrlP":
			editor.file.ScrollDown()
		case "altP":
			editor.file.ScrollRight()
		case "altU":
			editor.file.ScrollLeft()
		case "pageDown", "ctrlN":
			editor.file.CursorDown(10)
		case "pageUp", "ctrlB":
			editor.file.CursorUp(10)
		case "altL":
			editor.file.Refresh()
		case "altO":
			editor.OpenNewFile()
		case "altQ":
			editor.Quit()
		case "altW":
			editor.CloseFile()
		case "altN":
			editor.NextFile()
		case "altB":
			editor.PrevFile()
		case "altM":
			editor.SelectFile()
		case "ctrlX":
			editor.file.AddCursor()
		case "altC":
			editor.file.AddCursorCol()
		case "altX":
			editor.file.ClearCursors()
		case "ctrlZ":
			editor.Undo()
		case "ctrlY":
			editor.Redo()
		case "ctrlS":
			editor.Save()
		case "ctrlA":
			editor.file.StartOfLine()
		case "ctrlE":
			editor.file.EndOfLine()
		case "ctrlW":
			editor.file.NextWord()
		case "ctrlQ":
			editor.file.PrevWord()
		case "ctrlF":
			editor.Search()
		case "altF":
			editor.SearchAndReplace()
		case "ctrlC":
			editor.Cut()
		case "ctrlV":
			editor.Paste()
		case "altG":
			editor.file.GoFmt()
		case "altJ":
			editor.file.Justify()
		case "unknown":
			editor.msg = "Unknown keypress"
		case "char":
			editor.file.InsertChar(r)
		default:
			editor.msg = "Unknown keypress"
		}
		editor.copyContig--
		editor.RequestFlush()
	}

}

func (editor *Editor) Cut() {
	if editor.copyContig > 0 {
		editor.copyBuffer = append(editor.copyBuffer, editor.file.Cut()...)
	} else {
		editor.copyBuffer = editor.file.Cut()
	}
	editor.copyContig = 2
}

func (editor *Editor) Search() {
	editor.file.Search()
}

func (editor *Editor) SearchAndReplace() {
	editor.file.SearchAndReplace()
}

func (editor *Editor) Paste() {
	editor.file.Paste(editor.copyBuffer)
}

func (editor *Editor) Undo() {
	editor.file.Undo()
}

func (editor *Editor) Redo() {
	editor.file.Redo()
}

func (editor *Editor) NextFile() {
	editor.SwitchFile(editor.fileIdx + 1)
}

func (editor *Editor) PrevFile() {
	editor.SwitchFile(editor.fileIdx - 1)
}

func (editor *Editor) SelectFile() {
	names := []string{}
	for _, file := range editor.files {
		names = append(names, file.name)
	}
	menu := NewMenu(editor.screen)
	idx := menu.Choose(names)
	if idx >= 0 {
		editor.SwitchFile(idx)
	}
}

func (editor *Editor) Save() {
	editor.msg = editor.file.Save()
}

func intMod(a, n int) int {
	if a >= 0 {
		return a - n*(a/n)
	} else {
		return a - n*((a-n+1)/n)
	}
}

func (editor *Editor) SwitchFile(n int) {
	n = intMod(n, len(editor.files))
	editor.fileIdx = n
	editor.file = editor.files[n]
}

func (editor *Editor) HighlightCursors() {
	cells := termbox.CellBuffer()
	cols, _ := termbox.Size()
	for k, _ := range editor.file.multiCursor[1:] {
		r, c := editor.file.GetCursor(k + 1)
		j := r*cols + c
		if j < 0 || j >= len(cells) {
			continue
		}
		cell := cells[j]
		cells[j].Bg, cells[j].Fg = cell.Fg, cell.Bg
	}
}

func (editor *Editor) Flush() {
	editor.file.Flush()
	editor.HighlightCursors()
	editor.UpdateStatus()
	editor.screen.WriteMessage(editor.msg)
	editor.screen.Flush()
}

func (editor *Editor) KeepFlushed() {
	go func() {
		for {
			<-editor.flushChan
			editor.Flush()
		}
	}()
}

func (editor *Editor) RequestFlush() {
	select {
	case editor.flushChan <- struct{}{}:
	default:
	}
}

func (editor *Editor) UpdateStatus() {
	cols, rows := termbox.Size()
	message := fmt.Sprintf("%s (%d/%d)   %d/%d,%d",
		editor.file.name,
		editor.fileIdx,
		len(editor.files),
		editor.file.multiCursor[0].row,
		len(editor.file.buffer)-1,
		editor.file.multiCursor[0].col,
	)
	col := cols - len(message)
	editor.screen.WriteString(rows-1, col, message)
	editor.screen.WriteString(rows-1, 0, "[ Sith ]")
	editor.screen.DecorateStatusLine()
	editor.file.WriteStatus(rows-1, col)
	editor.screen.SetCursor(editor.file.GetCursor(0))
}

<|endoftext|>


<commit_before>// Copyright 2013 bee 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 main

import (
	"bytes"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
)

var (
	cmd          *exec.Cmd
	state        sync.Mutex
	eventTime    = make(map[string]int64)
	scheduleTime time.Time
)

// NewWatcher starts an fsnotify Watcher on the specified paths
func NewWatcher(paths []string, files []string, isgenerate bool) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		logger.Fatalf("Failed to create watcher: %s", err)
	}

	go func() {
		for {
			select {
			case e := <-watcher.Events:
				isbuild := true

				// Skip ignored files
				if shouldIgnoreFile(e.Name) {
					continue
				}
				if !shouldWatchFileWithExtension(e.Name) {
					continue
				}

				mt := getFileModTime(e.Name)
				if t := eventTime[e.Name]; mt == t {
					logger.Infof(bold("Skipping: ")+"%s", e.String())
					isbuild = false
				}

				eventTime[e.Name] = mt

				if isbuild {
					logger.Infof("Event fired: %s", e)
					go func() {
						// Wait 1s before autobuild util there is no file change.
						scheduleTime = time.Now().Add(1 * time.Second)
						for {
							time.Sleep(scheduleTime.Sub(time.Now()))
							if time.Now().After(scheduleTime) {
								break
							}
							return
						}
						AutoBuild(files, isgenerate)

						if conf.EnableReload {
							sendReload(e.String())
						}
					}()
				}
			case err := <-watcher.Errors:
				logger.Warnf("Watcher error: %s", err.Error()) // No need to exit here
			}
		}
	}()

	logger.Info("Initializing watcher...")
	for _, path := range paths {
		logger.Infof(bold("Watching: ")+"%s", path)
		err = watcher.Add(path)
		if err != nil {
			logger.Fatalf("Failed to watch directory: %s", err)
		}
	}
}

// getFileModTime returns unix timestamp of `os.File.ModTime` for the given path.
func getFileModTime(path string) int64 {
	path = strings.Replace(path, "\\", "/", -1)
	f, err := os.Open(path)
	if err != nil {
		logger.Errorf("Failed to open file on '%s': %s", path, err)
		return time.Now().Unix()
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		logger.Errorf("Failed to get file stats: %s", err)
		return time.Now().Unix()
	}

	return fi.ModTime().Unix()
}

// AutoBuild builds the specified set of files
func AutoBuild(files []string, isgenerate bool) {
	state.Lock()
	defer state.Unlock()

	os.Chdir(currpath)

	cmdName := "go"
	if conf.Gopm.Enable {
		cmdName = "gopm"
	}

	var (
		err    error
		stderr bytes.Buffer
		stdout bytes.Buffer
	)
	// For applications use full import path like "github.com/.../.."
	// are able to use "go install" to reduce build time.
	if conf.GoInstall {
		icmd := exec.Command(cmdName, "install", "-v")
		icmd.Stdout = os.Stdout
		icmd.Stderr = os.Stderr
		icmd.Env = append(os.Environ(), "GOGC=off")
		icmd.Run()
	}
	if conf.Gopm.Install {
		icmd := exec.Command("go", "list", "./...")
		icmd.Stdout = &stdout
		icmd.Env = append(os.Environ(), "GOGC=off")
		err = icmd.Run()
		if err == nil {
			list := strings.Split(stdout.String(), "\n")[1:]
			for _, pkg := range list {
				if len(pkg) == 0 {
					continue
				}
				icmd = exec.Command(cmdName, "install", pkg)
				icmd.Stdout = os.Stdout
				icmd.Stderr = os.Stderr
				icmd.Env = append(os.Environ(), "GOGC=off")
				err = icmd.Run()
				if err != nil {
					break
				}
			}
		}
	}

	if isgenerate {
		logger.Info("Generating the docs...")
		icmd := exec.Command("bee", "generate", "docs")
		icmd.Env = append(os.Environ(), "GOGC=off")
		err = icmd.Run()
		if err != nil {
			logger.Errorf("Failed to generate the docs.")
			return
		}
		logger.Success("Docs generated!")
	}

	if err == nil {
		appName := appname
		if runtime.GOOS == "windows" {
			appName += ".exe"
		}

		args := []string{"build"}
		args = append(args, "-o", appName)
		if buildTags != "" {
			args = append(args, "-tags", buildTags)
		}
		args = append(args, files...)

		bcmd := exec.Command(cmdName, args...)
		bcmd.Env = append(os.Environ(), "GOGC=off")
		bcmd.Stderr = &stderr
		err = bcmd.Run()
		if err != nil {
			logger.Errorf("Failed to build the application: %s", stderr.String())
			return
		}
	}

	logger.Success("Built Successfully!")
	Restart(appname)
}

// Kill kills the running command process
func Kill() {
	defer func() {
		if e := recover(); e != nil {
			logger.Infof("Kill recover: %s", e)
		}
	}()
	if cmd != nil && cmd.Process != nil {
		err := cmd.Process.Kill()
		if err != nil {
			logger.Errorf("Error while killing cmd process: %s", err)
		}
	}
}

// Restart kills the running command process and starts it again
func Restart(appname string) {
	logger.Debugf("Kill running process", __FILE__(), __LINE__())
	Kill()
	go Start(appname)
}

// Start starts the command process
func Start(appname string) {
	logger.Infof("Restarting '%s'...", appname)
	if strings.Index(appname, "./") == -1 {
		appname = "./" + appname
	}

	cmd = exec.Command(appname)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Args = append([]string{appname}, conf.CmdArgs...)
	cmd.Env = append(os.Environ(), conf.Envs...)

	go cmd.Run()
	logger.Successf("'%s' is running...", appname)
	started <- true
}

// shouldIgnoreFile ignores filenames generated by Emacs, Vim or SublimeText.
// It returns true if the file should be ignored, false otherwise.
func shouldIgnoreFile(filename string) bool {
	for _, regex := range ignoredFilesRegExps {
		r, err := regexp.Compile(regex)
		if err != nil {
			logger.Fatalf("Could not compile regular expression: %s", err)
		}
		if r.MatchString(filename) {
			return true
		}
		continue
	}
	return false
}

var watchExts = []string{".go"}
var ignoredFilesRegExps = []string{
	`.#(\w+).go`,
	`.(\w+).go.swp`,
	`(\w+).go~`,
	`(\w+).tmp`,
}

// shouldWatchFileWithExtension returns true if the name of the file
// hash a suffix that should be watched.
func shouldWatchFileWithExtension(name string) bool {
	for _, s := range watchExts {
		if strings.HasSuffix(name, s) {
			return true
		}
	}
	return false
}
<commit_msg>Fixes #351<commit_after>// Copyright 2013 bee 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 main

import (
	"bytes"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
)

var (
	cmd          *exec.Cmd
	state        sync.Mutex
	eventTime    = make(map[string]int64)
	scheduleTime time.Time
)

// NewWatcher starts an fsnotify Watcher on the specified paths
func NewWatcher(paths []string, files []string, isgenerate bool) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		logger.Fatalf("Failed to create watcher: %s", err)
	}

	go func() {
		for {
			select {
			case e := <-watcher.Events:
				isbuild := true

				// Skip ignored files
				if shouldIgnoreFile(e.Name) {
					continue
				}
				if !shouldWatchFileWithExtension(e.Name) {
					continue
				}

				mt := getFileModTime(e.Name)
				if t := eventTime[e.Name]; mt == t {
					logger.Infof(bold("Skipping: ")+"%s", e.String())
					isbuild = false
				}

				eventTime[e.Name] = mt

				if isbuild {
					logger.Infof("Event fired: %s", e)
					go func() {
						// Wait 1s before autobuild until there is no file change.
						scheduleTime = time.Now().Add(1 * time.Second)
						time.Sleep(scheduleTime.Sub(time.Now()))
						AutoBuild(files, isgenerate)

						if conf.EnableReload {
							sendReload(e.String())
						}
					}()
				}
			case err := <-watcher.Errors:
				logger.Warnf("Watcher error: %s", err.Error()) // No need to exit here
			}
		}
	}()

	logger.Info("Initializing watcher...")
	for _, path := range paths {
		logger.Infof(bold("Watching: ")+"%s", path)
		err = watcher.Add(path)
		if err != nil {
			logger.Fatalf("Failed to watch directory: %s", err)
		}
	}
}

// getFileModTime returns unix timestamp of `os.File.ModTime` for the given path.
func getFileModTime(path string) int64 {
	path = strings.Replace(path, "\\", "/", -1)
	f, err := os.Open(path)
	if err != nil {
		logger.Errorf("Failed to open file on '%s': %s", path, err)
		return time.Now().Unix()
	}
	defer f.Close()

	fi, err := f.Stat()
	if err != nil {
		logger.Errorf("Failed to get file stats: %s", err)
		return time.Now().Unix()
	}

	return fi.ModTime().Unix()
}

// AutoBuild builds the specified set of files
func AutoBuild(files []string, isgenerate bool) {
	state.Lock()
	defer state.Unlock()

	os.Chdir(currpath)

	cmdName := "go"
	if conf.Gopm.Enable {
		cmdName = "gopm"
	}

	var (
		err    error
		stderr bytes.Buffer
		stdout bytes.Buffer
	)
	// For applications use full import path like "github.com/.../.."
	// are able to use "go install" to reduce build time.
	if conf.GoInstall {
		icmd := exec.Command(cmdName, "install", "-v")
		icmd.Stdout = os.Stdout
		icmd.Stderr = os.Stderr
		icmd.Env = append(os.Environ(), "GOGC=off")
		icmd.Run()
	}
	if conf.Gopm.Install {
		icmd := exec.Command("go", "list", "./...")
		icmd.Stdout = &stdout
		icmd.Env = append(os.Environ(), "GOGC=off")
		err = icmd.Run()
		if err == nil {
			list := strings.Split(stdout.String(), "\n")[1:]
			for _, pkg := range list {
				if len(pkg) == 0 {
					continue
				}
				icmd = exec.Command(cmdName, "install", pkg)
				icmd.Stdout = os.Stdout
				icmd.Stderr = os.Stderr
				icmd.Env = append(os.Environ(), "GOGC=off")
				err = icmd.Run()
				if err != nil {
					break
				}
			}
		}
	}

	if isgenerate {
		logger.Info("Generating the docs...")
		icmd := exec.Command("bee", "generate", "docs")
		icmd.Env = append(os.Environ(), "GOGC=off")
		err = icmd.Run()
		if err != nil {
			logger.Errorf("Failed to generate the docs.")
			return
		}
		logger.Success("Docs generated!")
	}

	if err == nil {
		appName := appname
		if runtime.GOOS == "windows" {
			appName += ".exe"
		}

		args := []string{"build"}
		args = append(args, "-o", appName)
		if buildTags != "" {
			args = append(args, "-tags", buildTags)
		}
		args = append(args, files...)

		bcmd := exec.Command(cmdName, args...)
		bcmd.Env = append(os.Environ(), "GOGC=off")
		bcmd.Stderr = &stderr
		err = bcmd.Run()
		if err != nil {
			logger.Errorf("Failed to build the application: %s", stderr.String())
			return
		}
	}

	logger.Success("Built Successfully!")
	Restart(appname)
}

// Kill kills the running command process
func Kill() {
	defer func() {
		if e := recover(); e != nil {
			logger.Infof("Kill recover: %s", e)
		}
	}()
	if cmd != nil && cmd.Process != nil {
		err := cmd.Process.Kill()
		if err != nil {
			logger.Errorf("Error while killing cmd process: %s", err)
		}
	}
}

// Restart kills the running command process and starts it again
func Restart(appname string) {
	logger.Debugf("Kill running process", __FILE__(), __LINE__())
	Kill()
	go Start(appname)
}

// Start starts the command process
func Start(appname string) {
	logger.Infof("Restarting '%s'...", appname)
	if strings.Index(appname, "./") == -1 {
		appname = "./" + appname
	}

	cmd = exec.Command(appname)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Args = append([]string{appname}, conf.CmdArgs...)
	cmd.Env = append(os.Environ(), conf.Envs...)

	go cmd.Run()
	logger.Successf("'%s' is running...", appname)
	started <- true
}

// shouldIgnoreFile ignores filenames generated by Emacs, Vim or SublimeText.
// It returns true if the file should be ignored, false otherwise.
func shouldIgnoreFile(filename string) bool {
	for _, regex := range ignoredFilesRegExps {
		r, err := regexp.Compile(regex)
		if err != nil {
			logger.Fatalf("Could not compile regular expression: %s", err)
		}
		if r.MatchString(filename) {
			return true
		}
		continue
	}
	return false
}

var watchExts = []string{".go"}
var ignoredFilesRegExps = []string{
	`.#(\w+).go`,
	`.(\w+).go.swp`,
	`(\w+).go~`,
	`(\w+).tmp`,
}

// shouldWatchFileWithExtension returns true if the name of the file
// hash a suffix that should be watched.
func shouldWatchFileWithExtension(name string) bool {
	for _, s := range watchExts {
		if strings.HasSuffix(name, s) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before><commit_msg>Add tests verifying that vertex membership is verified by Search<commit_after><|endoftext|>


<commit_before>// Copyright 2017 CoreOS, Inc.
//
// 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 upstream

import (
	"fmt"
	"os"

	"github.com/coreos-inc/pluton"
)

// Runs conformance tests on a master node of a Cluster
func RunConformanceTests(c *pluton.Cluster, k8sRepo, k8sVersion string) error {
	const (
		kcPath  = "/etc/kubernetes/kubeconfig"
		goImage = "docker://golang:1.7.4"
	)

	cmds := []string{
		fmt.Sprintf("git clone https://%s /home/core/k8s", k8sRepo),
		"mkdir /home/core/artifacts",
	}
	for _, cmd := range cmds {
		if _, err := c.Masters[0].SSH(cmd); err != nil {
			return err
		}
	}

	runConformance := fmt.Sprintf(`sudo /usr/bin/rkt --insecure-options=image run \
		--volume=kc,kind=host,source=%s \
		--volume=k8s,kind=host,source=/home/core/k8s \
		--mount volume=kc,target=/kubeconfig \
		--mount volume=k8s,target=/go/src/k8s.io/kubernetes \
		%s --exec /bin/bash -- -c "\
		apt-get update && \
		apt-get install -y rsync && \
		go get -u github.com/jteeuwen/go-bindata/go-bindata && \
		cd /go/src/k8s.io/kubernetes && \
 		git checkout %s && \
		make all WHAT=cmd/kubectl && \
 		make all WHAT=vendor/github.com/onsi/ginkgo/ginkgo && \
		make all WHAT=test/e2e/e2e.test && \
		KUBECONFIG=/kubeconfig KUBERNETES_PROVIDER=skeleton KUBERNETES_CONFORMANCE_TEST=Y go run hack/e2e.go \
 		-v --test -check_version_skew=false --test_args='--ginkgo.focus=\[Conformance\]'"`,
		kcPath, goImage, k8sVersion)

	// stream conformance output
	client, err := c.Masters[0].SSHClient()
	if err != nil {
		return err
	}
	defer client.Close()
	session, err := client.NewSession()
	if err != nil {
		return err
	}
	defer session.Close()

	session.Stderr = os.Stderr
	session.Stdout = os.Stdout

	if err := session.Run(runConformance); err != nil {
		return fmt.Errorf("Error in conformance run: %s", err)
	}

	return nil
}
<commit_msg>upstream: use admin-kubeconfig for test<commit_after>// Copyright 2017 CoreOS, Inc.
//
// 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 upstream

import (
	"fmt"
	"os"

	"github.com/coreos-inc/pluton"
)

// Runs conformance tests on a master node of a Cluster
func RunConformanceTests(c *pluton.Cluster, k8sRepo, k8sVersion string) error {
	const (
		kcPath  = "/etc/kubernetes/admin-kubeconfig"
		goImage = "docker://golang:1.7.4"
	)

	cmds := []string{
		fmt.Sprintf("git clone https://%s /home/core/k8s", k8sRepo),
		"mkdir /home/core/artifacts",
	}
	for _, cmd := range cmds {
		if _, err := c.Masters[0].SSH(cmd); err != nil {
			return err
		}
	}

	runConformance := fmt.Sprintf(`sudo /usr/bin/rkt --insecure-options=image run \
		--volume=kc,kind=host,source=%s \
		--volume=k8s,kind=host,source=/home/core/k8s \
		--mount volume=kc,target=/kubeconfig \
		--mount volume=k8s,target=/go/src/k8s.io/kubernetes \
		%s --exec /bin/bash -- -c "\
		apt-get update && \
		apt-get install -y rsync && \
		go get -u github.com/jteeuwen/go-bindata/go-bindata && \
		cd /go/src/k8s.io/kubernetes && \
 		git checkout %s && \
		make all WHAT=cmd/kubectl && \
 		make all WHAT=vendor/github.com/onsi/ginkgo/ginkgo && \
		make all WHAT=test/e2e/e2e.test && \
		KUBECONFIG=/kubeconfig KUBERNETES_PROVIDER=skeleton KUBERNETES_CONFORMANCE_TEST=Y go run hack/e2e.go \
 		-v --test -check_version_skew=false --test_args='--ginkgo.focus=\[Conformance\]'"`,
		kcPath, goImage, k8sVersion)

	// stream conformance output
	client, err := c.Masters[0].SSHClient()
	if err != nil {
		return err
	}
	defer client.Close()
	session, err := client.NewSession()
	if err != nil {
		return err
	}
	defer session.Close()

	session.Stderr = os.Stderr
	session.Stdout = os.Stdout

	if err := session.Run(runConformance); err != nil {
		return fmt.Errorf("Error in conformance run: %s", err)
	}

	return nil
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

	mdl "github.com/santiaago/gonawin/models"
)

type teamsByPhase struct {
	Name  string
	Teams []teamJson
}

// A teamJson is a variable to hold of team information.
type teamJson struct {
	Name string
	Iso  string
}

// Tournament teams handler:
// Use this handler to get the teams of a tournament.
// Returns an array of teams,
// You can specify the groupby parameter to be "phase".
//	GET	/j/tournament/[0-9]+/teams/
//
// The response is an array of teams group by phase.
//
func Teams(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "GET" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament Teams Handler:"

	rc := requestContext{c, desc, r}

	var err error
	var t *mdl.Tournament

	if t, err = rc.tournament(); err != nil {
		return err
	}

	groupby := r.FormValue("groupby")
	// if wrong data, we set rankby to "phase"
	if groupby != "phase" {
		groupby = "phase"
	} else if groupby == "phase" {
		log.Infof(c, "%s ready to build a team array", desc)
		matchesJson := buildMatchesFromTournament(c, t, u)
		teamsByPhases := teamsGroupByPhase(t, matchesJson)

		data := struct {
			Phases []teamsByPhase
		}{
			teamsByPhases,
		}

		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// From an array of Matches, create an array of Phases where the teams are grouped in.
// We use the Phases intervals and the IdNumber of each match to do this operation.
func teamsGroupByPhase(t *mdl.Tournament, matches []MatchJson) []teamsByPhase {
	var tb mdl.TournamentBuilder
	if tb = mdl.GetTournamentBuilder(t); tb == nil {
		return []teamsByPhase{}
	}

	limits := tb.MapOfPhaseIntervals()
	phaseNames := tb.ArrayOfPhases()

	phases := make([]teamsByPhase, len(limits))
	for i, _ := range phases {
		phases[i].Name = phaseNames[i]
		low := limits[phases[i].Name][0]
		high := limits[phases[i].Name][1]

		var filteredMatches []MatchJson
		for _, v := range matches {
			if v.IdNumber >= low && v.IdNumber <= high {
				filteredMatches = append(filteredMatches, v)
			}
		}
		teams := make([]teamJson, 0)
		for _, m := range filteredMatches {
			if !teamContains(teams, m.Team1) {
				t := teamJson{Name: m.Team1, Iso: m.Iso1}
				teams = append(teams, t)
			}
			if !teamContains(teams, m.Team2) {
				t := teamJson{Name: m.Team2, Iso: m.Iso2}
				teams = append(teams, t)
			}
		}
		phases[i].Teams = teams
	}
	return phases
}

func teamContains(teams []teamJson, name string) bool {
	for _, t := range teams {
		if t.Name == name {
			return true
		}
	}
	return false
}

// Update team handler. replaces a team for the second phase of the tournament.
func UpdateTeam(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	c := appengine.NewContext(r)
	desc := "Tournament Update Team handler:"

	if r.Method == "POST" {
		// get tournament id
		strTournamentId, err := route.Context.Get(r, "tournamentId")
		if err != nil {
			log.Errorf(c, "%s error getting tournament id, err:%v", desc, err)
			return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
		}

		var tournamentId int64
		tournamentId, err = strconv.ParseInt(strTournamentId, 0, 64)
		if err != nil {
			log.Errorf(c, "%s error converting tournament id from string to int64, err:%v", desc, err)
			return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
		}

		var t *mdl.Tournament
		t, err = mdl.TournamentById(c, tournamentId)
		if err != nil {
			log.Errorf(c, "%s tournament with id:%v was not found %v", desc, tournamentId, err)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
		}
		phaseName := r.FormValue("phase")
		// if wrong data exit
		if len(phaseName) == 0 {
			log.Errorf(c, "%s phase name is missing.", desc)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
		}

		oldName := r.FormValue("old")
		// if wrong data exit
		if len(oldName) == 0 {
			log.Errorf(c, "%s old name is missing.", desc)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
		}

		newName := r.FormValue("new")
		// if wrong data exit
		if len(newName) == 0 {
			log.Errorf(c, "%s new name is missing.", desc)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
		}
		if err := t.UpdateTournamentTeam(c, phaseName, oldName, newName); err != nil {
			log.Errorf(c, "%s something when wrong while updating a team in the tournament %v. %v", desc, tournamentId, err)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
		}

		matchesJson := buildMatchesFromTournament(c, t, u)
		teamsByPhases := teamsGroupByPhase(t, matchesJson)

		data := struct {
			Phases []teamsByPhase
		}{
			teamsByPhases,
		}
		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<commit_msg>tournament UpdateTeam - exit first<commit_after>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package tournaments

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"

	mdl "github.com/santiaago/gonawin/models"
)

type teamsByPhase struct {
	Name  string
	Teams []teamJson
}

// A teamJson is a variable to hold of team information.
type teamJson struct {
	Name string
	Iso  string
}

// Tournament teams handler:
// Use this handler to get the teams of a tournament.
// Returns an array of teams,
// You can specify the groupby parameter to be "phase".
//	GET	/j/tournament/[0-9]+/teams/
//
// The response is an array of teams group by phase.
//
func Teams(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "GET" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament Teams Handler:"

	rc := requestContext{c, desc, r}

	var err error
	var t *mdl.Tournament

	if t, err = rc.tournament(); err != nil {
		return err
	}

	groupby := r.FormValue("groupby")
	// if wrong data, we set rankby to "phase"
	if groupby != "phase" {
		groupby = "phase"
	} else if groupby == "phase" {
		log.Infof(c, "%s ready to build a team array", desc)
		matchesJson := buildMatchesFromTournament(c, t, u)
		teamsByPhases := teamsGroupByPhase(t, matchesJson)

		data := struct {
			Phases []teamsByPhase
		}{
			teamsByPhases,
		}

		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}

// From an array of Matches, create an array of Phases where the teams are grouped in.
// We use the Phases intervals and the IdNumber of each match to do this operation.
func teamsGroupByPhase(t *mdl.Tournament, matches []MatchJson) []teamsByPhase {
	var tb mdl.TournamentBuilder
	if tb = mdl.GetTournamentBuilder(t); tb == nil {
		return []teamsByPhase{}
	}

	limits := tb.MapOfPhaseIntervals()
	phaseNames := tb.ArrayOfPhases()

	phases := make([]teamsByPhase, len(limits))
	for i, _ := range phases {
		phases[i].Name = phaseNames[i]
		low := limits[phases[i].Name][0]
		high := limits[phases[i].Name][1]

		var filteredMatches []MatchJson
		for _, v := range matches {
			if v.IdNumber >= low && v.IdNumber <= high {
				filteredMatches = append(filteredMatches, v)
			}
		}
		teams := make([]teamJson, 0)
		for _, m := range filteredMatches {
			if !teamContains(teams, m.Team1) {
				t := teamJson{Name: m.Team1, Iso: m.Iso1}
				teams = append(teams, t)
			}
			if !teamContains(teams, m.Team2) {
				t := teamJson{Name: m.Team2, Iso: m.Iso2}
				teams = append(teams, t)
			}
		}
		phases[i].Teams = teams
	}
	return phases
}

func teamContains(teams []teamJson, name string) bool {
	for _, t := range teams {
		if t.Name == name {
			return true
		}
	}
	return false
}

// Update team handler. replaces a team for the second phase of the tournament.
func UpdateTeam(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "POST" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	c := appengine.NewContext(r)
	desc := "Tournament Update Team handler:"

	// get tournament id
	strTournamentId, err := route.Context.Get(r, "tournamentId")
	if err != nil {
		log.Errorf(c, "%s error getting tournament id, err:%v", desc, err)
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var tournamentId int64
	tournamentId, err = strconv.ParseInt(strTournamentId, 0, 64)
	if err != nil {
		log.Errorf(c, "%s error converting tournament id from string to int64, err:%v", desc, err)
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}

	var t *mdl.Tournament
	t, err = mdl.TournamentById(c, tournamentId)
	if err != nil {
		log.Errorf(c, "%s tournament with id:%v was not found %v", desc, tournamentId, err)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeTournamentNotFound)}
	}
	phaseName := r.FormValue("phase")
	// if wrong data exit
	if len(phaseName) == 0 {
		log.Errorf(c, "%s phase name is missing.", desc)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	oldName := r.FormValue("old")
	// if wrong data exit
	if len(oldName) == 0 {
		log.Errorf(c, "%s old name is missing.", desc)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	newName := r.FormValue("new")
	// if wrong data exit
	if len(newName) == 0 {
		log.Errorf(c, "%s new name is missing.", desc)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}
	if err := t.UpdateTournamentTeam(c, phaseName, oldName, newName); err != nil {
		log.Errorf(c, "%s something when wrong while updating a team in the tournament %v. %v", desc, tournamentId, err)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	matchesJson := buildMatchesFromTournament(c, t, u)
	teamsByPhases := teamsGroupByPhase(t, matchesJson)

	data := struct {
		Phases []teamsByPhase
	}{
		teamsByPhases,
	}
	return templateshlp.RenderJson(w, c, data)
}
<|endoftext|>


<commit_before>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}
<commit_msg>add ExecIDs<commit_after>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}
<|endoftext|>


<commit_before>package itchio

import (
	"fmt"
	"strings"

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

// User represents an itch.io account, with basic profile info
type User struct {
	ID            int64  `json:"id"`
	Username      string `json:"username"`
	CoverURL      string `json:"coverUrl"`
	StillCoverURL string `json:"stillCoverUrl"`
}

// Game represents a page on itch.io, it could be a game,
// a tool, a comic, etc.
type Game struct {
	ID  int64  `json:"id"`
	URL string `json:"url"`

	Title     string `json:"title"`
	ShortText string `json:"shortText"`
	Type      string `json:"type"`

	CoverURL      string `json:"coverUrl"`
	StillCoverURL string `json:"stillCoverUrl"`

	CreatedAt   string `json:"createdAt"`
	PublishedAt string `json:"publishedAt"`

	MinPrice      int64 `json:"minPrice"`
	InPressSystem bool  `json:"inPressSystem"`
	HasDemo       bool  `json:"hasDemo"`

	Classification string `json:"classification"`

	OSX     bool `json:"pOsx"`
	Linux   bool `json:"pLinux"`
	Windows bool `json:"pWindows"`
	Android bool `json:"pAndroid"`
}

// An Upload is a downloadable file
type Upload struct {
	ID          int64  `json:"id"`
	Filename    string `json:"filename"`
	DisplayName string `json:"displayName"`
	Size        int64  `json:"size"`
	ChannelName string `json:"channelName"`
	Build       *Build `json:"build"`
	Demo        bool   `json:"demo"`
	Preorder    bool   `json:"preorder"`

	Type    string `json:"type"`
	OSX     bool   `json:"pOsx"`
	Linux   bool   `json:"pLinux"`
	Windows bool   `json:"pWindows"`
	Android bool   `json:"pAndroid"`

	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// BuildFile contains information about a build's "file", which could be its
// archive, its signature, its patch, etc.
type BuildFile struct {
	ID      int64            `json:"id"`
	Size    int64            `json:"size"`
	State   BuildFileState   `json:"state"`
	Type    BuildFileType    `json:"type"`
	SubType BuildFileSubType `json:"subType"`

	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// Build contains information about a specific build
type Build struct {
	ID            int64      `json:"id"`
	ParentBuildID int64      `json:"parentBuildId"`
	State         BuildState `json:"state"`

	Version     int64  `json:"version"`
	UserVersion string `json:"userVersion"`

	Files []*BuildFile `json:"files"`

	User      User   `json:"user"`
	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// Channel contains information about a channel and its current status
type Channel struct {
	Name string `json:"name"`
	Tags string `json:"tags"`

	Upload  *Upload `json:"upload"`
	Head    *Build  `json:"head"`
	Pending *Build  `json:"pending"`
}

// A BuildEvent describes something that happened while we were processing a build.
type BuildEvent struct {
	Type    BuildEventType `json:"type"`
	Message string         `json:"message"`
	Data    BuildEventData `json:"data"`
}

type APIError struct {
	Messages []string
}

var _ error = (*APIError)(nil)

func (ae *APIError) Error() string {
	return fmt.Sprintf("itch.io API error: %s", strings.Join(ae.Messages, ", "))
}

// IsApiError returns true if an error is an itch.io API error,
// even if it's wrapped with github.com/go-errors/errors
func IsAPIError(err error) bool {
	if err == nil {
		return false
	}

	if se, ok := err.(*errors.Error); ok {
		return IsAPIError(se.Err)
	}

	_, ok := err.(*APIError)
	return ok
}
<commit_msg>Expand User type, introduce Collection type<commit_after>package itchio

import (
	"fmt"
	"strings"

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

// User represents an itch.io account, with basic profile info
type User struct {
	ID int64 `json:"id"`

	Username    string `json:"username"`
	DisplayName string `json:"displayName"`

	Developer bool `json:"developer"`
	PressUser bool `json:"pressUser"`

	URL           string `json:"url"`
	CoverURL      string `json:"coverUrl"`
	StillCoverURL string `json:"stillCoverUrl"`
}

// Game represents a page on itch.io, it could be a game,
// a tool, a comic, etc.
type Game struct {
	ID  int64  `json:"id"`
	URL string `json:"url"`

	Title     string `json:"title"`
	ShortText string `json:"shortText"`
	Type      string `json:"type"`

	CoverURL      string `json:"coverUrl"`
	StillCoverURL string `json:"stillCoverUrl"`

	CreatedAt   string `json:"createdAt"`
	PublishedAt string `json:"publishedAt"`

	MinPrice      int64 `json:"minPrice"`
	InPressSystem bool  `json:"inPressSystem"`
	HasDemo       bool  `json:"hasDemo"`

	Classification string `json:"classification"`

	OSX     bool `json:"pOsx"`
	Linux   bool `json:"pLinux"`
	Windows bool `json:"pWindows"`
	Android bool `json:"pAndroid"`
}

// An Upload is a downloadable file
type Upload struct {
	ID          int64  `json:"id"`
	Filename    string `json:"filename"`
	DisplayName string `json:"displayName"`
	Size        int64  `json:"size"`
	ChannelName string `json:"channelName"`
	Build       *Build `json:"build"`
	Demo        bool   `json:"demo"`
	Preorder    bool   `json:"preorder"`

	Type    string `json:"type"`
	OSX     bool   `json:"pOsx"`
	Linux   bool   `json:"pLinux"`
	Windows bool   `json:"pWindows"`
	Android bool   `json:"pAndroid"`

	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

type Collection struct {
	ID int64 `json:"id"`

	Title string `json:"title"`

	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`

	GamesCount int64 `json:"gamesCount"`
}

// BuildFile contains information about a build's "file", which could be its
// archive, its signature, its patch, etc.
type BuildFile struct {
	ID      int64            `json:"id"`
	Size    int64            `json:"size"`
	State   BuildFileState   `json:"state"`
	Type    BuildFileType    `json:"type"`
	SubType BuildFileSubType `json:"subType"`

	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// Build contains information about a specific build
type Build struct {
	ID            int64      `json:"id"`
	ParentBuildID int64      `json:"parentBuildId"`
	State         BuildState `json:"state"`

	Version     int64  `json:"version"`
	UserVersion string `json:"userVersion"`

	Files []*BuildFile `json:"files"`

	User      User   `json:"user"`
	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
}

// Channel contains information about a channel and its current status
type Channel struct {
	Name string `json:"name"`
	Tags string `json:"tags"`

	Upload  *Upload `json:"upload"`
	Head    *Build  `json:"head"`
	Pending *Build  `json:"pending"`
}

// A BuildEvent describes something that happened while we were processing a build.
type BuildEvent struct {
	Type    BuildEventType `json:"type"`
	Message string         `json:"message"`
	Data    BuildEventData `json:"data"`
}

type APIError struct {
	Messages []string
}

var _ error = (*APIError)(nil)

func (ae *APIError) Error() string {
	return fmt.Sprintf("itch.io API error: %s", strings.Join(ae.Messages, ", "))
}

// IsApiError returns true if an error is an itch.io API error,
// even if it's wrapped with github.com/go-errors/errors
func IsAPIError(err error) bool {
	if err == nil {
		return false
	}

	if se, ok := err.(*errors.Error); ok {
		return IsAPIError(se.Err)
	}

	_, ok := err.(*APIError)
	return ok
}
<|endoftext|>


<commit_before>package gomarathon

// RequestOptions passed for query api
type RequestOptions struct {
	Method string
	Path   string
	Datas  interface{}
	Params *Parameters
}

// Parameters to build url query
type Parameters struct {
	Cmd         string
	Host        string
	Scale       bool
	CallbackURL string
}

// Response representation of a full marathon response
type Response struct {
	Code     int
	Apps     []*Application `json:"apps,omitempty"`
	App      *Application   `json:"app,omitempty"`
	Versions []string       `json:",omitempty"`
	Tasks    []*Task        `json:"tasks,omitempty"`
}

// Application marathon application see :
// https://github.com/mesosphere/marathon/blob/master/REST.md#apps
type Application struct {
	ID            string            `json:"id"`
	Cmd           string            `json:"cmd,omitempty"`
	Constraints   [][]string        `json:"constraints,omitempty"`
	Container     *Container        `json:"container,omitempty"`
	CPU           int               `json:"cpu,omitempty"`
	Env           map[string]string `json:"env,omitempty"`
	Executor      string            `json:"executor,omitempty"`
	HealtChecks   []*HealthCheck    `json:"healtChecks,omitempty"`
	Instances     int               `json:"instances,omitemptys"`
	Mem           float32           `json:"mem,omitempty"`
	Tasks         []*Task           `json:"tasks,omitempty"`
	Ports         []int             `json:"ports,omitempty"`
	BackoffFactor int               `json:"backoffFactor,omitempty"`
	TasksRunning  int               `json:"tasksRunning,omitempty"`
	TasksStaged   int               `json:"tasksStaged,omitempty"`
	Uris          []string          `json:"uris,omitempty"`
	Version       string            `json:"version,omitempty"`
}

// Container is docker parameters
// options are passed to container, if you want your options
// to be passed at the end of your docker run
// add // in front of the parameters you want to pass
// Example:
// docker run -ti -p 4343:4343 mysql --listen 0.0.0.0:4343
// options := [ "-p", "4343", "//", "--listen", "0.0.0.0:4343" ]
type Container struct {
	Image   string   `json:"image,omitempty"`
	Options []string `json:"options,omitempty"`
}

// HealthCheck are described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#healthchecks
type HealthCheck struct {
	Protocol           string `json:"protocol,omitempty"`
	Path               string `json:"path,omitempty"`
	GracePeriodSeconds int    `json:"gracePeriodSeconds,omitempty"`
	IntervalSeconds    int    `json:"intervalSeconds,omitempty"`
	PortIndex          int    `json:"portIndex,omitempty"`
	TimeoutSeconds     int    `json:"timeoutSeconds,omitempty"`
}

// Task is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#tasks
type Task struct {
	AppID     string `json:"appId"`
	Host      string `json:"host"`
	ID        string `json:"id"`
	Ports     []int  `json:"ports"`
	StagedAt  string `json:"stagedAt"`
	StartedAt string `json:"startedAt"`
	Version   string `json:"version"`
}

// EventSubscription are described here :
// https://github.com/mesosphere/marathon/blob/master/REST.md#event-subscriptions
type EventSubscription struct {
	CallbackURL  string   `json:"CallbackUrl"`
	ClientIP     string   `json:"ClientIp"`
	EventType    string   `json:"eventType"`
	CallbackURLs []string `json:"CallbackUrls"`
}
<commit_msg>fixe cpu name on json<commit_after>package gomarathon

// RequestOptions passed for query api
type RequestOptions struct {
	Method string
	Path   string
	Datas  interface{}
	Params *Parameters
}

// Parameters to build url query
type Parameters struct {
	Cmd         string
	Host        string
	Scale       bool
	CallbackURL string
}

// Response representation of a full marathon response
type Response struct {
	Code     int
	Apps     []*Application `json:"apps,omitempty"`
	App      *Application   `json:"app,omitempty"`
	Versions []string       `json:",omitempty"`
	Tasks    []*Task        `json:"tasks,omitempty"`
}

// Application marathon application see :
// https://github.com/mesosphere/marathon/blob/master/REST.md#apps
type Application struct {
	ID            string            `json:"id"`
	Cmd           string            `json:"cmd,omitempty"`
	Constraints   [][]string        `json:"constraints,omitempty"`
	Container     *Container        `json:"container,omitempty"`
	CPU           int               `json:"cpus,omitempty"`
	Env           map[string]string `json:"env,omitempty"`
	Executor      string            `json:"executor,omitempty"`
	HealtChecks   []*HealthCheck    `json:"healtChecks,omitempty"`
	Instances     int               `json:"instances,omitemptys"`
	Mem           float32           `json:"mem,omitempty"`
	Tasks         []*Task           `json:"tasks,omitempty"`
	Ports         []int             `json:"ports,omitempty"`
	BackoffFactor int               `json:"backoffFactor,omitempty"`
	TasksRunning  int               `json:"tasksRunning,omitempty"`
	TasksStaged   int               `json:"tasksStaged,omitempty"`
	Uris          []string          `json:"uris,omitempty"`
	Version       string            `json:"version,omitempty"`
}

// Container is docker parameters
// options are passed to container, if you want your options
// to be passed at the end of your docker run
// add // in front of the parameters you want to pass
// Example:
// docker run -ti -p 4343:4343 mysql --listen 0.0.0.0:4343
// options := [ "-p", "4343", "//", "--listen", "0.0.0.0:4343" ]
type Container struct {
	Image   string   `json:"image,omitempty"`
	Options []string `json:"options,omitempty"`
}

// HealthCheck are described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#healthchecks
type HealthCheck struct {
	Protocol           string `json:"protocol,omitempty"`
	Path               string `json:"path,omitempty"`
	GracePeriodSeconds int    `json:"gracePeriodSeconds,omitempty"`
	IntervalSeconds    int    `json:"intervalSeconds,omitempty"`
	PortIndex          int    `json:"portIndex,omitempty"`
	TimeoutSeconds     int    `json:"timeoutSeconds,omitempty"`
}

// Task is described here:
// https://github.com/mesosphere/marathon/blob/master/REST.md#tasks
type Task struct {
	AppID     string `json:"appId"`
	Host      string `json:"host"`
	ID        string `json:"id"`
	Ports     []int  `json:"ports"`
	StagedAt  string `json:"stagedAt"`
	StartedAt string `json:"startedAt"`
	Version   string `json:"version"`
}

// EventSubscription are described here :
// https://github.com/mesosphere/marathon/blob/master/REST.md#event-subscriptions
type EventSubscription struct {
	CallbackURL  string   `json:"CallbackUrl"`
	ClientIP     string   `json:"ClientIp"`
	EventType    string   `json:"eventType"`
	CallbackURLs []string `json:"CallbackUrls"`
}
<|endoftext|>


<commit_before>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Network struct {
	RxBytes   uint64 `json:"rx_bytes"`
	RxPackets uint64 `json:"rx_packets"`
	RxErrors  uint64 `json:"rx_errors"`
	RxDropped uint64 `json:"rx_dropped"`
	TxBytes   uint64 `json:"tx_bytes"`
	TxPackets uint64 `json:"tx_packets"`
	TxErrors  uint64 `json:"tx_errors"`
	TxDropped uint64 `json:"tx_dropped"`
}

type Stats struct {
	Read        time.Time   `json:"read"`
	Network     Network     `json:"network,omitempty"`
	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}
<commit_msg>inline network struct<commit_after>package dockerclient

import "time"

type ContainerConfig struct {
	Hostname        string
	Domainname      string
	User            string
	Memory          int64
	MemorySwap      int64
	CpuShares       int64
	Cpuset          string
	AttachStdin     bool
	AttachStdout    bool
	AttachStderr    bool
	PortSpecs       []string
	ExposedPorts    map[string]struct{}
	Tty             bool
	OpenStdin       bool
	StdinOnce       bool
	Env             []string
	Cmd             []string
	Image           string
	Volumes         map[string]struct{}
	WorkingDir      string
	Entrypoint      []string
	NetworkDisabled bool
	OnBuild         []string

	// This is used only by the create command
	HostConfig HostConfig
}

type HostConfig struct {
	Binds           []string
	ContainerIDFile string
	LxcConf         []map[string]string
	Privileged      bool
	PortBindings    map[string][]PortBinding
	Links           []string
	PublishAllPorts bool
	Dns             []string
	DnsSearch       []string
	VolumesFrom     []string
	NetworkMode     string
	RestartPolicy   RestartPolicy
}

type ExecConfig struct {
	AttachStdin  bool
	AttachStdout bool
	AttachStderr bool
	Tty          bool
	Cmd          []string
	Container    string
	Detach       bool
}

type LogOptions struct {
	Follow     bool
	Stdout     bool
	Stderr     bool
	Timestamps bool
	Tail       int64
}

type RestartPolicy struct {
	Name              string
	MaximumRetryCount int64
}

type PortBinding struct {
	HostIp   string
	HostPort string
}

type ContainerInfo struct {
	Id      string
	Created string
	Path    string
	Name    string
	Args    []string
	ExecIDs []string
	Config  *ContainerConfig
	State   struct {
		Running    bool
		Paused     bool
		Restarting bool
		Pid        int
		ExitCode   int
		StartedAt  time.Time
		FinishedAt time.Time
		Ghost      bool
	}
	Image           string
	NetworkSettings struct {
		IpAddress   string
		IpPrefixLen int
		Gateway     string
		Bridge      string
		Ports       map[string][]PortBinding
	}
	SysInitPath    string
	ResolvConfPath string
	Volumes        map[string]string
	HostConfig     *HostConfig
}

type Port struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type Container struct {
	Id         string
	Names      []string
	Image      string
	Command    string
	Created    int64
	Status     string
	Ports      []Port
	SizeRw     int64
	SizeRootFs int64
}

type Event struct {
	Id     string
	Status string
	From   string
	Time   int64
}

type Version struct {
	Version   string
	GitCommit string
	GoVersion string
}

type RespContainersCreate struct {
	Id       string
	Warnings []string
}

type Image struct {
	Created     int64
	Id          string
	ParentId    string
	RepoTags    []string
	Size        int64
	VirtualSize int64
}

type Info struct {
	ID              string
	Containers      int64
	Driver          string
	DriverStatus    [][]string
	ExecutionDriver string
	Images          int64
	KernelVersion   string
	OperatingSystem string
	NCPU            int64
	MemTotal        int64
	Name            string
	Labels          []string
}

type ImageDelete struct {
	Deleted  string
	Untagged string
}

// The following are types for the API stats endpoint
type ThrottlingData struct {
	// Number of periods with throttling active
	Periods uint64 `json:"periods"`
	// Number of periods when the container hit its throttling limit.
	ThrottledPeriods uint64 `json:"throttled_periods"`
	// Aggregate time the container was throttled for in nanoseconds.
	ThrottledTime uint64 `json:"throttled_time"`
}

type CpuUsage struct {
	// Total CPU time consumed.
	// Units: nanoseconds.
	TotalUsage uint64 `json:"total_usage"`
	// Total CPU time consumed per core.
	// Units: nanoseconds.
	PercpuUsage []uint64 `json:"percpu_usage"`
	// Time spent by tasks of the cgroup in kernel mode.
	// Units: nanoseconds.
	UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
	// Time spent by tasks of the cgroup in user mode.
	// Units: nanoseconds.
	UsageInUsermode uint64 `json:"usage_in_usermode"`
}

type CpuStats struct {
	CpuUsage       CpuUsage       `json:"cpu_usage"`
	SystemUsage    uint64         `json:"system_cpu_usage"`
	ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}

type MemoryStats struct {
	Usage    uint64            `json:"usage"`
	MaxUsage uint64            `json:"max_usage"`
	Stats    map[string]uint64 `json:"stats"`
	Failcnt  uint64            `json:"failcnt"`
	Limit    uint64            `json:"limit"`
}

type BlkioStatEntry struct {
	Major uint64 `json:"major"`
	Minor uint64 `json:"minor"`
	Op    string `json:"op"`
	Value uint64 `json:"value"`
}

type BlkioStats struct {
	// number of bytes tranferred to and from the block device
	IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
	IoServicedRecursive     []BlkioStatEntry `json:"io_serviced_recursive"`
	IoQueuedRecursive       []BlkioStatEntry `json:"io_queue_recursive"`
	IoServiceTimeRecursive  []BlkioStatEntry `json:"io_service_time_recursive"`
	IoWaitTimeRecursive     []BlkioStatEntry `json:"io_wait_time_recursive"`
	IoMergedRecursive       []BlkioStatEntry `json:"io_merged_recursive"`
	IoTimeRecursive         []BlkioStatEntry `json:"io_time_recursive"`
	SectorsRecursive        []BlkioStatEntry `json:"sectors_recursive"`
}

type Stats struct {
	Read    time.Time `json:"read"`
	Network struct {
		RxBytes   uint64 `json:"rx_bytes"`
		RxPackets uint64 `json:"rx_packets"`
		RxErrors  uint64 `json:"rx_errors"`
		RxDropped uint64 `json:"rx_dropped"`
		TxBytes   uint64 `json:"tx_bytes"`
		TxPackets uint64 `json:"tx_packets"`
		TxErrors  uint64 `json:"tx_errors"`
		TxDropped uint64 `json:"tx_dropped"`
	}

	CpuStats    CpuStats    `json:"cpu_stats,omitempty"`
	MemoryStats MemoryStats `json:"memory_stats,omitempty"`
	BlkioStats  BlkioStats  `json:"blkio_stats,omitempty"`
}
<|endoftext|>


<commit_before>// Copyright © 2015 Clement 'cmc' Rey <cr.rey.clement@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package mmm

import (
	"fmt"
	"reflect"
)

// -----------------------------------------------------------------------------

// Type represents the underlying type of an interface.
type Type int

const (
	// TypeInvalid is an illegal type.
	TypeInvalid Type = iota
	// TypeNumeric is any of bool/int/uint/float/complex and their variants.
	TypeNumeric
	// TypeArray is an array of any underlying type.
	TypeArray
	// TypeStruct is any struct.
	TypeStruct
	// TypeUnsafePointer is any pointer from the unsafe package.
	TypeUnsafePointer
)

// TypeOf returns the underlying type of an interface.
func TypeOf(v interface{}) (Type, error) {
	return typeOf(reflect.ValueOf(v))
}

func typeOf(v reflect.Value) (Type, error) {
	if !v.IsValid() {
		return TypeInvalid, Error(fmt.Sprintf("unsuppported type: %#v", v))
	}

	k := v.Type().Kind()

	switch k {
	case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32,
		reflect.Float64, reflect.Complex64, reflect.Complex128:
		return TypeNumeric, nil
	case reflect.Array:
		return TypeArray, nil
	case reflect.Struct:
		return TypeStruct, nil
	case reflect.UnsafePointer:
		return TypeUnsafePointer, nil
	default:
		return TypeInvalid, Error(fmt.Sprintf("unsuppported type: %#v", k.String()))
	}
}
<commit_msg>combine TypeOf and typeOf<commit_after>// Copyright © 2015 Clement 'cmc' Rey <cr.rey.clement@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package mmm

import (
	"fmt"
	"reflect"
)

// -----------------------------------------------------------------------------

// Type represents the underlying type of an interface.
type Type int

const (
	// TypeInvalid is an illegal type.
	TypeInvalid Type = iota
	// TypeNumeric is any of bool/int/uint/float/complex and their variants.
	TypeNumeric
	// TypeArray is an array of any underlying type.
	TypeArray
	// TypeStruct is any struct.
	TypeStruct
	// TypeUnsafePointer is any pointer from the unsafe package.
	TypeUnsafePointer
)

// TypeOf returns the underlying type of an interface.
func TypeOf(i interface{}) (Type, error) {
	v := reflect.ValueOf(i)
	if !v.IsValid() {
		return TypeInvalid, Error(fmt.Sprintf("unsuppported type: %#v", v))
	}

	switch k := v.Type().Kind(); k {
	case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16,
		reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16,
		reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32,
		reflect.Float64, reflect.Complex64, reflect.Complex128:
		return TypeNumeric, nil
	case reflect.Array:
		return TypeArray, nil
	case reflect.Struct:
		return TypeStruct, nil
	case reflect.UnsafePointer:
		return TypeUnsafePointer, nil
	default:
		return TypeInvalid, Error(fmt.Sprintf("unsuppported type: %#v", k.String()))
	}
}
<|endoftext|>


<commit_before><commit_msg>If we truncate the message, save the whole thing in extra<commit_after><|endoftext|>


<commit_before><commit_msg>Implement Hkeys and Hrkeys methods.<commit_after><|endoftext|>


<commit_before>package models

import (
  "github.com/spacedock-io/registry/db"
)

type Repo struct {
  Id            int64
  RegistryId    string  `sql:"not null"`
  Namespace     string  `sql:"not null"`
  Name          string  `sql:"not null;unique"`
  Tokens        []Token
  Images        []Image
  Deleted       bool
}

type Image struct {
  Id            int64   `json:"-"`
  Uuid          string  `json:"id"`
  Checksum      string  `json:"checksum,omitempty"`
  RepoId        int64   `json:"-"`
}

func GetRepo(namespace string, repo string) (*Repo, error) {
  r := &Repo{}
  q := db.DB.Where("namespace = ? and name = ?", namespace, repo).Find(r)

  if q.Error != nil {
    if q.RecordNotFound() {
      return nil, NotFoundErr
    } else { return nil, DBErr }
  }
  return r, nil
}

func (r *Repo) GetImages() ([]Image, error) {
  var i []Image

  q := db.DB.Model(r).Related(&i)
  if q.Error != nil {
    if q.RecordNotFound() {
      return nil, NotFoundErr
    } else { return nil, DBErr }
  }

  return i, nil
}

func (r *Repo) Create(regId string, user *User,
                      images []interface{}) (string, error) {
  var fullname string
  r.RegistryId = regId

  if len(r.Namespace) == 0 {
    fullname = "library/" + r.Name
  } else {
    fullname = r.Namespace + "/" + r.Name
  }

  ok := user.SetAccess(r.Namespace, r.Name, "delete")
  if !ok {
    return "", AccessSetError
  }

  // @TODO: make sure this access level is right
  t, ok := CreateToken("write", user.Id, fullname)
  if !ok { return "", TokenErr }

  r.Tokens = append(r.Tokens, t)

  for _, v := range images {
    row := v.(map[string]interface{})
    id := row["id"].(string)
    img := Image{Uuid: id}
    r.Images = append(r.Images, img)
  }

  err := r.Save()
  if err != nil {
    return "", err
  }

  return t.String(), nil
}

func (repo *Repo) Delete() error {
  q := db.DB.Delete(repo)
  if q.Error != nil {
    return DBErr
  }
  return nil
}

func (repo *Repo) HasToken(token string) bool {
  for _, v := range repo.Tokens {
    if v.String() == token {
      return true
    }
  }

  return false
}

func (repo *Repo) MarkAsDeleted(uid int64) (string, error) {
  var fullname, ts string
  if len(repo.Namespace) == 0 {
    fullname = "library/" + repo.Name
  } else {
    fullname = repo.Namespace + repo.Name
  }
  t, ok := CreateToken("delete", uid, fullname)
  if !ok {
    return "", TokenErr
  }

  repo.Tokens = append(repo.Tokens, t)
  ts = t.String()

  repo.Deleted = true

  err := repo.Save()
  if err != nil {
    return "", err
  }

  return ts, nil
}

func (r *Repo) Save() error {
  q := db.DB.Save(r)
  if q.Error != nil {
    return DBErr
  }
  return nil
}

func (repo *Repo) UpdateImages(updates []interface{}) error {
  var imgs, updated []Image

  q := db.DB.Model(repo).Related(&imgs)
  if q.Error != nil {
    return DBErr
  }

  for _, update := range updates {
    var found bool
    row := update.(map[string]interface{})
    for _, image := range imgs {
      if row["id"].(string) == image.Uuid {
        image.Checksum = row["checksum"].(string)
        updated = append(updated, image)
        found = true
      }
    }
    if !found {
      img := Image{
        Uuid: row["id"].(string),
        Checksum: row["checksum"].(string),
      }
      updated = append(updated, img)
      found = false
    }
  }

  repo.Images = updated

  err := repo.Save()
  if err != nil {
    return err
  }

  return nil
}
<commit_msg>Add models.Repo.AddToken<commit_after>package models

import (
  "github.com/spacedock-io/registry/db"
)

type Repo struct {
  Id            int64
  RegistryId    string  `sql:"not null"`
  Namespace     string  `sql:"not null"`
  Name          string  `sql:"not null;unique"`
  Tokens        []Token
  Images        []Image
  Deleted       bool
}

type Image struct {
  Id            int64   `json:"-"`
  Uuid          string  `json:"id"`
  Checksum      string  `json:"checksum,omitempty"`
  RepoId        int64   `json:"-"`
}

func GetRepo(namespace string, repo string) (*Repo, error) {
  r := &Repo{}
  q := db.DB.Where("namespace = ? and name = ?", namespace, repo).Find(r)

  if q.Error != nil {
    if q.RecordNotFound() {
      return nil, NotFoundErr
    } else { return nil, DBErr }
  }
  return r, nil
}

func (r *Repo) AddToken(access string, user *User) (Token, error) {
  repo := r.Namespace + "/" + r.Name

  t, ok := CreateToken(access, user.Id, repo)
  if !ok {
    return Token{}, TokenErr
  }

  r.Tokens = append(r.Tokens, t)
  return t, nil
}

func (r *Repo) GetImages() ([]Image, error) {
  var i []Image

  q := db.DB.Model(r).Related(&i)
  if q.Error != nil {
    if q.RecordNotFound() {
      return nil, NotFoundErr
    } else { return nil, DBErr }
  }

  return i, nil
}

func (r *Repo) Create(regId string, user *User,
                      images []interface{}) (string, error) {
  r.RegistryId = regId

  if len(r.Namespace) == 0 {
    r.Namespace = "library"
  }

  ok := user.SetAccess(r.Namespace, r.Name, "delete")
  if !ok {
    return "", AccessSetError
  }

  t, err := r.AddToken("write", user)
  if err != nil {
    return "", err
  }

  for _, v := range images {
    row := v.(map[string]interface{})
    id := row["id"].(string)
    img := Image{Uuid: id}
    r.Images = append(r.Images, img)
  }

  err = r.Save()
  if err != nil {
    return "", err
  }

  return t.String(), nil
}

func (repo *Repo) Delete() error {
  q := db.DB.Delete(repo)
  if q.Error != nil {
    return DBErr
  }
  return nil
}

func (repo *Repo) HasToken(token string) bool {
  for _, v := range repo.Tokens {
    if v.String() == token {
      return true
    }
  }

  return false
}

func (repo *Repo) MarkAsDeleted(uid int64) (string, error) {
  var fullname, ts string
  if len(repo.Namespace) == 0 {
    fullname = "library/" + repo.Name
  } else {
    fullname = repo.Namespace + repo.Name
  }
  t, ok := CreateToken("delete", uid, fullname)
  if !ok {
    return "", TokenErr
  }

  repo.Tokens = append(repo.Tokens, t)
  ts = t.String()

  repo.Deleted = true

  err := repo.Save()
  if err != nil {
    return "", err
  }

  return ts, nil
}

func (r *Repo) Save() error {
  q := db.DB.Save(r)
  if q.Error != nil {
    return DBErr
  }
  return nil
}

func (repo *Repo) UpdateImages(updates []interface{}) error {
  var imgs, updated []Image

  q := db.DB.Model(repo).Related(&imgs)
  if q.Error != nil {
    return DBErr
  }

  for _, update := range updates {
    var found bool
    row := update.(map[string]interface{})
    for _, image := range imgs {
      if row["id"].(string) == image.Uuid {
        image.Checksum = row["checksum"].(string)
        updated = append(updated, image)
        found = true
      }
    }
    if !found {
      img := Image{
        Uuid: row["id"].(string),
        Checksum: row["checksum"].(string),
      }
      updated = append(updated, img)
      found = false
    }
  }

  repo.Images = updated

  err := repo.Save()
  if err != nil {
    return err
  }

  return nil
}
<|endoftext|>