<commit_before>package main

import (
	"fmt"
	"github.com/segmentio/go-prompt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"strings"
)

type Config struct {
	Directory []string `yaml:"Directory"`
}

func reCreateDirectory(directory string) {
	if err := os.RemoveAll(directory); err != nil {
		fmt.Println(err)
	} else {
		os.Mkdir(directory, 0775)
	}
}

func removeDirectories(directories []string) {
	if ok := prompt.Confirm("Directories\n%s\n\nAre you sure you want to delete directories? ", strings.Join(directories, "\n")); !ok {
		println("Do nothing")
		return
	}

	for _, directory := range directories {
		go reCreateDirectory(directory)
	}
	fmt.Println("Have cleaned")
}

func readConfigFile() Config {
	configFile := os.Getenv("HOME") + "/.houki.yml"

	buf, err := ioutil.ReadFile(configFile)
	if err != nil {
		panic(err)
	}

	var parsedMap Config
	if err = yaml.Unmarshal(buf, &parsedMap); err != nil {
		panic(err)
	}

	return parsedMap
}

func main() {
	config := readConfigFile()
	removeDirectories(config.Directory)
}
<commit_msg>remove needless message<commit_after>package main

import (
	"fmt"
	"github.com/segmentio/go-prompt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"strings"
)

type Config struct {
	Directory []string `yaml:"Directory"`
}

func reCreateDirectory(directory string) {
	if err := os.RemoveAll(directory); err != nil {
		fmt.Println(err)
	} else {
		os.Mkdir(directory, 0775)
	}
}

func removeDirectories(directories []string) {
	if ok := prompt.Confirm("Directories\n%s\n\nAre you sure you want to delete directories? ", strings.Join(directories, "\n")); !ok {
		return
	}

	for _, directory := range directories {
		go reCreateDirectory(directory)
	}
	fmt.Println("Have cleaned")
}

func readConfigFile() Config {
	configFile := os.Getenv("HOME") + "/.houki.yml"

	buf, err := ioutil.ReadFile(configFile)
	if err != nil {
		panic(err)
	}

	var parsedMap Config
	if err = yaml.Unmarshal(buf, &parsedMap); err != nil {
		panic(err)
	}

	return parsedMap
}

func main() {
	config := readConfigFile()
	removeDirectories(config.Directory)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
)

// オプション
type options struct {
	host string // リモートホスト
}

// 実行コンテキスト
type context struct {
	host   string // リモートホスト
	path   string // 処理中のファイル
	lineno uint   // 処理中の行番号

	env     []string // 環境変数
	user    string   // ユーザ
	workdir string   // 作業ディレクトリ

	remote  bool     // リモート実行
	cmd_run []string // RUN命令
	cmd_add []string // ADD命令
}

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "usage: %s [options] [file...]\n", filepath.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

// コマンドの実行
func (ctx *context) execl(name string, arg ...string) (*exec.Cmd, error) {
	cmd := exec.Command(name, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if !ctx.remote {
		cmd.Env = append(cmd.Env, ctx.env...)
	}

	err := cmd.Run()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s:%d: %s : %s\n", ctx.path, ctx.lineno, err, arg)
	}

	return cmd, err
}

// 初期化
func (ctx *context) init() error {
	ctx.remote = (0 < len(ctx.host))

	if ctx.remote {
		ssh, err := exec.LookPath("ssh")
		if err != nil {
			return err
		}
		scp, err := exec.LookPath("scp")
		if err != nil {
			return err
		}
		ctx.cmd_run = []string{ssh, ctx.host}
		ctx.cmd_add = []string{scp}
	} else {
		ctx.cmd_run = []string{"/bin/sh", "-c"}
		ctx.cmd_add = []string{"/bin/cp"}
	}

	return nil
}

// RUN命令
func (ctx *context) run(arg string) (*exec.Cmd, error) {
	if 0 < len(ctx.workdir) {
		arg = fmt.Sprintf("cd %s; %s", ctx.workdir, arg)
	}

	return ctx.execl(ctx.cmd_run[0], append(ctx.cmd_run[1:], arg)...)
}

// ADD命令
func (ctx *context) add(src string, dst string) (*exec.Cmd, error) {
	if 0 < len(ctx.workdir) && !filepath.IsAbs(dst) {
		// コピー先のパスを生成する
		dst = filepath.Join(ctx.workdir, dst)
	}

	if ctx.remote {
		// リモート・パスを生成する
		dst = fmt.Sprintf("%s:%s", ctx.host, dst)
	}

	return ctx.execl(ctx.cmd_add[0], src, dst)
}

// ENV命令
func (ctx *context) set_env(key string, val string) {
	ctx.env = append(ctx.env, fmt.Sprintf("%s=%s", key, val))
}

// Dockerfile の実行
func runDockerfile(path string, opts *options) error {
	var file *os.File
	var err error

	if len(path) == 0 {
		file = os.Stdin
	} else {
		finfo, err := os.Stat(path)
		if err != nil {
			return err
		}

		if finfo.IsDir() {
			// ディレクトリの場合
			os.Chdir(path)
			path = "Dockerfile"
		}

		file, err = os.Open(path)
		if err != nil {
			// エラー処理をする
			return err
		}
		defer file.Close()
	}

	scanner := bufio.NewScanner(file)

	// 正規表現のコンパイル
	re := regexp.MustCompile("(?i)^ *(ONBUILD +)?([A-Z]+) +([^#]+)")
	re_args := regexp.MustCompile("(?i)^([^ ]+) +(.+)")

	ctx := context{host: opts.host, path: path}

	err = ctx.init()
	if err != nil {
		return err
	}

	for scanner.Scan() {
		line := scanner.Text()
		ctx.lineno += 1
		match := re.FindStringSubmatch(line)
		if match != nil {
			//onbuild := match[1]
			instruction := match[2]
			args := match[3]

			switch instruction {
			case "FROM":
				// 何もしない
			case "MAINTAINER":
				// 何もしない
			case "RUN":
				// スクリプトを実行
				_, err := ctx.run(args)
				if err != nil {
					return err
				}
			case "CMD":
			case "EXPOSE":
				// iptables があれば書換える
			case "ENV":
				// 環境変数を設定
				match_args := re_args.FindStringSubmatch(args)
				if match_args != nil {
					ctx.set_env(match_args[1], match_args[2])
				}
			case "ADD":
				// ファイルを追加
				match_args := re_args.FindStringSubmatch(args)
				if match_args != nil {
					_, err := ctx.add(match_args[1], match_args[2])
					if err != nil {
						return err
					}
				}
			case "ENTRYPOINT":
			case "VOLUME":
				// 何もしない
			case "USER":
				// ユーザを設定
				ctx.user = args
			case "WORKDIR":
				// 作業ディレクトリを変更
				ctx.workdir = args
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}

	return err
}

func main() {
	var opts options

	flag.StringVar(&opts.host, "H", "", "host")
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help {
		usage()
	}

	if len(flag.Args()) == 0 {
		runDockerfile(".", &opts)
	} else {
		for _, v := range flag.Args() {
			runDockerfile(v, &opts)
		}
	}
}
<commit_msg>err 変数の宣言を削除<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
)

// オプション
type options struct {
	host string // リモートホスト
}

// 実行コンテキスト
type context struct {
	host   string // リモートホスト
	path   string // 処理中のファイル
	lineno uint   // 処理中の行番号

	env     []string // 環境変数
	user    string   // ユーザ
	workdir string   // 作業ディレクトリ

	remote  bool     // リモート実行
	cmd_run []string // RUN命令
	cmd_add []string // ADD命令
}

// コマンドの使い方
func usage() {
	cmd := os.Args[0]
	fmt.Fprintf(os.Stderr, "usage: %s [options] [file...]\n", filepath.Base(cmd))
	flag.PrintDefaults()
	os.Exit(0)
}

// コマンドの実行
func (ctx *context) execl(name string, arg ...string) (*exec.Cmd, error) {
	cmd := exec.Command(name, arg...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if !ctx.remote {
		cmd.Env = append(cmd.Env, ctx.env...)
	}

	err := cmd.Run()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s:%d: %s : %s\n", ctx.path, ctx.lineno, err, arg)
	}

	return cmd, err
}

// 初期化
func (ctx *context) init() error {
	ctx.remote = (0 < len(ctx.host))

	if ctx.remote {
		ssh, err := exec.LookPath("ssh")
		if err != nil {
			return err
		}
		scp, err := exec.LookPath("scp")
		if err != nil {
			return err
		}
		ctx.cmd_run = []string{ssh, ctx.host}
		ctx.cmd_add = []string{scp}
	} else {
		ctx.cmd_run = []string{"/bin/sh", "-c"}
		ctx.cmd_add = []string{"/bin/cp"}
	}

	return nil
}

// RUN命令
func (ctx *context) run(arg string) (*exec.Cmd, error) {
	if 0 < len(ctx.workdir) {
		arg = fmt.Sprintf("cd %s; %s", ctx.workdir, arg)
	}

	return ctx.execl(ctx.cmd_run[0], append(ctx.cmd_run[1:], arg)...)
}

// ADD命令
func (ctx *context) add(src string, dst string) (*exec.Cmd, error) {
	if 0 < len(ctx.workdir) && !filepath.IsAbs(dst) {
		// コピー先のパスを生成する
		dst = filepath.Join(ctx.workdir, dst)
	}

	if ctx.remote {
		// リモート・パスを生成する
		dst = fmt.Sprintf("%s:%s", ctx.host, dst)
	}

	return ctx.execl(ctx.cmd_add[0], src, dst)
}

// ENV命令
func (ctx *context) set_env(key string, val string) {
	ctx.env = append(ctx.env, fmt.Sprintf("%s=%s", key, val))
}

// Dockerfile の実行
func runDockerfile(path string, opts *options) error {
	var file *os.File

	if len(path) == 0 {
		file = os.Stdin
	} else {
		finfo, err := os.Stat(path)
		if err != nil {
			return err
		}

		if finfo.IsDir() {
			// ディレクトリの場合
			os.Chdir(path)
			path = "Dockerfile"
		}

		file, err = os.Open(path)
		if err != nil {
			// エラー処理をする
			return err
		}
		defer file.Close()
	}

	scanner := bufio.NewScanner(file)

	// 正規表現のコンパイル
	re := regexp.MustCompile("(?i)^ *(ONBUILD +)?([A-Z]+) +([^#]+)")
	re_args := regexp.MustCompile("(?i)^([^ ]+) +(.+)")

	ctx := context{host: opts.host, path: path}

	err := ctx.init()
	if err != nil {
		return err
	}

	for scanner.Scan() {
		line := scanner.Text()
		ctx.lineno += 1
		match := re.FindStringSubmatch(line)
		if match != nil {
			//onbuild := match[1]
			instruction := match[2]
			args := match[3]

			switch instruction {
			case "FROM":
				// 何もしない
			case "MAINTAINER":
				// 何もしない
			case "RUN":
				// スクリプトを実行
				_, err := ctx.run(args)
				if err != nil {
					return err
				}
			case "CMD":
			case "EXPOSE":
				// iptables があれば書換える
			case "ENV":
				// 環境変数を設定
				match_args := re_args.FindStringSubmatch(args)
				if match_args != nil {
					ctx.set_env(match_args[1], match_args[2])
				}
			case "ADD":
				// ファイルを追加
				match_args := re_args.FindStringSubmatch(args)
				if match_args != nil {
					_, err := ctx.add(match_args[1], match_args[2])
					if err != nil {
						return err
					}
				}
			case "ENTRYPOINT":
			case "VOLUME":
				// 何もしない
			case "USER":
				// ユーザを設定
				ctx.user = args
			case "WORKDIR":
				// 作業ディレクトリを変更
				ctx.workdir = args
			}
		}
	}

	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}

	return err
}

