<commit_before>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package backend

import (
	// "code.google.com/p/log4go" Later
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"strings"
)

type (
	Package interface {
		Name() string
		Get() interface{}
		Path() string
	}

	Plugin struct {
		setting *Setting
		keymap  *KeyMap
		path    string
		files   []os.FileInfo
	}

	Setting struct {
		path string
		data []byte
	}

	KeyMap struct {
		path string
		data []byte
	}
)

const (
	DEFAULT_SUBLIME_SETTINGS    = "../../backend/packages/Default/Default.sublime-settings"
	DEFAULT_SUBLIME_KEYBINDINGS = "../../backend/packages/Default/Default.sublime-keymap"
	SUBLIME_USER_PACKAGES_PATH  = "../../3rdparty/bundles/"
)

var Packages = make(map[string][]Package)

func NewPlugin(path string) *Plugin {
	f, err := os.Open(path)
	if err != nil {
		return nil
	}
	defer f.Close()
	fi, err := f.Readdir(-1)
	if err != nil {
		return nil
	}
	p := &Plugin{path: path}
	files := make([]os.FileInfo, 0)
	for _, f := range fi {
		if strings.HasSuffix(f.Name(), ".py") {
			files = append(files, f)
		} else if strings.HasSuffix(f.Name(), ".sublime-settings") {
			p.setting = NewSetting(path + string(os.PathSeparator) + f.Name())
		} else if strings.HasSuffix(f.Name(), ".sublime-keymap") {
			p.keymap = NewKeyMap(path + string(os.PathSeparator) + f.Name())
		}
	}
	p.files = files
	return p
}

func (p *Plugin) Get() interface{} {
	return p.files
}

func (p *Plugin) Name() string {
	return path.Base(p.path)
}

func (p *Plugin) Path() string {
	return p.path
}

func NewSetting(path string) *Setting {
	d, err := ioutil.ReadFile(path)
	if err != nil {
		return nil
	}
	return &Setting{path, d}
}

func (p *Setting) Get() interface{} {
	return p.data
}

func (p *Setting) Name() string {
	return path.Base(p.path)
}

func (p *Setting) Path() string {
	return p.path
}

func NewKeyMap(path string) *KeyMap {
	d, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return &KeyMap{path, d}
}

func (p *KeyMap) Get() interface{} {
	return p.data
}

func (p *KeyMap) Name() string {
	return path.Base(p.path)
}

func (p *KeyMap) Path() string {
	return p.path
}

func add(key string, p Package) {
	if !reflect.ValueOf(p).IsNil() {
		Packages[key] = append(Packages[key], p)
	}
}

func Scanpath(path string) []*Plugin {
	f, err := os.Open(path)
	if err != nil {
		return nil
	}
	defer f.Close()
	dirs, err := f.Readdirnames(-1)
	if err != nil {
		return nil
	}
	plugins := make([]*Plugin, 0)
	for _, dir := range dirs {
		dir2 := path + dir
		f2, err := os.Open(dir2)
		if err != nil {
			continue
		}
		defer f2.Close()
		fi, err := f2.Readdir(-1)
		if err != nil {
			continue
		}
		for _, f := range fi {
			if strings.HasSuffix(f.Name(), ".py") {
				plugins = append(plugins, NewPlugin(dir2))
				break
			}
		}
	}
	return plugins
}

func init() {
	add("settings", NewSetting(DEFAULT_SUBLIME_SETTINGS))
	add("keymaps", NewKeyMap(DEFAULT_SUBLIME_KEYBINDINGS))

	f, err := os.Open(SUBLIME_USER_PACKAGES_PATH)
	if err != nil {
		return
	}
	defer f.Close()
	dirs, err := f.Readdirnames(-1)
	if err != nil {
		return
	}
	for _, dir := range dirs {
		dir2 := SUBLIME_USER_PACKAGES_PATH + dir
		f2, err := os.Open(dir2)
		if err != nil {
			continue
		}
		defer f2.Close()
		fi, err := f2.Readdir(-1)
		if err != nil {
			continue
		}
		for _, f := range fi {
			if strings.HasSuffix(f.Name(), ".py") {
				add("plugins", NewPlugin(dir2))
				break
			}
		}
	}
}
<commit_msg>Added access for plugin settings and keymap also some comments on Package interface methods<commit_after>// Copyright 2013 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.

package backend

import (
	// "code.google.com/p/log4go" Later
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"strings"
)

type (
	Package interface {
		// Returns the name of the package for sth
		// like settings is the filename and for
		// plugins is the dir name
		Name() string
		// Returns the useful data that we need
		// from this package for example for a
		// plugin will be the python files or for
		// a keymap will be the file data
		Get() interface{}
		// Returns the path that the package exists
		Path() string
	}

	Plugin struct {
		setting *Setting
		keymap  *KeyMap
		path    string
		files   []os.FileInfo
	}

	Setting struct {
		path string
		data []byte
	}

	KeyMap struct {
		path string
		data []byte
	}
)

const (
	DEFAULT_SUBLIME_SETTINGS    = "../../backend/packages/Default/Default.sublime-settings"
	DEFAULT_SUBLIME_KEYBINDINGS = "../../backend/packages/Default/Default.sublime-keymap"
	SUBLIME_USER_PACKAGES_PATH  = "../../3rdparty/bundles/"
)

var Packages = make(map[string][]Package)

func NewPlugin(path string) *Plugin {
	f, err := os.Open(path)
	if err != nil {
		return nil
	}
	defer f.Close()
	fi, err := f.Readdir(-1)
	if err != nil {
		return nil
	}
	p := &Plugin{path: path}
	files := make([]os.FileInfo, 0)
	for _, f := range fi {
		if strings.HasSuffix(f.Name(), ".py") {
			files = append(files, f)
		} else if strings.HasSuffix(f.Name(), ".sublime-settings") {
			p.setting = NewSetting(path + string(os.PathSeparator) + f.Name())
		} else if strings.HasSuffix(f.Name(), ".sublime-keymap") {
			p.keymap = NewKeyMap(path + string(os.PathSeparator) + f.Name())
		}
	}
	p.files = files
	return p
}

func (p *Plugin) Get() interface{} {
	return p.files
}

func (p *Plugin) Name() string {
	return path.Base(p.path)
}

func (p *Plugin) Path() string {
	return p.path
}

func (p *Plugin) Setting() *Setting {
	return p.setting
}

func (p *Plugin) KeyMap() *KeyMap {
	return p.keymap
}

func NewSetting(path string) *Setting {
	d, err := ioutil.ReadFile(path)
	if err != nil {
		return nil
	}
	return &Setting{path, d}
}

func (p *Setting) Get() interface{} {
	return p.data
}

func (p *Setting) Name() string {
	return path.Base(p.path)
}

func (p *Setting) Path() string {
	return p.path
}

func NewKeyMap(path string) *KeyMap {
	d, err := ioutil.ReadFile(path)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return &KeyMap{path, d}
}

func (p *KeyMap) Get() interface{} {
	return p.data
}

func (p *KeyMap) Name() string {
	return path.Base(p.path)
}

func (p *KeyMap) Path() string {
	return p.path
}

func add(key string, p Package) {
	if !reflect.ValueOf(p).IsNil() {
		Packages[key] = append(Packages[key], p)
	}
}

func Scanpath(path string) []*Plugin {
	f, err := os.Open(path)
	if err != nil {
		return nil
	}
	defer f.Close()
	dirs, err := f.Readdirnames(-1)
	if err != nil {
		return nil
	}
	plugins := make([]*Plugin, 0)
	for _, dir := range dirs {
		dir2 := path + dir
		f2, err := os.Open(dir2)
		if err != nil {
			continue
		}
		defer f2.Close()
		fi, err := f2.Readdir(-1)
		if err != nil {
			continue
		}
		for _, f := range fi {
			if strings.HasSuffix(f.Name(), ".py") {
				plugins = append(plugins, NewPlugin(dir2))
				break
			}
		}
	}
	return plugins
}

func init() {
	add("settings", NewSetting(DEFAULT_SUBLIME_SETTINGS))
	add("keymaps", NewKeyMap(DEFAULT_SUBLIME_KEYBINDINGS))

	f, err := os.Open(SUBLIME_USER_PACKAGES_PATH)
	if err != nil {
		return
	}
	defer f.Close()
	dirs, err := f.Readdirnames(-1)
	if err != nil {
		return
	}
	for _, dir := range dirs {
		dir2 := SUBLIME_USER_PACKAGES_PATH + dir
		f2, err := os.Open(dir2)
		if err != nil {
			continue
		}
		defer f2.Close()
		fi, err := f2.Readdir(-1)
		if err != nil {
			continue
		}
		for _, f := range fi {
			if strings.HasSuffix(f.Name(), ".py") {
				add("plugins", NewPlugin(dir2))
				break
			}
		}
	}
}
<|endoftext|>


<commit_before>package cobra

import (
	"bytes"
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/spf13/pflag"
)

const (
	BashCompFilenameExt     = "cobra_annotation_bash_completion_filename_extentions"
	BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
	BashCompSubdirsInDir    = "cobra_annotation_bash_completion_subdirs_in_dir"
)

func preamble(out *bytes.Buffer) {
	fmt.Fprintf(out, `#!/bin/bash

__debug()
{
    if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
        echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    fi
}

__index_of_word()
{
    local w word=$1
    shift
    index=0
    for w in "$@"; do
        [[ $w = "$word" ]] && return
        index=$((index+1))
    done
    index=-1
}

__contains_word()
{
    local w word=$1; shift
    for w in "$@"; do
        [[ $w = "$word" ]] && return
    done
    return 1
}

__handle_reply()
{
    __debug "${FUNCNAME}"
    case $cur in
        -*)
            compopt -o nospace
            local allflags
            if [ ${#must_have_one_flag[@]} -ne 0 ]; then
                allflags=("${must_have_one_flag[@]}")
            else
                allflags=("${flags[*]} ${two_word_flags[*]}")
            fi
            COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
            [[ $COMPREPLY == *= ]] || compopt +o nospace
            return 0;
            ;;
    esac

    # check if we are handling a flag with special work handling
    local index
    __index_of_word "${prev}" "${flags_with_completion[@]}"
    if [[ ${index} -ge 0 ]]; then
        ${flags_completion[${index}]}
        return
    fi

    # we are parsing a flag and don't have a special handler, no completion
    if [[ ${cur} != "${words[cword]}" ]]; then
        return
    fi

    local completions
    if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
        completions=("${must_have_one_flag[@]}")
    elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
        completions=("${must_have_one_noun[@]}")
    else
        completions=("${commands[@]}")
    fi
    COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )

    if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
        declare -F __custom_func >/dev/null && __custom_func
    fi
}

# The arguments should be in the form "ext1|ext2|extn"
__handle_filename_extension_flag()
{
    local ext="$1"
    _filedir "@(${ext})"
}

__handle_subdirs_in_dir_flag()
{
    local dir="$1"
    pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1
}

__handle_flag()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    # if a command required a flag, and we found it, unset must_have_one_flag()
    local flagname=${words[c]}
    # if the word contained an =
    if [[ ${words[c]} == *"="* ]]; then
        flagname=${flagname%%=*} # strip everything after the =
        flagname="${flagname}=" # but put the = back
    fi
    __debug "${FUNCNAME}: looking for ${flagname}"
    if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
        must_have_one_flag=()
    fi

    # skip the argument to a two word flag
    if __contains_word "${words[c]}" "${two_word_flags[@]}"; then
        c=$((c+1))
        # if we are looking for a flags value, don't show commands
        if [[ $c -eq $cword ]]; then
            commands=()
        fi
    fi

    # skip the flag itself
    c=$((c+1))

}

__handle_noun()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
        must_have_one_noun=()
    fi

    nouns+=("${words[c]}")
    c=$((c+1))
}

__handle_command()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    local next_command
    if [[ -n ${last_command} ]]; then
        next_command="_${last_command}_${words[c]}"
    else
        next_command="_${words[c]}"
    fi
    c=$((c+1))
    __debug "${FUNCNAME}: looking for ${next_command}"
    declare -F $next_command >/dev/null && $next_command
}

__handle_word()
{
    if [[ $c -ge $cword ]]; then
        __handle_reply
	return
    fi
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
    if [[ "${words[c]}" == -* ]]; then
	__handle_flag
    elif __contains_word "${words[c]}" "${commands[@]}"; then
        __handle_command
    else
        __handle_noun
    fi
    __handle_word
}

`)
}

