<commit_before>package gonvim

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"
	"unsafe"

	"github.com/dzhou121/neovim-fzf-shim/rplugin/go/fzf"
	"github.com/dzhou121/neovim-locpopup/rplugin/go/locpopup"
	"github.com/dzhou121/ui"
	"github.com/neovim/go-client/nvim"
)

var editor *Editor

// Highlight is
type Highlight struct {
	foreground *RGBA
	background *RGBA
}

// Char is
type Char struct {
	char      string
	highlight Highlight
}

// Editor is the editor
type Editor struct {
	nvim             *nvim.Nvim
	nvimAttached     bool
	mode             string
	font             *Font
	smallerFont      *Font
	rows             int
	cols             int
	cursor           *CursorBox
	Foreground       RGBA
	Background       RGBA
	window           *ui.Window
	screen           *Screen
	areaBox          *ui.Box
	close            chan bool
	popup            *PopupMenu
	finder           *Finder
	tabline          *Tabline
	statusline       *Statusline
	statuslineHeight int
	width            int
	height           int
	tablineHeight    int
	selectedBg       *RGBA
	matchFg          *RGBA
}

func initMainWindow(box *ui.Box, width, height int) *ui.Window {
	window := ui.NewWindow("Gonvim", width, height, false)
	window.SetChild(box)
	window.OnClosing(func(*ui.Window) bool {
		ui.Quit()
		return true
	})
	window.OnContentSizeChanged(func(w *ui.Window, data unsafe.Pointer) bool {
		if editor == nil {
			return true
		}
		width, height = window.ContentSize()
		height = height - editor.tablineHeight
		if width == editor.width && height == editor.height {
			return true
		}
		editor.width = width
		editor.height = height
		editor.areaBox.SetSize(width, height)
		editor.screen.box.SetSize(width, height)
		editor.screen.setSize(width, height)
		editor.cursor.setSize(width, height)
		editor.tabline.resize(width, editor.tablineHeight)
		editor.resize()
		editor.finder.rePosition()
		return true
	})
	window.Show()
	return window
}

// InitEditor inits the editor
func InitEditor() error {
	if editor != nil {
		return nil
	}
	width := 800
	height := 600
	tablineHeight := 34
	statuslineHeight := 28

	screen := initScreen(width, height)
	cursor := initCursorBox(width, height)
	popupMenu := initPopupmenu()
	finder := initFinder()
	tabline := initTabline(width, tablineHeight)
	loc := initLocpopup()
	statusline := initStatusline(width, statuslineHeight)

	box := ui.NewHorizontalBox()
	areaBox := ui.NewHorizontalBox()
	areaBox.Append(screen.box, false)
	areaBox.Append(cursor.box, false)
	areaBox.Append(loc.box, false)
	areaBox.Append(popupMenu.box, false)
	areaBox.Append(finder.box, false)
	box.Append(tabline.box, false)
	box.Append(areaBox, false)
	box.Append(statusline.box, false)

	areaBox.SetSize(width, height)
	areaBox.SetPosition(0, tablineHeight)
	statusline.box.SetPosition(0, tablineHeight+height)
	window := initMainWindow(box, width, height+tablineHeight+statuslineHeight)

	neovim, err := nvim.NewEmbedded(&nvim.EmbedOptions{
		Args: os.Args[1:],
	})
	if err != nil {
		return err
	}

	font := initFont("", 14, 0)
	smallerFont := initFont("", 14, 0)

	editor = &Editor{
		nvim:             neovim,
		nvimAttached:     false,
		window:           window,
		screen:           screen,
		areaBox:          areaBox,
		mode:             "normal",
		close:            make(chan bool),
		cursor:           cursor,
		popup:            popupMenu,
		finder:           finder,
		tabline:          tabline,
		width:            width,
		height:           height,
		tablineHeight:    tablineHeight,
		statusline:       statusline,
		statuslineHeight: statuslineHeight,
		font:             font,
		smallerFont:      smallerFont,
		cols:             0,
		rows:             0,
		selectedBg:       newRGBA(81, 154, 186, 0.5),
		matchFg:          newRGBA(81, 154, 186, 1),
	}

	editor.resize()
	editor.handleNotification()
	editor.finder.rePosition()
	go func() {
		err := neovim.Serve()
		if err != nil {
			fmt.Println(err)
		}
		editor.close <- true
	}()

	o := make(map[string]interface{})
	o["rgb"] = true
	o["ext_popupmenu"] = true
	o["ext_tabline"] = true
	editor.nvim.AttachUI(editor.cols, editor.rows, o)
	editor.nvim.Subscribe("Gui")
	editor.nvim.Command("runtime plugin/nvim_gui_shim.vim")
	editor.nvim.Command("runtime! ginit.vim")
	fzf.RegisterPlugin(editor.nvim)
	locpopup.RegisterPlugin(editor.nvim)

	go func() {
		<-editor.close
		ui.Quit()
	}()

	return nil
}

func (e *Editor) handleNotification() {
	screen := e.screen
	e.nvim.RegisterHandler("Gui", func(updates ...interface{}) {
		event := updates[0].(string)
		switch event {
		case "Font":
			e.guiFont(updates[1:])
		case "Linespace":
			e.guiLinespace(updates[1:])
		case "finder_pattern":
			e.finder.showPattern(updates[1:])
		case "finder_pattern_pos":
			e.finder.cursorPos(updates[1:])
		case "finder_show_result":
			e.finder.showResult(updates[1:])
		case "finder_show":
			e.finder.show()
		case "finder_hide":
			e.finder.hide()
		case "finder_select":
			e.finder.selectResult(updates[1:])
		case "locpopup_show":
			arg, ok := updates[1].(map[string]interface{})
			if !ok {
				return
			}
			e.cursor.locpopup.show(arg)
		case "locpopup_hide":
			e.cursor.locpopup.hide()
		case "signature_show":
			e.cursor.signature.show(updates[1:])
		case "signature_pos":
			e.cursor.signature.pos(updates[1:])
		case "signature_hide":
			e.cursor.signature.hide()
		default:
			fmt.Println("unhandled Gui event", event)
		}
	})
	mutex := &sync.Mutex{}
	e.nvim.RegisterHandler("redraw", func(updates ...[]interface{}) {
		mutex.Lock()
		e.screen.redrawWindows()
		for _, update := range updates {
			event := update[0].(string)
			args := update[1:]
			switch event {
			case "update_fg":
				args := update[1].([]interface{})
				editor.Foreground = calcColor(reflectToInt(args[0]))
			case "update_bg":
				args := update[1].([]interface{})
				bg := calcColor(reflectToInt(args[0]))
				editor.Background = bg
			case "cursor_goto":
				screen.cursorGoto(args)
			case "put":
				screen.put(args)
			case "eol_clear":
				screen.eolClear(args)
			case "clear":
				screen.clear(args)
			case "resize":
				screen.resize(args)
			case "highlight_set":
				screen.highlightSet(args)
			case "set_scroll_region":
				screen.setScrollRegion(args)
			case "scroll":
				screen.scroll(args)
			case "mode_change":
				arg := update[1].([]interface{})
				editor.mode = arg[0].(string)
			case "popupmenu_show":
				editor.popup.show(args)
			case "popupmenu_hide":
				editor.popup.hide(args)
			case "popupmenu_select":
				editor.popup.selectItem(args)
			case "tabline_update":
				editor.tabline.update(args)
			default:
				fmt.Println("Unhandle event", event)
			}
		}
		screen.redraw()
		mutex.Unlock()
		if !e.nvimAttached {
			e.nvimAttached = true
		}
		editor.cursor.draw()
		go editor.statusline.redraw()
	})
}

func (e *Editor) guiFont(args ...interface{}) {
	fontArg := args[0].([]interface{})
	parts := strings.Split(fontArg[0].(string), ":")
	if len(parts) < 1 {
		return
	}

	height := 14
	for _, p := range parts[1:] {
		if strings.HasPrefix(p, "h") {
			var err error
			height, err = strconv.Atoi(p[1:])
			if err != nil {
				return
			}
		}
	}

	e.font.change(parts[0], height)
	e.smallerFont.change(parts[0], height-2)
	e.resize()
}

func (e *Editor) guiLinespace(args ...interface{}) {
	fontArg := args[0].([]interface{})
	lineSpace, err := strconv.Atoi(fontArg[0].(string))
	if err != nil {
		return
	}
	e.font.changeLineSpace(lineSpace)
	e.smallerFont.changeLineSpace(lineSpace)
	e.resize()
}

func (e *Editor) resize() {
	width := e.width
	height := e.height
	cols := width / editor.font.width
	rows := height / editor.font.lineHeight
	oldCols := editor.cols
	oldRows := editor.rows
	editor.cols = cols
	editor.rows = rows
	if oldCols > 0 && oldRows > 0 {
		editor.nvim.TryResizeUI(cols, rows)
	}
}

func (hl *Highlight) copy() Highlight {
	highlight := Highlight{}
	if hl.foreground != nil {
		highlight.foreground = hl.foreground.copy()
	}
	if hl.background != nil {
		highlight.background = hl.background.copy()
	}
	return highlight
}
<commit_msg>statusline position<commit_after>package gonvim

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"
	"unsafe"

	"github.com/dzhou121/neovim-fzf-shim/rplugin/go/fzf"
	"github.com/dzhou121/neovim-locpopup/rplugin/go/locpopup"
	"github.com/dzhou121/ui"
	"github.com/neovim/go-client/nvim"
)

var editor *Editor

// Highlight is
type Highlight struct {
	foreground *RGBA
	background *RGBA
}

// Char is
type Char struct {
	char      string
	highlight Highlight
}

// Editor is the editor
type Editor struct {
	nvim             *nvim.Nvim
	nvimAttached     bool
	mode             string
	font             *Font
	smallerFont      *Font
	rows             int
	cols             int
	cursor           *CursorBox
	Foreground       RGBA
	Background       RGBA
	window           *ui.Window
	screen           *Screen
	areaBox          *ui.Box
	close            chan bool
	popup            *PopupMenu
	finder           *Finder
	tabline          *Tabline
	statusline       *Statusline
	statuslineHeight int
	width            int
	height           int
	tablineHeight    int
	selectedBg       *RGBA
	matchFg          *RGBA
}

func initMainWindow(box *ui.Box, width, height int) *ui.Window {
	window := ui.NewWindow("Gonvim", width, height, false)
	window.SetChild(box)
	window.OnClosing(func(*ui.Window) bool {
		ui.Quit()
		return true
	})
	window.OnContentSizeChanged(func(w *ui.Window, data unsafe.Pointer) bool {
		if editor == nil {
			return true
		}
		width, height = window.ContentSize()
		height = height - editor.tablineHeight - editor.statuslineHeight
		if width == editor.width && height == editor.height {
			return true
		}
		editor.width = width
		editor.height = height
		editor.areaBox.SetSize(width, height)
		editor.screen.box.SetSize(width, height)
		editor.screen.setSize(width, height)
		editor.cursor.setSize(width, height)
		editor.tabline.resize(width, editor.tablineHeight)
		editor.statusline.box.SetSize(width, editor.statuslineHeight)
		editor.statusline.setSize(width, editor.statuslineHeight)
		editor.statusline.box.SetPosition(0, editor.tablineHeight+height)
		editor.statusline.redraw()
		editor.resize()
		editor.finder.rePosition()
		return true
	})
	window.Show()
	return window
}