func main() {
	var opts options

	flag.StringVar(&opts.host, "H", "", "host")
	help := flag.Bool("h", false, "help")
	flag.Parse()

	if *help {
		usage()
	}

	if len(flag.Args()) == 0 {
		runDockerfile(".", &opts)
	} else {
		for _, v := range flag.Args() {
			runDockerfile(v, &opts)
		}
	}
}
<|endoftext|>


<commit_before>package terraform

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/dag"

	"github.com/hashicorp/terraform/addrs"

	"github.com/hashicorp/terraform/config/configschema"
)

// GraphNodeAttachResourceSchema is an interface implemented by node types
// that need a resource schema attached.
type GraphNodeAttachResourceSchema interface {
	GraphNodeResource
	GraphNodeProviderConsumer

	AttachResourceSchema(*configschema.Block)
}

// GraphNodeAttachProviderConfigSchema is an interface implemented by node types
// that need a provider configuration schema attached.
type GraphNodeAttachProviderConfigSchema interface {
	GraphNodeProvider

	AttachProviderConfigSchema(*configschema.Block)
}

// AttachSchemaTransformer finds nodes that implement either
// GraphNodeAttachResourceSchema or GraphNodeAttachProviderConfigSchema, looks up
// the schema for each, and then passes it to a method implemented by the
// node.
type AttachSchemaTransformer struct {
	Components contextComponentFactory
}

func (t *AttachSchemaTransformer) Transform(g *Graph) error {

	// First we'll figure out which provider types we need to fetch schemas for.
	needProviders := make(map[string]struct{})
	for _, v := range g.Vertices() {
		switch tv := v.(type) {
		case GraphNodeAttachResourceSchema:
			providerAddr, _ := tv.ProvidedBy()
			needProviders[providerAddr.ProviderConfig.Type] = struct{}{}
		case GraphNodeAttachProviderConfigSchema:
			providerAddr := tv.ProviderAddr()
			needProviders[providerAddr.ProviderConfig.Type] = struct{}{}
		}
	}

	// Now we'll fetch each one. This requires us to temporarily instantiate
	// them, though this is not a full bootstrap since we don't yet have
	// configuration information; the providers will be re-instantiated and
	// properly configured during the graph walk.
	schemas := make(map[string]*ProviderSchema)
	for typeName := range needProviders {
		log.Printf("[TRACE] AttachSchemaTransformer: retrieving schema for provider type %q", typeName)
		provider, err := t.Components.ResourceProvider(typeName, "early/"+typeName)
		if err != nil {
			return fmt.Errorf("failed to instantiate provider %q to obtain schema: %s", typeName, err)
		}

		// FIXME: The provider interface is currently awkward in that it
		// requires us to tell the provider which resources types and data
		// sources we need. In future this will change to just return
		// everything available, but for now we'll fake that by fetching all
		// of the available names and then requesting them.
		resourceTypes := provider.Resources()
		dataSources := provider.DataSources()
		resourceTypeNames := make([]string, len(resourceTypes))
		for i, o := range resourceTypes {
			resourceTypeNames[i] = o.Name
		}
		dataSourceNames := make([]string, len(dataSources))
		for i, o := range dataSources {
			dataSourceNames[i] = o.Name
		}

		schema, err := provider.GetSchema(&ProviderSchemaRequest{
			ResourceTypes: resourceTypeNames,
			DataSources:   dataSourceNames,
		})
		if err != nil {
			return fmt.Errorf("failed to retrieve schema from provider %q: %s", typeName, err)
		}

		schemas[typeName] = schema

		if closer, ok := provider.(ResourceProviderCloser); ok {
			closer.Close()
		}
	}

	// Finally we'll once again visit all of the vertices and attach to
	// them the schemas we found for them.
	for _, v := range g.Vertices() {
		switch tv := v.(type) {
		case GraphNodeAttachResourceSchema:
			addr := tv.ResourceAddr()
			mode := addr.Resource.Mode
			typeName := addr.Resource.Type
			providerAddr, _ := tv.ProvidedBy()
			var schema *configschema.Block
			providerSchema := schemas[providerAddr.ProviderConfig.Type]
			if providerSchema == nil {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s because provider schema for %q is missing", addr, providerAddr.ProviderConfig.Type)
				continue
			}
			switch mode {
			case addrs.ManagedResourceMode:
				schema = providerSchema.ResourceTypes[typeName]
			case addrs.DataResourceMode:
				schema = providerSchema.DataSources[typeName]
			}
			if schema != nil {
				log.Printf("[TRACE] AttachSchemaTransformer: attaching schema to %s", dag.VertexName(v))
				tv.AttachResourceSchema(schema)
			} else {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s", addr)
			}
		case GraphNodeAttachProviderConfigSchema:
			providerAddr := tv.ProviderAddr()
			providerSchema := schemas[providerAddr.ProviderConfig.Type]
			if providerSchema == nil {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s because the whole provider schema is missing", providerAddr)
				continue
			}

			schema := schemas[providerAddr.ProviderConfig.Type].Provider

			if schema != nil {
				log.Printf("[TRACE] AttachSchemaTransformer: attaching schema to %s", dag.VertexName(v))
				tv.AttachProviderConfigSchema(schema)
			} else {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s", providerAddr)
			}
		}
	}

	return nil
}
<commit_msg>core: AttachSchemaTransformer fail gracefully with no schema<commit_after>package terraform

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/dag"

	"github.com/hashicorp/terraform/addrs"

	"github.com/hashicorp/terraform/config/configschema"
)

// GraphNodeAttachResourceSchema is an interface implemented by node types
// that need a resource schema attached.
type GraphNodeAttachResourceSchema interface {
	GraphNodeResource
	GraphNodeProviderConsumer

	AttachResourceSchema(*configschema.Block)
}

// GraphNodeAttachProviderConfigSchema is an interface implemented by node types
// that need a provider configuration schema attached.
type GraphNodeAttachProviderConfigSchema interface {
	GraphNodeProvider

	AttachProviderConfigSchema(*configschema.Block)
}

// AttachSchemaTransformer finds nodes that implement either
// GraphNodeAttachResourceSchema or GraphNodeAttachProviderConfigSchema, looks up
// the schema for each, and then passes it to a method implemented by the
// node.
type AttachSchemaTransformer struct {
	Components contextComponentFactory
}