func postscript(out *bytes.Buffer, name string) {
	fmt.Fprintf(out, "__start_%s()\n", name)
	fmt.Fprintf(out, `{
    local cur prev words cword
    _init_completion -s || return

    local c=0
    local flags=()
    local two_word_flags=()
    local flags_with_completion=()
    local flags_completion=()
    local commands=("%s")
    local must_have_one_flag=()
    local must_have_one_noun=()
    local last_command
    local nouns=()

    __handle_word
}

`, name)
	fmt.Fprintf(out, "complete -F __start_%s %s\n", name, name)
	fmt.Fprintf(out, "# ex: ts=4 sw=4 et filetype=sh\n")
}

func writeCommands(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    commands=()\n")
	for _, c := range cmd.Commands() {
		if len(c.Deprecated) > 0 || c == cmd.helpCommand {
			continue
		}
		fmt.Fprintf(out, "    commands+=(%q)\n", c.Name())
	}
	fmt.Fprintf(out, "\n")
}

func writeFlagHandler(name string, annotations map[string][]string, out *bytes.Buffer) {
	for key, value := range annotations {
		switch key {
		case BashCompFilenameExt:
			fmt.Fprintf(out, "    flags_with_completion+=(%q)\n", name)

			if len(value) > 0 {
				ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			} else {
				ext := "_filedir"
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			}
		case BashCompSubdirsInDir:
			fmt.Fprintf(out, "    flags_with_completion+=(%q)\n", name)

			if len(value) == 1 {
				ext := "__handle_subdirs_in_dir_flag " + value[0]
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			} else {
				ext := "_filedir -d"
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			}
		}
	}
}

func writeShortFlag(flag *pflag.Flag, out *bytes.Buffer) {
	b := (flag.Value.Type() == "bool")
	name := flag.Shorthand
	format := "    "
	if !b {
		format += "two_word_"
	}
	format += "flags+=(\"-%s\")\n"
	fmt.Fprintf(out, format, name)
	writeFlagHandler("-"+name, flag.Annotations, out)
}

func writeFlag(flag *pflag.Flag, out *bytes.Buffer) {
	b := (flag.Value.Type() == "bool")
	name := flag.Name
	format := "    flags+=(\"--%s"
	if !b {
		format += "="
	}
	format += "\")\n"
	fmt.Fprintf(out, format, name)
	writeFlagHandler("--"+name, flag.Annotations, out)
}

func writeFlags(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, `    flags=()
    two_word_flags=()
    flags_with_completion=()
    flags_completion=()

`)
	cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
		writeFlag(flag, out)
		if len(flag.Shorthand) > 0 {
			writeShortFlag(flag, out)
		}
	})

	fmt.Fprintf(out, "\n")
}

func writeRequiredFlag(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    must_have_one_flag=()\n")
	flags := cmd.NonInheritedFlags()
	flags.VisitAll(func(flag *pflag.Flag) {
		for key, _ := range flag.Annotations {
			switch key {
			case BashCompOneRequiredFlag:
				format := "    must_have_one_flag+=(\"--%s"
				b := (flag.Value.Type() == "bool")
				if !b {
					format += "="
				}
				format += "\")\n"
				fmt.Fprintf(out, format, flag.Name)

				if len(flag.Shorthand) > 0 {
					fmt.Fprintf(out, "    must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)
				}
			}
		}
	})
}

func writeRequiredNoun(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    must_have_one_noun=()\n")
	sort.Sort(sort.StringSlice(cmd.ValidArgs))
	for _, value := range cmd.ValidArgs {
		fmt.Fprintf(out, "    must_have_one_noun+=(%q)\n", value)
	}
}

func gen(cmd *Command, out *bytes.Buffer) {
	for _, c := range cmd.Commands() {
		if len(c.Deprecated) > 0 || c == cmd.helpCommand {
			continue
		}
		gen(c, out)
	}
	commandName := cmd.CommandPath()
	commandName = strings.Replace(commandName, " ", "_", -1)
	fmt.Fprintf(out, "_%s()\n{\n", commandName)
	fmt.Fprintf(out, "    last_command=%q\n", commandName)
	writeCommands(cmd, out)
	writeFlags(cmd, out)
	writeRequiredFlag(cmd, out)
	writeRequiredNoun(cmd, out)
	fmt.Fprintf(out, "}\n\n")
}

func (cmd *Command) GenBashCompletion(out *bytes.Buffer) {
	preamble(out)
	if len(cmd.BashCompletionFunction) > 0 {
		fmt.Fprintf(out, "%s\n", cmd.BashCompletionFunction)
	}
	gen(cmd, out)
	postscript(out, cmd.Name())
}

func (cmd *Command) GenBashCompletionFile(filename string) error {
	out := new(bytes.Buffer)

	cmd.GenBashCompletion(out)

	outFile, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer outFile.Close()

	_, err = outFile.Write(out.Bytes())
	if err != nil {
		return err
	}
	return nil
}

// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
func (cmd *Command) MarkFlagRequired(name string) error {
	return MarkFlagRequired(cmd.Flags(), name)
}

// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
	return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
}

// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error {
	return MarkFlagFilename(cmd.Flags(), name, extensions...)
}

// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error {
	return flags.SetAnnotation(name, BashCompFilenameExt, extensions)
}
<commit_msg>Enable bash completions on Macs<commit_after>package cobra

import (
	"bytes"
	"fmt"
	"os"
	"sort"
	"strings"

	"github.com/spf13/pflag"
)

const (
	BashCompFilenameExt     = "cobra_annotation_bash_completion_filename_extentions"
	BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag"
	BashCompSubdirsInDir    = "cobra_annotation_bash_completion_subdirs_in_dir"
)

func preamble(out *bytes.Buffer) {
	fmt.Fprintf(out, `#!/bin/bash

__debug()
{
    if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then
        echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    fi
}

# Homebrew on Macs have version 1.3 of bash-completion which doesn't include
# _init_completion. This is a very minimal version of that function.
__my_init_completion()
{
    COMPREPLY=()
    _get_comp_words_by_ref cur prev words cword
}

__index_of_word()
{
    local w word=$1
    shift
    index=0
    for w in "$@"; do
        [[ $w = "$word" ]] && return
        index=$((index+1))
    done
    index=-1
}

__contains_word()
{
    local w word=$1; shift
    for w in "$@"; do
        [[ $w = "$word" ]] && return
    done
    return 1
}

__handle_reply()
{
    __debug "${FUNCNAME}"
    case $cur in
        -*)
            compopt -o nospace
            local allflags
            if [ ${#must_have_one_flag[@]} -ne 0 ]; then
                allflags=("${must_have_one_flag[@]}")
            else
                allflags=("${flags[*]} ${two_word_flags[*]}")
            fi
            COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
            [[ $COMPREPLY == *= ]] || compopt +o nospace
            return 0;
            ;;
    esac

    # check if we are handling a flag with special work handling
    local index
    __index_of_word "${prev}" "${flags_with_completion[@]}"
    if [[ ${index} -ge 0 ]]; then
        ${flags_completion[${index}]}
        return
    fi

    # we are parsing a flag and don't have a special handler, no completion
    if [[ ${cur} != "${words[cword]}" ]]; then
        return
    fi

    local completions
    if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
        completions=("${must_have_one_flag[@]}")
    elif [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
        completions=("${must_have_one_noun[@]}")
    else
        completions=("${commands[@]}")
    fi
    COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )

    if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
        declare -F __custom_func >/dev/null && __custom_func
    fi
}

# The arguments should be in the form "ext1|ext2|extn"
__handle_filename_extension_flag()
{
    local ext="$1"
    _filedir "@(${ext})"
}

__handle_subdirs_in_dir_flag()
{
    local dir="$1"
    pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1
}

__handle_flag()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    # if a command required a flag, and we found it, unset must_have_one_flag()
    local flagname=${words[c]}
    # if the word contained an =
    if [[ ${words[c]} == *"="* ]]; then
        flagname=${flagname%%=*} # strip everything after the =
        flagname="${flagname}=" # but put the = back
    fi
    __debug "${FUNCNAME}: looking for ${flagname}"
    if __contains_word "${flagname}" "${must_have_one_flag[@]}"; then
        must_have_one_flag=()
    fi

    # skip the argument to a two word flag
    if __contains_word "${words[c]}" "${two_word_flags[@]}"; then
        c=$((c+1))
        # if we are looking for a flags value, don't show commands
        if [[ $c -eq $cword ]]; then
            commands=()
        fi
    fi

    # skip the flag itself
    c=$((c+1))

}

__handle_noun()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    if __contains_word "${words[c]}" "${must_have_one_noun[@]}"; then
        must_have_one_noun=()
    fi

    nouns+=("${words[c]}")
    c=$((c+1))
}

__handle_command()
{
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"

    local next_command
    if [[ -n ${last_command} ]]; then
        next_command="_${last_command}_${words[c]}"
    else
        next_command="_${words[c]}"
    fi
    c=$((c+1))
    __debug "${FUNCNAME}: looking for ${next_command}"
    declare -F $next_command >/dev/null && $next_command
}

__handle_word()
{
    if [[ $c -ge $cword ]]; then
        __handle_reply
	return
    fi
    __debug "${FUNCNAME}: c is $c words[c] is ${words[c]}"
    if [[ "${words[c]}" == -* ]]; then
	__handle_flag
    elif __contains_word "${words[c]}" "${commands[@]}"; then
        __handle_command
    else
        __handle_noun
    fi
    __handle_word
}

`)
}

func postscript(out *bytes.Buffer, name string) {
	fmt.Fprintf(out, "__start_%s()\n", name)
	fmt.Fprintf(out, `{
    local cur prev words cword
    if declare -F _init_completions >/dev/null 2>&1; then
        _init_completion -s || return
    else
        __my_init_completion || return
    fi

    local c=0
    local flags=()
    local two_word_flags=()
    local flags_with_completion=()
    local flags_completion=()
    local commands=("%s")
    local must_have_one_flag=()
    local must_have_one_noun=()
    local last_command
    local nouns=()

    __handle_word
}

`, name)
	fmt.Fprintf(out, "complete -F __start_%s %s\n", name, name)
	fmt.Fprintf(out, "# ex: ts=4 sw=4 et filetype=sh\n")
}

func writeCommands(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    commands=()\n")
	for _, c := range cmd.Commands() {
		if len(c.Deprecated) > 0 || c == cmd.helpCommand {
			continue
		}
		fmt.Fprintf(out, "    commands+=(%q)\n", c.Name())
	}
	fmt.Fprintf(out, "\n")
}

func writeFlagHandler(name string, annotations map[string][]string, out *bytes.Buffer) {
	for key, value := range annotations {
		switch key {
		case BashCompFilenameExt:
			fmt.Fprintf(out, "    flags_with_completion+=(%q)\n", name)

			if len(value) > 0 {
				ext := "__handle_filename_extension_flag " + strings.Join(value, "|")
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			} else {
				ext := "_filedir"
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			}
		case BashCompSubdirsInDir:
			fmt.Fprintf(out, "    flags_with_completion+=(%q)\n", name)

			if len(value) == 1 {
				ext := "__handle_subdirs_in_dir_flag " + value[0]
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			} else {
				ext := "_filedir -d"
				fmt.Fprintf(out, "    flags_completion+=(%q)\n", ext)
			}
		}
	}
}

func writeShortFlag(flag *pflag.Flag, out *bytes.Buffer) {
	b := (flag.Value.Type() == "bool")
	name := flag.Shorthand
	format := "    "
	if !b {
		format += "two_word_"
	}
	format += "flags+=(\"-%s\")\n"
	fmt.Fprintf(out, format, name)
	writeFlagHandler("-"+name, flag.Annotations, out)
}

func writeFlag(flag *pflag.Flag, out *bytes.Buffer) {
	b := (flag.Value.Type() == "bool")
	name := flag.Name
	format := "    flags+=(\"--%s"
	if !b {
		format += "="
	}
	format += "\")\n"
	fmt.Fprintf(out, format, name)
	writeFlagHandler("--"+name, flag.Annotations, out)
}

func writeFlags(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, `    flags=()
    two_word_flags=()
    flags_with_completion=()
    flags_completion=()

`)
	cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
		writeFlag(flag, out)
		if len(flag.Shorthand) > 0 {
			writeShortFlag(flag, out)
		}
	})

	fmt.Fprintf(out, "\n")
}