// InitEditor inits the editor
func InitEditor() error {
	if editor != nil {
		return nil
	}
	width := 800
	height := 600
	tablineHeight := 34
	statuslineHeight := 28

	screen := initScreen(width, height)
	cursor := initCursorBox(width, height)
	popupMenu := initPopupmenu()
	finder := initFinder()
	tabline := initTabline(width, tablineHeight)
	loc := initLocpopup()
	statusline := initStatusline(width, statuslineHeight)

	box := ui.NewHorizontalBox()
	areaBox := ui.NewHorizontalBox()
	areaBox.Append(screen.box, false)
	areaBox.Append(cursor.box, false)
	areaBox.Append(loc.box, false)
	areaBox.Append(popupMenu.box, false)
	areaBox.Append(finder.box, false)
	box.Append(tabline.box, false)
	box.Append(areaBox, false)
	box.Append(statusline.box, false)

	areaBox.SetSize(width, height)
	areaBox.SetPosition(0, tablineHeight)
	statusline.box.SetPosition(0, tablineHeight+height)
	window := initMainWindow(box, width, height+tablineHeight+statuslineHeight)

	neovim, err := nvim.NewEmbedded(&nvim.EmbedOptions{
		Args: os.Args[1:],
	})
	if err != nil {
		return err
	}

	font := initFont("", 14, 0)
	smallerFont := initFont("", 14, 0)

	editor = &Editor{
		nvim:             neovim,
		nvimAttached:     false,
		window:           window,
		screen:           screen,
		areaBox:          areaBox,
		mode:             "normal",
		close:            make(chan bool),
		cursor:           cursor,
		popup:            popupMenu,
		finder:           finder,
		tabline:          tabline,
		width:            width,
		height:           height,
		tablineHeight:    tablineHeight,
		statusline:       statusline,
		statuslineHeight: statuslineHeight,
		font:             font,
		smallerFont:      smallerFont,
		cols:             0,
		rows:             0,
		selectedBg:       newRGBA(81, 154, 186, 0.5),
		matchFg:          newRGBA(81, 154, 186, 1),
	}

	editor.resize()
	editor.handleNotification()
	editor.finder.rePosition()
	go func() {
		err := neovim.Serve()
		if err != nil {
			fmt.Println(err)
		}
		editor.close <- true
	}()

	o := make(map[string]interface{})
	o["rgb"] = true
	o["ext_popupmenu"] = true
	o["ext_tabline"] = true
	editor.nvim.AttachUI(editor.cols, editor.rows, o)
	editor.nvim.Subscribe("Gui")
	editor.nvim.Command("runtime plugin/nvim_gui_shim.vim")
	editor.nvim.Command("runtime! ginit.vim")
	fzf.RegisterPlugin(editor.nvim)
	locpopup.RegisterPlugin(editor.nvim)

	go func() {
		<-editor.close
		ui.Quit()
	}()

	return nil
}

func (e *Editor) handleNotification() {
	screen := e.screen
	e.nvim.RegisterHandler("Gui", func(updates ...interface{}) {
		event := updates[0].(string)
		switch event {
		case "Font":
			e.guiFont(updates[1:])
		case "Linespace":
			e.guiLinespace(updates[1:])
		case "finder_pattern":
			e.finder.showPattern(updates[1:])
		case "finder_pattern_pos":
			e.finder.cursorPos(updates[1:])
		case "finder_show_result":
			e.finder.showResult(updates[1:])
		case "finder_show":
			e.finder.show()
		case "finder_hide":
			e.finder.hide()
		case "finder_select":
			e.finder.selectResult(updates[1:])
		case "locpopup_show":
			arg, ok := updates[1].(map[string]interface{})
			if !ok {
				return
			}
			e.cursor.locpopup.show(arg)
		case "locpopup_hide":
			e.cursor.locpopup.hide()
		case "signature_show":
			e.cursor.signature.show(updates[1:])
		case "signature_pos":
			e.cursor.signature.pos(updates[1:])
		case "signature_hide":
			e.cursor.signature.hide()
		default:
			fmt.Println("unhandled Gui event", event)
		}
	})
	mutex := &sync.Mutex{}
	e.nvim.RegisterHandler("redraw", func(updates ...[]interface{}) {
		mutex.Lock()
		e.screen.redrawWindows()
		for _, update := range updates {
			event := update[0].(string)
			args := update[1:]
			switch event {
			case "update_fg":
				args := update[1].([]interface{})
				editor.Foreground = calcColor(reflectToInt(args[0]))
			case "update_bg":
				args := update[1].([]interface{})
				bg := calcColor(reflectToInt(args[0]))
				editor.Background = bg
			case "cursor_goto":
				screen.cursorGoto(args)
			case "put":
				screen.put(args)
			case "eol_clear":
				screen.eolClear(args)
			case "clear":
				screen.clear(args)
			case "resize":
				screen.resize(args)
			case "highlight_set":
				screen.highlightSet(args)
			case "set_scroll_region":
				screen.setScrollRegion(args)
			case "scroll":
				screen.scroll(args)
			case "mode_change":
				arg := update[1].([]interface{})
				editor.mode = arg[0].(string)
			case "popupmenu_show":
				editor.popup.show(args)
			case "popupmenu_hide":
				editor.popup.hide(args)
			case "popupmenu_select":
				editor.popup.selectItem(args)
			case "tabline_update":
				editor.tabline.update(args)
			default:
				fmt.Println("Unhandle event", event)
			}
		}
		screen.redraw()
		mutex.Unlock()
		if !e.nvimAttached {
			e.nvimAttached = true
		}
		editor.cursor.draw()
		go editor.statusline.redraw()
	})
}

func (e *Editor) guiFont(args ...interface{}) {
	fontArg := args[0].([]interface{})
	parts := strings.Split(fontArg[0].(string), ":")
	if len(parts) < 1 {
		return
	}

	height := 14
	for _, p := range parts[1:] {
		if strings.HasPrefix(p, "h") {
			var err error
			height, err = strconv.Atoi(p[1:])
			if err != nil {
				return
			}
		}
	}

	e.font.change(parts[0], height)
	e.smallerFont.change(parts[0], height-2)
	e.resize()
}

func (e *Editor) guiLinespace(args ...interface{}) {
	fontArg := args[0].([]interface{})
	lineSpace, err := strconv.Atoi(fontArg[0].(string))
	if err != nil {
		return
	}
	e.font.changeLineSpace(lineSpace)
	e.smallerFont.changeLineSpace(lineSpace)
	e.resize()
}

func (e *Editor) resize() {
	width := e.width
	height := e.height
	cols := width / editor.font.width
	rows := height / editor.font.lineHeight
	oldCols := editor.cols
	oldRows := editor.rows
	editor.cols = cols
	editor.rows = rows
	if oldCols > 0 && oldRows > 0 {
		editor.nvim.TryResizeUI(cols, rows)
	}
}

func (hl *Highlight) copy() Highlight {
	highlight := Highlight{}
	if hl.foreground != nil {
		highlight.foreground = hl.foreground.copy()
	}
	if hl.background != nil {
		highlight.background = hl.background.copy()
	}
	return highlight
}
<|endoftext|>


<commit_before>// Copyright 2016 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package input

import (
	"sort"
	"strings"
)

// 所有支持的语言模型定义
//
// NOTE: 应该保持键名为非大写，按字母顺序排列，方便查找。
// langs 应该和 langExts 保持一一对应关系。
var langs = map[string][]blocker{
	// C#
	"c#": cStyle,

	// c/c++
	"c++": cStyle,

	// d
	"d": cStyle,

	// erlang
	"erlang": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `%`},
	},

	// go
	"go": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "`", End: "`"},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// groovy
	"groovy": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeString, Begin: "'''", End: "'''", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// java
	"java": cStyle,

	// javascript
	"javascript": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeString, Begin: "`", End: "`", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
		// NOTE: js 中若出现 /*abc/.test() 应该是先优先注释的。放最后，优先匹配 // 和 /*
		&block{Type: blockTypeString, Begin: "/", End: "/", Escape: `\`}, // 正则表达式
	},

	// pascal/delphi
	"pascal": {
		newPascalStringBlock('\''),
		newPascalStringBlock('"'),
		&block{Type: blockTypeMComment, Begin: "{", End: "}"},
		&block{Type: blockTypeMComment, Begin: "(*", End: "*)"},
	},

	// perl
	"perl": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
		&block{Type: blockTypeMComment, Begin: "\n=pod\n", End: "\n=cut\n"},
	},

	// python
	"python": {
		&block{Type: blockTypeMComment, Begin: `"""`, End: `"""`},
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
	},

	// php
	"php": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// ruby
	"ruby": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
		&block{Type: blockTypeMComment, Begin: "\n=begin\n", End: "\n=end\n"},
	},

	// rust
	"rust": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `///`}, // 需要在 // 之前定义
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// scala
	"scala": cStyle,

	// swift
	"swift": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		newSwiftNestMCommentBlock("/*", "*/"),
	},
}

var cStyle = []blocker{
	&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
	&block{Type: blockTypeSComment, Begin: `//`},
	&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
}

// 各语言默认支持的文件扩展名。
//
// NOTE: 键名与 langs 中的键一一对应。
// 键值为可能的文件扩展名列表，应该使用非大写状态。
// `go test` 会作大量名称是否规范的检测。
var langExts = map[string][]string{
	"c#":         {".cs"},
	"c++":        {".h", ".c", ".cpp", ".cxx", ".hpp"},
	"d":          {".d"},
	"erlang":     {".erl", ".hrl"},
	"go":         {".go"},
	"groovy":     {".groovy"},
	"java":       {".java"},
	"javascript": {".js"},
	"pascal":     {".pas", ".pp"},
	"perl":       {".perl", ".prl", ".pl"},
	"php":        {".php"},
	"python":     {".py"},
	"ruby":       {".rb"},
	"rust":       {".rs"},
	"scala":      {".scala"},
	"swift":      {".swift"},
}

// Languages 返回所有支持的语言
func Languages() []string {
	ret := make([]string, 0, len(langs))
	for l := range langs {
		ret = append(ret, l)
	}

	sort.SliceStable(ret, func(i, j int) bool {
		return ret[i] > ret[j]
	})

	return ret
}

// 根据扩展名获取其对应的语言名称。
// 若返回空值，则表示没有找到对应的。
func getLangByExt(ext string) string {
	ext = strings.ToLower(ext)
	for lang, exts := range langExts {
		for _, elem := range exts {
			if elem == ext {
				return lang
			}
		}
	}
	return ""
}

// 是否支持该语言
func langIsSupported(lang string) bool {
	// 由测试函数保证 langs 和 langExts 拥有相同的键名。
	_, found := langs[lang]
	return found
}
<commit_msg>为 PHP 添加 # 单行注释<commit_after>// Copyright 2016 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

package input

import (
	"sort"
	"strings"
)