func (t *AttachSchemaTransformer) Transform(g *Graph) error {

	if t.Components == nil {
		// Should never happen with a reasonable caller, but we'll return a
		// proper error here anyway so that we'll fail gracefully.
		return fmt.Errorf("AttachSchemaTransformer used with nil Components")
	}

	// First we'll figure out which provider types we need to fetch schemas for.
	needProviders := make(map[string]struct{})
	for _, v := range g.Vertices() {
		switch tv := v.(type) {
		case GraphNodeAttachResourceSchema:
			providerAddr, _ := tv.ProvidedBy()
			log.Printf("[TRACE] AttachSchemaTransformer: %q (%T) needs %s", dag.VertexName(v), v, providerAddr)
			needProviders[providerAddr.ProviderConfig.Type] = struct{}{}
		case GraphNodeAttachProviderConfigSchema:
			providerAddr := tv.ProviderAddr()
			log.Printf("[TRACE] AttachSchemaTransformer: %q (%T) needs %s", dag.VertexName(v), v, providerAddr)
			needProviders[providerAddr.ProviderConfig.Type] = struct{}{}
		}
	}

	// Now we'll fetch each one. This requires us to temporarily instantiate
	// them, though this is not a full bootstrap since we don't yet have
	// configuration information; the providers will be re-instantiated and
	// properly configured during the graph walk.
	schemas := make(map[string]*ProviderSchema)
	for typeName := range needProviders {
		log.Printf("[TRACE] AttachSchemaTransformer: retrieving schema for provider type %q", typeName)
		provider, err := t.Components.ResourceProvider(typeName, "early/"+typeName)
		if err != nil {
			return fmt.Errorf("failed to instantiate provider %q to obtain schema: %s", typeName, err)
		}

		// FIXME: The provider interface is currently awkward in that it
		// requires us to tell the provider which resources types and data
		// sources we need. In future this will change to just return
		// everything available, but for now we'll fake that by fetching all
		// of the available names and then requesting them.
		resourceTypes := provider.Resources()
		dataSources := provider.DataSources()
		resourceTypeNames := make([]string, len(resourceTypes))
		for i, o := range resourceTypes {
			resourceTypeNames[i] = o.Name
		}
		dataSourceNames := make([]string, len(dataSources))
		for i, o := range dataSources {
			dataSourceNames[i] = o.Name
		}

		schema, err := provider.GetSchema(&ProviderSchemaRequest{
			ResourceTypes: resourceTypeNames,
			DataSources:   dataSourceNames,
		})
		if err != nil {
			return fmt.Errorf("failed to retrieve schema from provider %q: %s", typeName, err)
		}

		schemas[typeName] = schema

		if closer, ok := provider.(ResourceProviderCloser); ok {
			closer.Close()
		}
	}

	// Finally we'll once again visit all of the vertices and attach to
	// them the schemas we found for them.
	for _, v := range g.Vertices() {
		switch tv := v.(type) {
		case GraphNodeAttachResourceSchema:
			addr := tv.ResourceAddr()
			mode := addr.Resource.Mode
			typeName := addr.Resource.Type
			providerAddr, _ := tv.ProvidedBy()
			var schema *configschema.Block
			providerSchema := schemas[providerAddr.ProviderConfig.Type]
			if providerSchema == nil {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s because provider schema for %q is missing", addr, providerAddr.ProviderConfig.Type)
				continue
			}
			switch mode {
			case addrs.ManagedResourceMode:
				schema = providerSchema.ResourceTypes[typeName]
			case addrs.DataResourceMode:
				schema = providerSchema.DataSources[typeName]
			}
			if schema != nil {
				log.Printf("[TRACE] AttachSchemaTransformer: attaching schema to %s", dag.VertexName(v))
				tv.AttachResourceSchema(schema)
			} else {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s", addr)
			}
		case GraphNodeAttachProviderConfigSchema:
			providerAddr := tv.ProviderAddr()
			providerSchema := schemas[providerAddr.ProviderConfig.Type]
			if providerSchema == nil {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s because the whole provider schema is missing", providerAddr)
				continue
			}

			schema := schemas[providerAddr.ProviderConfig.Type].Provider

			if schema != nil {
				log.Printf("[TRACE] AttachSchemaTransformer: attaching schema to %s", dag.VertexName(v))
				tv.AttachProviderConfigSchema(schema)
			} else {
				log.Printf("[ERROR] AttachSchemaTransformer: No schema available for %s", providerAddr)
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package classfile

import (
	"github.com/zxh0/jvm.go/jvmgo/jutil/bigendian"
)

type ClassReader struct {
	data []byte
}

func newClassReader(data []byte) *ClassReader {
	return &ClassReader{data}
}

func (self *ClassReader) readUint8() uint8 {
	val := self.data[0]
	self.data = self.data[1:]
	return val
}

func (self *ClassReader) readUint16() uint16 {
	val := bigendian.Uint16(self.data)
	self.data = self.data[2:]
	return val
}

func (self *ClassReader) readUint16s() []uint16 {
	n := self.readUint16()
	s := make([]uint16, n)
	for i := range s {
		s[i] = self.readUint16()
	}
	return s
}

func (self *ClassReader) readUint32() uint32 {
	val := bigendian.Int32(self.data)
	self.data = self.data[4:]
	return uint32(val)
}
func (self *ClassReader) readInt32() int32 {
	val := bigendian.Int32(self.data)
	self.data = self.data[4:]
	return val
}

func (self *ClassReader) readInt64() int64 {
	val := bigendian.Int64(self.data)
	self.data = self.data[8:]
	return val
}

func (self *ClassReader) readFloat32() float32 {
	val := bigendian.Float32(self.data)
	self.data = self.data[4:]
	return val
}

func (self *ClassReader) readFloat64() float64 {
	val := bigendian.Float64(self.data)
	self.data = self.data[8:]
	return val
}

func (self *ClassReader) readBytes(length uint32) []byte {
	bytes := self.data[:length]
	self.data = self.data[length:]
	return bytes
}

// todo
func (self *ClassReader) readString() string {
	length := uint32(self.readUint16())
	bytes := self.readBytes(length)
	return string(bytes)
}

// todo
// see java.io.DataInputStream.readUTF()
func (self *ClassReader) readMUTF8() string {
	return ""

	// int utflen = in.readUnsignedShort();
	// byte[] bytearr = null;
	// char[] chararr = null;
	// if (in instanceof DataInputStream) {
	//     DataInputStream dis = (DataInputStream)in;
	//     if (dis.bytearr.length < utflen){
	//         dis.bytearr = new byte[utflen*2];
	//         dis.chararr = new char[utflen*2];
	//     }
	//     chararr = dis.chararr;
	//     bytearr = dis.bytearr;
	// } else {
	//     bytearr = new byte[utflen];
	//     chararr = new char[utflen];
	// }

	// int c, char2, char3;
	// int count = 0;
	// int chararr_count=0;

	// in.readFully(bytearr, 0, utflen);

	// while (count < utflen) {
	//     c = (int) bytearr[count] & 0xff;
	//     if (c > 127) break;
	//     count++;
	//     chararr[chararr_count++]=(char)c;
	// }

	// while (count < utflen) {
	//     c = (int) bytearr[count] & 0xff;
	//     switch (c >> 4) {
	//         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
	//             /* 0xxxxxxx*/
	//             count++;
	//             chararr[chararr_count++]=(char)c;
	//             break;
	//         case 12: case 13:
	//             /* 110x xxxx   10xx xxxx*/
	//             count += 2;
	//             if (count > utflen)
	//                 throw new UTFDataFormatException(
	//                     "malformed input: partial character at end");
	//             char2 = (int) bytearr[count-1];
	//             if ((char2 & 0xC0) != 0x80)
	//                 throw new UTFDataFormatException(
	//                     "malformed input around byte " + count);
	//             chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
	//                                             (char2 & 0x3F));
	//             break;
	//         case 14:
	//             /* 1110 xxxx  10xx xxxx  10xx xxxx */
	//             count += 3;
	//             if (count > utflen)
	//                 throw new UTFDataFormatException(
	//                     "malformed input: partial character at end");
	//             char2 = (int) bytearr[count-2];
	//             char3 = (int) bytearr[count-1];
	//             if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
	//                 throw new UTFDataFormatException(
	//                     "malformed input around byte " + (count-1));
	//             chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
	//                                             ((char2 & 0x3F) << 6)  |
	//                                             ((char3 & 0x3F) << 0));
	//             break;
	//         default:
	//             /* 10xx xxxx,  1111 xxxx */
	//             throw new UTFDataFormatException(
	//                 "malformed input around byte " + count);
	//     }
	// }
	// // The number of chars produced may be less than utflen
	// return new String(chararr, 0, chararr_count);
}
<commit_msg>readMUTF8() ..<commit_after>package classfile

import (
	"github.com/zxh0/jvm.go/jvmgo/jutil/bigendian"
)

type ClassReader struct {
	data []byte
}

func newClassReader(data []byte) *ClassReader {
	return &ClassReader{data}
}

func (self *ClassReader) readUint8() uint8 {
	val := self.data[0]
	self.data = self.data[1:]
	return val
}

func (self *ClassReader) readUint16() uint16 {
	val := bigendian.Uint16(self.data)
	self.data = self.data[2:]
	return val
}

func (self *ClassReader) readUint16s() []uint16 {
	n := self.readUint16()
	s := make([]uint16, n)
	for i := range s {
		s[i] = self.readUint16()
	}
	return s
}

func (self *ClassReader) readUint32() uint32 {
	val := bigendian.Int32(self.data)
	self.data = self.data[4:]
	return uint32(val)
}
func (self *ClassReader) readInt32() int32 {
	val := bigendian.Int32(self.data)
	self.data = self.data[4:]
	return val
}

func (self *ClassReader) readInt64() int64 {
	val := bigendian.Int64(self.data)
	self.data = self.data[8:]
	return val
}

func (self *ClassReader) readFloat32() float32 {
	val := bigendian.Float32(self.data)
	self.data = self.data[4:]
	return val
}

func (self *ClassReader) readFloat64() float64 {
	val := bigendian.Float64(self.data)
	self.data = self.data[8:]
	return val
}

func (self *ClassReader) readBytes(length uint32) []byte {
	bytes := self.data[:length]
	self.data = self.data[length:]
	return bytes
}

// todo
func (self *ClassReader) readString() string {
	length := uint32(self.readUint16())
	bytes := self.readBytes(length)
	return string(bytes)
}

// todo
// see java.io.DataInputStream.readUTF(DataInput)
func (self *ClassReader) readMUTF8() string {

	utflen := uint32(self.readUint16())
	bytearr := self.readBytes(utflen)
	chararr := make([]uint16, utflen)

	var c, char2, char3 int32
	var count uint32 = 0
	var chararr_count int32 = 0

	for count < utflen {
		c = int32(bytearr[count])
		if c > 127 {
			break
		}
		count++
		chararr[chararr_count] = uint16(c)
		chararr_count++
	}
	println(char2, char3)
	// while (count < utflen) {
	//     c = (int) bytearr[count] & 0xff;
	//     switch (c >> 4) {
	//         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
	//             /* 0xxxxxxx*/
	//             count++;
	//             chararr[chararr_count++]=(char)c;
	//             break;
	//         case 12: case 13:
	//             /* 110x xxxx   10xx xxxx*/
	//             count += 2;
	//             if (count > utflen)
	//                 throw new UTFDataFormatException(
	//                     "malformed input: partial character at end");
	//             char2 = (int) bytearr[count-1];
	//             if ((char2 & 0xC0) != 0x80)
	//                 throw new UTFDataFormatException(
	//                     "malformed input around byte " + count);
	//             chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
	//                                             (char2 & 0x3F));
	//             break;
	//         case 14:
	//             /* 1110 xxxx  10xx xxxx  10xx xxxx */
	//             count += 3;
	//             if (count > utflen)
	//                 throw new UTFDataFormatException(
	//                     "malformed input: partial character at end");
	//             char2 = (int) bytearr[count-2];
	//             char3 = (int) bytearr[count-1];
	//             if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
	//                 throw new UTFDataFormatException(
	//                     "malformed input around byte " + (count-1));
	//             chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
	//                                             ((char2 & 0x3F) << 6)  |
	//                                             ((char3 & 0x3F) << 0));
	//             break;
	//         default:
	//             /* 10xx xxxx,  1111 xxxx */
	//             throw new UTFDataFormatException(
	//                 "malformed input around byte " + count);
	//     }
	// }
	// // The number of chars produced may be less than utflen
	// return new String(chararr, 0, chararr_count);
	return ""
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"strings"
)

var separator = os.Getenv("BRONZE_SEPARATOR")
var thinSeparator = os.Getenv("BRONZE_THIN_SEPARATOR")
var iconMode = os.Getenv("BRONZE_ICONS")
var icons = map[string]string{}

func init() {
	// set defaults
	if separator == "" {
		separator = "\ue0b0" // Powerline
	}
	if thinSeparator == "" {
		thinSeparator = "\ue0b1" // Powerline
	}
	if iconMode == "" {
		iconMode = "nerd"
	}

	switch iconMode {
	case "nerd":
		initIcon("apple", "\uf179")      // Font Awesome; apple
		initIcon("arch", "\uf300")       // Font Linux
		initIcon("centOS", "\uf301")     // Font Linux
		initIcon("debian", "\uf302")     // Font Linux
		initIcon("fedora", "\uf303")     // Font Linux
		initIcon("mint", "\uf304")       // Font Linux
		initIcon("SUSE", "\uf308")       // Font Linux
		initIcon("ubuntu", "\uf30c")     // Font Linux
		initIcon("elementary", "\uf311") // Font Linux
		initIcon("linux", "\uf17c")      // Font Awesome; linux
		initIcon("bsd", "\uf30e")        // Font Linux
		initIcon("root", "\ue00a")       // Pomicons; lightning
		initIcon("readonly", "\uf023")   // Font Awesome; lock
		initIcon("failed", "\ue009")     // Pomicons; exclamation
		initIcon("job", "\ue615")        // Seti UI
		initIcon("package", "\uf187")    // Font Awesome; archive
		initIcon("home", "\uf015")       // Font Awesome; home
		initIcon("github", "\uf09b")     // Font Awesome; github
		initIcon("gitlab", "\uf296")     // Font Awesome; gitlab
		initIcon("bitbucket", "\uf171")  // Font Awesome; bitbucket
		initIcon("git", "\ue0a0")        // Powerline
		initIcon("stash", "\uf01c")      // Font Awesome; inbox
		initIcon("ahead", "\uf148")      // Font Awesome; level-up
		initIcon("behind", "\uf149")     // Font Awesome; level-down
		initIcon("modified", "\u25cf")   // Unicode
		initIcon("staged", "\u271a")     // Unicode
	case "unicode":
		// TODO: test if it's possible to use \uf8ff on an Apple machine
		initIcon("apple", "\U0001f34e") // Emoji; red apple
		initIcon("arch", "")
		initIcon("centOS", "")
		initIcon("debian", "")
		initIcon("fedora", "")
		initIcon("mint", "")
		initIcon("SUSE", "")
		initIcon("ubuntu", "")
		initIcon("elementary", "")
		initIcon("linux", "\U0001f427") // Emoji; penguin
		initIcon("bsd", "")
		initIcon("root", "\u26a1")         // Emoji; high voltage
		initIcon("readonly", "\U0001f512") // Emoji; locked
		initIcon("failed", "\u2757")       // Emoji; exclamation mark
		initIcon("job", "\u2699")          // Emoji; gear
		initIcon("package", "\U0001f4e6")  // Emoji; package
		initIcon("home", "\U0001f3e0")     // Emoji; house
		initIcon("github", "")
		initIcon("gitlab", "")
		initIcon("bitbucket", "")
		initIcon("git", "")
		initIcon("stash", "\U0001f4e5") // Emoji; inbox tray
		initIcon("ahead", "\u2191")     // Unicode
		initIcon("behind", "\u2193")    // Unicode
		initIcon("modified", "\u25cf")  // Unicode
		initIcon("staged", "\u271a")    // Unicode
	case "ascii":
		initIcon("apple", "")
		initIcon("arch", "")
		initIcon("centOS", "")
		initIcon("debian", "")
		initIcon("fedora", "")
		initIcon("mint", "")
		initIcon("SUSE", "")
		initIcon("ubuntu", "")
		initIcon("elementary", "")
		initIcon("linux", "")
		initIcon("bsd", "")
		initIcon("root", "#")
		initIcon("readonly", "@")
		initIcon("failed", "!")
		initIcon("job", "&")
		initIcon("package", "")
		initIcon("home", "~")
		initIcon("github", "")
		initIcon("gitlab", "")
		initIcon("bitbucket", "")
		initIcon("git", "")
		initIcon("stash", "#")
		initIcon("ahead", ">")
		initIcon("behind", "<")
		initIcon("modified", "*")
		initIcon("staged", "+")
	}
}

func initIcon(name, defaultValue string) {
	env := os.Getenv("BRONZE_ICON_" + strings.ToUpper(name))
	if env == "" {
		icons[name] = defaultValue
	} else {
		icons[name] = env
	}
}
<commit_msg>added bsd unicode icon<commit_after>package main

import (
	"os"
	"strings"
)

var separator = os.Getenv("BRONZE_SEPARATOR")
var thinSeparator = os.Getenv("BRONZE_THIN_SEPARATOR")
var iconMode = os.Getenv("BRONZE_ICONS")
var icons = map[string]string{}

func init() {
	// set defaults
	if separator == "" {
		separator = "\ue0b0" // Powerline
	}
	if thinSeparator == "" {
		thinSeparator = "\ue0b1" // Powerline
	}
	if iconMode == "" {
		iconMode = "nerd"
	}

	switch iconMode {
	case "nerd":
		initIcon("apple", "\uf179")      // Font Awesome; apple
		initIcon("arch", "\uf300")       // Font Linux
		initIcon("centOS", "\uf301")     // Font Linux
		initIcon("debian", "\uf302")     // Font Linux
		initIcon("fedora", "\uf303")     // Font Linux
		initIcon("mint", "\uf304")       // Font Linux
		initIcon("SUSE", "\uf308")       // Font Linux
		initIcon("ubuntu", "\uf30c")     // Font Linux
		initIcon("elementary", "\uf311") // Font Linux
		initIcon("linux", "\uf17c")      // Font Awesome; linux
		initIcon("bsd", "\uf30e")        // Font Linux
		initIcon("root", "\ue00a")       // Pomicons; lightning
		initIcon("readonly", "\uf023")   // Font Awesome; lock
		initIcon("failed", "\ue009")     // Pomicons; exclamation
		initIcon("job", "\ue615")        // Seti UI
		initIcon("package", "\uf187")    // Font Awesome; archive
		initIcon("home", "\uf015")       // Font Awesome; home
		initIcon("github", "\uf09b")     // Font Awesome; github
		initIcon("gitlab", "\uf296")     // Font Awesome; gitlab
		initIcon("bitbucket", "\uf171")  // Font Awesome; bitbucket
		initIcon("git", "\ue0a0")        // Powerline
		initIcon("stash", "\uf01c")      // Font Awesome; inbox
		initIcon("ahead", "\uf148")      // Font Awesome; level-up
		initIcon("behind", "\uf149")     // Font Awesome; level-down
		initIcon("modified", "\u25cf")   // Unicode
		initIcon("staged", "\u271a")     // Unicode
	case "unicode":
		// TODO: test if it's possible to use \uf8ff on an Apple machine
		initIcon("apple", "\U0001f34e") // Emoji; red apple
		initIcon("arch", "")
		initIcon("centOS", "")
		initIcon("debian", "")
		initIcon("fedora", "")
		initIcon("mint", "")
		initIcon("SUSE", "")
		initIcon("ubuntu", "")
		initIcon("elementary", "")
		initIcon("linux", "\U0001f427")    // Emoji; penguin
		initIcon("bsd", "\U0001f608")      // Emoji; smiling face with horns
		initIcon("root", "\u26a1")         // Emoji; high voltage
		initIcon("readonly", "\U0001f512") // Emoji; locked
		initIcon("failed", "\u2757")       // Emoji; exclamation mark
		initIcon("job", "\u2699")          // Emoji; gear
		initIcon("package", "\U0001f4e6")  // Emoji; package
		initIcon("home", "\U0001f3e0")     // Emoji; house
		initIcon("github", "")
		initIcon("gitlab", "")
		initIcon("bitbucket", "")
		initIcon("git", "")
		initIcon("stash", "\U0001f4e5") // Emoji; inbox tray
		initIcon("ahead", "\u2191")     // Unicode
		initIcon("behind", "\u2193")    // Unicode
		initIcon("modified", "\u25cf")  // Unicode
		initIcon("staged", "\u271a")    // Unicode
	case "ascii":
		initIcon("apple", "")
		initIcon("arch", "")
		initIcon("centOS", "")
		initIcon("debian", "")
		initIcon("fedora", "")
		initIcon("mint", "")
		initIcon("SUSE", "")
		initIcon("ubuntu", "")
		initIcon("elementary", "")
		initIcon("linux", "")
		initIcon("bsd", "")
		initIcon("root", "#")
		initIcon("readonly", "@")
		initIcon("failed", "!")
		initIcon("job", "&")
		initIcon("package", "")
		initIcon("home", "~")
		initIcon("github", "")
		initIcon("gitlab", "")
		initIcon("bitbucket", "")
		initIcon("git", "")
		initIcon("stash", "#")
		initIcon("ahead", ">")
		initIcon("behind", "<")
		initIcon("modified", "*")
		initIcon("staged", "+")
	}
}

func initIcon(name, defaultValue string) {
	env := os.Getenv("BRONZE_ICON_" + strings.ToUpper(name))
	if env == "" {
		icons[name] = defaultValue
	} else {
		icons[name] = env
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ebiten

import (
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"runtime"
	"sync"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
	"github.com/hajimehoshi/ebiten/internal/loop"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

var (
	imageM sync.Mutex
)

type images struct {
	images map[*imageImpl]struct{}
	m      sync.Mutex
}

var theImages = images{
	images: map[*imageImpl]struct{}{},
}

func (i *images) add(img *imageImpl) (*Image, error) {
	i.m.Lock()
	defer i.m.Unlock()
	i.images[img] = struct{}{}
	eimg := &Image{img}
	runtime.SetFinalizer(eimg, theImages.remove)
	return eimg, nil
}

func (i *images) remove(img *Image) {
	i.m.Lock()
	defer i.m.Unlock()
	delete(i.images, img.impl)
}

func (i *images) savePixels(context *opengl.Context, exceptions map[*imageImpl]struct{}) error {
	i.m.Lock()
	defer i.m.Unlock()
	for img := range i.images {
		if _, ok := exceptions[img]; ok {
			continue
		}
		if img.isDisposed() {
			continue
		}
		if err := img.savePixels(context); err != nil {
			return err
		}
	}
	return nil
}

func (i *images) restorePixels(context *opengl.Context) error {
	i.m.Lock()
	defer i.m.Unlock()
	for img := range i.images {
		if img.defaultFramebuffer {
			continue
		}
		if img.isDisposed() {
			continue
		}
		if err := img.image.Dispose(); err != nil {
			return err
		}
	}
	for img := range i.images {
		if err := img.restorePixels(context); err != nil {
			return err
		}
	}
	return nil
}

// Image represents an image.
// The pixel format is alpha-premultiplied.
// Image implements image.Image.
type Image struct {
	impl *imageImpl
}

// Size returns the size of the image.
//
// This function is concurrent-safe.
func (i *Image) Size() (width, height int) {
	return i.impl.width, i.impl.height
}

// Clear resets the pixels of the image into 0.
//
// This function is concurrent-safe.
func (i *Image) Clear() error {
	return i.impl.Fill(color.Transparent)
}

// Fill fills the image with a solid color.
//
// This function is concurrent-safe.
func (i *Image) Fill(clr color.Color) error {
	return i.impl.Fill(clr)
}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     ImageParts:    (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
//                    (i.e. the whole source image)
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// Note that this function returns immediately and actual drawing is done lazily.
//
// This function is concurrent-safe.
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
	return i.impl.DrawImage(image, options)
}

// Bounds returns the bounds of the image.
//
// This function is concurrent-safe.
func (i *Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, i.impl.width, i.impl.height)
}

// ColorModel returns the color model of the image.
//
// This function is concurrent-safe.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from VRAM to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
//
// This function is concurrent-safe.
func (i *Image) At(x, y int) color.Color {
	return i.impl.At(x, y)
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// This function is concurrent-safe.
func (i *Image) Dispose() error {
	return i.impl.Dispose()
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// This function may be slow (as for implementation, this calls glTexSubImage2D).
//
// This function is concurrent-safe.
func (i *Image) ReplacePixels(p []uint8) error {
	return i.impl.ReplacePixels(p)
}

type imageImpl struct {
	image              *graphics.Image
	defaultFramebuffer bool
	disposed           bool
	width              int
	height             int
	filter             Filter
	pixels             []uint8
}

func (i *imageImpl) Fill(clr color.Color) error {
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	i.pixels = nil
	return i.image.Fill(clr)
}

func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	if parts == nil {
		// Check options.Parts for backward-compatibility.
		dparts := options.Parts
		if dparts != nil {
			parts = imageParts(dparts)
		} else {
			parts = &wholeImage{image.impl.width, image.impl.height}
		}
	}
	quads := &textureQuads{parts: parts, width: image.impl.width, height: image.impl.height}
	// TODO: Reuse one vertices instead of making here, but this would need locking.
	vertices := make([]int16, parts.Len()*16)
	n := quads.vertices(vertices)
	if n == 0 {
		return nil
	}
	if i == image.impl {
		return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	i.pixels = nil
	geom := &options.GeoM
	colorm := &options.ColorM
	mode := opengl.CompositeMode(options.CompositeMode)
	if err := i.image.DrawImage(image.impl.image, vertices[:16*n], geom, colorm, mode); err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) At(x, y int) color.Color {
	if !loop.IsRunning() {
		panic("ebiten: At can't be called when the GL context is not initialized (this panic happens as of version 1.4.0-alpha)")
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return color.Transparent
	}
	if i.pixels == nil {
		var err error
		i.pixels, err = i.image.Pixels(ui.GLContext())
		if err != nil {
			panic(err)
		}
	}
	idx := 4*x + 4*y*i.width
	r, g, b, a := i.pixels[idx], i.pixels[idx+1], i.pixels[idx+2], i.pixels[idx+3]
	return color.RGBA{r, g, b, a}
}

func (i *imageImpl) savePixels(context *opengl.Context) error {
	if i.pixels != nil {
		return nil
	}
	var err error
	i.pixels, err = i.image.Pixels(context)
	if err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) restorePixels(context *opengl.Context) error {
	if i.defaultFramebuffer {
		return nil
	}
	if i.disposed {
		return nil
	}
	if i.pixels != nil {
		img := image.NewRGBA(image.Rect(0, 0, i.width, i.height))
		for j := 0; j < i.height; j++ {
			copy(img.Pix[j*img.Stride:], i.pixels[j*i.width*4:(j+1)*i.width*4])
		}
		var err error
		i.image, err = graphics.NewImageFromImage(img, glFilter(context, i.filter))
		if err != nil {
			return err
		}
		return nil
	}
	var err error
	i.image, err = graphics.NewImage(i.width, i.height, glFilter(context, i.filter))
	if err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) Dispose() error {
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	if err := i.image.Dispose(); err != nil {
		return err
	}
	i.image = nil
	i.disposed = true
	i.pixels = nil
	runtime.SetFinalizer(i, nil)
	return nil
}

func (i *imageImpl) isDisposed() bool {
	return i.disposed
}

func (i *imageImpl) ReplacePixels(p []uint8) error {
	if l := 4 * i.width * i.height; len(p) != l {
		return fmt.Errorf("ebiten: p's length must be %d", l)
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.pixels == nil {
		i.pixels = make([]uint8, len(p))
	}
	copy(i.pixels, p)
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	return i.image.ReplacePixels(p)
}

func (i *imageImpl) isInvalidated(context *opengl.Context) bool {
	return i.image.IsInvalidated(context)
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	ImageParts    ImageParts
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.1.0-alpha): Use ImageParts instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// NewImage generates a new texture and a new framebuffer.
//
// This function is concurrent-safe.
func NewImage(width, height int, filter Filter) (*Image, error) {
	image := &imageImpl{
		width:  width,
		height: height,
		filter: filter,
	}
	imageM.Lock()
	defer imageM.Unlock()
	eimg, err := theImages.add(image)
	if err != nil {
		return nil, err
	}
	image.image, err = graphics.NewImage(width, height, glFilter(ui.GLContext(), filter))
	if err != nil {
		return nil, err
	}
	runtime.SetFinalizer(image, (*imageImpl).Dispose)
	if err := image.image.Fill(color.Transparent); err != nil {
		return nil, err
	}
	return eimg, nil
}

// NewImageFromImage creates a new image with the given image (source).
//
// NewImageFromImage generates a new texture and a new framebuffer.
//
// This function is concurrent-safe.
func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
	size := source.Bounds().Size()
	w, h := size.X, size.Y
	// TODO: Return error when the image is too big!
	// Don't lock while manipulating an image.Image interface.
	rgbaImg, ok := source.(*image.RGBA)
	if !ok || source.Bounds().Min != image.ZP {
		origImg := source
		newImg := image.NewRGBA(origImg.Bounds())
		draw.Draw(newImg, newImg.Bounds(), origImg, origImg.Bounds().Min, draw.Src)
		rgbaImg = newImg
	}
	pixels := make([]uint8, 4*w*h)
	for j := 0; j < h; j++ {
		copy(pixels[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:])
	}
	imageM.Lock()
	defer imageM.Unlock()
	img := &imageImpl{
		width:  w,
		height: h,
		filter: filter,
		pixels: pixels,
	}
	var err error
	img.image, err = graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter))
	if err != nil {
		// TODO: texture should be removed here?
		return nil, err
	}
	runtime.SetFinalizer(img, (*imageImpl).Dispose)
	eimg, err := theImages.add(img)
	if err != nil {
		return nil, err
	}
	return eimg, nil
}

func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
	img, err := newImageWithZeroFramebufferImpl(width, height)
	if err != nil {
		return nil, err
	}
	return img, nil
}

func newImageWithZeroFramebufferImpl(width, height int) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	i, err := graphics.NewZeroFramebufferImage(width, height)
	if err != nil {
		return nil, err
	}
	img := &imageImpl{
		image:              i,
		width:              width,
		height:             height,
		defaultFramebuffer: true,
	}
	eimg, err := theImages.add(img)
	if err != nil {
		return nil, err
	}
	runtime.SetFinalizer(img, (*imageImpl).Dispose)
	return eimg, nil
}
<commit_msg>graphics: Refactoring: Remove unneeded function<commit_after>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ebiten

import (
	"errors"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"runtime"
	"sync"

	"github.com/hajimehoshi/ebiten/internal/graphics"
	"github.com/hajimehoshi/ebiten/internal/graphics/opengl"
	"github.com/hajimehoshi/ebiten/internal/loop"
	"github.com/hajimehoshi/ebiten/internal/ui"
)

var (
	imageM sync.Mutex
)

type images struct {
	images map[*imageImpl]struct{}
	m      sync.Mutex
}

var theImages = images{
	images: map[*imageImpl]struct{}{},
}

func (i *images) add(img *imageImpl) (*Image, error) {
	i.m.Lock()
	defer i.m.Unlock()
	i.images[img] = struct{}{}
	eimg := &Image{img}
	runtime.SetFinalizer(eimg, theImages.remove)
	return eimg, nil
}

func (i *images) remove(img *Image) {
	i.m.Lock()
	defer i.m.Unlock()
	delete(i.images, img.impl)
}

func (i *images) savePixels(context *opengl.Context, exceptions map[*imageImpl]struct{}) error {
	i.m.Lock()
	defer i.m.Unlock()
	for img := range i.images {
		if _, ok := exceptions[img]; ok {
			continue
		}
		if img.isDisposed() {
			continue
		}
		if err := img.savePixels(context); err != nil {
			return err
		}
	}
	return nil
}

func (i *images) restorePixels(context *opengl.Context) error {
	i.m.Lock()
	defer i.m.Unlock()
	for img := range i.images {
		if img.defaultFramebuffer {
			continue
		}
		if img.isDisposed() {
			continue
		}
		if err := img.image.Dispose(); err != nil {
			return err
		}
	}
	for img := range i.images {
		if err := img.restorePixels(context); err != nil {
			return err
		}
	}
	return nil
}

// Image represents an image.
// The pixel format is alpha-premultiplied.
// Image implements image.Image.
type Image struct {
	impl *imageImpl
}

// Size returns the size of the image.
//
// This function is concurrent-safe.
func (i *Image) Size() (width, height int) {
	return i.impl.width, i.impl.height
}

// Clear resets the pixels of the image into 0.
//
// This function is concurrent-safe.
func (i *Image) Clear() error {
	return i.impl.Fill(color.Transparent)
}

// Fill fills the image with a solid color.
//
// This function is concurrent-safe.
func (i *Image) Fill(clr color.Color) error {
	return i.impl.Fill(clr)
}

// DrawImage draws the given image on the receiver image.
//
// This method accepts the options.
// The parts of the given image at the parts of the destination.
// After determining parts to draw, this applies the geometry matrix and the color matrix.
//
// Here are the default values:
//     ImageParts:    (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
//                    (i.e. the whole source image)
//     GeoM:          Identity matrix
//     ColorM:        Identity matrix (that changes no colors)
//     CompositeMode: CompositeModeSourceOver (regular alpha blending)
//
// Note that this function returns immediately and actual drawing is done lazily.
//
// This function is concurrent-safe.
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
	return i.impl.DrawImage(image, options)
}

// Bounds returns the bounds of the image.
//
// This function is concurrent-safe.
func (i *Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, i.impl.width, i.impl.height)
}

// ColorModel returns the color model of the image.
//
// This function is concurrent-safe.
func (i *Image) ColorModel() color.Model {
	return color.RGBAModel
}

// At returns the color of the image at (x, y).
//
// This method loads pixels from VRAM to system memory if necessary.
//
// This method can't be called before the main loop (ebiten.Run) starts (as of version 1.4.0-alpha).
//
// This function is concurrent-safe.
func (i *Image) At(x, y int) color.Color {
	return i.impl.At(x, y)
}

// Dispose disposes the image data. After disposing, the image becomes invalid.
// This is useful to save memory.
//
// The behavior of any functions for a disposed image is undefined.
//
// This function is concurrent-safe.
func (i *Image) Dispose() error {
	return i.impl.Dispose()
}

// ReplacePixels replaces the pixels of the image with p.
//
// The given p must represent RGBA pre-multiplied alpha values. len(p) must equal to 4 * (image width) * (image height).
//
// This function may be slow (as for implementation, this calls glTexSubImage2D).
//
// This function is concurrent-safe.
func (i *Image) ReplacePixels(p []uint8) error {
	return i.impl.ReplacePixels(p)
}

type imageImpl struct {
	image              *graphics.Image
	defaultFramebuffer bool
	disposed           bool
	width              int
	height             int
	filter             Filter
	pixels             []uint8
}

func (i *imageImpl) Fill(clr color.Color) error {
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	i.pixels = nil
	return i.image.Fill(clr)
}

func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
	// Calculate vertices before locking because the user can do anything in
	// options.ImageParts interface without deadlock (e.g. Call Image functions).
	if options == nil {
		options = &DrawImageOptions{}
	}
	parts := options.ImageParts
	if parts == nil {
		// Check options.Parts for backward-compatibility.
		dparts := options.Parts
		if dparts != nil {
			parts = imageParts(dparts)
		} else {
			parts = &wholeImage{image.impl.width, image.impl.height}
		}
	}
	quads := &textureQuads{parts: parts, width: image.impl.width, height: image.impl.height}
	// TODO: Reuse one vertices instead of making here, but this would need locking.
	vertices := make([]int16, parts.Len()*16)
	n := quads.vertices(vertices)
	if n == 0 {
		return nil
	}
	if i == image.impl {
		return errors.New("ebiten: Image.DrawImage: image should be different from the receiver")
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	i.pixels = nil
	geom := &options.GeoM
	colorm := &options.ColorM
	mode := opengl.CompositeMode(options.CompositeMode)
	if err := i.image.DrawImage(image.impl.image, vertices[:16*n], geom, colorm, mode); err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) At(x, y int) color.Color {
	if !loop.IsRunning() {
		panic("ebiten: At can't be called when the GL context is not initialized (this panic happens as of version 1.4.0-alpha)")
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return color.Transparent
	}
	if i.pixels == nil {
		var err error
		i.pixels, err = i.image.Pixels(ui.GLContext())
		if err != nil {
			panic(err)
		}
	}
	idx := 4*x + 4*y*i.width
	r, g, b, a := i.pixels[idx], i.pixels[idx+1], i.pixels[idx+2], i.pixels[idx+3]
	return color.RGBA{r, g, b, a}
}

func (i *imageImpl) savePixels(context *opengl.Context) error {
	if i.pixels != nil {
		return nil
	}
	var err error
	i.pixels, err = i.image.Pixels(context)
	if err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) restorePixels(context *opengl.Context) error {
	if i.defaultFramebuffer {
		return nil
	}
	if i.disposed {
		return nil
	}
	if i.pixels != nil {
		img := image.NewRGBA(image.Rect(0, 0, i.width, i.height))
		for j := 0; j < i.height; j++ {
			copy(img.Pix[j*img.Stride:], i.pixels[j*i.width*4:(j+1)*i.width*4])
		}
		var err error
		i.image, err = graphics.NewImageFromImage(img, glFilter(context, i.filter))
		if err != nil {
			return err
		}
		return nil
	}
	var err error
	i.image, err = graphics.NewImage(i.width, i.height, glFilter(context, i.filter))
	if err != nil {
		return err
	}
	return nil
}

func (i *imageImpl) Dispose() error {
	imageM.Lock()
	defer imageM.Unlock()
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	if err := i.image.Dispose(); err != nil {
		return err
	}
	i.image = nil
	i.disposed = true
	i.pixels = nil
	runtime.SetFinalizer(i, nil)
	return nil
}

func (i *imageImpl) isDisposed() bool {
	return i.disposed
}

func (i *imageImpl) ReplacePixels(p []uint8) error {
	if l := 4 * i.width * i.height; len(p) != l {
		return fmt.Errorf("ebiten: p's length must be %d", l)
	}
	imageM.Lock()
	defer imageM.Unlock()
	if i.pixels == nil {
		i.pixels = make([]uint8, len(p))
	}
	copy(i.pixels, p)
	if i.isDisposed() {
		return errors.New("ebiten: image is already disposed")
	}
	return i.image.ReplacePixels(p)
}

func (i *imageImpl) isInvalidated(context *opengl.Context) bool {
	return i.image.IsInvalidated(context)
}

// A DrawImageOptions represents options to render an image on an image.
type DrawImageOptions struct {
	ImageParts    ImageParts
	GeoM          GeoM
	ColorM        ColorM
	CompositeMode CompositeMode

	// Deprecated (as of 1.1.0-alpha): Use ImageParts instead.
	Parts []ImagePart
}

// NewImage returns an empty image.
//
// NewImage generates a new texture and a new framebuffer.
//
// This function is concurrent-safe.
func NewImage(width, height int, filter Filter) (*Image, error) {
	image := &imageImpl{
		width:  width,
		height: height,
		filter: filter,
	}
	imageM.Lock()
	defer imageM.Unlock()
	eimg, err := theImages.add(image)
	if err != nil {
		return nil, err
	}
	image.image, err = graphics.NewImage(width, height, glFilter(ui.GLContext(), filter))
	if err != nil {
		return nil, err
	}
	runtime.SetFinalizer(image, (*imageImpl).Dispose)
	if err := image.image.Fill(color.Transparent); err != nil {
		return nil, err
	}
	return eimg, nil
}

// NewImageFromImage creates a new image with the given image (source).
//
// NewImageFromImage generates a new texture and a new framebuffer.
//
// This function is concurrent-safe.
func NewImageFromImage(source image.Image, filter Filter) (*Image, error) {
	size := source.Bounds().Size()
	w, h := size.X, size.Y
	// TODO: Return error when the image is too big!
	// Don't lock while manipulating an image.Image interface.
	rgbaImg, ok := source.(*image.RGBA)
	if !ok || source.Bounds().Min != image.ZP {
		origImg := source
		newImg := image.NewRGBA(origImg.Bounds())
		draw.Draw(newImg, newImg.Bounds(), origImg, origImg.Bounds().Min, draw.Src)
		rgbaImg = newImg
	}
	pixels := make([]uint8, 4*w*h)
	for j := 0; j < h; j++ {
		copy(pixels[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:])
	}
	imageM.Lock()
	defer imageM.Unlock()
	img := &imageImpl{
		width:  w,
		height: h,
		filter: filter,
		pixels: pixels,
	}
	var err error
	img.image, err = graphics.NewImageFromImage(rgbaImg, glFilter(ui.GLContext(), filter))
	if err != nil {
		// TODO: texture should be removed here?
		return nil, err
	}
	runtime.SetFinalizer(img, (*imageImpl).Dispose)
	eimg, err := theImages.add(img)
	if err != nil {
		return nil, err
	}
	return eimg, nil
}

func newImageWithZeroFramebuffer(width, height int) (*Image, error) {
	imageM.Lock()
	defer imageM.Unlock()
	i, err := graphics.NewZeroFramebufferImage(width, height)
	if err != nil {
		return nil, err
	}
	img := &imageImpl{
		image:              i,
		width:              width,
		height:             height,
		defaultFramebuffer: true,
	}
	eimg, err := theImages.add(img)
	if err != nil {
		return nil, err
	}
	runtime.SetFinalizer(img, (*imageImpl).Dispose)
	return eimg, nil
}
<|endoftext|>


<commit_before>package cryptostore_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	crypto "github.com/tendermint/go-crypto"
	"github.com/tendermint/go-crypto/keys"
	"github.com/tendermint/go-crypto/keys/cryptostore"
	"github.com/tendermint/go-crypto/keys/storage/memstorage"
)

// TestKeyManagement makes sure we can manipulate these keys well
func TestKeyManagement(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameEd25519
	n1, n2, n3 := "personal", "business", "other"
	p1, p2 := "1234", "really-secure!@#$"

	// Check empty state
	l, err := cstore.List()
	require.Nil(err)
	assert.Empty(l)

	// create some keys
	_, err = cstore.Get(n1)
	assert.NotNil(err)
	i, _, err := cstore.Create(n1, p1, algo)
	require.Equal(n1, i.Name)
	require.Nil(err)
	_, _, err = cstore.Create(n2, p2, algo)
	require.Nil(err)

	// we can get these keys
	i2, err := cstore.Get(n2)
	assert.Nil(err)
	_, err = cstore.Get(n3)
	assert.NotNil(err)

	// list shows them in order
	keys, err := cstore.List()
	require.Nil(err)
	require.Equal(2, len(keys))
	// note these are in alphabetical order
	assert.Equal(n2, keys[0].Name)
	assert.Equal(n1, keys[1].Name)
	assert.Equal(i2.PubKey, keys[0].PubKey)

	// deleting a key removes it
	err = cstore.Delete("bad name", "foo")
	require.NotNil(err)
	err = cstore.Delete(n1, p1)
	require.Nil(err)
	keys, err = cstore.List()
	require.Nil(err)
	assert.Equal(1, len(keys))
	_, err = cstore.Get(n1)
	assert.NotNil(err)

	// make sure that it only signs with the right password
	// tx := mock.NewSig([]byte("mytransactiondata"))
	// err = cstore.Sign(n2, p1, tx)
	// assert.NotNil(err)
	// err = cstore.Sign(n2, p2, tx)
	// assert.Nil(err, "%+v", err)
	// sigs, err := tx.Signers()
	// assert.Nil(err, "%+v", err)
	// if assert.Equal(1, len(sigs)) {
	// 	assert.Equal(i2.PubKey, sigs[0])
	// }
}

// TestSignVerify does some detailed checks on how we sign and validate
// signatures
// func TestSignVerify(t *testing.T) {
// 	assert, require := assert.New(t), require.New(t)

// 	// make the storage with reasonable defaults
// 	cstore := cryptostore.New(
// 		cryptostore.GenSecp256k1,
// 		cryptostore.SecretBox,
// 		memstorage.New(),
// 	)

// 	n1, n2 := "some dude", "a dudette"
// 	p1, p2 := "1234", "foobar"

// 	// create two users and get their info
// 	err := cstore.Create(n1, p1)
// 	require.Nil(err)
// 	i1, err := cstore.Get(n1)
// 	require.Nil(err)

// 	err = cstore.Create(n2, p2)
// 	require.Nil(err)
// 	i2, err := cstore.Get(n2)
// 	require.Nil(err)

// 	// let's try to sign some messages
// 	d1 := []byte("my first message")
// 	d2 := []byte("some other important info!")

// 	// try signing both data with both keys...
// 	s11, err := cstore.Signature(n1, p1, d1)
// 	require.Nil(err)
// 	s12, err := cstore.Signature(n1, p1, d2)
// 	require.Nil(err)
// 	s21, err := cstore.Signature(n2, p2, d1)
// 	require.Nil(err)
// 	s22, err := cstore.Signature(n2, p2, d2)
// 	require.Nil(err)

// 	// let's try to validate and make sure it only works when everything is proper
// 	keys := [][]byte{i1.PubKey, i2.PubKey}
// 	data := [][]byte{d1, d2}
// 	sigs := [][]byte{s11, s12, s21, s22}

// 	// loop over keys and data
// 	for k := 0; k < 2; k++ {
// 		for d := 0; d < 2; d++ {
// 			// make sure only the proper sig works
// 			good := 2*k + d
// 			for s := 0; s < 4; s++ {
// 				err = cstore.Verify(data[d], sigs[s], keys[k])
// 				if s == good {
// 					assert.Nil(err, "%+v", err)
// 				} else {
// 					assert.NotNil(err)
// 				}
// 			}
// 		}
// 	}
// }

func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) {
	err := cstore.Update(name, badpass, pass)
	assert.NotNil(err)
	err = cstore.Update(name, pass, pass)
	assert.Nil(err, "%+v", err)
}