func writeRequiredFlag(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    must_have_one_flag=()\n")
	flags := cmd.NonInheritedFlags()
	flags.VisitAll(func(flag *pflag.Flag) {
		for key := range flag.Annotations {
			switch key {
			case BashCompOneRequiredFlag:
				format := "    must_have_one_flag+=(\"--%s"
				b := (flag.Value.Type() == "bool")
				if !b {
					format += "="
				}
				format += "\")\n"
				fmt.Fprintf(out, format, flag.Name)

				if len(flag.Shorthand) > 0 {
					fmt.Fprintf(out, "    must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)
				}
			}
		}
	})
}

func writeRequiredNoun(cmd *Command, out *bytes.Buffer) {
	fmt.Fprintf(out, "    must_have_one_noun=()\n")
	sort.Sort(sort.StringSlice(cmd.ValidArgs))
	for _, value := range cmd.ValidArgs {
		fmt.Fprintf(out, "    must_have_one_noun+=(%q)\n", value)
	}
}

func gen(cmd *Command, out *bytes.Buffer) {
	for _, c := range cmd.Commands() {
		if len(c.Deprecated) > 0 || c == cmd.helpCommand {
			continue
		}
		gen(c, out)
	}
	commandName := cmd.CommandPath()
	commandName = strings.Replace(commandName, " ", "_", -1)
	fmt.Fprintf(out, "_%s()\n{\n", commandName)
	fmt.Fprintf(out, "    last_command=%q\n", commandName)
	writeCommands(cmd, out)
	writeFlags(cmd, out)
	writeRequiredFlag(cmd, out)
	writeRequiredNoun(cmd, out)
	fmt.Fprintf(out, "}\n\n")
}

func (cmd *Command) GenBashCompletion(out *bytes.Buffer) {
	preamble(out)
	if len(cmd.BashCompletionFunction) > 0 {
		fmt.Fprintf(out, "%s\n", cmd.BashCompletionFunction)
	}
	gen(cmd, out)
	postscript(out, cmd.Name())
}

func (cmd *Command) GenBashCompletionFile(filename string) error {
	out := new(bytes.Buffer)

	cmd.GenBashCompletion(out)

	outFile, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer outFile.Close()

	_, err = outFile.Write(out.Bytes())
	if err != nil {
		return err
	}
	return nil
}

// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag, if it exists.
func (cmd *Command) MarkFlagRequired(name string) error {
	return MarkFlagRequired(cmd.Flags(), name)
}

// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag in the flag set, if it exists.
func MarkFlagRequired(flags *pflag.FlagSet, name string) error {
	return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"})
}

// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func (cmd *Command) MarkFlagFilename(name string, extensions ...string) error {
	return MarkFlagFilename(cmd.Flags(), name, extensions...)
}

// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists.
// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided.
func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error {
	return flags.SetAnnotation(name, BashCompFilenameExt, extensions)
}
<|endoftext|>


<commit_before>package db

import (
	"context"
	"database/sql"
	"fmt"
	"runtime/trace"

	"pixur.org/pixur/be/status"
)

type sqlpreprocessor func(string) string

type dbWrapper struct {
	adap DBAdapter
	db   *sql.DB
	// sqlpreprocessor modifies the sql strings just before they are passed to database/sql
	// may be nil
	pp sqlpreprocessor
}

func (w *dbWrapper) Adapter() DBAdapter {
	return w.adap
}

var _ Retryable = &sqlError{}
var _ error = &sqlError{}

type sqlError struct {
	wrapped error
	adap    DBAdapter
}

func (e *sqlError) Error() string {
	return e.wrapped.Error()
}

func (e *sqlError) String() string {
	if ws, ok := e.wrapped.(fmt.Stringer); ok {
		return ws.String()
	}
	return e.Error()
}

func (e *sqlError) CanRetry() bool {
	return e.adap.RetryableErr(e.wrapped)
}

func (w *dbWrapper) Begin(ctx context.Context) (QuerierExecutorCommitter, error) {
	return w.begin(ctx)
}

func (w *dbWrapper) begin(ctx context.Context) (*txWrapper, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(ctx, "SqlBeginTx").End()
	}
	tx, err := w.db.Begin()
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "failed to begin query")
	}
	return &txWrapper{
		tx:   tx,
		ctx:  ctx,
		adap: w.adap,
		pp:   w.pp,
	}, nil
}

func (w *dbWrapper) Close() error {
	return w._close()
}

func (w *dbWrapper) _close() status.S {
	if err := w.db.Close(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't close db")
	}
	return nil
}

func (w *dbWrapper) InitSchema(ctx context.Context, tables []string) error {
	return w.initSchema(ctx, tables)
}

func (w *dbWrapper) initSchema(ctx context.Context, tables []string) status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(ctx, "SqlInitSchema").End()
	}
	// also includes initial data
	for _, table := range tables {
		if _, err := w.db.Exec(table); err != nil {
			return status.Unknown(&sqlError{
				wrapped: err,
				adap:    w.adap,
			}, "can't init table", table)
		}
	}
	return nil
}

type txWrapper struct {
	ctx  context.Context
	tx   *sql.Tx
	pp   sqlpreprocessor
	adap DBAdapter
	done bool
}

func (w *txWrapper) Exec(query string, args ...interface{}) (Result, error) {
	return w.exec(query, args...)
}

func (w *txWrapper) exec(query string, args ...interface{}) (Result, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlExec").End()
	}
	if w.pp != nil {
		query = w.pp(query)
	}
	res, err := w.tx.ExecContext(w.ctx, query, args...)
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't exec")
	}
	return Result(res), nil
}

func (w *txWrapper) Query(query string, args ...interface{}) (Rows, error) {
	return w._query(query, args...)
}

func (w *txWrapper) _query(query string, args ...interface{}) (Rows, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlQuery").End()
	}
	if w.pp != nil {
		query = w.pp(query)
	}
	rows, err := w.tx.QueryContext(w.ctx, query, args...)
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't query")
	}
	return Rows(rows), nil
}

func (w *txWrapper) Commit() error {
	return w.commit()
}

func (w *txWrapper) commit() status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlCommit").End()
	}
	if err := w.tx.Commit(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't commit")
	}
	w.done = true
	return nil
}

func (w *txWrapper) Rollback() error {
	return w.rollback()
}

func (w *txWrapper) rollback() status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlRollback").End()
	}
	if w.done {
		return nil
	}
	w.done = true
	if err := w.tx.Rollback(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't rollback")
	}
	return nil
}
<commit_msg>be/schema: add more docs, and set isolation level<commit_after>package db

import (
	"context"
	"database/sql"
	"fmt"
	"runtime/trace"

	"pixur.org/pixur/be/status"
)

type sqlpreprocessor func(string) string

type dbWrapper struct {
	adap DBAdapter
	db   *sql.DB
	// sqlpreprocessor modifies the sql strings just before they are passed to database/sql
	// may be nil
	pp sqlpreprocessor
}

func (w *dbWrapper) Adapter() DBAdapter {
	return w.adap
}

var _ Retryable = &sqlError{}
var _ error = &sqlError{}

type sqlError struct {
	wrapped error
	adap    DBAdapter
}

func (e *sqlError) Error() string {
	return e.wrapped.Error()
}

func (e *sqlError) String() string {
	if ws, ok := e.wrapped.(fmt.Stringer); ok {
		return ws.String()
	}
	return e.Error()
}

func (e *sqlError) CanRetry() bool {
	return e.adap.RetryableErr(e.wrapped)
}

func (w *dbWrapper) Begin(ctx context.Context) (QuerierExecutorCommitter, error) {
	return w.begin(ctx)
}

func (w *dbWrapper) begin(ctx context.Context) (*txWrapper, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(ctx, "SqlBeginTx").End()
	}
	tx, err := w.db.BeginTx(ctx, &sql.TxOptions{
		Isolation: sql.LevelSerializable,
	})
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "failed to begin query")
	}
	return &txWrapper{
		tx:   tx,
		ctx:  ctx,
		adap: w.adap,
		pp:   w.pp,
	}, nil
}

func (w *dbWrapper) Close() error {
	return w._close()
}

func (w *dbWrapper) _close() status.S {
	if err := w.db.Close(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't close db")
	}
	return nil
}

func (w *dbWrapper) InitSchema(ctx context.Context, tables []string) error {
	return w.initSchema(ctx, tables)
}

func (w *dbWrapper) initSchema(ctx context.Context, tables []string) status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(ctx, "SqlInitSchema").End()
	}

	// also includes initial data
	for _, table := range tables {
		if _, err := w.db.ExecContext(ctx, table); err != nil {
			return status.Unknown(&sqlError{
				wrapped: err,
				adap:    w.adap,
			}, "can't init table", table)
		}
	}
	return nil
}

type txWrapper struct {
	ctx  context.Context
	tx   *sql.Tx
	pp   sqlpreprocessor
	adap DBAdapter
	done bool
}

func (w *txWrapper) Exec(query string, args ...interface{}) (Result, error) {
	return w.exec(query, args...)
}

func (w *txWrapper) exec(query string, args ...interface{}) (Result, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlExec").End()
	}
	if w.pp != nil {
		query = w.pp(query)
	}
	res, err := w.tx.ExecContext(w.ctx, query, args...)
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't exec")
	}
	return Result(res), nil
}

func (w *txWrapper) Query(query string, args ...interface{}) (Rows, error) {
	return w._query(query, args...)
}

func (w *txWrapper) _query(query string, args ...interface{}) (Rows, status.S) {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlQuery").End()
	}
	if w.pp != nil {
		query = w.pp(query)
	}
	rows, err := w.tx.QueryContext(w.ctx, query, args...)
	if err != nil {
		return nil, status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't query")
	}
	return Rows(rows), nil
}

func (w *txWrapper) Commit() error {
	return w.commit()
}

func (w *txWrapper) commit() status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlCommit").End()
	}
	if err := w.tx.Commit(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't commit")
	}
	w.done = true
	return nil
}

func (w *txWrapper) Rollback() error {
	return w.rollback()
}

func (w *txWrapper) rollback() status.S {
	if trace.IsEnabled() {
		defer trace.StartRegion(w.ctx, "SqlRollback").End()
	}
	if w.done {
		return nil
	}
	w.done = true
	if err := w.tx.Rollback(); err != nil {
		return status.Unknown(&sqlError{
			wrapped: err,
			adap:    w.adap,
		}, "can't rollback")
	}
	return nil
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// TODO: Check CPU performance governor before each benchmark.

// TODO: Mode to prioritize commits around big performance changes.

// TODO: Support running pre-built binaries without specific hashes.
// This is useful for testing things that aren't yet committed or that
// require unusual build steps.

var run struct {
	order      string
	topLevel   string
	benchFlags string
	iterations int
	goverSave  bool
}

var cmdRunFlags = flag.NewFlagSet(os.Args[0]+" run", flag.ExitOnError)

func init() {
	f := cmdRunFlags
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s run [flags] <revision range>\n", os.Args[0])
		f.PrintDefaults()
	}
	f.StringVar(&run.order, "order", "seq", "run benchmarks in `order`, which must be one of: seq, spread")
	f.StringVar(&gitDir, "C", "", "run git in `dir`")
	f.StringVar(&run.benchFlags, "benchflags", "", "pass `flags` to benchmark")
	f.IntVar(&run.iterations, "n", 5, "run each benchmark `N` times")
	f.StringVar(&outDir, "o", "", "write binaries and logs to `directory`")
	f.BoolVar(&run.goverSave, "gover-save", false, "save toolchain builds with gover")
	f.BoolVar(&dryRun, "dry-run", false, "print commands but do not run them")
	registerSubcommand("run", "[flags] <revision range> - run benchmarks", cmdRun, f)
}