// 所有支持的语言模型定义
//
// NOTE: 应该保持键名为非大写，按字母顺序排列，方便查找。
// langs 应该和 langExts 保持一一对应关系。
var langs = map[string][]blocker{
	// C#
	"c#": cStyle,

	// c/c++
	"c++": cStyle,

	// d
	"d": cStyle,

	// erlang
	"erlang": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `%`},
	},

	// go
	"go": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "`", End: "`"},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// groovy
	"groovy": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeString, Begin: "'''", End: "'''", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// java
	"java": cStyle,

	// javascript
	"javascript": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeString, Begin: "`", End: "`", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
		// NOTE: js 中若出现 /*abc/.test() 应该是先优先注释的。放最后，优先匹配 // 和 /*
		&block{Type: blockTypeString, Begin: "/", End: "/", Escape: `\`}, // 正则表达式
	},

	// pascal/delphi
	"pascal": {
		newPascalStringBlock('\''),
		newPascalStringBlock('"'),
		&block{Type: blockTypeMComment, Begin: "{", End: "}"},
		&block{Type: blockTypeMComment, Begin: "(*", End: "*)"},
	},

	// perl
	"perl": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
		&block{Type: blockTypeMComment, Begin: "\n=pod\n", End: "\n=cut\n"},
	},

	// python
	"python": {
		&block{Type: blockTypeMComment, Begin: `"""`, End: `"""`},
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
	},

	// php
	"php": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeSComment, Begin: `#`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// ruby
	"ruby": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeString, Begin: "'", End: "'", Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `#`},
		&block{Type: blockTypeMComment, Begin: "\n=begin\n", End: "\n=end\n"},
	},

	// rust
	"rust": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `///`}, // 需要在 // 之前定义
		&block{Type: blockTypeSComment, Begin: `//`},
		&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
	},

	// scala
	"scala": cStyle,

	// swift
	"swift": {
		&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
		&block{Type: blockTypeSComment, Begin: `//`},
		newSwiftNestMCommentBlock("/*", "*/"),
	},
}

var cStyle = []blocker{
	&block{Type: blockTypeString, Begin: `"`, End: `"`, Escape: `\`},
	&block{Type: blockTypeSComment, Begin: `//`},
	&block{Type: blockTypeMComment, Begin: `/*`, End: `*/`},
}

// 各语言默认支持的文件扩展名。
//
// NOTE: 键名与 langs 中的键一一对应。
// 键值为可能的文件扩展名列表，应该使用非大写状态。
// `go test` 会作大量名称是否规范的检测。
var langExts = map[string][]string{
	"c#":         {".cs"},
	"c++":        {".h", ".c", ".cpp", ".cxx", ".hpp"},
	"d":          {".d"},
	"erlang":     {".erl", ".hrl"},
	"go":         {".go"},
	"groovy":     {".groovy"},
	"java":       {".java"},
	"javascript": {".js"},
	"pascal":     {".pas", ".pp"},
	"perl":       {".perl", ".prl", ".pl"},
	"php":        {".php"},
	"python":     {".py"},
	"ruby":       {".rb"},
	"rust":       {".rs"},
	"scala":      {".scala"},
	"swift":      {".swift"},
}

// Languages 返回所有支持的语言
func Languages() []string {
	ret := make([]string, 0, len(langs))
	for l := range langs {
		ret = append(ret, l)
	}

	sort.SliceStable(ret, func(i, j int) bool {
		return ret[i] > ret[j]
	})

	return ret
}

// 根据扩展名获取其对应的语言名称。
// 若返回空值，则表示没有找到对应的。
func getLangByExt(ext string) string {
	ext = strings.ToLower(ext)
	for lang, exts := range langExts {
		for _, elem := range exts {
			if elem == ext {
				return lang
			}
		}
	}
	return ""
}

// 是否支持该语言
func langIsSupported(lang string) bool {
	// 由测试函数保证 langs 和 langExts 拥有相同的键名。
	_, found := langs[lang]
	return found
}
<|endoftext|>


<commit_before>package model

import (
	"fmt"
	"os"
	"path/filepath"
	"testing"

	"github.com/go-ggz/ggz/config"

	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// ggzRoot a path to the ggz root
var ggzRoot string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGgzRoot string) {
	var err error
	ggzRoot = pathToGgzRoot
	fixturesDir := filepath.Join(pathToGgzRoot, "model", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}
	exitStatus := m.Run()
	os.Exit(exitStatus)
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GGZ_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(config.Debug)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<commit_msg>chore: update main testing<commit_after>package model

import (
	"fmt"
	"os"
	"path/filepath"
	"testing"

	"github.com/go-ggz/ggz/config"

	"github.com/go-xorm/core"
	"github.com/go-xorm/xorm"
	"github.com/stretchr/testify/assert"
	"gopkg.in/testfixtures.v2"
)

// ggzRoot a path to the ggz root
var ggzRoot string

func fatalTestError(fmtStr string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, fmtStr, args...)
	os.Exit(1)
}

// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGgzRoot string) {
	var err error
	ggzRoot = pathToGgzRoot
	fixturesDir := filepath.Join(pathToGgzRoot, "model", "fixtures")
	if err = createTestEngine(fixturesDir); err != nil {
		fatalTestError("Error creating test engine: %v\n", err)
	}
	os.Exit(m.Run())
}

func createTestEngine(fixturesDir string) error {
	var err error
	x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
	if err != nil {
		return err
	}
	x.SetMapper(core.GonicMapper{})
	if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
		return err
	}
	switch os.Getenv("GGZ_UNIT_TESTS_VERBOSE") {
	case "true", "1":
		x.ShowSQL(config.Debug)
	}

	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
}

// PrepareTestDatabase load test fixtures into test database
func PrepareTestDatabase() error {
	return LoadFixtures()
}

// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
	assert.NoError(t, PrepareTestDatabase())
}

type testCond struct {
	query interface{}
	args  []interface{}
}

// Cond create a condition with arguments for a test
func Cond(query interface{}, args ...interface{}) interface{} {
	return &testCond{query: query, args: args}
}

func whereConditions(sess *xorm.Session, conditions []interface{}) {
	for _, condition := range conditions {
		switch cond := condition.(type) {
		case *testCond:
			sess.Where(cond.query, cond.args...)
		default:
			sess.Where(cond)
		}
	}
}

func loadBeanIfExists(bean interface{}, conditions ...interface{}) (bool, error) {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	return sess.Get(bean)
}

// BeanExists for testing, check if a bean exists
func BeanExists(t testing.TB, bean interface{}, conditions ...interface{}) bool {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	return exists
}

// AssertExistsAndLoadBean assert that a bean exists and load it from the test
// database
func AssertExistsAndLoadBean(t testing.TB, bean interface{}, conditions ...interface{}) interface{} {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.True(t, exists,
		"Expected to find %+v (of type %T, with conditions %+v), but did not",
		bean, bean, conditions)
	return bean
}

// GetCount get the count of a bean
func GetCount(t testing.TB, bean interface{}, conditions ...interface{}) int {
	sess := x.NewSession()
	defer sess.Close()
	whereConditions(sess, conditions)
	count, err := sess.Count(bean)
	assert.NoError(t, err)
	return int(count)
}

// AssertNotExistsBean assert that a bean does not exist in the test database
func AssertNotExistsBean(t testing.TB, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.False(t, exists)
}

// AssertExistsIf asserts that a bean exists or does not exist, depending on
// what is expected.
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
	exists, err := loadBeanIfExists(bean, conditions...)
	assert.NoError(t, err)
	assert.Equal(t, expected, exists)
}

// AssertSuccessfulInsert assert that beans is successfully inserted
func AssertSuccessfulInsert(t testing.TB, beans ...interface{}) {
	_, err := x.Insert(beans...)
	assert.NoError(t, err)
}

// AssertCount assert the count of a bean
func AssertCount(t testing.TB, bean interface{}, expected interface{}) {
	assert.EqualValues(t, expected, GetCount(t, bean))
}

// AssertInt64InRange assert value is in range [low, high]
func AssertInt64InRange(t testing.TB, low, high, value int64) {
	assert.True(t, value >= low && value <= high,
		"Expected value in range [%d, %d], found %d", low, high, value)
}
<|endoftext|>


<commit_before>// Copyright 2017, Project ArteMisc
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package godium

import (
	"crypto/cipher"
	"errors"
	"hash"
	"io"
)

var (
	// ErrForgedOrCorrupted is returned by decryption method that perform
	// message authentication whenever the authentication check fails. When such
	// a check fails, it indicates that the message is either forged, corrupted,
	// or incorrectly encrypted. These could be indicators of protocol or
	// implementation failures, but also be a sign of an active
	// man-in-the-middle attack
	ErrForgedOrCorrupted = errors.New("authentication tag is invalid, message is forged or corrupted")

	// ErrInvalidPoint is returned when a point on an elliptic curve is
	// considered illegal, unsafe, or incorrectly formatted.
	ErrInvalidPoint = errors.New("elliptic curve point not valid, rejected, or considered unsafe")

	// ErrCipherTooShort is returned when a ciphertext is shorter than a minimal
	// amount of bytes, for example when an authenticated ciphertext is not long
	// enough to at least contain the full authentication tag.
	ErrCipherTooShort = errors.New("cipher shorter than minimal size")

	// ErrBufferTooShort is returned when a buffer provided to a method is
	// shorter than a minimal amount of expected bytes, for example a header
	// that should at least contain a certain amount of bytes to hold a full
	// piece of data for an algorithm.
	ErrBufferTooShort = errors.New("buffer shorter than expected size")
)

// Wipe will override the contents of the buffer p with 0's.
func Wipe(p []byte) {
	for i := range p {
		p[i] = 0x00
	}
}

// Wiper defines an interface that types implement to indicate they can wipe
// their internal state.
type Wiper interface {
	Wipe()
}

// Key
type Key []byte

// PrivateKey
type PrivateKey []byte

// PublicKey
type PublicKey []byte

// AEAD
type AEAD interface {
	cipher.AEAD
	Wiper

	SealDetached(dst, dstMac, nonce, plain, ad []byte) (cipher, mac []byte)

	OpenDetached(dst, nonce, cipher, mac, ad []byte) (plain []byte, err error)

	KeyBytes() (c int)
	NSecBytes() (c int)
	NPubBytes() (c int)
	ABytes() (c int)
}

// Auth
type Auth interface {
	Hash
	Wiper

	// Verify will check if the resulting Sum() of the Auth equals the provided
	// authentication tag.
	Verify(tag []byte) (matches bool)

	KeyBytes() (c int)
}

// Box
type Box interface {
	Wiper

	SealDetached(dst, dstMac, nonce, plain []byte, remote PublicKey) (cipher, mac []byte, err error)

	Seal(dst, nonce, plain []byte, remote PublicKey) (cipher []byte, err error)

	OpenDetached(dst, nonce, cipher, mac []byte, remote PublicKey) (plain []byte, err error)

	Open(dst, nonce, cipher []byte, remote PublicKey) (plain []byte, err error)

	BeforeNM(remote PublicKey) (sb SecretBox, err error)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	MacBytes() (c int)
	NonceBytes() (c int)
	SeedBytes() (c int)
	BeforeNmBytes() (c int)
}

// GenericHash
type GenericHash interface {
	hash.Hash
	Wiper

	BytesMin() (c int)
	BytesMax() (c int)
	KeyBytesMin() (c int)
	KeyBytesMax() (c int)
	KeyBytes() (c int)
}

// Hash
type Hash interface {
	hash.Hash

	Bytes() (c int)
}

// Kdf
type Kdf interface {
	Wiper

	// Derive
	Derive(dst []byte, subKeyLength, subKeyId uint64) (subKey []byte)

	BytesMin() (c int)
	BytesMax() (c int)
	ContextBytes() (c int)
	KeyBytes() (c int)
}

// Kx
type Kx interface {
	Wiper

	// ServerSessionKeys
	ServerSessionKeys(dstRx, dstTx []byte, remote PublicKey) (rx, tx Key, err error)

	// ServerSessionKeys
	ClientSessionKeys(dstRx, dstTx []byte, remote PublicKey) (rx, tx Key, err error)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	SeedBytes() (c int)
	SessionKeyBytes() (c int)
}

// OneTimeAuth
type OneTimeAuth interface {
	Auth

	// ReKey re-initializes the OneTimeAuth state with the new key. OneTimeAuth
	// instances should only be used once. To use it again, it needs to be
	// re-initialized with a new one-time key.
	ReKey(key []byte)
}