// TestAdvancedKeyManagement verifies update, import, export functionality
func TestAdvancedKeyManagement(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameSecp256k1
	n1, n2 := "old-name", "new name"
	p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"

	// make sure key works with initial password
	_, _, err := cstore.Create(n1, p1, algo)
	require.Nil(err, "%+v", err)
	assertPassword(assert, cstore, n1, p1, p2)

	// update password requires the existing password
	err = cstore.Update(n1, "jkkgkg", p2)
	assert.NotNil(err)
	assertPassword(assert, cstore, n1, p1, p2)

	// then it changes the password when correct
	err = cstore.Update(n1, p1, p2)
	assert.Nil(err)
	// p2 is now the proper one!
	assertPassword(assert, cstore, n1, p2, p1)

	// exporting requires the proper name and passphrase
	_, err = cstore.Export(n2, p2, pt)
	assert.NotNil(err)
	_, err = cstore.Export(n1, p1, pt)
	assert.NotNil(err)
	exported, err := cstore.Export(n1, p2, pt)
	require.Nil(err, "%+v", err)

	// import fails on bad transfer pass
	err = cstore.Import(n2, p3, p2, exported)
	assert.NotNil(err)
	// import cannot overwrite existing keys
	err = cstore.Import(n1, p3, pt, exported)
	assert.NotNil(err)
	// we can now import under another name
	err = cstore.Import(n2, p3, pt, exported)
	require.Nil(err, "%+v", err)

	// make sure both passwords are now properly set (not to the transfer pass)
	assertPassword(assert, cstore, n1, p2, pt)
	assertPassword(assert, cstore, n2, p3, pt)
}