func cmdRun() {
	if cmdRunFlags.NArg() < 1 {
		cmdRunFlags.Usage()
		os.Exit(2)
	}

	var pickCommit func([]*commitInfo) *commitInfo
	switch run.order {
	case "seq":
		pickCommit = pickCommitSeq
	case "spread":
		pickCommit = pickCommitSpread
	default:
		fmt.Fprintf(os.Stderr, "unknown order: %s\n", run.order)
		cmdRunFlags.Usage()
		os.Exit(2)
	}

	commits := getCommits(cmdRunFlags.Args())

	// Get other git information.
	run.topLevel = trimNL(git("rev-parse", "--show-toplevel"))

	status := NewStatusReporter()
	defer status.Stop()

	for {
		doneIters, totalIters, partialCommits, doneCommits, failedCommits := runStats(commits)
		unstartedCommits := len(commits) - (partialCommits + doneCommits + failedCommits)
		msg := fmt.Sprintf("%d/%d runs, %d unstarted+%d partial+%d done+%d failed commits", doneIters, totalIters, unstartedCommits, partialCommits, doneCommits, failedCommits)
		// TODO: Count builds and runs separately.
		status.Progress(msg, float64(doneIters)/float64(totalIters))

		commit := pickCommit(commits)
		if commit == nil {
			break
		}
		runBenchmark(commit, status)
	}
}

func runStats(commits []*commitInfo) (doneIters, totalIters, partialCommits, doneCommits, failedCommits int) {
	for _, c := range commits {
		if c.count >= run.iterations {
			// Don't care if it failed.
			doneIters += c.count
			totalIters += c.count
		} else if c.runnable() {
			doneIters += c.count
			totalIters += run.iterations
		}

		if c.count == run.iterations {
			doneCommits++
		} else if c.runnable() {
			if c.count != 0 {
				partialCommits++
			}
		} else {
			failedCommits++
		}
	}
	return
}

// pickCommitSeq picks the next commit to run based on the most recent
// commit with the fewest iterations.
func pickCommitSeq(commits []*commitInfo) *commitInfo {
	var minCommit *commitInfo
	for _, commit := range commits {
		if !commit.runnable() {
			continue
		}
		if minCommit == nil || commit.count < minCommit.count {
			minCommit = commit
		}
	}
	return minCommit
}

// pickCommitSpread picks the next commit to run from commits using an
// algorithm that spreads out the runs.
func pickCommitSpread(commits []*commitInfo) *commitInfo {
	// Assign weights to each commit. This is thoroughly
	// heuristic, but it's geared toward either increasing the
	// iteration count of commits that we have, or picking a new
	// commit so as to spread out the commits we have.
	weights := make([]int, len(commits))
	totalWeight := 0

	nPartial := 0
	for _, commit := range commits {
		if commit.partial() {
			nPartial++
		}
	}
	if nPartial >= len(commits)/10 {
		// Limit the number of partially completed revisions
		// to 10% by only choosing a partial commit in this
		// case.
		for i, commit := range commits {
			if commit.partial() {
				// Bias toward commits that are
				// further from done.
				weights[i] = run.iterations - commit.count
			}
		}
	} else {
		// Pick a new commit weighted by its distance from a
		// commit that we already have.

		// Find distance from left to right.
		distance := len(commits)
		haveAny := false
		for i, commit := range commits {
			if commit.count > 0 {
				distance = 1
				haveAny = true
			} else if commit.runnable() {
				distance++
			}
			weights[i] = distance
		}

		// Find distance from right to left.
		distance = len(commits)
		for i := len(commits) - 1; i >= 0; i-- {
			commit := commits[i]
			if commit.count > 0 {
				distance = 1
			} else if commit.runnable() {
				distance++
			}

			if distance < weights[i] {
				weights[i] = distance
			}
		}

		if !haveAny {
			// We don't have any commits. Pick one uniformly.
			for i := range commits {
				weights[i] = 1
			}
		}

		// Zero non-runnable commits.
		for i, commit := range commits {
			if !commit.runnable() {
				weights[i] = 0
			}
		}
	}

	for _, w := range weights {
		totalWeight += w
	}
	if totalWeight == 0 {
		return nil
	}

	// Pick a commit based on the weights.
	x := rand.Intn(totalWeight)
	cumulative := 0
	for i, w := range weights {
		cumulative += w
		if cumulative > x {
			return commits[i]
		}
	}
	panic("unreachable")
}

// runBenchmark runs the benchmark at commit. It updates commit.count,
// commit.fails, and commit.buildFailed as appropriate and writes to
// the commit log to record the outcome.
func runBenchmark(commit *commitInfo, status *StatusReporter) {
	isXBenchmark := false
	if abs, _ := os.Getwd(); strings.Contains(abs, "golang.org/x/benchmarks/") {
		isXBenchmark = true
	}

	// Build the benchmark if necessary.
	if !exists(commit.binPath) {
		runStatus(status, commit, "building")

		// Check out the appropriate commit. This is necessary
		// even if we're using gover because the benchmark
		// itself might have changed (e.g., bug fixes).
		git("checkout", "-q", commit.hash)

		var buildCmd []string
		if commit.gover {
			// TODO: It would be better if gover took a
			// long hash and did the right thing.
			buildCmd = []string{"gover", "run", commit.hash[:7], "go"}
		} else {
			// If this is the Go toolchain, do a full
			// make.bash. Otherwise, we assume that go
			// test -c will build the necessary
			// dependencies.
			if exists(filepath.Join(run.topLevel, "src", "make.bash")) {
				cmd := exec.Command("./make.bash")
				cmd.Dir = filepath.Join(run.topLevel, "src")
				if dryRun {
					dryPrint(cmd)
				} else if out, err := cmd.CombinedOutput(); err != nil {
					detail := indent(string(out)) + indent(err.Error())
					fmt.Fprintf(os.Stderr, "failed to build toolchain at %s:\n%s", commit.hash, detail)
					commit.buildFailed = true
					commit.writeLog([]byte("BUILD FAILED:\n" + detail))
					return
				}
				if run.goverSave && doGoverSave() == nil {
					commit.gover = true
				}
				buildCmd = []string{filepath.Join(run.topLevel, "bin", "go")}
			} else {
				// Assume go is in $PATH.
				buildCmd = []string{"go"}
			}
		}

		if isXBenchmark {
			buildCmd = append(buildCmd, "build", "-o", commit.binPath)
		} else {
			buildCmd = append(buildCmd, "test", "-c", "-o", commit.binPath)
		}
		cmd := exec.Command(buildCmd[0], buildCmd[1:]...)
		if dryRun {
			dryPrint(cmd)
		} else if out, err := cmd.CombinedOutput(); err != nil {
			detail := indent(string(out)) + indent(err.Error())
			fmt.Fprintf(os.Stderr, "failed to build tests at %s:\n%s", commit.hash, detail)
			commit.buildFailed = true
			commit.writeLog([]byte("BUILD FAILED:\n" + detail))
			return
		}
	}

	// Run the benchmark.
	runStatus(status, commit, "running")
	var args []string
	if isXBenchmark {
		args = []string{}
	} else {
		args = []string{"-test.run", "NONE", "-test.bench", "."}
	}
	args = append(args, strings.Fields(run.benchFlags)...)
	cmd := exec.Command("./"+commit.binPath, args...)
	if dryRun {
		dryPrint(cmd)
		commit.count++
		return
	}
	out, err := cmd.CombinedOutput()
	if err == nil {
		commit.count++
	} else {
		fmt.Fprintf(os.Stderr, "failed to run benchmark at %s:\n%s", commit.hash, out)
		commit.fails++
		// Indent the output so we don't get confused by
		// benchmarks in it or "PASS" lines.
		out = []byte("FAILED:\n" + indent(string(out)) + indent(err.Error()))
	}

	// Write the benchmark output.
	commit.writeLog(out)
}

func doGoverSave() error {
	cmd := exec.Command("gover", "save")
	cmd.Env = append([]string{"GOROOT=" + run.topLevel}, os.Environ()...)
	if dryRun {
		dryPrint(cmd)
		return nil
	} else {
		out, err := cmd.CombinedOutput()
		if err != nil {
			fmt.Fprintf(os.Stderr, "gover save failed: %s:\n%s", err, indent(string(out)))
		}
		return err
	}
}

// runStatus updates the status message for commit.
func runStatus(sr *StatusReporter, commit *commitInfo, status string) {
	sr.Message(fmt.Sprintf("commit %s, iteration %d/%d: %s...", commit.hash[:7], commit.count+1, run.iterations, status))
}
<commit_msg>benchmany: fix running benchmarks from non-relative paths<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

// TODO: Check CPU performance governor before each benchmark.

// TODO: Mode to prioritize commits around big performance changes.

// TODO: Support running pre-built binaries without specific hashes.
// This is useful for testing things that aren't yet committed or that
// require unusual build steps.

var run struct {
	order      string
	topLevel   string
	benchFlags string
	iterations int
	goverSave  bool
}

var cmdRunFlags = flag.NewFlagSet(os.Args[0]+" run", flag.ExitOnError)

func init() {
	f := cmdRunFlags
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s run [flags] <revision range>\n", os.Args[0])
		f.PrintDefaults()
	}
	f.StringVar(&run.order, "order", "seq", "run benchmarks in `order`, which must be one of: seq, spread")
	f.StringVar(&gitDir, "C", "", "run git in `dir`")
	f.StringVar(&run.benchFlags, "benchflags", "", "pass `flags` to benchmark")
	f.IntVar(&run.iterations, "n", 5, "run each benchmark `N` times")
	f.StringVar(&outDir, "o", "", "write binaries and logs to `directory`")
	f.BoolVar(&run.goverSave, "gover-save", false, "save toolchain builds with gover")
	f.BoolVar(&dryRun, "dry-run", false, "print commands but do not run them")
	registerSubcommand("run", "[flags] <revision range> - run benchmarks", cmdRun, f)
}

func cmdRun() {
	if cmdRunFlags.NArg() < 1 {
		cmdRunFlags.Usage()
		os.Exit(2)
	}

	var pickCommit func([]*commitInfo) *commitInfo
	switch run.order {
	case "seq":
		pickCommit = pickCommitSeq
	case "spread":
		pickCommit = pickCommitSpread
	default:
		fmt.Fprintf(os.Stderr, "unknown order: %s\n", run.order)
		cmdRunFlags.Usage()
		os.Exit(2)
	}

	commits := getCommits(cmdRunFlags.Args())

	// Get other git information.
	run.topLevel = trimNL(git("rev-parse", "--show-toplevel"))

	status := NewStatusReporter()
	defer status.Stop()

	for {
		doneIters, totalIters, partialCommits, doneCommits, failedCommits := runStats(commits)
		unstartedCommits := len(commits) - (partialCommits + doneCommits + failedCommits)
		msg := fmt.Sprintf("%d/%d runs, %d unstarted+%d partial+%d done+%d failed commits", doneIters, totalIters, unstartedCommits, partialCommits, doneCommits, failedCommits)
		// TODO: Count builds and runs separately.
		status.Progress(msg, float64(doneIters)/float64(totalIters))

		commit := pickCommit(commits)
		if commit == nil {
			break
		}
		runBenchmark(commit, status)
	}
}

func runStats(commits []*commitInfo) (doneIters, totalIters, partialCommits, doneCommits, failedCommits int) {
	for _, c := range commits {
		if c.count >= run.iterations {
			// Don't care if it failed.
			doneIters += c.count
			totalIters += c.count
		} else if c.runnable() {
			doneIters += c.count
			totalIters += run.iterations
		}

		if c.count == run.iterations {
			doneCommits++
		} else if c.runnable() {
			if c.count != 0 {
				partialCommits++
			}
		} else {
			failedCommits++
		}
	}
	return
}

// pickCommitSeq picks the next commit to run based on the most recent
// commit with the fewest iterations.
func pickCommitSeq(commits []*commitInfo) *commitInfo {
	var minCommit *commitInfo
	for _, commit := range commits {
		if !commit.runnable() {
			continue
		}
		if minCommit == nil || commit.count < minCommit.count {
			minCommit = commit
		}
	}
	return minCommit
}