// SecretBox
type SecretBox interface {
	Wiper

	Seal(dst, nonce, plain []byte) (cipher []byte)

	SealDetached(dst, dstMac, nonce, plain []byte) (cipher, mac []byte)

	Open(dst, nonce, cipher []byte) (plain []byte, err error)

	OpenDetached(dst, nonce, cipher, mac []byte) (plain []byte, err error)

	KeyBytes() (c int)
	MacBytes() (c int)
	NonceBytes() (c int)
}

type SecretStream interface {
	InitPush(dst []byte, key Key) (header []byte)
	InitPull(header []byte, key Key) (err error)
	Push(dst, plain, ad []byte, tag byte) (cipher []byte)
	Pull(dst, cipher, ad []byte) (plain []byte, tag byte, err error)
	ReKey()

	ABytes() (c int)
	HeaderBytes() (c int)
	KeyBytes() (c int)
	TAG_MESSAGE() (c byte)
	TAG_PUSH() (c byte)
	TAG_REKEY() (c byte)
	TAG_FINAL() (c byte)
}

// ShortHash
type ShortHash interface {
	Hash

	KeyBytes() (c int)
}

// ShortHash64Func
type ShortHash64Func func(key, data []byte) (sum uint64)

// ShortHash128Func
type ShortHash128Func func(key, data []byte) (sum1, sum2 uint64)

// ShortHash64
type ShortHash64 interface {
	ShortHash
	Sum64() (sum uint64)
}

// ShortHash128
type ShortHash128 interface {
	ShortHash
	Sum128() (s1, s2 uint64)
}

// Sign
type Sign interface {
	Wiper

	// Detached signs the message data in unsigned, and returns a message with
	// the signature
	Sign(dst, unsigned []byte) (signed []byte)

	// SignDetached creates a signature
	SignDetached(dst, unsigned []byte) (signature []byte)

	// io.Writer provides the Write method to the Signature interface. When
	// Write is used, the Signature implementation moves to Multipart mode,
	// which pre-hashes the message before signing.
	//
	// Note that this may produce a different signature then when full-message
	// signatures are used, as the pre-hashing generated a different value for
	// the signature key to sign.
	io.Writer

	// Final is the SignDetached method's equivalent for Multipart messages.
	// This operation will fail if Write has not been called before.
	Final(dst []byte) (signature []byte)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	Bytes() (c int)
	SeedBytes() (c int)
}

// SignVerifier
type SignVerifier interface {
	// Open will verify the signature, and return the message data without the
	// signature.
	Open(dst, signed []byte) (unsigned []byte, valid bool)

	// VerifyDetached is the detached equivalent of Open, which simply verifies
	// the signature.
	VerifyDetached(signature, message []byte) (valid bool)

	// io.Writer provides the Write method to the Signature interface. When
	// Write is used, the Signature implementation moves to Multipart mode,
	// which pre-hashes the message before signing.
	//
	// Note that this may produce a different signature then when full-message
	// signatures are used, as the pre-hashing generated a different value for
	// the signature key to sign.
	io.Writer

	// FinalVerify is the Verify method's equivalent for Multipart messages.
	// This operation will fail if Write has not been called before.
	FinalVerify(signature []byte) (valid bool)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	Bytes() (c int)
	SeedBytes() (c int)
}

// Stream
type Stream interface {
	cipher.Stream
	Wiper

	// KeyStream generated len(dst) bytes of key from the stream
	KeyStream(dst []byte)

	// Seek sets the stream's internal counter. As this is usually followed
	// directly by a call to KeyStream or XORKeyStream, it returns a reference
	// to itself to enable chaining.
	//
	// example: stream.Seek(1).KeyStream(stream)
	Seek(counter uint64) Stream

	// ReKey will re-initialize the stream with the given key/nonce combination.
	ReKey(key, nonce []byte)

	KeyBytes() (c int)
	NonceBytes() (c int)
	BlockBytes() (c int)
}

// Codec implements a constant-time encoding algorithm to convert between binary
// data a printable text representation.
type Codec interface {
	// Encode appends the encoded value of bin to dst.
	Encode(dst, bin []byte) (txt []byte)

	// Decode appends the decoded value of txt to dst.
	Decode(dst, txt []byte) (bin []byte)

	// EncodedLength calculates what the length of the encoded value would be
	// for this codec.
	EncodedLength(decoded int) (encoded int)

	// DecodedLength calculates what the length of the decoded value would be
	// for this codec.
	DecodedLength(encoded int) (decoded int)
}

// Random provides an interface for CSPRNG functionality.
type Random interface {
	UInt32() uint32
	UniformUInt32(upper uint32) uint32

	UInt64() uint64
	UniformUInt64(upper uint64) uint64

	// Buf will fill the buffer p with random bytes.
	Buf(p []byte) (err error)

	// KeyGen is a simplified call to Buf which allocates the byte slice to fit
	// the provided key size.
	KeyGen(size int) (key []byte, err error)

	// Implements the io.Reader interface, functions like Buf(p)
	io.Reader
}

// Multipart is the generic interface used to describe a primitive that can
// update its state incrementally.
type Multipart interface {
	// Writer implements the Write method, which can be used to update the state
	// of the Multipart
	io.Writer

	Update(p []byte) Multipart

	Final(dst []byte) (out []byte)

	FinalVerify(expect []byte) (valid bool)
}
<commit_msg>secret stream implements Wiper<commit_after>// Copyright 2017, Project ArteMisc
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package godium

import (
	"crypto/cipher"
	"errors"
	"hash"
	"io"
)

var (
	// ErrForgedOrCorrupted is returned by decryption method that perform
	// message authentication whenever the authentication check fails. When such
	// a check fails, it indicates that the message is either forged, corrupted,
	// or incorrectly encrypted. These could be indicators of protocol or
	// implementation failures, but also be a sign of an active
	// man-in-the-middle attack
	ErrForgedOrCorrupted = errors.New("authentication tag is invalid, message is forged or corrupted")

	// ErrInvalidPoint is returned when a point on an elliptic curve is
	// considered illegal, unsafe, or incorrectly formatted.
	ErrInvalidPoint = errors.New("elliptic curve point not valid, rejected, or considered unsafe")

	// ErrCipherTooShort is returned when a ciphertext is shorter than a minimal
	// amount of bytes, for example when an authenticated ciphertext is not long
	// enough to at least contain the full authentication tag.
	ErrCipherTooShort = errors.New("cipher shorter than minimal size")

	// ErrBufferTooShort is returned when a buffer provided to a method is
	// shorter than a minimal amount of expected bytes, for example a header
	// that should at least contain a certain amount of bytes to hold a full
	// piece of data for an algorithm.
	ErrBufferTooShort = errors.New("buffer shorter than expected size")
)

// Wipe will override the contents of the buffer p with 0's.
func Wipe(p []byte) {
	for i := range p {
		p[i] = 0x00
	}
}

// Wiper defines an interface that types implement to indicate they can wipe
// their internal state.
type Wiper interface {
	Wipe()
}

// Key
type Key []byte

// PrivateKey
type PrivateKey []byte

// PublicKey
type PublicKey []byte

// AEAD
type AEAD interface {
	cipher.AEAD
	Wiper

	SealDetached(dst, dstMac, nonce, plain, ad []byte) (cipher, mac []byte)

	OpenDetached(dst, nonce, cipher, mac, ad []byte) (plain []byte, err error)

	KeyBytes() (c int)
	NSecBytes() (c int)
	NPubBytes() (c int)
	ABytes() (c int)
}

// Auth
type Auth interface {
	Hash
	Wiper

	// Verify will check if the resulting Sum() of the Auth equals the provided
	// authentication tag.
	Verify(tag []byte) (matches bool)

	KeyBytes() (c int)
}

// Box
type Box interface {
	Wiper

	SealDetached(dst, dstMac, nonce, plain []byte, remote PublicKey) (cipher, mac []byte, err error)

	Seal(dst, nonce, plain []byte, remote PublicKey) (cipher []byte, err error)

	OpenDetached(dst, nonce, cipher, mac []byte, remote PublicKey) (plain []byte, err error)

	Open(dst, nonce, cipher []byte, remote PublicKey) (plain []byte, err error)

	BeforeNM(remote PublicKey) (sb SecretBox, err error)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	MacBytes() (c int)
	NonceBytes() (c int)
	SeedBytes() (c int)
	BeforeNmBytes() (c int)
}

// GenericHash
type GenericHash interface {
	hash.Hash
	Wiper

	BytesMin() (c int)
	BytesMax() (c int)
	KeyBytesMin() (c int)
	KeyBytesMax() (c int)
	KeyBytes() (c int)
}

// Hash
type Hash interface {
	hash.Hash

	Bytes() (c int)
}

// Kdf
type Kdf interface {
	Wiper

	// Derive
	Derive(dst []byte, subKeyLength, subKeyId uint64) (subKey []byte)

	BytesMin() (c int)
	BytesMax() (c int)
	ContextBytes() (c int)
	KeyBytes() (c int)
}

// Kx
type Kx interface {
	Wiper

	// ServerSessionKeys
	ServerSessionKeys(dstRx, dstTx []byte, remote PublicKey) (rx, tx Key, err error)

	// ServerSessionKeys
	ClientSessionKeys(dstRx, dstTx []byte, remote PublicKey) (rx, tx Key, err error)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	SeedBytes() (c int)
	SessionKeyBytes() (c int)
}

// OneTimeAuth
type OneTimeAuth interface {
	Auth

	// ReKey re-initializes the OneTimeAuth state with the new key. OneTimeAuth
	// instances should only be used once. To use it again, it needs to be
	// re-initialized with a new one-time key.
	ReKey(key []byte)
}

// SecretBox
type SecretBox interface {
	Wiper

	Seal(dst, nonce, plain []byte) (cipher []byte)

	SealDetached(dst, dstMac, nonce, plain []byte) (cipher, mac []byte)

	Open(dst, nonce, cipher []byte) (plain []byte, err error)

	OpenDetached(dst, nonce, cipher, mac []byte) (plain []byte, err error)

	KeyBytes() (c int)
	MacBytes() (c int)
	NonceBytes() (c int)
}

// SecretStream
type SecretStream interface {
	Wiper

	InitPush(dst []byte, key Key) (header []byte)
	InitPull(header []byte, key Key) (err error)
	Push(dst, plain, ad []byte, tag byte) (cipher []byte)
	Pull(dst, cipher, ad []byte) (plain []byte, tag byte, err error)
	ReKey()

	ABytes() (c int)
	HeaderBytes() (c int)
	KeyBytes() (c int)
	TAG_MESSAGE() (c byte)
	TAG_PUSH() (c byte)
	TAG_REKEY() (c byte)
	TAG_FINAL() (c byte)
}

// ShortHash
type ShortHash interface {
	Hash

	KeyBytes() (c int)
}

// ShortHash64Func
type ShortHash64Func func(key, data []byte) (sum uint64)

// ShortHash128Func
type ShortHash128Func func(key, data []byte) (sum1, sum2 uint64)

// ShortHash64
type ShortHash64 interface {
	ShortHash
	Sum64() (sum uint64)
}

// ShortHash128
type ShortHash128 interface {
	ShortHash
	Sum128() (s1, s2 uint64)
}