// TestSeedPhrase verifies restoring from a seed phrase
func TestSeedPhrase(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameEd25519
	n1, n2 := "lost-key", "found-again"
	p1, p2 := "1234", "foobar"

	// make sure key works with initial password
	info, seed, err := cstore.Create(n1, p1, algo)
	require.Nil(err, "%+v", err)
	assert.Equal(n1, info.Name)
	assert.NotEmpty(seed)

	// now, let us delete this key
	err = cstore.Delete(n1, p1)
	require.Nil(err, "%+v", err)
	_, err = cstore.Get(n1)
	require.NotNil(err)

	// let us re-create it from the seed-phrase
	newInfo, err := cstore.Recover(n2, p2, seed)
	require.Nil(err, "%+v", err)
	assert.Equal(n2, newInfo.Name)
	assert.Equal(info.Address, newInfo.Address)
	assert.Equal(info.PubKey, newInfo.PubKey)
}

// func ExampleStore() {
// 	// Select the encryption and storage for your cryptostore
// 	cstore := cryptostore.New(
// 		cryptostore.GenEd25519,
// 		cryptostore.SecretBox,
// 		// Note: use filestorage.New(dir) for real data
// 		memstorage.New(),
// 	)

// 	// Add keys and see they return in alphabetical order
// 	cstore.Create("Bob", "friend")
// 	cstore.Create("Alice", "secret")
// 	cstore.Create("Carl", "mitm")
// 	info, _ := cstore.List()
// 	for _, i := range info {
// 		fmt.Println(i.Name)
// 	}