// pickCommitSpread picks the next commit to run from commits using an
// algorithm that spreads out the runs.
func pickCommitSpread(commits []*commitInfo) *commitInfo {
	// Assign weights to each commit. This is thoroughly
	// heuristic, but it's geared toward either increasing the
	// iteration count of commits that we have, or picking a new
	// commit so as to spread out the commits we have.
	weights := make([]int, len(commits))
	totalWeight := 0

	nPartial := 0
	for _, commit := range commits {
		if commit.partial() {
			nPartial++
		}
	}
	if nPartial >= len(commits)/10 {
		// Limit the number of partially completed revisions
		// to 10% by only choosing a partial commit in this
		// case.
		for i, commit := range commits {
			if commit.partial() {
				// Bias toward commits that are
				// further from done.
				weights[i] = run.iterations - commit.count
			}
		}
	} else {
		// Pick a new commit weighted by its distance from a
		// commit that we already have.

		// Find distance from left to right.
		distance := len(commits)
		haveAny := false
		for i, commit := range commits {
			if commit.count > 0 {
				distance = 1
				haveAny = true
			} else if commit.runnable() {
				distance++
			}
			weights[i] = distance
		}

		// Find distance from right to left.
		distance = len(commits)
		for i := len(commits) - 1; i >= 0; i-- {
			commit := commits[i]
			if commit.count > 0 {
				distance = 1
			} else if commit.runnable() {
				distance++
			}

			if distance < weights[i] {
				weights[i] = distance
			}
		}

		if !haveAny {
			// We don't have any commits. Pick one uniformly.
			for i := range commits {
				weights[i] = 1
			}
		}

		// Zero non-runnable commits.
		for i, commit := range commits {
			if !commit.runnable() {
				weights[i] = 0
			}
		}
	}

	for _, w := range weights {
		totalWeight += w
	}
	if totalWeight == 0 {
		return nil
	}

	// Pick a commit based on the weights.
	x := rand.Intn(totalWeight)
	cumulative := 0
	for i, w := range weights {
		cumulative += w
		if cumulative > x {
			return commits[i]
		}
	}
	panic("unreachable")
}

// runBenchmark runs the benchmark at commit. It updates commit.count,
// commit.fails, and commit.buildFailed as appropriate and writes to
// the commit log to record the outcome.
func runBenchmark(commit *commitInfo, status *StatusReporter) {
	isXBenchmark := false
	if abs, _ := os.Getwd(); strings.Contains(abs, "golang.org/x/benchmarks/") {
		isXBenchmark = true
	}

	// Build the benchmark if necessary.
	if !exists(commit.binPath) {
		runStatus(status, commit, "building")

		// Check out the appropriate commit. This is necessary
		// even if we're using gover because the benchmark
		// itself might have changed (e.g., bug fixes).
		git("checkout", "-q", commit.hash)

		var buildCmd []string
		if commit.gover {
			// TODO: It would be better if gover took a
			// long hash and did the right thing.
			buildCmd = []string{"gover", "run", commit.hash[:7], "go"}
		} else {
			// If this is the Go toolchain, do a full
			// make.bash. Otherwise, we assume that go
			// test -c will build the necessary
			// dependencies.
			if exists(filepath.Join(run.topLevel, "src", "make.bash")) {
				cmd := exec.Command("./make.bash")
				cmd.Dir = filepath.Join(run.topLevel, "src")
				if dryRun {
					dryPrint(cmd)
				} else if out, err := cmd.CombinedOutput(); err != nil {
					detail := indent(string(out)) + indent(err.Error())
					fmt.Fprintf(os.Stderr, "failed to build toolchain at %s:\n%s", commit.hash, detail)
					commit.buildFailed = true
					commit.writeLog([]byte("BUILD FAILED:\n" + detail))
					return
				}
				if run.goverSave && doGoverSave() == nil {
					commit.gover = true
				}
				buildCmd = []string{filepath.Join(run.topLevel, "bin", "go")}
			} else {
				// Assume go is in $PATH.
				buildCmd = []string{"go"}
			}
		}

		if isXBenchmark {
			buildCmd = append(buildCmd, "build", "-o", commit.binPath)
		} else {
			buildCmd = append(buildCmd, "test", "-c", "-o", commit.binPath)
		}
		cmd := exec.Command(buildCmd[0], buildCmd[1:]...)
		if dryRun {
			dryPrint(cmd)
		} else if out, err := cmd.CombinedOutput(); err != nil {
			detail := indent(string(out)) + indent(err.Error())
			fmt.Fprintf(os.Stderr, "failed to build tests at %s:\n%s", commit.hash, detail)
			commit.buildFailed = true
			commit.writeLog([]byte("BUILD FAILED:\n" + detail))
			return
		}
	}

	// Run the benchmark.
	runStatus(status, commit, "running")
	var args []string
	if isXBenchmark {
		args = []string{}
	} else {
		args = []string{"-test.run", "NONE", "-test.bench", "."}
	}
	args = append(args, strings.Fields(run.benchFlags)...)
	name := commit.binPath
	if filepath.Base(name) == name {
		// Make exec.Command treat this as a relative path.
		name = "./" + name
	}
	cmd := exec.Command(name, args...)
	if dryRun {
		dryPrint(cmd)
		commit.count++
		return
	}
	out, err := cmd.CombinedOutput()
	if err == nil {
		commit.count++
	} else {
		fmt.Fprintf(os.Stderr, "failed to run benchmark at %s:\n%s", commit.hash, out)
		commit.fails++
		// Indent the output so we don't get confused by
		// benchmarks in it or "PASS" lines.
		out = []byte("FAILED:\n" + indent(string(out)) + indent(err.Error()))
	}

	// Write the benchmark output.
	commit.writeLog(out)
}

func doGoverSave() error {
	cmd := exec.Command("gover", "save")
	cmd.Env = append([]string{"GOROOT=" + run.topLevel}, os.Environ()...)
	if dryRun {
		dryPrint(cmd)
		return nil
	} else {
		out, err := cmd.CombinedOutput()
		if err != nil {
			fmt.Fprintf(os.Stderr, "gover save failed: %s:\n%s", err, indent(string(out)))
		}
		return err
	}
}

// runStatus updates the status message for commit.
func runStatus(sr *StatusReporter, commit *commitInfo, status string) {
	sr.Message(fmt.Sprintf("commit %s, iteration %d/%d: %s...", commit.hash[:7], commit.count+1, run.iterations, status))
}
<|endoftext|>


<commit_before>package suit

import (
	"bytes"
	"encoding/json"
	"log"
	"testing"
)

var fixture = ConfigurationScreen{
	Title: "Create new security light",
	Sections: []Section{
		Section{
			Contents: []Typed{
				InputText{
					Name:        "name",
					Before:      "Name",
					Placeholder: "My Security Light",
					Value:       "Front door light",
				},
				OptionGroup{
					Name:           "sensors",
					Title:          "When these devices detect motion",
					MinimumChoices: 1,
					Options: []OptionGroupOption{
						OptionGroupOption{
							Title:    "Front Door Motion",
							Subtitle: "Motion",
							Value:    "fd",
						},
						OptionGroupOption{
							Title:    "Back Door 1",
							Subtitle: "Presence",
							Value:    "bd",
							Selected: true,
						},
					},
				},
				OptionGroup{
					Name:           "lights",
					Title:          "Turn on these lights",
					MinimumChoices: 1,
					Options: []OptionGroupOption{
						OptionGroupOption{
							Title:    "Front Door",
							Subtitle: "Lamp in Hallway",
							Value:    "fd",
						},
						OptionGroupOption{
							Title:    "Front Door Spotlight",
							Subtitle: "Light in Front Step",
							Value:    "fds",
							Selected: true,
						},
					},
				},
				InputTimeRange{
					Name:  "time",
					Title: "When",
					Value: TimeRange{
						From: "10:00",
						To:   "sunset",
					},
				},
				InputText{
					Title:     "Turn off again after",
					After:     "minutes",
					Name:      "timeout",
					InputType: "number",
					Minimum:   i(0),
					Value:     5,
				},
			},
		},
	},
	Actions: []Typed{
		CloseAction{
			Label: "Cancel",
		},
		ReplyAction{
			Label:        "Save",
			Name:         "save",
			DisplayClass: "success",
			DisplayIcon:  "star",
		},
	},
}

func TestLowerCaseJSON(t *testing.T) {

	js, err := json.Marshal(&fixture)
	log.Printf("JSON: %s %v", js, err)
}

func i(i int) *int {
	return &i
}

func roundtrip(t *testing.T, cs *ConfigurationScreen) {
	log.Printf("original form is %+v", cs)
	if buf, err := cs.MarshalJSON(); err != nil {
		t.Fatalf("marshalling failed: %v", err)
	} else {
		log.Printf("marshalled form is %s", string(buf))
		read := ConfigurationScreen{}
		if err := read.UnmarshalJSON(buf); err != nil {
			t.Fatalf("unmarshalling failed: %v", err)
		}
		log.Printf("unmarshalled form is %+v", read)
		if buf2, err := read.MarshalJSON(); err != nil {
			t.Fatalf("remarshalling failed: %v", err)
		} else {
			if bytes.Compare(buf, buf2) != 0 {
				t.Fatalf("inconsistent remarshalling:\n%s\n---\n%s\n", string(buf), string(buf2))
			}
		}
	}
}

func TestRoundTripEmpty(t *testing.T) {
	roundtrip(t, &ConfigurationScreen{})
}

func TestRoundTripFixture(t *testing.T) {
	roundtrip(t, &fixture)
}
<commit_msg>Add tests for round tripping from json.<commit_after>package suit

import (
	"bytes"
	"encoding/json"
	"log"
	"testing"
)

var fixture = ConfigurationScreen{
	Title: "Create new security light",
	Sections: []Section{
		Section{
			Contents: []Typed{
				InputText{
					Name:        "name",
					Before:      "Name",
					Placeholder: "My Security Light",
					Value:       "Front door light",
				},
				OptionGroup{
					Name:           "sensors",
					Title:          "When these devices detect motion",
					MinimumChoices: 1,
					Options: []OptionGroupOption{
						OptionGroupOption{
							Title:    "Front Door Motion",
							Subtitle: "Motion",
							Value:    "fd",
						},
						OptionGroupOption{
							Title:    "Back Door 1",
							Subtitle: "Presence",
							Value:    "bd",
							Selected: true,
						},
					},
				},
				OptionGroup{
					Name:           "lights",
					Title:          "Turn on these lights",
					MinimumChoices: 1,
					Options: []OptionGroupOption{
						OptionGroupOption{
							Title:    "Front Door",
							Subtitle: "Lamp in Hallway",
							Value:    "fd",
						},
						OptionGroupOption{
							Title:    "Front Door Spotlight",
							Subtitle: "Light in Front Step",
							Value:    "fds",
							Selected: true,
						},
					},
				},
				InputTimeRange{
					Name:  "time",
					Title: "When",
					Value: TimeRange{
						From: "10:00",
						To:   "sunset",
					},
				},
				InputText{
					Title:     "Turn off again after",
					After:     "minutes",
					Name:      "timeout",
					InputType: "number",
					Minimum:   i(1),
					Value:     5,
				},
			},
		},
	},
	Actions: []Typed{
		CloseAction{
			Label: "Cancel",
		},
		ReplyAction{
			Label:        "Save",
			Name:         "save",
			DisplayClass: "success",
			DisplayIcon:  "star",
		},
	},
}

var jsonFixture = `{
  "actions": [
    {
      "label": "Cancel",
      "type": "close"
    },
    {
      "displayClass": "success",
      "displayIcon": "star",
      "label": "Save",
      "name": "save",
      "type": "reply"
    }
  ],
  "sections": [
    {
      "contents": [
        {
          "before": "Name",
          "name": "name",
          "placeholder": "My Security Light",
          "type": "inputText",
          "value": "Front door light"
        },
        {
          "minimumChoices": 1,
          "name": "sensors",
          "options": [
            {
              "subtitle": "Motion",
              "title": "Front Door Motion",
              "value": "fd"
            },
            {
              "selected": true,
              "subtitle": "Presence",
              "title": "Back Door 1",
              "value": "bd"
            }
          ],
          "title": "When these devices detect motion",
          "type": "optionGroup"
        },
        {
          "minimumChoices": 1,
          "name": "lights",
          "options": [
            {
              "subtitle": "Lamp in Hallway",
              "title": "Front Door",
              "value": "fd"
            },
            {
              "selected": true,
              "subtitle": "Light in Front Step",
              "title": "Front Door Spotlight",
              "value": "fds"
            }
          ],
          "title": "Turn on these lights",
          "type": "optionGroup"
        },
        {
          "name": "time",
          "title": "When",
          "type": "inputTimeRange",
          "value": {
            "from": "10:00",
            "to": "sunset"
          }
        },
        {
          "after": "minutes",
          "inputType": "number",
          "name": "timeout",
          "title": "Turn off again after",
          "type": "inputText",
          "value": 5,
          "minimum": 1
        }
      ]
    }
  ],
  "title": "Create new security light"
}`

func TestLowerCaseJSON(t *testing.T) {

	js, err := json.Marshal(&fixture)
	log.Printf("JSON: %s %v", js, err)
}

func i(i int) *int {
	return &i
}