// Sign
type Sign interface {
	Wiper

	// Detached signs the message data in unsigned, and returns a message with
	// the signature
	Sign(dst, unsigned []byte) (signed []byte)

	// SignDetached creates a signature
	SignDetached(dst, unsigned []byte) (signature []byte)

	// io.Writer provides the Write method to the Signature interface. When
	// Write is used, the Signature implementation moves to Multipart mode,
	// which pre-hashes the message before signing.
	//
	// Note that this may produce a different signature then when full-message
	// signatures are used, as the pre-hashing generated a different value for
	// the signature key to sign.
	io.Writer

	// Final is the SignDetached method's equivalent for Multipart messages.
	// This operation will fail if Write has not been called before.
	Final(dst []byte) (signature []byte)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	Bytes() (c int)
	SeedBytes() (c int)
}

// SignVerifier
type SignVerifier interface {
	// Open will verify the signature, and return the message data without the
	// signature.
	Open(dst, signed []byte) (unsigned []byte, valid bool)

	// VerifyDetached is the detached equivalent of Open, which simply verifies
	// the signature.
	VerifyDetached(signature, message []byte) (valid bool)

	// io.Writer provides the Write method to the Signature interface. When
	// Write is used, the Signature implementation moves to Multipart mode,
	// which pre-hashes the message before signing.
	//
	// Note that this may produce a different signature then when full-message
	// signatures are used, as the pre-hashing generated a different value for
	// the signature key to sign.
	io.Writer

	// FinalVerify is the Verify method's equivalent for Multipart messages.
	// This operation will fail if Write has not been called before.
	FinalVerify(signature []byte) (valid bool)

	PublicKeyBytes() (c int)
	SecretKeyBytes() (c int)
	Bytes() (c int)
	SeedBytes() (c int)
}

// Stream
type Stream interface {
	cipher.Stream
	Wiper

	// KeyStream generated len(dst) bytes of key from the stream
	KeyStream(dst []byte)

	// Seek sets the stream's internal counter. As this is usually followed
	// directly by a call to KeyStream or XORKeyStream, it returns a reference
	// to itself to enable chaining.
	//
	// example: stream.Seek(1).KeyStream(stream)
	Seek(counter uint64) Stream

	// ReKey will re-initialize the stream with the given key/nonce combination.
	ReKey(key, nonce []byte)

	KeyBytes() (c int)
	NonceBytes() (c int)
	BlockBytes() (c int)
}

// Codec implements a constant-time encoding algorithm to convert between binary
// data a printable text representation.
type Codec interface {
	// Encode appends the encoded value of bin to dst.
	Encode(dst, bin []byte) (txt []byte)

	// Decode appends the decoded value of txt to dst.
	Decode(dst, txt []byte) (bin []byte)

	// EncodedLength calculates what the length of the encoded value would be
	// for this codec.
	EncodedLength(decoded int) (encoded int)

	// DecodedLength calculates what the length of the decoded value would be
	// for this codec.
	DecodedLength(encoded int) (decoded int)
}

// Random provides an interface for CSPRNG functionality.
type Random interface {
	UInt32() uint32
	UniformUInt32(upper uint32) uint32

	UInt64() uint64
	UniformUInt64(upper uint64) uint64

	// Buf will fill the buffer p with random bytes.
	Buf(p []byte) (err error)

	// KeyGen is a simplified call to Buf which allocates the byte slice to fit
	// the provided key size.
	KeyGen(size int) (key []byte, err error)

	// Implements the io.Reader interface, functions like Buf(p)
	io.Reader
}

// Multipart is the generic interface used to describe a primitive that can
// update its state incrementally.
type Multipart interface {
	// Writer implements the Write method, which can be used to update the state
	// of the Multipart
	io.Writer

	Update(p []byte) Multipart

	Final(dst []byte) (out []byte)

	FinalVerify(expect []byte) (valid bool)
}
<|endoftext|>


<commit_before>// Copyright 2015 go-swagger maintainers
//
// 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 runtime

import (
	"io"
	"net/http"

	"github.com/go-openapi/strfmt"
)

// OperationHandlerFunc an adapter for a function to the OperationHandler interface
type OperationHandlerFunc func(interface{}) (interface{}, error)

// Handle implements the operation handler interface
func (s OperationHandlerFunc) Handle(data interface{}) (interface{}, error) {
	return s(data)
}

// OperationHandler a handler for a swagger operation
type OperationHandler interface {
	Handle(interface{}) (interface{}, error)
}

// ConsumerFunc represents a function that can be used as a consumer
type ConsumerFunc func(io.Reader, interface{}) error

// Consume consumes the reader into the data parameter
func (fn ConsumerFunc) Consume(reader io.Reader, data interface{}) error {
	return fn(reader, data)
}

// Consumer implementations know how to bind the values on the provided interface to
// data provided by the request body
type Consumer interface {
	// Consume performs the binding of request values
	Consume(io.Reader, interface{}) error
}

// ProducerFunc represents a function that can be used as a producer
type ProducerFunc func(io.Writer, interface{}) error

// Produce produces the response for the provided data
func (f ProducerFunc) Produce(writer io.Writer, data interface{}) error {
	return f(writer, data)
}

// Producer implementations know how to turn the provided interface into a valid
// HTTP response
type Producer interface {
	// Produce writes to the http response
	Produce(io.Writer, interface{}) error
}

// AuthenticatorFunc turns a function into an authenticator
type AuthenticatorFunc func(interface{}) (bool, interface{}, error)

// Authenticate authenticates the request with the provided data
func (f AuthenticatorFunc) Authenticate(params interface{}) (bool, interface{}, error) {
	return f(params)
}

// Authenticator represents an authentication strategy
// implementations of Authenticator know how to authenticate the
// request data and translate that into a valid principal object or an error
type Authenticator interface {
	Authenticate(interface{}) (bool, interface{}, error)
}

// AuthorizerFunc turns a function into an authorizer
type AuthorizerFunc func(*http.Request, interface{}) error

// Authorize authorizes the processing of the request for the principal
func (f AuthorizerFunc) Authorize(r *http.Request, principal interface{}) error {
	return f(r, principal)
}

// Authorizer represents an authorization strategy
// implementations of Authorizer know how to authorize the principal object
// using the request data and returns error if unauthorized
type Authorizer interface {
	Authorize(*http.Request, interface{}) error
}

// Validatable types implementing this interface allow customizing their validation
// this will be used instead of the reflective validation based on the spec document.
// the implementations are assumed to have been generated by the swagger tool so they should
// contain all the validations obtained from the spec
type Validatable interface {
	Validate(strfmt.Registry) error
}
<commit_msg>add contextValidatable interface<commit_after>// Copyright 2015 go-swagger maintainers
//
// 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 runtime

import (
	"context"
	"io"
	"net/http"

	"github.com/go-openapi/strfmt"
)

// OperationHandlerFunc an adapter for a function to the OperationHandler interface
type OperationHandlerFunc func(interface{}) (interface{}, error)

// Handle implements the operation handler interface
func (s OperationHandlerFunc) Handle(data interface{}) (interface{}, error) {
	return s(data)
}

// OperationHandler a handler for a swagger operation
type OperationHandler interface {
	Handle(interface{}) (interface{}, error)
}

// ConsumerFunc represents a function that can be used as a consumer
type ConsumerFunc func(io.Reader, interface{}) error

// Consume consumes the reader into the data parameter
func (fn ConsumerFunc) Consume(reader io.Reader, data interface{}) error {
	return fn(reader, data)
}

// Consumer implementations know how to bind the values on the provided interface to
// data provided by the request body
type Consumer interface {
	// Consume performs the binding of request values
	Consume(io.Reader, interface{}) error
}

// ProducerFunc represents a function that can be used as a producer
type ProducerFunc func(io.Writer, interface{}) error

// Produce produces the response for the provided data
func (f ProducerFunc) Produce(writer io.Writer, data interface{}) error {
	return f(writer, data)
}

// Producer implementations know how to turn the provided interface into a valid
// HTTP response
type Producer interface {
	// Produce writes to the http response
	Produce(io.Writer, interface{}) error
}

// AuthenticatorFunc turns a function into an authenticator
type AuthenticatorFunc func(interface{}) (bool, interface{}, error)

// Authenticate authenticates the request with the provided data
func (f AuthenticatorFunc) Authenticate(params interface{}) (bool, interface{}, error) {
	return f(params)
}

// Authenticator represents an authentication strategy
// implementations of Authenticator know how to authenticate the
// request data and translate that into a valid principal object or an error
type Authenticator interface {
	Authenticate(interface{}) (bool, interface{}, error)
}

// AuthorizerFunc turns a function into an authorizer
type AuthorizerFunc func(*http.Request, interface{}) error

// Authorize authorizes the processing of the request for the principal
func (f AuthorizerFunc) Authorize(r *http.Request, principal interface{}) error {
	return f(r, principal)
}

// Authorizer represents an authorization strategy
// implementations of Authorizer know how to authorize the principal object
// using the request data and returns error if unauthorized
type Authorizer interface {
	Authorize(*http.Request, interface{}) error
}

// Validatable types implementing this interface allow customizing their validation
// this will be used instead of the reflective validation based on the spec document.
// the implementations are assumed to have been generated by the swagger tool so they should
// contain all the validations obtained from the spec
type Validatable interface {
	Validate(strfmt.Registry) error
}

// ContextValidatable types implementing this interface allow customizing their validation
// this will be used instead of the reflective validation based on the spec document.
// the implementations are assumed to have been generated by the swagger tool so they should
// contain all the context validations obtained from the spec
type ContextValidatable interface {
	ContextValidate(context.Context, strfmt.Registry) error
}
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package tools

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/errgo/errgo"

	coretools "launchpad.net/juju-core/tools"
	"launchpad.net/juju-core/version"
)

const toolsFile = "downloaded-tools.txt"

// SharedToolsDir returns the directory that is used to
// store binaries for the given version of the juju tools
// within the dataDir directory.
func SharedToolsDir(dataDir string, vers version.Binary) string {
	return path.Join(dataDir, "tools", vers.String())
}

// ToolsDir returns the directory that is used/ to store binaries for
// the tools used by the given agent within the given dataDir directory.
// Conventionally it is a symbolic link to the actual tools directory.
func ToolsDir(dataDir, agentName string) string {
	return path.Join(dataDir, "tools", agentName)
}

// UnpackTools reads a set of juju tools in gzipped tar-archive
// format and unpacks them into the appropriate tools directory
// within dataDir. If a valid tools directory already exists,
// UnpackTools returns without error.
func UnpackTools(dataDir string, tools *coretools.Tools, r io.Reader) (err error) {
	// Unpack the gzip file and compute the checksum.
	sha256hash := sha256.New()
	zr, err := gzip.NewReader(io.TeeReader(r, sha256hash))
	if err != nil {
		return err
	}
	defer zr.Close()
	f, err := ioutil.TempFile(os.TempDir(), "tools-tar")
	if err != nil {
		return err
	}
	_, err = io.Copy(f, zr)
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())
	// TODO(wallyworld) - 2013-09-24 bug=1229512
	// When we can ensure all tools records have valid checksums recorded,
	// we can remove this test short circuit.
	gzipSHA256 := fmt.Sprintf("%x", sha256hash.Sum(nil))
	if tools.SHA256 != "" && tools.SHA256 != gzipSHA256 {
		return fmt.Errorf("tarball sha256 mismatch, expected %s, got %s", tools.SHA256, gzipSHA256)
	}

	// Make a temporary directory in the tools directory,
	// first ensuring that the tools directory exists.
	toolsDir := path.Join(dataDir, "tools")
	err = os.MkdirAll(toolsDir, 0755)
	if err != nil {
		return err
	}
	dir, err := ioutil.TempDir(toolsDir, "unpacking-")
	if err != nil {
		return err
	}
	defer removeAll(dir)

	// Checksum matches, now reset the file and untar it.
	_, err = f.Seek(0, 0)
	if err != nil {
		return err
	}
	tr := tar.NewReader(f)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		if strings.ContainsAny(hdr.Name, "/\\") {
			return fmt.Errorf("bad name %q in tools archive", hdr.Name)
		}
		if hdr.Typeflag != tar.TypeReg {
			return fmt.Errorf("bad file type %c in file %q in tools archive", hdr.Typeflag, hdr.Name)
		}
		name := path.Join(dir, hdr.Name)
		if err := writeFile(name, os.FileMode(hdr.Mode&0777), tr); err != nil {
			return errgo.Annotatef(err, "tar extract %q failed", name)
		}
	}
	toolsMetadataData, err := json.Marshal(tools)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(dir, toolsFile), []byte(toolsMetadataData), 0644)
	if err != nil {
		return err
	}

	err = os.Rename(dir, SharedToolsDir(dataDir, tools.Version))
	// If we've failed to rename the directory, it may be because
	// the directory already exists - if ReadTools succeeds, we
	// assume all's ok.
	if err != nil {
		if _, err := ReadTools(dataDir, tools.Version); err == nil {
			return nil
		}
	}
	return err
}