// 	// We need to use passphrase to generate a signature
// 	tx := mock.NewSig([]byte("deadbeef"))
// 	err := cstore.Sign("Bob", "friend", tx)
// 	if err != nil {
// 		fmt.Println("don't accept real passphrase")
// 	}

// 	// and we can validate the signature with publically available info
// 	binfo, _ := cstore.Get("Bob")
// 	sigs, err := tx.Signers()
// 	if err != nil {
// 		fmt.Println("badly signed")
// 	} else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) {
// 		fmt.Println("signed by Bob")
// 	} else {
// 		fmt.Println("signed by someone else")
// 	}

// 	// Output:
// 	// Alice
// 	// Bob
// 	// Carl
// 	// signed by Bob
// }
<commit_msg>Test importing raw private key<commit_after>package cryptostore_test

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	cmn "github.com/tendermint/tmlibs/common"

	crypto "github.com/tendermint/go-crypto"
	"github.com/tendermint/go-crypto/keys"
	"github.com/tendermint/go-crypto/keys/cryptostore"
	"github.com/tendermint/go-crypto/keys/storage/memstorage"
)

// TestKeyManagement makes sure we can manipulate these keys well
func TestKeyManagement(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameEd25519
	n1, n2, n3 := "personal", "business", "other"
	p1, p2 := "1234", "really-secure!@#$"

	// Check empty state
	l, err := cstore.List()
	require.Nil(err)
	assert.Empty(l)

	// create some keys
	_, err = cstore.Get(n1)
	assert.NotNil(err)
	i, _, err := cstore.Create(n1, p1, algo)
	require.Equal(n1, i.Name)
	require.Nil(err)
	_, _, err = cstore.Create(n2, p2, algo)
	require.Nil(err)

	// we can get these keys
	i2, err := cstore.Get(n2)
	assert.Nil(err)
	_, err = cstore.Get(n3)
	assert.NotNil(err)

	// list shows them in order
	keys, err := cstore.List()
	require.Nil(err)
	require.Equal(2, len(keys))
	// note these are in alphabetical order
	assert.Equal(n2, keys[0].Name)
	assert.Equal(n1, keys[1].Name)
	assert.Equal(i2.PubKey, keys[0].PubKey)

	// deleting a key removes it
	err = cstore.Delete("bad name", "foo")
	require.NotNil(err)
	err = cstore.Delete(n1, p1)
	require.Nil(err)
	keys, err = cstore.List()
	require.Nil(err)
	assert.Equal(1, len(keys))
	_, err = cstore.Get(n1)
	assert.NotNil(err)

	// make sure that it only signs with the right password
	// tx := mock.NewSig([]byte("mytransactiondata"))
	// err = cstore.Sign(n2, p1, tx)
	// assert.NotNil(err)
	// err = cstore.Sign(n2, p2, tx)
	// assert.Nil(err, "%+v", err)
	// sigs, err := tx.Signers()
	// assert.Nil(err, "%+v", err)
	// if assert.Equal(1, len(sigs)) {
	// 	assert.Equal(i2.PubKey, sigs[0])
	// }
}

// TestSignVerify does some detailed checks on how we sign and validate
// signatures
// func TestSignVerify(t *testing.T) {
// 	assert, require := assert.New(t), require.New(t)

// 	// make the storage with reasonable defaults
// 	cstore := cryptostore.New(
// 		cryptostore.GenSecp256k1,
// 		cryptostore.SecretBox,
// 		memstorage.New(),
// 	)