func normalizeJSON(j string) string {
	m := make(map[string]interface{})
	if err := json.Unmarshal([]byte(j), &m); err != nil {
		return j
	} else {
		b, _ := json.MarshalIndent(m, "", "  ")
		return string(b)
	}
}

func roundtripFromJSON(t *testing.T, j string) {
	n := normalizeJSON(j)
	cs := ConfigurationScreen{}
	if err := cs.UnmarshalJSON([]byte(n)); err != nil {
		t.Fatalf("Failed while unmarshalling json: %v: %s", err, j)
	} else {
		if b, err := cs.MarshalJSON(); err != nil {
			t.Fatalf("Failed while marshalling json: %v", err)
		} else {
			nn := normalizeJSON(string(b))
			if n != nn {
				t.Fatalf("Round trip failed: \n%s\n != \n%s\n", n, nn)
			} else {
				log.Printf("n==nn \n%s\n==\n%s\n", n, nn)
			}
		}
	}
}

func roundtrip(t *testing.T, cs *ConfigurationScreen) {
	log.Printf("original form is %+v", cs)
	if buf, err := cs.MarshalJSON(); err != nil {
		t.Fatalf("marshalling failed: %v", err)
	} else {
		log.Printf("marshalled form is %s", normalizeJSON(string(buf)))
		read := ConfigurationScreen{}
		if err := read.UnmarshalJSON(buf); err != nil {
			t.Fatalf("unmarshalling failed: %v", err)
		}
		log.Printf("unmarshalled form is %+v", read)
		if buf2, err := read.MarshalJSON(); err != nil {
			t.Fatalf("remarshalling failed: %v", err)
		} else {
			if bytes.Compare(buf, buf2) != 0 {
				t.Fatalf("inconsistent remarshalling:\n%s\n---\n%s\n", normalizeJSON(string(buf)), normalizeJSON(string(buf2)))
			}
		}
	}
}

func TestRoundTripEmpty(t *testing.T) {
	roundtrip(t, &ConfigurationScreen{})
}

func TestRoundTripFixture(t *testing.T) {
	roundtrip(t, &fixture)
}

func TestRoundTripFromJSON(t *testing.T) {
	roundtripFromJSON(t, jsonFixture)
}
<|endoftext|>


<commit_before>// Abstracts a layered filesystem provider, such as docker's Graph
package layercake

import (
	"crypto/sha256"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
	"github.com/docker/docker/pkg/archive"
)

type QuotaedDriver interface {
	graphdriver.Driver
	GetQuotaed(id, mountlabel string, quota int64) (string, error)
}

type Docker struct {
	Graph  *graph.Graph
	Driver graphdriver.Driver
}

func (d *Docker) DriverName() string {
	return d.Driver.String()
}

func (d *Docker) Create(layerID, parentID ID, containerID string) error {
	return d.Register(
		&image.Image{
			ID:        layerID.GraphID(),
			Parent:    parentID.GraphID(),
			Container: containerID,
		}, nil)
}

func (d *Docker) Register(image *image.Image, layer archive.ArchiveReader) error {
	return d.Graph.Register(&descriptor{image}, layer)
}

func (d *Docker) Get(id ID) (*image.Image, error) {
	return d.Graph.Get(id.GraphID())
}

func (d *Docker) Unmount(id ID) error {
	return d.Driver.Put(id.GraphID())
}

func (d *Docker) Remove(id ID) error {
	if err := d.Driver.Put(id.GraphID()); err != nil {
		return err
	}

	return d.Graph.Delete(id.GraphID())
}

func (d *Docker) Path(id ID) (string, error) {
	return d.Driver.Get(id.GraphID(), "")
}

func (d *Docker) QuotaedPath(id ID, quota int64) (string, error) {
	if d.DriverName() == "aufs" {
		return d.Driver.(QuotaedDriver).GetQuotaed(id.GraphID(), "", quota)
	} else {
		return "", errors.New("quotas are not supported for this driver")
	}
}

func (d *Docker) All() (layers []*image.Image) {
	for _, layer := range d.Graph.Map() {
		layers = append(layers, layer)
	}
	return layers
}

func (d *Docker) IsLeaf(id ID) (bool, error) {
	heads := d.Graph.Heads()
	_, ok := heads[id.GraphID()]
	return ok, nil
}

func (d *Docker) GetAllLeaves() ([]ID, error) {
	heads := d.Graph.Heads()
	var result []ID

	for head := range heads {
		result = append(result, DockerImageID(head))
	}

	return result, nil
}

type ContainerID string
type DockerImageID string

type LocalImageID struct {
	Path         string
	ModifiedTime time.Time
}

type NamespacedLayerID struct {
	LayerID  ID
	CacheKey string
}

func NamespacedID(id ID, cacheKey string) NamespacedLayerID {
	return NamespacedLayerID{id, cacheKey}
}

func (c ContainerID) GraphID() string {
	return shaID(string(c))
}

func (d DockerImageID) GraphID() string {
	return string(d)
}

func (c LocalImageID) GraphID() string {
	return shaID(fmt.Sprintf("%s-%d", c.Path, c.ModifiedTime))
}

func (n NamespacedLayerID) GraphID() string {
	return shaID(n.LayerID.GraphID() + "@" + n.CacheKey)
}

func shaID(id string) string {
	if id == "" {
		return id
	}

	return fmt.Sprintf("%x", sha256.Sum256([]byte(id)))
}

type descriptor struct {
	image *image.Image
}

func (d descriptor) ID() string {
	return d.image.ID
}

func (d descriptor) Parent() string {
	return d.image.Parent
}

func (d descriptor) MarshalConfig() ([]byte, error) {
	return json.Marshal(d.image)
}
<commit_msg>Retry aufs mount<commit_after>// Abstracts a layered filesystem provider, such as docker's Graph
package layercake

import (
	"crypto/sha256"
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"github.com/docker/docker/daemon/graphdriver"
	"github.com/docker/docker/graph"
	"github.com/docker/docker/image"
	"github.com/docker/docker/pkg/archive"
)

type QuotaedDriver interface {
	graphdriver.Driver
	GetQuotaed(id, mountlabel string, quota int64) (string, error)
}

type Docker struct {
	Graph  *graph.Graph
	Driver graphdriver.Driver
}

func (d *Docker) DriverName() string {
	return d.Driver.String()
}

func (d *Docker) Create(layerID, parentID ID, containerID string) error {
	return d.Register(
		&image.Image{
			ID:        layerID.GraphID(),
			Parent:    parentID.GraphID(),
			Container: containerID,
		}, nil)
}

func (d *Docker) Register(image *image.Image, layer archive.ArchiveReader) error {
	return d.Graph.Register(&descriptor{image}, layer)
}

func (d *Docker) Get(id ID) (*image.Image, error) {
	return d.Graph.Get(id.GraphID())
}

func (d *Docker) Unmount(id ID) error {
	return d.Driver.Put(id.GraphID())
}

func (d *Docker) Remove(id ID) error {
	if err := d.Driver.Put(id.GraphID()); err != nil {
		return err
	}

	return d.Graph.Delete(id.GraphID())
}

func (d *Docker) Path(id ID) (result string, err error) {
	for i := 0; i < 5; i++ {
		result, err = d.Driver.Get(id.GraphID(), "")
		if err == nil {
			return
		}
	}
	return
}

func (d *Docker) QuotaedPath(id ID, quota int64) (string, error) {
	if d.DriverName() == "aufs" {
		return d.Driver.(QuotaedDriver).GetQuotaed(id.GraphID(), "", quota)
	} else {
		return "", errors.New("quotas are not supported for this driver")
	}
}

func (d *Docker) All() (layers []*image.Image) {
	for _, layer := range d.Graph.Map() {
		layers = append(layers, layer)
	}
	return layers
}

func (d *Docker) IsLeaf(id ID) (bool, error) {
	heads := d.Graph.Heads()
	_, ok := heads[id.GraphID()]
	return ok, nil
}

func (d *Docker) GetAllLeaves() ([]ID, error) {
	heads := d.Graph.Heads()
	var result []ID

	for head := range heads {
		result = append(result, DockerImageID(head))
	}

	return result, nil
}

type ContainerID string
type DockerImageID string

type LocalImageID struct {
	Path         string
	ModifiedTime time.Time
}

type NamespacedLayerID struct {
	LayerID  ID
	CacheKey string
}

func NamespacedID(id ID, cacheKey string) NamespacedLayerID {
	return NamespacedLayerID{id, cacheKey}
}

func (c ContainerID) GraphID() string {
	return shaID(string(c))
}

func (d DockerImageID) GraphID() string {
	return string(d)
}

func (c LocalImageID) GraphID() string {
	return shaID(fmt.Sprintf("%s-%d", c.Path, c.ModifiedTime))
}

func (n NamespacedLayerID) GraphID() string {
	return shaID(n.LayerID.GraphID() + "@" + n.CacheKey)
}

func shaID(id string) string {
	if id == "" {
		return id
	}

	return fmt.Sprintf("%x", sha256.Sum256([]byte(id)))
}

type descriptor struct {
	image *image.Image
}

func (d descriptor) ID() string {
	return d.image.ID
}

func (d descriptor) Parent() string {
	return d.image.Parent
}

func (d descriptor) MarshalConfig() ([]byte, error) {
	return json.Marshal(d.image)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/gonum/plot"
	"github.com/gonum/plot/plotter"
	"github.com/gonum/plot/plotutil"
	"github.com/gonum/plot/vg"
)

func main() {
	fpath := flag.String("f", "data.txt", "data file path")
	dtype := flag.String("t", "density", "data type")
	flag.Parse()

	if *dtype != "density" {
		fmt.Fprintf(os.Stderr, "Unsupported data type: %s. Only support density.\n", dtype)
		os.Exit(1)
	}

	f, err := os.Open(*fpath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open file: %v\n", err)
		os.Exit(1)
	}

	plotDensity(parseDensity(f))
}

type densityResult struct {
	// x axis
	seconds int

	// y axis
	created int
	running int
	pending int
	waiting int
}

// wanted format:
// Nov 25 23:05:18.250: INFO: densityN-X Pods: 12000 out of 12000 created, 1012 running,
// 23 pending, 10965 waiting, 0 inactive, 0 terminating, 0 unknown, 0 runningButNotReady
func parseDensity(r io.Reader) (results []densityResult) {
	densityFormat := "Pods: %d out of %d created, %d running, %d pending, %d waiting, %s"
	//10 seconds interval
	interval := 10
	seconds := interval

	br := bufio.NewReader(r)
	for {
		var r densityResult
		var garbageString string
		var garbageInt int

		bytes, err := br.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			return results
		}

		line := strings.TrimSpace(string(bytes[:len(bytes)-1]))

		if !strings.HasSuffix(line, "runningButNotReady") {
			continue
		}

		pi := strings.Index(line, "Pods")
		if pi == -1 {
			fmt.Fprintln(os.Stderr, "Bad density format: cannot find Pods")
			os.Exit(1)
		}

		line = line[pi:]

		_, err = fmt.Sscanf(line, densityFormat, &r.created, &garbageInt, &r.running,
			&r.pending, &r.waiting, &garbageString)

		if err != nil {
			fmt.Fprintln(os.Stderr, "Bad density format:", err)
			os.Exit(1)
		}

		r.seconds = seconds
		seconds += interval

		results = append(results, r)
	}

	return results
}

func plotDensity(results []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Density"
	p.X.Label.Text = "Seconds"
	p.Y.Label.Text = "Number of Pods"

	err = plotutil.AddLinePoints(p,
		"Created", getCreatedPoints(results),
		"Running", getRunningPoints(results),
		"Pending", getPendingPoints(results),
		"Waiting", getWaitingPoints(results))
	if err != nil {
		panic(err)
	}

	// Save the plot to a PNG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density.svg")
}

func getCreatedPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].created)
	}
	return pts
}

func getRunningPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].running)
	}
	return pts
}

func getPendingPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].pending)
	}
	return pts
}

func getWaitingPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].waiting)
	}
	return pts
}
<commit_msg>logplot: plot rateVsPods<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/gonum/plot"
	"github.com/gonum/plot/plotter"
	"github.com/gonum/plot/plotutil"
	"github.com/gonum/plot/vg"
)