func removeAll(dir string) {
	err := os.RemoveAll(dir)
	if err == nil || os.IsNotExist(err) {
		return
	}
	logger.Warningf("cannot remove %q: %v", dir, err)
}

func writeFile(name string, mode os.FileMode, r io.Reader) error {
	f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}

// ReadTools checks that the tools information for the given version exists
// in the dataDir directory, and returns a Tools instance.
// The tools information is json encoded in a text file, "downloaded-tools.txt".
func ReadTools(dataDir string, vers version.Binary) (*coretools.Tools, error) {
	dir := SharedToolsDir(dataDir, vers)
	toolsData, err := ioutil.ReadFile(path.Join(dir, toolsFile))
	if err != nil {
		return nil, fmt.Errorf("cannot read tools metadata in tools directory: %v", err)
	}
	var tools coretools.Tools
	if err := json.Unmarshal(toolsData, &tools); err != nil {
		return nil, fmt.Errorf("invalid tools metadata in tools directory %q: %v", dir, err)
	}
	return &tools, nil
}

// ChangeAgentTools atomically replaces the agent-specific symlink
// under dataDir so it points to the previously unpacked
// version vers. It returns the new tools read.
func ChangeAgentTools(dataDir string, agentName string, vers version.Binary) (*coretools.Tools, error) {
	tools, err := ReadTools(dataDir, vers)
	if err != nil {
		return nil, err
	}
	tmpName := ToolsDir(dataDir, "tmplink-"+agentName)
	err = os.Symlink(tools.Version.String(), tmpName)
	if err != nil {
		return nil, fmt.Errorf("cannot create tools symlink: %v", err)
	}
	err = os.Rename(tmpName, ToolsDir(dataDir, agentName))
	if err != nil {
		return nil, fmt.Errorf("cannot update tools symlink: %v", err)
	}
	return tools, nil
}
<commit_msg>Make sure the new tools directory has the right permissions.<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package tools

import (
	"archive/tar"
	"compress/gzip"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/errgo/errgo"

	coretools "launchpad.net/juju-core/tools"
	"launchpad.net/juju-core/version"
)

const toolsFile = "downloaded-tools.txt"

// SharedToolsDir returns the directory that is used to
// store binaries for the given version of the juju tools
// within the dataDir directory.
func SharedToolsDir(dataDir string, vers version.Binary) string {
	return path.Join(dataDir, "tools", vers.String())
}

// ToolsDir returns the directory that is used/ to store binaries for
// the tools used by the given agent within the given dataDir directory.
// Conventionally it is a symbolic link to the actual tools directory.
func ToolsDir(dataDir, agentName string) string {
	return path.Join(dataDir, "tools", agentName)
}

// UnpackTools reads a set of juju tools in gzipped tar-archive
// format and unpacks them into the appropriate tools directory
// within dataDir. If a valid tools directory already exists,
// UnpackTools returns without error.
func UnpackTools(dataDir string, tools *coretools.Tools, r io.Reader) (err error) {
	// Unpack the gzip file and compute the checksum.
	sha256hash := sha256.New()
	zr, err := gzip.NewReader(io.TeeReader(r, sha256hash))
	if err != nil {
		return err
	}
	defer zr.Close()
	f, err := ioutil.TempFile(os.TempDir(), "tools-tar")
	if err != nil {
		return err
	}
	_, err = io.Copy(f, zr)
	if err != nil {
		return err
	}
	defer os.Remove(f.Name())
	// TODO(wallyworld) - 2013-09-24 bug=1229512
	// When we can ensure all tools records have valid checksums recorded,
	// we can remove this test short circuit.
	gzipSHA256 := fmt.Sprintf("%x", sha256hash.Sum(nil))
	if tools.SHA256 != "" && tools.SHA256 != gzipSHA256 {
		return fmt.Errorf("tarball sha256 mismatch, expected %s, got %s", tools.SHA256, gzipSHA256)
	}

	// Make a temporary directory in the tools directory,
	// first ensuring that the tools directory exists.
	toolsDir := path.Join(dataDir, "tools")
	err = os.MkdirAll(toolsDir, 0755)
	if err != nil {
		return err
	}
	dir, err := ioutil.TempDir(toolsDir, "unpacking-")
	if err != nil {
		return err
	}
	defer removeAll(dir)

	// Checksum matches, now reset the file and untar it.
	_, err = f.Seek(0, 0)
	if err != nil {
		return err
	}
	tr := tar.NewReader(f)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
		if strings.ContainsAny(hdr.Name, "/\\") {
			return fmt.Errorf("bad name %q in tools archive", hdr.Name)
		}
		if hdr.Typeflag != tar.TypeReg {
			return fmt.Errorf("bad file type %c in file %q in tools archive", hdr.Typeflag, hdr.Name)
		}
		name := path.Join(dir, hdr.Name)
		if err := writeFile(name, os.FileMode(hdr.Mode&0777), tr); err != nil {
			return errgo.Annotatef(err, "tar extract %q failed", name)
		}
	}
	toolsMetadataData, err := json.Marshal(tools)
	if err != nil {
		return err
	}
	err = ioutil.WriteFile(path.Join(dir, toolsFile), []byte(toolsMetadataData), 0644)
	if err != nil {
		return err
	}

	// The tempdir is created with 0700, so we need to make it more
	// accessable for juju-run.
	err = os.Chmod(dir, 0755)
	if err != nil {
		return err
	}

	err = os.Rename(dir, SharedToolsDir(dataDir, tools.Version))
	// If we've failed to rename the directory, it may be because
	// the directory already exists - if ReadTools succeeds, we
	// assume all's ok.
	if err != nil {
		if _, err := ReadTools(dataDir, tools.Version); err == nil {
			return nil
		}
	}
	return err
}

func removeAll(dir string) {
	err := os.RemoveAll(dir)
	if err == nil || os.IsNotExist(err) {
		return
	}
	logger.Warningf("cannot remove %q: %v", dir, err)
}

func writeFile(name string, mode os.FileMode, r io.Reader) error {
	f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}

// ReadTools checks that the tools information for the given version exists
// in the dataDir directory, and returns a Tools instance.
// The tools information is json encoded in a text file, "downloaded-tools.txt".
func ReadTools(dataDir string, vers version.Binary) (*coretools.Tools, error) {
	dir := SharedToolsDir(dataDir, vers)
	toolsData, err := ioutil.ReadFile(path.Join(dir, toolsFile))
	if err != nil {
		return nil, fmt.Errorf("cannot read tools metadata in tools directory: %v", err)
	}
	var tools coretools.Tools
	if err := json.Unmarshal(toolsData, &tools); err != nil {
		return nil, fmt.Errorf("invalid tools metadata in tools directory %q: %v", dir, err)
	}
	return &tools, nil
}

// ChangeAgentTools atomically replaces the agent-specific symlink
// under dataDir so it points to the previously unpacked
// version vers. It returns the new tools read.
func ChangeAgentTools(dataDir string, agentName string, vers version.Binary) (*coretools.Tools, error) {
	tools, err := ReadTools(dataDir, vers)
	if err != nil {
		return nil, err
	}
	tmpName := ToolsDir(dataDir, "tmplink-"+agentName)
	err = os.Symlink(tools.Version.String(), tmpName)
	if err != nil {
		return nil, fmt.Errorf("cannot create tools symlink: %v", err)
	}
	err = os.Rename(tmpName, ToolsDir(dataDir, agentName))
	if err != nil {
		return nil, fmt.Errorf("cannot update tools symlink: %v", err)
	}
	return tools, nil
}
<|endoftext|>


<commit_before>package io

import (
	"encoding/binary"
	"fmt"
	"math"
	"os"

	"unsafe"
)

type GotetraBuffer struct {
	open bool

	sheet [][3]float32
	out [][3]float32

	sw, gw int

	hd SheetHeader
}

func NewGotetraBuffer(fname string) (VectorBuffer, error) {
	hd := &SheetHeader{}
	err := ReadSheetHeaderAt(fname, hd)
	return nil, err

	sw, gw := hd.SegmentWidth, hd.GridWidth
	buf := &GotetraBuffer{
		sheet: make([][3]float32, gw * gw * gw),
		out: make([][3]float32, sw * sw * sw),
		open: false,
		sw: int(sw), gw: int(gw),
	}

	return buf, nil
}

func (buf *GotetraBuffer) IsOpen() bool { return buf.open }

func (buf *GotetraBuffer) Read(fname string) ([][3]float32, error) {
	if buf.open { panic("Buffer already open.") }

	err := readSheetPositionsAt(fname, buf.sheet)
	if err != nil { return nil, err }

	for z := 0; z < buf.sw; z++ {
		for y := 0; y < buf.sw; y++ {
			for x := 0; x < buf.sw; x++ {
				si := x + y*buf.sw + z*buf.sw*buf.sw
				gi := x + y*buf.gw + z*buf.gw*buf.gw
				buf.out[si] = buf.sheet[gi]
			}
		}
	}

	return buf.out, nil
}

func (buf *GotetraBuffer) Close() {
	if !buf.open { panic("Buffer already closed.") }

	buf.open = false
}

/*
The binary format used for phase sheets is as follows:
    |-- 1 --||-- 2 --||-- ... 3 ... --||-- ... 4 ... --||-- ... 5 ... --|

    1 - (int32) Flag indicating the endianness of the file. 0 indicates a big
        endian byte ordering and -1 indicates a little endian byte order.
    2 - (int32) Size of a Header struct. Should be checked for consistency.
    3 - (sheet.Header) Header file containing meta-information about the
        sheet fragment.
    4 - ([][3]float32) Contiguous block of x, y, z coordinates. Given in Mpc.
 */
type sheetHeader struct {
	Cosmo                              CosmologyHeader
	Count, CountWidth                  int64
	SegmentWidth, GridWidth, GridCount int64
	Idx, Cells                         int64

	Mass                               float64
	TotalWidth                         float64

	Origin, Width                      [3]float32
}

type SheetHeader struct {
	sheetHeader
	N int64
}

// endianness is a utility function converting an endianness flag to a
// byte order.
func endianness(flag int32) binary.ByteOrder {
	if flag == 0 {
		return binary.LittleEndian
	} else if flag == -1 {
		return binary.BigEndian
	} else {
		panic("Unrecognized endianness flag.")
	}
}