// 	n1, n2 := "some dude", "a dudette"
// 	p1, p2 := "1234", "foobar"

// 	// create two users and get their info
// 	err := cstore.Create(n1, p1)
// 	require.Nil(err)
// 	i1, err := cstore.Get(n1)
// 	require.Nil(err)

// 	err = cstore.Create(n2, p2)
// 	require.Nil(err)
// 	i2, err := cstore.Get(n2)
// 	require.Nil(err)

// 	// let's try to sign some messages
// 	d1 := []byte("my first message")
// 	d2 := []byte("some other important info!")

// 	// try signing both data with both keys...
// 	s11, err := cstore.Signature(n1, p1, d1)
// 	require.Nil(err)
// 	s12, err := cstore.Signature(n1, p1, d2)
// 	require.Nil(err)
// 	s21, err := cstore.Signature(n2, p2, d1)
// 	require.Nil(err)
// 	s22, err := cstore.Signature(n2, p2, d2)
// 	require.Nil(err)

// 	// let's try to validate and make sure it only works when everything is proper
// 	keys := [][]byte{i1.PubKey, i2.PubKey}
// 	data := [][]byte{d1, d2}
// 	sigs := [][]byte{s11, s12, s21, s22}

// 	// loop over keys and data
// 	for k := 0; k < 2; k++ {
// 		for d := 0; d < 2; d++ {
// 			// make sure only the proper sig works
// 			good := 2*k + d
// 			for s := 0; s < 4; s++ {
// 				err = cstore.Verify(data[d], sigs[s], keys[k])
// 				if s == good {
// 					assert.Nil(err, "%+v", err)
// 				} else {
// 					assert.NotNil(err)
// 				}
// 			}
// 		}
// 	}
// }

func assertPassword(assert *assert.Assertions, cstore cryptostore.Manager, name, pass, badpass string) {
	err := cstore.Update(name, badpass, pass)
	assert.NotNil(err)
	err = cstore.Update(name, pass, pass)
	assert.Nil(err, "%+v", err)
}

// TestImportUnencrypted tests accepting raw priv keys bytes as input
func TestImportUnencrypted(t *testing.T) {
	require := require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	key := cryptostore.GenEd25519.Generate(cmn.RandBytes(16))
	addr := key.PubKey().Address()
	name := "john"
	pass := "top-secret"

	// import raw bytes
	err := cstore.Import(name, pass, "", key.Bytes())
	require.Nil(err, "%+v", err)

	// make sure the address matches
	info, err := cstore.Get(name)
	require.Nil(err, "%+v", err)
	require.EqualValues(addr, info.Address)
}

// TestAdvancedKeyManagement verifies update, import, export functionality
func TestAdvancedKeyManagement(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameSecp256k1
	n1, n2 := "old-name", "new name"
	p1, p2, p3, pt := "1234", "foobar", "ding booms!", "really-secure!@#$"

	// make sure key works with initial password
	_, _, err := cstore.Create(n1, p1, algo)
	require.Nil(err, "%+v", err)
	assertPassword(assert, cstore, n1, p1, p2)

	// update password requires the existing password
	err = cstore.Update(n1, "jkkgkg", p2)
	assert.NotNil(err)
	assertPassword(assert, cstore, n1, p1, p2)

	// then it changes the password when correct
	err = cstore.Update(n1, p1, p2)
	assert.Nil(err)
	// p2 is now the proper one!
	assertPassword(assert, cstore, n1, p2, p1)

	// exporting requires the proper name and passphrase
	_, err = cstore.Export(n2, p2, pt)
	assert.NotNil(err)
	_, err = cstore.Export(n1, p1, pt)
	assert.NotNil(err)
	exported, err := cstore.Export(n1, p2, pt)
	require.Nil(err, "%+v", err)

	// import fails on bad transfer pass
	err = cstore.Import(n2, p3, p2, exported)
	assert.NotNil(err)
}

// TestSeedPhrase verifies restoring from a seed phrase
func TestSeedPhrase(t *testing.T) {
	assert, require := assert.New(t), require.New(t)

	// make the storage with reasonable defaults
	cstore := cryptostore.New(
		cryptostore.SecretBox,
		memstorage.New(),
		keys.MustLoadCodec("english"),
	)

	algo := crypto.NameEd25519
	n1, n2 := "lost-key", "found-again"
	p1, p2 := "1234", "foobar"

	// make sure key works with initial password
	info, seed, err := cstore.Create(n1, p1, algo)
	require.Nil(err, "%+v", err)
	assert.Equal(n1, info.Name)
	assert.NotEmpty(seed)

	// now, let us delete this key
	err = cstore.Delete(n1, p1)
	require.Nil(err, "%+v", err)
	_, err = cstore.Get(n1)
	require.NotNil(err)

	// let us re-create it from the seed-phrase
	newInfo, err := cstore.Recover(n2, p2, seed)
	require.Nil(err, "%+v", err)
	assert.Equal(n2, newInfo.Name)
	assert.Equal(info.Address, newInfo.Address)
	assert.Equal(info.PubKey, newInfo.PubKey)
}

// func ExampleStore() {
// 	// Select the encryption and storage for your cryptostore
// 	cstore := cryptostore.New(
// 		cryptostore.GenEd25519,
// 		cryptostore.SecretBox,
// 		// Note: use filestorage.New(dir) for real data
// 		memstorage.New(),
// 	)

// 	// Add keys and see they return in alphabetical order
// 	cstore.Create("Bob", "friend")
// 	cstore.Create("Alice", "secret")
// 	cstore.Create("Carl", "mitm")
// 	info, _ := cstore.List()
// 	for _, i := range info {
// 		fmt.Println(i.Name)
// 	}

// 	// We need to use passphrase to generate a signature
// 	tx := mock.NewSig([]byte("deadbeef"))
// 	err := cstore.Sign("Bob", "friend", tx)
// 	if err != nil {
// 		fmt.Println("don't accept real passphrase")
// 	}

// 	// and we can validate the signature with publically available info
// 	binfo, _ := cstore.Get("Bob")
// 	sigs, err := tx.Signers()
// 	if err != nil {
// 		fmt.Println("badly signed")
// 	} else if bytes.Equal(sigs[0].Bytes(), binfo.PubKey.Bytes()) {
// 		fmt.Println("signed by Bob")
// 	} else {
// 		fmt.Println("signed by someone else")
// 	}

// 	// Output:
// 	// Alice
// 	// Bob
// 	// Carl
// 	// signed by Bob
// }
<|endoftext|>


<commit_before>package git

/*
#include <git2.h>

extern int _go_git_index_add_all(git_index*, const git_strarray*, unsigned int, void*);
extern int _go_git_index_update_all(git_index*, const git_strarray*, void*);
extern int _go_git_index_remove_all(git_index*, const git_strarray*, void*);

*/
import "C"
import (
	"fmt"
	"runtime"
	"time"
	"unsafe"
)

type IndexMatchedPathCallback func(string, string) int

type IndexAddOpts uint

const (
	IndexAddDefault              IndexAddOpts = C.GIT_INDEX_ADD_DEFAULT
	IndexAddForce                IndexAddOpts = C.GIT_INDEX_ADD_FORCE
	IndexAddDisablePathspecMatch IndexAddOpts = C.GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
	IndexAddCheckPathspec        IndexAddOpts = C.GIT_INDEX_ADD_CHECK_PATHSPEC
)

type Index struct {
	ptr *C.git_index
}

type IndexEntry struct {
	Ctime time.Time
	Mtime time.Time
	Mode  Filemode
	Uid   uint
	Gid   uint
	Size  uint
	Id    *Oid
	Path  string
}

func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry {
	if entry == nil {
		return nil
	}
	return &IndexEntry{
		time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)),
		time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)),
		Filemode(entry.mode),
		uint(entry.uid),
		uint(entry.gid),
		uint(entry.file_size),
		newOidFromC(&entry.id),
		C.GoString(entry.path),
	}
}

func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) {
	dest.ctime.seconds = C.git_time_t(source.Ctime.Unix())
	dest.ctime.nanoseconds = C.uint(source.Ctime.UnixNano())
	dest.mtime.seconds = C.git_time_t(source.Mtime.Unix())
	dest.mtime.nanoseconds = C.uint(source.Mtime.UnixNano())
	dest.mode = C.uint(source.Mode)
	dest.uid = C.uint(source.Uid)
	dest.gid = C.uint(source.Gid)
	dest.file_size = C.git_off_t(source.Size)
	dest.id = *source.Id.toC()
	dest.path = C.CString(source.Path)
}

func freeCIndexEntry(entry *C.git_index_entry) {
	C.free(unsafe.Pointer(entry.path))
}

func newIndexFromC(ptr *C.git_index) *Index {
	idx := &Index{ptr}
	runtime.SetFinalizer(idx, (*Index).Free)
	return idx
}

// NewIndex allocates a new index. It won't be associated with any
// file on the filesystem or repository
func NewIndex() (*Index, error) {
	var ptr *C.git_index

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if err := C.git_index_new(&ptr); err < 0 {
		return nil, MakeGitError(err)
	}

	return &Index{ptr: ptr}, nil
}

// Add adds or replaces the given entry to the index, making a copy of
// the data
func (v *Index) Add(entry *IndexEntry) error {
	var centry C.git_index_entry

	populateCIndexEntry(entry, &centry)
	defer freeCIndexEntry(&centry)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if err := C.git_index_add(v.ptr, &centry); err < 0 {
		return MakeGitError(err)
	}

	return nil
}