func main() {
	fpath := flag.String("f", "data.txt", "data file path")
	dtype := flag.String("t", "density", "data type")
	flag.Parse()

	if *dtype != "density" {
		fmt.Fprintf(os.Stderr, "Unsupported data type: %s. Only support density.\n", dtype)
		os.Exit(1)
	}

	f, err := os.Open(*fpath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open file: %v\n", err)
		os.Exit(1)
	}

	rs := parseDensity(f)
	plotDensity(rs)
	plotCreatingRateVsPods(rs)
	plotRunningRateVsPods(rs)
}

type densityResult struct {
	// x axis
	seconds int

	// y axis
	created int
	running int
	pending int
	waiting int
}

// wanted format:
// Nov 25 23:05:18.250: INFO: densityN-X Pods: 12000 out of 12000 created, 1012 running,
// 23 pending, 10965 waiting, 0 inactive, 0 terminating, 0 unknown, 0 runningButNotReady
func parseDensity(r io.Reader) (results []densityResult) {
	densityFormat := "Pods: %d out of %d created, %d running, %d pending, %d waiting, %s"
	//10 seconds interval
	interval := 10
	seconds := interval

	br := bufio.NewReader(r)
	for {
		var r densityResult
		var garbageString string
		var garbageInt int

		bytes, err := br.ReadBytes('\n')
		if err != nil {
			if err != io.EOF {
				panic(err)
			}
			return results
		}

		line := strings.TrimSpace(string(bytes[:len(bytes)-1]))

		if !strings.HasSuffix(line, "runningButNotReady") {
			continue
		}

		pi := strings.Index(line, "Pods")
		if pi == -1 {
			fmt.Fprintln(os.Stderr, "Bad density format: cannot find Pods")
			os.Exit(1)
		}

		line = line[pi:]

		_, err = fmt.Sscanf(line, densityFormat, &r.created, &garbageInt, &r.running,
			&r.pending, &r.waiting, &garbageString)

		if err != nil {
			fmt.Fprintln(os.Stderr, "Bad density format:", err)
			os.Exit(1)
		}

		r.seconds = seconds
		seconds += interval

		results = append(results, r)
	}

	return results
}

func plotDensity(results []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "Density"
	p.X.Label.Text = "Seconds"
	p.Y.Label.Text = "Number of Pods"

	err = plotutil.AddLinePoints(p,
		"Created", getCreatedPoints(results),
		"Running", getRunningPoints(results),
		"Pending", getPendingPoints(results),
		"Waiting", getWaitingPoints(results))
	if err != nil {
		panic(err)
	}

	// Save the plot to a SVG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density-all.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density-all.svg")
}

func plotCreatingRateVsPods(rs []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "CreatingRate"
	p.X.Label.Text = "Number of Pods"
	p.Y.Label.Text = "Rate"

	err = plotutil.AddLinePoints(p, "CreatingRate", getCreatingRatePoints(rs))
	if err != nil {
		panic(err)
	}

	// Save the plot to a SVG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density-creating-rate.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density-creating-rate.svg")
}

func plotRunningRateVsPods(rs []densityResult) {
	p, err := plot.New()
	if err != nil {
		panic(err)
	}

	p.Title.Text = "RunningRate"
	p.X.Label.Text = "Number of Pods"
	p.Y.Label.Text = "Rate"

	err = plotutil.AddLinePoints(p, "RunningRate", getRunningRatePoints(rs))
	if err != nil {
		panic(err)
	}

	// Save the plot to a SVG file.
	if err := p.Save(10*vg.Inch, 10*vg.Inch, "density-running-rate.svg"); err != nil {
		panic(err)
	}

	fmt.Println("successfully plotted density graph to density-running-rate.svg")
}

func getCreatedPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].created)
	}
	return pts
}

func getRunningPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].running)
	}
	return pts
}

func getPendingPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].pending)
	}
	return pts
}

func getWaitingPoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))

	for i := range rs {
		pts[i].X = float64(rs[i].seconds)
		pts[i].Y = float64(rs[i].waiting)
	}
	return pts
}

func getCreatingRatePoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))
	interval := 10

	for i := range rs {
		if i == 0 {
			continue
		}
		pts[i].X = float64(rs[i].created)
		pts[i].Y = float64(rs[i].created-rs[i-1].created) / float64(interval)
	}
	return pts
}

func getRunningRatePoints(rs []densityResult) plotter.XYs {
	pts := make(plotter.XYs, len(rs))
	interval := 10

	for i := range rs {
		if i == 0 {
			continue
		}
		pts[i].X = float64(rs[i].running)
		pts[i].Y = float64(rs[i].running-rs[i-1].running) / float64(interval)
	}
	return pts
}
<|endoftext|>


<commit_before>// +build rpi

/*
  Go Language Raspberry Pi Interface
  (c) Copyright David Thorpe 2016-2017
  All Rights Reserved

  Documentation http://djthorpe.github.io/gopi/
  For Licensing and Usage information, please see LICENSE.md
*/

package rpi

import (
	"fmt"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

type Model uint
type Processor uint
type Revision uint

type Product struct {
	model       Model
	processor   Processor
	revision    Revision
	warrantyBit bool
}

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	RPI_WARRANTY_MASK     uint32 = 0x03000000
	RPI_ENCODING_MASK     uint32 = 0x00800000
	RPI_REVISION_MASK     uint32 = 0x0000000F
	RPI_MODEL_MASK        uint32 = 0x00000FF0
	RPI_PROCESSOR_MASK    uint32 = 0x0000F000
	RPI_MANUFACTURER_MASK uint32 = 0x000F0000
	RPI_MEMORY_MASK       uint32 = 0x00700000
)

const (
	RPI_MODEL_A                Model = (0 << 4)
	RPI_MODEL_B                Model = (1 << 4)
	RPI_MODEL_A_PLUS           Model = (2 << 4)
	RPI_MODEL_B_PLUS           Model = (3 << 4)
	RPI_MODEL_B_PI_2           Model = (4 << 4)
	RPI_MODEL_ALPHA            Model = (5 << 4)
	RPI_MODEL_COMPUTE_MODULE   Model = (6 << 4)
	RPI_MODEL_ZERO             Model = (7 << 4)
	RPI_MODEL_B_PI_3           Model = (8 << 4)
	RPI_MODEL_COMPUTE_MODULE_3 Model = (9 << 4)
	RPI_MODEL_ZERO_W           Model = (10 << 4)
	RPI_MODEL_UNKNOWN          Model = (15 << 4)
)

const (
	RPI_PROCESSOR_UNKNOWN Processor = 0xFFFFFFFF
	RPI_PROCESSOR_BCM2835 Processor = (0 << 12)
	RPI_PROCESSOR_BCM2836 Processor = (1 << 12)
	RPI_PROCESSOR_BCM2837 Processor = (2 << 12)
)

const (
	RPI_REVISION_UNKNOWN Revision = 0
)

////////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES

var (
	productmap1 = map[uint32]Model{
		0x02: RPI_MODEL_B,
		0x03: RPI_MODEL_B,
		0x04: RPI_MODEL_B,
		0x05: RPI_MODEL_B,
		0x06: RPI_MODEL_B,
		0x07: RPI_MODEL_A,
		0x08: RPI_MODEL_A,
		0x09: RPI_MODEL_A,
		0x0D: RPI_MODEL_B,
		0x0E: RPI_MODEL_B,
		0x0F: RPI_MODEL_B,
		0x10: RPI_MODEL_B_PLUS,
		0x11: RPI_MODEL_COMPUTE_MODULE,
		0x12: RPI_MODEL_A_PLUS,
		0x13: RPI_MODEL_B_PLUS,
		0x14: RPI_MODEL_COMPUTE_MODULE,
		0x15: RPI_MODEL_A_PLUS,
	}
	pcbmap1 = map[uint32]Revision{
		0x02: Revision(1),
		0x03: Revision(1),
		0x04: Revision(2),
		0x05: Revision(2),
		0x06: Revision(2),
		0x07: Revision(2),
		0x08: Revision(2),
		0x09: Revision(2),
		0x0D: Revision(2),
		0x0E: Revision(2),
		0x0F: Revision(2),
		0x10: Revision(1),
		0x11: Revision(1),
		0x12: Revision(1),
		0x13: Revision(1),
		0x14: Revision(1),
		0x15: Revision(1),
	}
)

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

func (this *hardware) GetProduct() (*Product, error) {
	if r, err := this.GetRevisionUint32(); err != nil {
		return nil, err
	} else {
		model, revision := modelRevision(r)
		return &Product{model, processor(r), revision, warrantyBit(r)}, nil
	}
}

////////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS

// warrantyBit returns the value of the warranty bit
func warrantyBit(revision uint32) bool {
	return ((revision & uint32(RPI_WARRANTY_MASK)) != 0)
}

// modelRevision returns model and revision information
func modelRevision(revision uint32) (Model, Revision) {
	revision = revision & ^RPI_WARRANTY_MASK
	if (revision & RPI_ENCODING_MASK) != 0 {
		// Raspberry Pi 2 style revision coding
		return Model(revision & RPI_MODEL_MASK), Revision(revision & RPI_REVISION_MASK)
	} else {
		// Raspberry Pi 1 style revision coding
		if model, ok := productmap1[revision]; !ok {
			return RPI_MODEL_UNKNOWN, RPI_REVISION_UNKNOWN
		} else if pcb, ok := pcbmap1[revision]; !ok {
			return RPI_MODEL_UNKNOWN, RPI_REVISION_UNKNOWN
		} else {
			return model, pcb
		}
	}
}

// processor returns processor information
func processor(revision uint32) Processor {
	revision = revision & ^RPI_WARRANTY_MASK
	if (revision & RPI_ENCODING_MASK) != 0 {
		// Raspberry Pi 2 style revision coding
		return Processor(revision & RPI_PROCESSOR_MASK)
	} else {
		// Raspberry Pi 1 style revision coding
		return RPI_PROCESSOR_BCM2835
	}
}

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (p *Product) String() string {
	return fmt.Sprintf("sys.hw.rpi.Product{ model=%v processor=%v revision=%v warrantyBit=%v }", p.model, p.processor, p.revision, p.warrantyBit)
}

func (m Model) String() string {
	switch m {
	case RPI_MODEL_A:
		return "RPI_MODEL_A"
	case RPI_MODEL_B:
		return "RPI_MODEL_B"
	case RPI_MODEL_A_PLUS:
		return "RPI_MODEL_A_PLUS"
	case RPI_MODEL_B_PLUS:
		return "RPI_MODEL_B_PLUS"
	case RPI_MODEL_B_PI_2:
		return "RPI_MODEL_B_PI_2"
	case RPI_MODEL_B_PI_3:
		return "RPI_MODEL_B_PI_3"
	case RPI_MODEL_ALPHA:
		return "RPI_MODEL_ALPHA"
	case RPI_MODEL_COMPUTE_MODULE:
		return "RPI_MODEL_COMPUTE_MODULE"
	case RPI_MODEL_COMPUTE_MODULE_3:
		return "RPI_MODEL_COMPUTE_MODULE_3"
	case RPI_MODEL_ZERO:
		return "RPI_MODEL_ZERO"
	case RPI_MODEL_ZERO_W:
		return "RPI_MODEL_ZERO_W"
	default:
		return fmt.Sprintf("[?? Unknown Model value %v]", m)
	}
}

func (p Processor) String() string {
	switch p {
	case RPI_PROCESSOR_BCM2835:
		return "RPI_PROCESSOR_BCM2835"
	case RPI_PROCESSOR_BCM2836:
		return "RPI_PROCESSOR_BCM2836"
	case RPI_PROCESSOR_BCM2837:
		return "RPI_PROCESSOR_BCM2837"
	default:
		return "[?? Unknown Processor value]"
	}
}

func (p Revision) String() string {
	if p == RPI_REVISION_UNKNOWN {
		return "[?? Unknwon Revision value]"
	}
	return fmt.Sprintf("RPI_REVISION_V%v", uint(p))
}
<commit_msg>Debugging model<commit_after>// +build rpi

/*
  Go Language Raspberry Pi Interface
  (c) Copyright David Thorpe 2016-2017
  All Rights Reserved

  Documentation http://djthorpe.github.io/gopi/
  For Licensing and Usage information, please see LICENSE.md
*/

package rpi