func readSheetHeaderAt(
file string, hdBuf *SheetHeader,
) (*os.File, binary.ByteOrder, error) {
	f, err := os.OpenFile(file, os.O_RDONLY, os.ModePerm)
	if err != nil { return nil, binary.LittleEndian, err }

	// order doesn't matter for this read, since flags are symmetric.
	order := endianness(readInt32(f, binary.LittleEndian))

	headerSize := readInt32(f, order)
	if headerSize != int32(unsafe.Sizeof(sheetHeader{})) {
		return nil, binary.LittleEndian,
		fmt.Errorf("Expected catalog.SheetHeader size of %d, found %d.",
			unsafe.Sizeof(sheetHeader{}), headerSize,
		)
	}

	_, err = f.Seek(4 + 4, 0)
	if err != nil { return nil, binary.LittleEndian, err }

	err = binary.Read(f, order, &hdBuf.sheetHeader)
	if err != nil { return nil, binary.LittleEndian, err }

	hdBuf.Count = hdBuf.CountWidth*hdBuf.CountWidth*hdBuf.CountWidth
	hdBuf.N = hdBuf.SegmentWidth *hdBuf.SegmentWidth *hdBuf.SegmentWidth
	return f, order, nil
}

// ReadHeaderAt reads the header in the given file into the target Header.
func ReadSheetHeaderAt(file string, hdBuf *SheetHeader) error {
	f, _, err := readSheetHeaderAt(file, hdBuf)
	if err != nil { return err }
	if err = f.Close(); err != nil { return err }
	return nil
}

// ReadPositionsAt reads the velocities in the given file into a buffer.
func readSheetPositionsAt(file string, xsBuf [][3]float32) error {
	h := &SheetHeader{}
	f, order, err := readSheetHeaderAt(file, h)
	if err != nil { return nil }

	if h.GridCount != int64(len(xsBuf)) {
		return fmt.Errorf("Position buffer has length %d, but file %s has %d " +
		"vectors.", len(xsBuf), file, h.GridCount)
	}

	// Go to block 4 in the file.
	// The file pointer should already be here, but let's just be safe, okay?
	f.Seek(int64(4 + 4 + int(unsafe.Sizeof(SheetHeader{}))), 0)
	if err := readVecAsByte(f, order, xsBuf); err != nil { return err }

	if err := f.Close(); err != nil { return err }
	return nil
}

type CellBounds struct {
	Origin, Width [3]int
}

func (hd *SheetHeader) CellBounds(cells int) *CellBounds {
	cb := &CellBounds{}
	cellWidth := hd.TotalWidth / float64(cells)

	for j := 0; j < 3; j++ {
		cb.Origin[j] = int(
			math.Floor(float64(hd.Origin[j]) / cellWidth),
		)
		cb.Width[j] = 1 + int(
			math.Floor(float64(hd.Origin[j] + hd.Width[j]) / cellWidth),
		)

		cb.Width[j] -= cb.Origin[j]
	}

	return cb
}<commit_msg>Corrected size of SheetHeader struct.<commit_after>package io

import (
	"encoding/binary"
	"fmt"
	"math"
	"os"

	"unsafe"
)

type GotetraBuffer struct {
	open bool

	sheet [][3]float32
	out [][3]float32

	sw, gw int

	hd SheetHeader
}

func NewGotetraBuffer(fname string) (VectorBuffer, error) {
	hd := &SheetHeader{}
	err := ReadSheetHeaderAt(fname, hd)
	return nil, err

	sw, gw := hd.SegmentWidth, hd.GridWidth
	buf := &GotetraBuffer{
		sheet: make([][3]float32, gw * gw * gw),
		out: make([][3]float32, sw * sw * sw),
		open: false,
		sw: int(sw), gw: int(gw),
	}

	return buf, nil
}

func (buf *GotetraBuffer) IsOpen() bool { return buf.open }

func (buf *GotetraBuffer) Read(fname string) ([][3]float32, error) {
	if buf.open { panic("Buffer already open.") }

	err := readSheetPositionsAt(fname, buf.sheet)
	if err != nil { return nil, err }

	for z := 0; z < buf.sw; z++ {
		for y := 0; y < buf.sw; y++ {
			for x := 0; x < buf.sw; x++ {
				si := x + y*buf.sw + z*buf.sw*buf.sw
				gi := x + y*buf.gw + z*buf.gw*buf.gw
				buf.out[si] = buf.sheet[gi]
			}
		}
	}

	return buf.out, nil
}

func (buf *GotetraBuffer) Close() {
	if !buf.open { panic("Buffer already closed.") }

	buf.open = false
}

/*
The binary format used for phase sheets is as follows:
    |-- 1 --||-- 2 --||-- ... 3 ... --||-- ... 4 ... --||-- ... 5 ... --|

    1 - (int32) Flag indicating the endianness of the file. 0 indicates a big
        endian byte ordering and -1 indicates a little endian byte order.
    2 - (int32) Size of a Header struct. Should be checked for consistency.
    3 - (sheet.Header) Header file containing meta-information about the
        sheet fragment.
    4 - ([][3]float32) Contiguous block of x, y, z coordinates. Given in Mpc.
 */
type sheetHeader struct {
	Cosmo                              CosmologyHeader
	Count, CountWidth                  int64
	SegmentWidth, GridWidth, GridCount int64
	Idx, Cells                         int64

	Mass                               float64
	TotalWidth                         float64

	Origin, Width                      [3]float32
	VelocityOrigin, VelocityWidth      [3]float32
}

type SheetHeader struct {
	sheetHeader
	N int64
}

// endianness is a utility function converting an endianness flag to a
// byte order.
func endianness(flag int32) binary.ByteOrder {
	if flag == 0 {
		return binary.LittleEndian
	} else if flag == -1 {
		return binary.BigEndian
	} else {
		panic("Unrecognized endianness flag.")
	}
}

func readSheetHeaderAt(
file string, hdBuf *SheetHeader,
) (*os.File, binary.ByteOrder, error) {
	f, err := os.OpenFile(file, os.O_RDONLY, os.ModePerm)
	if err != nil { return nil, binary.LittleEndian, err }

	// order doesn't matter for this read, since flags are symmetric.
	order := endianness(readInt32(f, binary.LittleEndian))

	headerSize := readInt32(f, order)
	if headerSize != int32(unsafe.Sizeof(sheetHeader{})) {
		return nil, binary.LittleEndian,
		fmt.Errorf("Expected catalog.SheetHeader size of %d, found %d.",
			unsafe.Sizeof(sheetHeader{}), headerSize,
		)
	}

	_, err = f.Seek(4 + 4, 0)
	if err != nil { return nil, binary.LittleEndian, err }

	err = binary.Read(f, order, &hdBuf.sheetHeader)
	if err != nil { return nil, binary.LittleEndian, err }

	hdBuf.Count = hdBuf.CountWidth*hdBuf.CountWidth*hdBuf.CountWidth
	hdBuf.N = hdBuf.SegmentWidth *hdBuf.SegmentWidth *hdBuf.SegmentWidth
	return f, order, nil
}

// ReadHeaderAt reads the header in the given file into the target Header.
func ReadSheetHeaderAt(file string, hdBuf *SheetHeader) error {
	f, _, err := readSheetHeaderAt(file, hdBuf)
	if err != nil { return err }
	if err = f.Close(); err != nil { return err }
	return nil
}

// ReadPositionsAt reads the velocities in the given file into a buffer.
func readSheetPositionsAt(file string, xsBuf [][3]float32) error {
	h := &SheetHeader{}
	f, order, err := readSheetHeaderAt(file, h)
	if err != nil { return nil }

	if h.GridCount != int64(len(xsBuf)) {
		return fmt.Errorf("Position buffer has length %d, but file %s has %d " +
		"vectors.", len(xsBuf), file, h.GridCount)
	}

	// Go to block 4 in the file.
	// The file pointer should already be here, but let's just be safe, okay?
	f.Seek(int64(4 + 4 + int(unsafe.Sizeof(SheetHeader{}))), 0)
	if err := readVecAsByte(f, order, xsBuf); err != nil { return err }

	if err := f.Close(); err != nil { return err }
	return nil
}

type CellBounds struct {
	Origin, Width [3]int
}

func (hd *SheetHeader) CellBounds(cells int) *CellBounds {
	cb := &CellBounds{}
	cellWidth := hd.TotalWidth / float64(cells)

	for j := 0; j < 3; j++ {
		cb.Origin[j] = int(
			math.Floor(float64(hd.Origin[j]) / cellWidth),
		)
		cb.Width[j] = 1 + int(
			math.Floor(float64(hd.Origin[j] + hd.Width[j]) / cellWidth),
		)

		cb.Width[j] -= cb.Origin[j]
	}

	return cb
}
<|endoftext|>


<commit_before>package qb

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-sqlite3"
)

// NewEngine generates a new engine and returns it as an engine pointer
func NewEngine(driver string, dsn string) (*Engine, error) {

	conn, err := sql.Open(driver, dsn)
	if err != nil {
		return nil, err
	}

	return &Engine{
		driver: driver,
		dsn:    dsn,
		db:     conn,
	}, err
}

// Engine is the generic struct for handling db connections
type Engine struct {
	driver string
	dsn    string
	db     *sql.DB
}

// Exec executes insert & update type queries and returns sql.Result and error
func (e *Engine) Exec(query *Query) (sql.Result, error) {

	stmt, err := e.db.Prepare(query.SQL())
	if err != nil {
		return nil, err
	}

	res, err := stmt.Exec(query.Bindings()...)
	if err != nil {
		return nil, err
	}

	return res, nil
}

// QueryRow wraps *sql.DB.QueryRow()
func (e *Engine) QueryRow(query *Query) *sql.Row {
	return e.db.QueryRow(query.SQL(), query.Bindings()...)
}

// Query wraps *sql.DB.Query()
func (e *Engine) Query(query *Query) (*sql.Rows, error) {
	return e.db.Query(query.SQL(), query.Bindings()...)
}

// DB returns sql.DB of wrapped engine connection
func (e *Engine) DB() *sql.DB {
	return e.db
}

// Ping pings the db using connection and returns error if connectivity is not present
func (e *Engine) Ping() error {
	return e.db.Ping()
}

// Driver returns the driver as string
func (e *Engine) Driver() string {
	return e.driver
}

// Dsn returns the connection dsn
func (e *Engine) Dsn() string {
	return e.dsn
}
<commit_msg>add initial sqlx integration, fix #20, add sqlx wraps<commit_after>package qb

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-sqlite3"
)

// NewEngine generates a new engine and returns it as an engine pointer
func NewEngine(driver string, dsn string) (*Engine, error) {

	conn, err := sqlx.Open(driver, dsn)
	if err != nil {
		return nil, err
	}

	return &Engine{
		driver: driver,
		dsn:    dsn,
		db:     conn,
	}, err
}

// Engine is the generic struct for handling db connections
type Engine struct {
	driver string
	dsn    string
	db     *sqlx.DB
}

// Exec executes insert & update type queries and returns sql.Result and error
func (e *Engine) Exec(query *Query) (sql.Result, error) {

	stmt, err := e.db.Prepare(query.SQL())
	if err != nil {
		return nil, err
	}

	res, err := stmt.Exec(query.Bindings()...)
	if err != nil {
		return nil, err
	}

	return res, nil
}

// QueryRow wraps *sql.DB.QueryRow()
func (e *Engine) QueryRow(query *Query) *sql.Row {
	return e.db.QueryRow(query.SQL(), query.Bindings()...)
}

// Query wraps *sql.DB.Query()
func (e *Engine) Query(query *Query) (*sql.Rows, error) {
	return e.db.Query(query.SQL(), query.Bindings()...)
}