func (v *Index) AddByPath(path string) error {
	cstr := C.CString(path)
	defer C.free(unsafe.Pointer(cstr))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_add_bypath(v.ptr, cstr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_add_all(
		v.ptr,
		&cpathspecs,
		C.uint(flags),
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

func (v *Index) UpdateAll(pathspecs []string, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_update_all(
		v.ptr,
		&cpathspecs,
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_remove_all(
		v.ptr,
		&cpathspecs,
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

//export indexMatchedPathCallback
func indexMatchedPathCallback(cPath, cMatchedPathspec *C.char, payload unsafe.Pointer) int {
	callback := (*IndexMatchedPathCallback)(payload)
	return (*callback)(C.GoString(cPath), C.GoString(cMatchedPathspec))
}

func (v *Index) RemoveByPath(path string) error {
	cstr := C.CString(path)
	defer C.free(unsafe.Pointer(cstr))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_remove_bypath(v.ptr, cstr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) {
	oid := new(Oid)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr)
	if ret < 0 {
		return nil, MakeGitError(ret)
	}

	return oid, nil
}

func (v *Index) WriteTree() (*Oid, error) {
	oid := new(Oid)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write_tree(oid.toC(), v.ptr)
	if ret < 0 {
		return nil, MakeGitError(ret)
	}

	return oid, nil
}

func (v *Index) Write() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write(v.ptr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_index_free(v.ptr)
}

func (v *Index) EntryCount() uint {
	return uint(C.git_index_entrycount(v.ptr))
}

func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) {
	centry := C.git_index_get_byindex(v.ptr, C.size_t(index))
	if centry == nil {
		return nil, fmt.Errorf("Index out of Bounds")
	}
	return newIndexEntryFromC(centry), nil
}

func (v *Index) HasConflicts() bool {
	return C.git_index_has_conflicts(v.ptr) != 0
}

func (v *Index) CleanupConflicts() {
	C.git_index_conflict_cleanup(v.ptr)
}

func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error {

	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	if ancestor != nil {
		cancestor = &C.git_index_entry{}
		populateCIndexEntry(ancestor, cancestor)
		defer freeCIndexEntry(cancestor)
	}

	if our != nil {
		cour = &C.git_index_entry{}
		populateCIndexEntry(our, cour)
		defer freeCIndexEntry(cour)
	}

	if their != nil {
		ctheir = &C.git_index_entry{}
		populateCIndexEntry(their, ctheir)
		defer freeCIndexEntry(ctheir)
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir)
	if ecode < 0 {
		return MakeGitError(ecode)
	}
	return nil
}

type IndexConflict struct {
	Ancestor *IndexEntry
	Our      *IndexEntry
	Their    *IndexEntry
}

func (v *Index) GetConflict(path string) (IndexConflict, error) {

	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_get(&cancestor, &cour, &ctheir, v.ptr, cpath)
	if ecode < 0 {
		return IndexConflict{}, MakeGitError(ecode)
	}
	return IndexConflict{
		Ancestor: newIndexEntryFromC(cancestor),
		Our:      newIndexEntryFromC(cour),
		Their:    newIndexEntryFromC(ctheir),
	}, nil
}

func (v *Index) RemoveConflict(path string) error {

	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_remove(v.ptr, cpath)
	if ecode < 0 {
		return MakeGitError(ecode)
	}
	return nil
}

type IndexConflictIterator struct {
	ptr   *C.git_index_conflict_iterator
	index *Index
}

func newIndexConflictIteratorFromC(index *Index, ptr *C.git_index_conflict_iterator) *IndexConflictIterator {
	i := &IndexConflictIterator{ptr: ptr, index: index}
	runtime.SetFinalizer(i, (*IndexConflictIterator).Free)
	return i
}

func (v *IndexConflictIterator) Index() *Index {
	return v.index
}

func (v *IndexConflictIterator) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_index_conflict_iterator_free(v.ptr)
}

func (v *Index) ConflictIterator() (*IndexConflictIterator, error) {
	var i *C.git_index_conflict_iterator

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_iterator_new(&i, v.ptr)
	if ecode < 0 {
		return nil, MakeGitError(ecode)
	}
	return newIndexConflictIteratorFromC(v, i), nil
}

func (v *IndexConflictIterator) Next() (IndexConflict, error) {
	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_next(&cancestor, &cour, &ctheir, v.ptr)
	if ecode < 0 {
		return IndexConflict{}, MakeGitError(ecode)
	}
	return IndexConflict{
		Ancestor: newIndexEntryFromC(cancestor),
		Our:      newIndexEntryFromC(cour),
		Their:    newIndexEntryFromC(ctheir),
	}, nil
}
<commit_msg>Add a FIXME.<commit_after>package git

/*
#include <git2.h>

extern int _go_git_index_add_all(git_index*, const git_strarray*, unsigned int, void*);
extern int _go_git_index_update_all(git_index*, const git_strarray*, void*);
extern int _go_git_index_remove_all(git_index*, const git_strarray*, void*);

*/
import "C"
import (
	"fmt"
	"runtime"
	"time"
	"unsafe"
)

type IndexMatchedPathCallback func(string, string) int

type IndexAddOpts uint

const (
	IndexAddDefault              IndexAddOpts = C.GIT_INDEX_ADD_DEFAULT
	IndexAddForce                IndexAddOpts = C.GIT_INDEX_ADD_FORCE
	IndexAddDisablePathspecMatch IndexAddOpts = C.GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH
	IndexAddCheckPathspec        IndexAddOpts = C.GIT_INDEX_ADD_CHECK_PATHSPEC
)

type Index struct {
	ptr *C.git_index
}

type IndexEntry struct {
	Ctime time.Time
	Mtime time.Time
	Mode  Filemode
	Uid   uint
	Gid   uint
	Size  uint
	Id    *Oid
	Path  string
}

func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry {
	if entry == nil {
		return nil
	}
	return &IndexEntry{
		time.Unix(int64(entry.ctime.seconds), int64(entry.ctime.nanoseconds)),
		time.Unix(int64(entry.mtime.seconds), int64(entry.mtime.nanoseconds)),
		Filemode(entry.mode),
		uint(entry.uid),
		uint(entry.gid),
		uint(entry.file_size),
		newOidFromC(&entry.id),
		C.GoString(entry.path),
	}
}

func populateCIndexEntry(source *IndexEntry, dest *C.git_index_entry) {
	dest.ctime.seconds = C.git_time_t(source.Ctime.Unix())
	dest.ctime.nanoseconds = C.uint(source.Ctime.UnixNano())
	dest.mtime.seconds = C.git_time_t(source.Mtime.Unix())
	dest.mtime.nanoseconds = C.uint(source.Mtime.UnixNano())
	dest.mode = C.uint(source.Mode)
	dest.uid = C.uint(source.Uid)
	dest.gid = C.uint(source.Gid)
	dest.file_size = C.git_off_t(source.Size)
	dest.id = *source.Id.toC()
	dest.path = C.CString(source.Path)
}

func freeCIndexEntry(entry *C.git_index_entry) {
	C.free(unsafe.Pointer(entry.path))
}

func newIndexFromC(ptr *C.git_index) *Index {
	idx := &Index{ptr}
	runtime.SetFinalizer(idx, (*Index).Free)
	return idx
}

// NewIndex allocates a new index. It won't be associated with any
// file on the filesystem or repository
func NewIndex() (*Index, error) {
	var ptr *C.git_index

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if err := C.git_index_new(&ptr); err < 0 {
		return nil, MakeGitError(err)
	}

	return &Index{ptr: ptr}, nil
}

// Add adds or replaces the given entry to the index, making a copy of
// the data
func (v *Index) Add(entry *IndexEntry) error {
	var centry C.git_index_entry

	populateCIndexEntry(entry, &centry)
	defer freeCIndexEntry(&centry)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if err := C.git_index_add(v.ptr, &centry); err < 0 {
		return MakeGitError(err)
	}

	return nil
}

func (v *Index) AddByPath(path string) error {
	cstr := C.CString(path)
	defer C.free(unsafe.Pointer(cstr))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_add_bypath(v.ptr, cstr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_add_all(
		v.ptr,
		&cpathspecs,
		C.uint(flags),
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

func (v *Index) UpdateAll(pathspecs []string, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_update_all(
		v.ptr,
		&cpathspecs,
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback) error {
	cpathspecs := C.git_strarray{}
	cpathspecs.count = C.size_t(len(pathspecs))
	cpathspecs.strings = makeCStringsFromStrings(pathspecs)
	defer freeStrarray(&cpathspecs)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	var cb *IndexMatchedPathCallback
	if callback != nil {
		cb = &callback
	}

	ret := C._go_git_index_remove_all(
		v.ptr,
		&cpathspecs,
		unsafe.Pointer(cb),
	)
	if ret < 0 {
		return MakeGitError(ret)
	}
	return nil
}

//export indexMatchedPathCallback
func indexMatchedPathCallback(cPath, cMatchedPathspec *C.char, payload unsafe.Pointer) int {
	callback := (*IndexMatchedPathCallback)(payload)
	return (*callback)(C.GoString(cPath), C.GoString(cMatchedPathspec))
}

func (v *Index) RemoveByPath(path string) error {
	cstr := C.CString(path)
	defer C.free(unsafe.Pointer(cstr))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_remove_bypath(v.ptr, cstr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) {
	oid := new(Oid)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr)
	if ret < 0 {
		return nil, MakeGitError(ret)
	}

	return oid, nil
}

func (v *Index) WriteTree() (*Oid, error) {
	oid := new(Oid)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write_tree(oid.toC(), v.ptr)
	if ret < 0 {
		return nil, MakeGitError(ret)
	}

	return oid, nil
}

func (v *Index) Write() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_index_write(v.ptr)
	if ret < 0 {
		return MakeGitError(ret)
	}

	return nil
}

func (v *Index) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_index_free(v.ptr)
}

func (v *Index) EntryCount() uint {
	return uint(C.git_index_entrycount(v.ptr))
}

func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) {
	centry := C.git_index_get_byindex(v.ptr, C.size_t(index))
	if centry == nil {
		return nil, fmt.Errorf("Index out of Bounds")
	}
	return newIndexEntryFromC(centry), nil
}

func (v *Index) HasConflicts() bool {
	return C.git_index_has_conflicts(v.ptr) != 0
}

// FIXME: this might return an error
func (v *Index) CleanupConflicts() {
	C.git_index_conflict_cleanup(v.ptr)
}

func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error {

	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	if ancestor != nil {
		cancestor = &C.git_index_entry{}
		populateCIndexEntry(ancestor, cancestor)
		defer freeCIndexEntry(cancestor)
	}

	if our != nil {
		cour = &C.git_index_entry{}
		populateCIndexEntry(our, cour)
		defer freeCIndexEntry(cour)
	}

	if their != nil {
		ctheir = &C.git_index_entry{}
		populateCIndexEntry(their, ctheir)
		defer freeCIndexEntry(ctheir)
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir)
	if ecode < 0 {
		return MakeGitError(ecode)
	}
	return nil
}

type IndexConflict struct {
	Ancestor *IndexEntry
	Our      *IndexEntry
	Their    *IndexEntry
}

func (v *Index) GetConflict(path string) (IndexConflict, error) {

	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_get(&cancestor, &cour, &ctheir, v.ptr, cpath)
	if ecode < 0 {
		return IndexConflict{}, MakeGitError(ecode)
	}
	return IndexConflict{
		Ancestor: newIndexEntryFromC(cancestor),
		Our:      newIndexEntryFromC(cour),
		Their:    newIndexEntryFromC(ctheir),
	}, nil
}

func (v *Index) RemoveConflict(path string) error {

	cpath := C.CString(path)
	defer C.free(unsafe.Pointer(cpath))

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_remove(v.ptr, cpath)
	if ecode < 0 {
		return MakeGitError(ecode)
	}
	return nil
}

type IndexConflictIterator struct {
	ptr   *C.git_index_conflict_iterator
	index *Index
}

func newIndexConflictIteratorFromC(index *Index, ptr *C.git_index_conflict_iterator) *IndexConflictIterator {
	i := &IndexConflictIterator{ptr: ptr, index: index}
	runtime.SetFinalizer(i, (*IndexConflictIterator).Free)
	return i
}

func (v *IndexConflictIterator) Index() *Index {
	return v.index
}

func (v *IndexConflictIterator) Free() {
	runtime.SetFinalizer(v, nil)
	C.git_index_conflict_iterator_free(v.ptr)
}

func (v *Index) ConflictIterator() (*IndexConflictIterator, error) {
	var i *C.git_index_conflict_iterator

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_iterator_new(&i, v.ptr)
	if ecode < 0 {
		return nil, MakeGitError(ecode)
	}
	return newIndexConflictIteratorFromC(v, i), nil
}

func (v *IndexConflictIterator) Next() (IndexConflict, error) {
	var cancestor *C.git_index_entry
	var cour *C.git_index_entry
	var ctheir *C.git_index_entry

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_index_conflict_next(&cancestor, &cour, &ctheir, v.ptr)
	if ecode < 0 {
		return IndexConflict{}, MakeGitError(ecode)
	}
	return IndexConflict{
		Ancestor: newIndexEntryFromC(cancestor),
		Our:      newIndexEntryFromC(cour),
		Their:    newIndexEntryFromC(ctheir),
	}, nil
}
<|endoftext|>


<commit_before>package main

import "github.com/gopherjs/gopherjs/js"

const Message = "Hello world!"

func HelloWorld(req *js.Object, res *js.Object) {
	res.Call("send", Message)
}

func main() {
	js.Module.Get("exports").Set("helloGO", HelloWorld)
}
<commit_msg>MAke it twork!<commit_after>package main

import (
	"encoding/json"

	"github.com/gopherjs/gopherjs/js"
)

type Result struct {
	Message string `json:"message"`
	Id      int    `json:"id"`
}

func (r Result) JSON() []byte {
	b, err := json.Marshal(r)
	if err != nil {
		panic(err)
	}
	return b
}

func HelloWorld(req *js.Object, res *js.Object) {

	r := Result{"Hello, world", 1}

	res.Call("set", "Content-Type", "application/json")
	res.Call("send", string(r.JSON()))
}

func main() {
	js.Module.Get("exports").Set("helloGO", HelloWorld)
}
<|endoftext|>