import (
	"fmt"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

type Model uint
type Processor uint
type Revision uint

type Product struct {
	model       Model
	processor   Processor
	revision    Revision
	warrantyBit bool
}

////////////////////////////////////////////////////////////////////////////////
// CONSTANTS

const (
	RPI_WARRANTY_MASK     uint32 = 0x03000000
	RPI_ENCODING_MASK     uint32 = 0x00800000
	RPI_REVISION_MASK     uint32 = 0x0000000F
	RPI_MODEL_MASK        uint32 = 0x00000FF0
	RPI_PROCESSOR_MASK    uint32 = 0x0000F000
	RPI_MANUFACTURER_MASK uint32 = 0x000F0000
	RPI_MEMORY_MASK       uint32 = 0x00700000
)

const (
	RPI_MODEL_A                Model = (0 << 4)
	RPI_MODEL_B                Model = (1 << 4)
	RPI_MODEL_A_PLUS           Model = (2 << 4)
	RPI_MODEL_B_PLUS           Model = (3 << 4)
	RPI_MODEL_B_PI_2           Model = (4 << 4)
	RPI_MODEL_ALPHA            Model = (5 << 4)
	RPI_MODEL_COMPUTE_MODULE   Model = (6 << 4)
	RPI_MODEL_ZERO             Model = (7 << 4)
	RPI_MODEL_B_PI_3           Model = (8 << 4)
	RPI_MODEL_COMPUTE_MODULE_3 Model = (9 << 4)
	RPI_MODEL_ZERO_W           Model = (10 << 4)
	RPI_MODEL_UNKNOWN          Model = (15 << 4)
)

const (
	RPI_PROCESSOR_UNKNOWN Processor = 0xFFFFFFFF
	RPI_PROCESSOR_BCM2835 Processor = (0 << 12)
	RPI_PROCESSOR_BCM2836 Processor = (1 << 12)
	RPI_PROCESSOR_BCM2837 Processor = (2 << 12)
)

const (
	RPI_REVISION_UNKNOWN Revision = 0
)

////////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES

var (
	productmap1 = map[uint32]Model{
		0x02: RPI_MODEL_B,
		0x03: RPI_MODEL_B,
		0x04: RPI_MODEL_B,
		0x05: RPI_MODEL_B,
		0x06: RPI_MODEL_B,
		0x07: RPI_MODEL_A,
		0x08: RPI_MODEL_A,
		0x09: RPI_MODEL_A,
		0x0D: RPI_MODEL_B,
		0x0E: RPI_MODEL_B,
		0x0F: RPI_MODEL_B,
		0x10: RPI_MODEL_B_PLUS,
		0x11: RPI_MODEL_COMPUTE_MODULE,
		0x12: RPI_MODEL_A_PLUS,
		0x13: RPI_MODEL_B_PLUS,
		0x14: RPI_MODEL_COMPUTE_MODULE,
		0x15: RPI_MODEL_A_PLUS,
	}
	pcbmap1 = map[uint32]Revision{
		0x02: Revision(1),
		0x03: Revision(1),
		0x04: Revision(2),
		0x05: Revision(2),
		0x06: Revision(2),
		0x07: Revision(2),
		0x08: Revision(2),
		0x09: Revision(2),
		0x0D: Revision(2),
		0x0E: Revision(2),
		0x0F: Revision(2),
		0x10: Revision(1),
		0x11: Revision(1),
		0x12: Revision(1),
		0x13: Revision(1),
		0x14: Revision(1),
		0x15: Revision(1),
	}
)

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

func (this *hardware) GetProduct() (*Product, error) {
	if r, err := this.GetRevisionUint32(); err != nil {
		return nil, err
	} else {
		model, revision := modelRevision(r)
		return &Product{model, processor(r), revision, warrantyBit(r)}, nil
	}
}

////////////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS

// warrantyBit returns the value of the warranty bit
func warrantyBit(revision uint32) bool {
	return ((revision & uint32(RPI_WARRANTY_MASK)) != 0)
}

// modelRevision returns model and revision information
func modelRevision(revision uint32) (Model, Revision) {
	revision = revision & ^RPI_WARRANTY_MASK
	if (revision & RPI_ENCODING_MASK) != 0 {
		// Raspberry Pi 2 style revision coding
		return Model(revision & RPI_MODEL_MASK), Revision(revision & RPI_REVISION_MASK)
	} else {
		// Raspberry Pi 1 style revision coding
		if model, ok := productmap1[revision]; !ok {
			return RPI_MODEL_UNKNOWN, RPI_REVISION_UNKNOWN
		} else if pcb, ok := pcbmap1[revision]; !ok {
			return RPI_MODEL_UNKNOWN, RPI_REVISION_UNKNOWN
		} else {
			return model, pcb
		}
	}
}

// processor returns processor information
func processor(revision uint32) Processor {
	revision = revision & ^RPI_WARRANTY_MASK
	if (revision & RPI_ENCODING_MASK) != 0 {
		// Raspberry Pi 2 style revision coding
		return Processor(revision & RPI_PROCESSOR_MASK)
	} else {
		// Raspberry Pi 1 style revision coding
		return RPI_PROCESSOR_BCM2835
	}
}

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (p *Product) String() string {
	return fmt.Sprintf("sys.hw.rpi.Product{ model=%v processor=%v revision=%v warrantyBit=%v }", p.model, p.processor, p.revision, p.warrantyBit)
}

func (m Model) String() string {
	switch m {
	case RPI_MODEL_A:
		return "RPI_MODEL_A"
	case RPI_MODEL_B:
		return "RPI_MODEL_B"
	case RPI_MODEL_A_PLUS:
		return "RPI_MODEL_A_PLUS"
	case RPI_MODEL_B_PLUS:
		return "RPI_MODEL_B_PLUS"
	case RPI_MODEL_B_PI_2:
		return "RPI_MODEL_B_PI_2"
	case RPI_MODEL_B_PI_3:
		return "RPI_MODEL_B_PI_3"
	case RPI_MODEL_ALPHA:
		return "RPI_MODEL_ALPHA"
	case RPI_MODEL_COMPUTE_MODULE:
		return "RPI_MODEL_COMPUTE_MODULE"
	case RPI_MODEL_COMPUTE_MODULE_3:
		return "RPI_MODEL_COMPUTE_MODULE_3"
	case RPI_MODEL_ZERO:
		return "RPI_MODEL_ZERO"
	case RPI_MODEL_ZERO_W:
		return "RPI_MODEL_ZERO_W"
	default:
		return fmt.Sprintf("[?? Unknown Model value %d]", uint32(m))
	}
}

func (p Processor) String() string {
	switch p {
	case RPI_PROCESSOR_BCM2835:
		return "RPI_PROCESSOR_BCM2835"
	case RPI_PROCESSOR_BCM2836:
		return "RPI_PROCESSOR_BCM2836"
	case RPI_PROCESSOR_BCM2837:
		return "RPI_PROCESSOR_BCM2837"
	default:
		return "[?? Unknown Processor value]"
	}
}

func (p Revision) String() string {
	if p == RPI_REVISION_UNKNOWN {
		return "[?? Unknwon Revision value]"
	}
	return fmt.Sprintf("RPI_REVISION_V%v", uint(p))
}
<|endoftext|>


<commit_before>package main

const (
	// StatusOK means no problems.
	StatusOK = iota
	// StatusNoCredentials means wrong inputs to login.
	StatusNoCredentials = iota
	// StatusNoAuth means no or wrong auth token was passed.
	StatusNoAuth = iota
	// StatusAuthFailed means username or password was wrong, or account non-existent.
	StatusAuthFailed = iota
	// StatusNoAccess means the token given does not have access to the requested data.
	StatusNoAccess = iota
)

var messages = map[int]string{
	StatusOK:            "OK",
	StatusNoCredentials: "Missing username or password.",
	StatusNoAuth:        "No authorisation token provided.",
	StatusAuthFailed:    "Login failed.",
	StatusNoAccess:      "Not accessible with provided credentials.",
}
<commit_msg>Improved token-related error message.<commit_after>package main

const (
	// StatusOK means no problems.
	StatusOK = iota
	// StatusNoCredentials means wrong inputs to login.
	StatusNoCredentials = iota
	// StatusNoAuth means no or wrong auth token was passed.
	StatusNoAuth = iota
	// StatusAuthFailed means username or password was wrong, or account non-existent.
	StatusAuthFailed = iota
	// StatusNoAccess means the token given does not have access to the requested data.
	StatusNoAccess = iota
)

var messages = map[int]string{
	StatusOK:            "OK",
	StatusNoCredentials: "Missing username or password.",
	StatusNoAuth:        "No valid authorisation token provided.",
	StatusAuthFailed:    "Login failed.",
	StatusNoAccess:      "Not accessible with provided credentials.",
}
<|endoftext|>


<commit_before>package timber

import (
	"fmt"
	"log/syslog"
	"os"
	"time"
)

// Mapping from the timber levels to the syslog severity
// If you override this, make sure all the entries are in the map
// since the syslog.Priority zero value will cause a message at
// the Emergency severity
var DefaultSeverityMap = map[Level]syslog.Priority{
	NONE:     syslog.LOG_INFO,
	FINEST:   syslog.LOG_DEBUG,
	FINE:     syslog.LOG_DEBUG,
	DEBUG:    syslog.LOG_DEBUG,
	TRACE:    syslog.LOG_INFO,
	INFO:     syslog.LOG_INFO,
	WARNING:  syslog.LOG_WARNING,
	ERROR:    syslog.LOG_ERR,
	CRITICAL: syslog.LOG_CRIT,
}

// Syslog formatter wraps a PatFormatter but adds the
// syslog protocol format to the message.
// Defaults:
// Facility: syslog.LOG_USER (1 << 3 for pre-go1.1 compatibility)
// Hostname: os.Hostname()
// Tag: os.Args[0]
type SyslogFormatter struct {
	pf          *PatFormatter
	pid         int
	Hostname    string
	Tag         string
	Facility    syslog.Priority
	SeverityMap map[Level]syslog.Priority
}

func NewSyslogFormatter(format string) *SyslogFormatter {
	hostname, _ := os.Hostname()
	return &SyslogFormatter{NewPatFormatter(format), os.Getpid(), hostname, os.Args[0], syslog.Priority(1 << 3), DefaultSeverityMap}
}

func (sf *SyslogFormatter) Format(rec *LogRecord) string {
	msg := sf.pf.Format(rec)
	return fmt.Sprintf("<%d>%s %s %s[%d]: %s",
		sf.Facility|sf.SeverityMap[rec.Level],
		rec.Timestamp.Format(time.RFC3339),
		sf.Hostname,
		sf.Tag,
		sf.pid,
		msg)
}

<commit_msg>fuck you syslog for not having any reasonably documented format that works<commit_after>package timber

import (
	"fmt"
	"log/syslog"
	"os"
	"time"
)

// Mapping from the timber levels to the syslog severity
// If you override this, make sure all the entries are in the map
// since the syslog.Priority zero value will cause a message at
// the Emergency severity
var DefaultSeverityMap = map[Level]syslog.Priority{
	NONE:     syslog.LOG_INFO,
	FINEST:   syslog.LOG_DEBUG,
	FINE:     syslog.LOG_DEBUG,
	DEBUG:    syslog.LOG_DEBUG,
	TRACE:    syslog.LOG_INFO,
	INFO:     syslog.LOG_INFO,
	WARNING:  syslog.LOG_WARNING,
	ERROR:    syslog.LOG_ERR,
	CRITICAL: syslog.LOG_CRIT,
}

// Syslog formatter wraps a PatFormatter but adds the
// syslog protocol format to the message.
// Defaults:
// Facility: syslog.LOG_USER (1 << 3 for pre-go1.1 compatibility)
// Hostname: os.Hostname()
// Tag: os.Args[0]
type SyslogFormatter struct {
	pf          *PatFormatter
	pid         int
	Hostname    string
	Tag         string
	Facility    syslog.Priority
	SeverityMap map[Level]syslog.Priority
}

func NewSyslogFormatter(format string) *SyslogFormatter {
	hostname, _ := os.Hostname()
	return &SyslogFormatter{NewPatFormatter(format), os.Getpid(), hostname, os.Args[0], syslog.Priority(1 << 3), DefaultSeverityMap}
}

func (sf *SyslogFormatter) Format(rec *LogRecord) string {
	msg := sf.pf.Format(rec)
	return fmt.Sprintf("<%d>%s %s[%d]: %s",
		sf.Facility|sf.SeverityMap[rec.Level],
		rec.Timestamp.Format(time.Stamp),
		sf.Tag,
		sf.pid,
		msg)
}

<|endoftext|>