// Get maps the single row to a model
func (e *Engine) Get(query *Query, model interface{}) error {
	return e.db.Get(model, query.SQL(), query.Bindings()...)
}

// Select maps multiple rows to a model array
func (e *Engine) Select(query *Query, model interface{}) error {
	return e.db.Select(model, query.SQL(), query.Bindings()...)
}

// Queryx wraps sqlx's Queryx
func (e *Engine) Queryx(query *Query) (*sqlx.Rows, error) {
	return e.db.Queryx(query.SQL(), query.Bindings()...)
}

// DB returns sql.DB of wrapped engine connection
func (e *Engine) DB() *sqlx.DB {
	return e.db
}

// Ping pings the db using connection and returns error if connectivity is not present
func (e *Engine) Ping() error {
	return e.db.Ping()
}

// Driver returns the driver as string
func (e *Engine) Driver() string {
	return e.driver
}

// Dsn returns the connection dsn
func (e *Engine) Dsn() string {
	return e.dsn
}
<|endoftext|>


<commit_before>package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/rest"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

// Config holds the information needed to build connect to remote kubernetes clusters as a given user
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type KubeConfig struct {
	metav1.TypeMeta `json:",inline,omitempty,omitempty"`
	// Preferences holds general information to be use for cli interactions
	Preferences Preferences `json:"preferences" protobuf:"bytes,1,opt,name=preferences"`
	// Clusters is a map of referencable names to cluster configs
	Cluster NamedCluster `json:"cluster" protobuf:"bytes,2,opt,name=cluster"`
	// AuthInfos is a map of referencable names to user configs
	AuthInfo NamedAuthInfo `json:"user" protobuf:"bytes,3,opt,name=user"`
	// Contexts is a map of referencable names to context configs
	Context NamedContext `json:"context" protobuf:"bytes,4,opt,name=context"`
}

type Preferences struct {
	// +optional
	Colors bool `json:"colors,omitempty" protobuf:"varint,1,opt,name=colors"`
}

// NamedCluster relates nicknames to cluster information
type NamedCluster struct {
	// Name is the nickname for this Cluster
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// Server is the address of the kubernetes cluster (https://hostname:port).
	Server string `json:"server" protobuf:"bytes,2,opt,name=server"`
	// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthorityData
	// +optional
	CertificateAuthorityData []byte `json:"certificateAuthorityData,omitempty" protobuf:"bytes,3,opt,name=certificateAuthorityData"`
}

// NamedContext relates nicknames to context information
type NamedContext struct {
	// Name is the nickname for this Context
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// Cluster is the name of the cluster for this context
	Cluster string `json:"cluster" protobuf:"bytes,2,opt,name=cluster"`
	// AuthInfo is the name of the authInfo for this context
	AuthInfo string `json:"user" protobuf:"bytes,3,opt,name=user"`
}

// NamedAuthInfo relates nicknames to auth information
type NamedAuthInfo struct {
	// Name is the nickname for this AuthInfo
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// ClientCertificateData contains PEM-encoded data from a client cert file for TLS.
	// +optional
	ClientCertificateData []byte `json:"clientCertificateData,omitempty" protobuf:"bytes,2,opt,name=clientCertificateData"`
	// ClientKeyData contains PEM-encoded data from a client key file for TLS.
	// +optional
	ClientKeyData []byte `json:"clientKeyData,omitempty" protobuf:"bytes,3,opt,name=clientKeyData"`
	// Token is the bearer token for authentication to the kubernetes cluster.
	// +optional
	Token string `json:"token,omitempty" protobuf:"bytes,4,opt,name=token"`
}

func Convert_KubeConfig_To_Config(in *KubeConfig) *clientcmdapi.Config {
	return &clientcmdapi.Config{
		Kind:       "Config",
		APIVersion: clientcmdapi.SchemeGroupVersion.String(),
		Preferences: clientcmdapi.Preferences{
			Colors: in.Preferences.Colors,
		},
		Clusters: map[string]*clientcmdapi.Cluster{
			in.Cluster.Name: {
				CertificateAuthorityData: append([]byte(nil), in.Cluster.CertificateAuthorityData...),
			},
		},
		AuthInfos: map[string]*clientcmdapi.AuthInfo{
			in.AuthInfo.Name: {
				Token: in.AuthInfo.Token,
				ClientCertificateData: append([]byte(nil), in.AuthInfo.ClientCertificateData...),
				ClientKeyData:         append([]byte(nil), in.AuthInfo.ClientKeyData...),
			},
		},
		Contexts: map[string]*clientcmdapi.Context{
			in.Context.Name: {
				Cluster:  in.Context.Cluster,
				AuthInfo: in.Context.AuthInfo,
			},
		},
		CurrentContext: in.Context.Name,
	}
}

func NewRestConfig(in *KubeConfig) *rest.Config {
	out := &rest.Config{
		Host: in.Cluster.Server,
		TLSClientConfig: rest.TLSClientConfig{
			CAData: append([]byte(nil), in.Cluster.CertificateAuthorityData...),
		},
	}
	if in.AuthInfo.Token == "" {
		out.TLSClientConfig.CertData = append([]byte(nil), in.AuthInfo.ClientCertificateData...)
		out.TLSClientConfig.KeyData = append([]byte(nil), in.AuthInfo.ClientKeyData...)
	} else {
		out.BearerToken = in.AuthInfo.Token
	}
	return out
}
<commit_msg>add server on kubeconfig (#348)<commit_after>package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/rest"
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

// Config holds the information needed to build connect to remote kubernetes clusters as a given user
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type KubeConfig struct {
	metav1.TypeMeta `json:",inline,omitempty,omitempty"`
	// Preferences holds general information to be use for cli interactions
	Preferences Preferences `json:"preferences" protobuf:"bytes,1,opt,name=preferences"`
	// Clusters is a map of referencable names to cluster configs
	Cluster NamedCluster `json:"cluster" protobuf:"bytes,2,opt,name=cluster"`
	// AuthInfos is a map of referencable names to user configs
	AuthInfo NamedAuthInfo `json:"user" protobuf:"bytes,3,opt,name=user"`
	// Contexts is a map of referencable names to context configs
	Context NamedContext `json:"context" protobuf:"bytes,4,opt,name=context"`
}

type Preferences struct {
	// +optional
	Colors bool `json:"colors,omitempty" protobuf:"varint,1,opt,name=colors"`
}

// NamedCluster relates nicknames to cluster information
type NamedCluster struct {
	// Name is the nickname for this Cluster
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// Server is the address of the kubernetes cluster (https://hostname:port).
	Server string `json:"server" protobuf:"bytes,2,opt,name=server"`
	// CertificateAuthorityData contains PEM-encoded certificate authority certificates. Overrides CertificateAuthorityData
	// +optional
	CertificateAuthorityData []byte `json:"certificateAuthorityData,omitempty" protobuf:"bytes,3,opt,name=certificateAuthorityData"`
}

// NamedContext relates nicknames to context information
type NamedContext struct {
	// Name is the nickname for this Context
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// Cluster is the name of the cluster for this context
	Cluster string `json:"cluster" protobuf:"bytes,2,opt,name=cluster"`
	// AuthInfo is the name of the authInfo for this context
	AuthInfo string `json:"user" protobuf:"bytes,3,opt,name=user"`
}

// NamedAuthInfo relates nicknames to auth information
type NamedAuthInfo struct {
	// Name is the nickname for this AuthInfo
	Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
	// ClientCertificateData contains PEM-encoded data from a client cert file for TLS.
	// +optional
	ClientCertificateData []byte `json:"clientCertificateData,omitempty" protobuf:"bytes,2,opt,name=clientCertificateData"`
	// ClientKeyData contains PEM-encoded data from a client key file for TLS.
	// +optional
	ClientKeyData []byte `json:"clientKeyData,omitempty" protobuf:"bytes,3,opt,name=clientKeyData"`
	// Token is the bearer token for authentication to the kubernetes cluster.
	// +optional
	Token string `json:"token,omitempty" protobuf:"bytes,4,opt,name=token"`
}

func Convert_KubeConfig_To_Config(in *KubeConfig) *clientcmdapi.Config {
	return &clientcmdapi.Config{
		Kind:       "Config",
		APIVersion: clientcmdapi.SchemeGroupVersion.String(),
		Preferences: clientcmdapi.Preferences{
			Colors: in.Preferences.Colors,
		},
		Clusters: map[string]*clientcmdapi.Cluster{
			in.Cluster.Name: {
				Server: in.Cluster.Server,
				CertificateAuthorityData: append([]byte(nil), in.Cluster.CertificateAuthorityData...),
			},
		},
		AuthInfos: map[string]*clientcmdapi.AuthInfo{
			in.AuthInfo.Name: {
				Token: in.AuthInfo.Token,
				ClientCertificateData: append([]byte(nil), in.AuthInfo.ClientCertificateData...),
				ClientKeyData:         append([]byte(nil), in.AuthInfo.ClientKeyData...),
			},
		},
		Contexts: map[string]*clientcmdapi.Context{
			in.Context.Name: {
				Cluster:  in.Context.Cluster,
				AuthInfo: in.Context.AuthInfo,
			},
		},
		CurrentContext: in.Context.Name,
	}
}

func NewRestConfig(in *KubeConfig) *rest.Config {
	out := &rest.Config{
		Host: in.Cluster.Server,
		TLSClientConfig: rest.TLSClientConfig{
			CAData: append([]byte(nil), in.Cluster.CertificateAuthorityData...),
		},
	}
	if in.AuthInfo.Token == "" {
		out.TLSClientConfig.CertData = append([]byte(nil), in.AuthInfo.ClientCertificateData...)
		out.TLSClientConfig.KeyData = append([]byte(nil), in.AuthInfo.ClientKeyData...)
	} else {
		out.BearerToken = in.AuthInfo.Token
	}
	return out
}
<|endoftext|>


<commit_before>package user

import (
	"fmt"
	"github.com/bearded-web/bearded/pkg/pagination"
	"gopkg.in/mgo.v2/bson"
	"time"
)

type User struct {
	Id       bson.ObjectId `json:"id,omitempty" bson:"_id"`
	Email    string        `json:"email"`
	Password string        `json:"-"` // password hash in passlib format: $hashAlgo[$values]$hexdigest_hash$

	Created time.Time `json:"created,omitempty"`
	Updated time.Time `json:"updated,omitempty"`
}

func (u *User) String() string {
	return fmt.Sprintf("%x %s", u.Id, u.Email)
}

// Id in hex
func (u *User) IdStr() string {
	return fmt.Sprintf("%x", u.Id)
}

type UserList struct {
	pagination.Meta `json:",inline"`
	Results         []*User `json:"results"`
}
<commit_msg>fix bug<commit_after>package user

import (
	"fmt"
	"github.com/bearded-web/bearded/pkg/pagination"
	"gopkg.in/mgo.v2/bson"
	"time"
)

type User struct {
	Id       bson.ObjectId `json:"id,omitempty" bson:"_id"`
	Email    string        `json:"email"`
	Password string        `json:"-"` // password hash in passlib format: $hashAlgo[$values]$hexdigest_hash$

	Created time.Time `json:"created,omitempty"`
	Updated time.Time `json:"updated,omitempty"`
}

func (u *User) String() string {
	return fmt.Sprintf("%x %s", u.Id, u.Email)
}

// Id in hex
func (u *User) IdStr() string {
	return fmt.Sprintf("%x", string(u.Id))
}

type UserList struct {
	pagination.Meta `json:",inline"`
	Results         []*User `json:"results"`
}
<|endoftext|>