<commit_before>// Copyright 2015 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.

// +build js

package ui

import (
	"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/webgl"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"strconv"
	"time"
)

var canvas js.Object
var context *opengl.Context

func Use(f func(*opengl.Context)) {
	f(context)
}

func DoEvents() {
	time.Sleep(0)
}

func Terminate() {
	// Do nothing.
}

func IsClosed() bool {
	return false
}

func SwapBuffers() {
	// Do nothing.
}

func init() {
	ch := make(chan struct{})
	js.Global.Get("window").Set("onload", func() {
		close(ch)
	})
	<-ch

	doc := js.Global.Get("document")
	canvas = doc.Call("createElement", "canvas")
	canvas.Set("width", 16)
	canvas.Set("height", 16)
	doc.Get("body").Call("appendChild", canvas)

	htmlStyle := doc.Get("documentElement").Get("style")
	htmlStyle.Set("height", "100%")
	htmlStyle.Set("margin", "0")
	htmlStyle.Set("padding", "0")

	bodyStyle := doc.Get("body").Get("style")
	bodyStyle.Set("backgroundColor", "#000")
	bodyStyle.Set("position", "relative")
	bodyStyle.Set("height", "100%")
	bodyStyle.Set("margin", "0")
	bodyStyle.Set("padding", "0")
	doc.Get("body").Set("onclick", func() {
		canvas.Call("focus")
	})

	canvasStyle := canvas.Get("style")
	canvasStyle.Set("position", "absolute")

	webglContext, err := webgl.NewContext(canvas, &webgl.ContextAttributes{
		Alpha:              true,
		PremultipliedAlpha: true,
	})
	if err != nil {
		panic(err)
	}
	context = opengl.NewContext(webglContext)

	// Make the canvas focusable.
	canvas.Call("setAttribute", "tabindex", 1)
	canvas.Get("style").Set("outline", "none")

	canvas.Set("onkeydown", func(e js.Object) {
		code := e.Get("keyCode").Int()
		currentInput.keyDown(code)
		button := e.Get("button").Int()
		currentInput.mouseDown(button)
	})
	canvas.Set("onkeyup", func(e js.Object) {
		code := e.Get("keyCode").Int()
		currentInput.keyUp(code)
		button := e.Get("button").Int()
		currentInput.mouseUp(button)
	})
	canvas.Set("onmousedown", func(e js.Object) {
		button := e.Get("button").Int()
		currentInput.mouseDown(button)
	})
	canvas.Set("onmouseup", func(e js.Object) {
		button := e.Get("button").Int()
		currentInput.mouseUp(button)
	})
	canvas.Set("oncontextmenu", func(e js.Object) bool {
		return false
	})
}

func Start(width, height, scale int, title string) (actualScale int, err error) {
	doc := js.Global.Get("document")
	doc.Set("title", title)
	canvas.Set("width", width*scale)
	canvas.Set("height", height*scale)
	canvasStyle := canvas.Get("style")
	canvasStyle.Set("left", "calc(50% - "+strconv.Itoa(width*scale/2)+"px)")
	canvasStyle.Set("top", "calc(50% - "+strconv.Itoa(height*scale/2)+"px)")

	canvas.Set("onmousemove", func(e js.Object) {
		rect := canvas.Call("getBoundingClientRect")
		x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
		x -= rect.Get("left").Int()
		y -= rect.Get("top").Int()
		currentInput.mouseMove(x/scale, y/scale)
	})
	canvas.Call("focus")

	return scale, nil
}
<commit_msg>Bug fix: invalidate function keys, backspace on browsers<commit_after>// Copyright 2015 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.

// +build js

package ui

import (
	"github.com/gopherjs/gopherjs/js"
	"github.com/gopherjs/webgl"
	"github.com/hajimehoshi/ebiten/internal/opengl"
	"strconv"
	"time"
)

var canvas js.Object
var context *opengl.Context

func Use(f func(*opengl.Context)) {
	f(context)
}

func DoEvents() {
	time.Sleep(0)
}

func Terminate() {
	// Do nothing.
}

func IsClosed() bool {
	return false
}

func SwapBuffers() {
	// Do nothing.
}

func init() {
	ch := make(chan struct{})
	js.Global.Get("window").Set("onload", func() {
		close(ch)
	})
	<-ch

	doc := js.Global.Get("document")
	doc.Set("onkeydown", func(e js.Object) bool {
		code := e.Get("keyCode").Int()
		// Backspace
		if code == 8 {
			return false
		}
		// Functions
		if 112 <= code && code <= 123 {
			return false
		}
		// Alt and arrows
		if code == 37 && code == 39 {
			// Don't need to check Alt.
			return false
		}
		return true
	})

	canvas = doc.Call("createElement", "canvas")
	canvas.Set("width", 16)
	canvas.Set("height", 16)
	doc.Get("body").Call("appendChild", canvas)

	htmlStyle := doc.Get("documentElement").Get("style")
	htmlStyle.Set("height", "100%")
	htmlStyle.Set("margin", "0")
	htmlStyle.Set("padding", "0")

	bodyStyle := doc.Get("body").Get("style")
	bodyStyle.Set("backgroundColor", "#000")
	bodyStyle.Set("position", "relative")
	bodyStyle.Set("height", "100%")
	bodyStyle.Set("margin", "0")
	bodyStyle.Set("padding", "0")
	doc.Get("body").Set("onclick", func() {
		canvas.Call("focus")
	})

	canvasStyle := canvas.Get("style")
	canvasStyle.Set("position", "absolute")

	webglContext, err := webgl.NewContext(canvas, &webgl.ContextAttributes{
		Alpha:              true,
		PremultipliedAlpha: true,
	})
	if err != nil {
		panic(err)
	}
	context = opengl.NewContext(webglContext)

	// Make the canvas focusable.
	canvas.Call("setAttribute", "tabindex", 1)
	canvas.Get("style").Set("outline", "none")

	canvas.Set("onkeydown", func(e js.Object) {
		code := e.Get("keyCode").Int()
		currentInput.keyDown(code)
	})
	canvas.Set("onkeyup", func(e js.Object) {
		code := e.Get("keyCode").Int()
		currentInput.keyUp(code)
	})
	canvas.Set("onmousedown", func(e js.Object) {
		button := e.Get("button").Int()
		currentInput.mouseDown(button)
	})
	canvas.Set("onmouseup", func(e js.Object) {
		button := e.Get("button").Int()
		currentInput.mouseUp(button)
	})
	canvas.Set("oncontextmenu", func(e js.Object) bool {
		return false
	})
}

func Start(width, height, scale int, title string) (actualScale int, err error) {
	doc := js.Global.Get("document")
	doc.Set("title", title)
	canvas.Set("width", width*scale)
	canvas.Set("height", height*scale)
	canvasStyle := canvas.Get("style")
	canvasStyle.Set("left", "calc(50% - "+strconv.Itoa(width*scale/2)+"px)")
	canvasStyle.Set("top", "calc(50% - "+strconv.Itoa(height*scale/2)+"px)")

	canvas.Set("onmousemove", func(e js.Object) {
		rect := canvas.Call("getBoundingClientRect")
		x, y := e.Get("clientX").Int(), e.Get("clientY").Int()
		x -= rect.Get("left").Int()
		y -= rect.Get("top").Int()
		currentInput.mouseMove(x/scale, y/scale)
	})
	canvas.Call("focus")

	return scale, nil
}
<|endoftext|>


<commit_before>package core_test

import (
	"fmt"
	"github.com/APTrust/bagit/core"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"path/filepath"
	"runtime"
	"testing"
)

func getPathToProfile(profileName string) (string, error) {
	_, filename, _, ok := runtime.Caller(0)
	if !ok {
		return "", fmt.Errorf("Rumtime cannot get caller file name.")
	}
	absFileName, err := filepath.Abs(filename)
	if err != nil {
		return "", err
	}
	bagPath := filepath.Join(absFileName, "..", "..", "testdata", "profiles", profileName)
	return filepath.Abs(bagPath)
}

func TestLoadBagItProfile(t *testing.T) {
	aptrustFile, err := getPathToProfile("aptrust_bagit_profile_2.0.json")
	require.Nil(t, err)
	profile, err := core.LoadBagItProfile(aptrustFile)
	require.Nil(t, err)
	assert.EqualValues(t, []string{"0.97"}, profile.AcceptBagItVersion)
	assert.EqualValues(t, []string{"application/tar"}, profile.AcceptSerialization)
	assert.False(t, profile.AllowFetchTxt)
	assert.True(t, profile.AllowMiscTopLevelFiles)
	assert.True(t, profile.AllowMiscDirectories)
	assert.EqualValues(t, []string{"md5"}, profile.ManifestsRequired)
	assert.Equal(t, "required", profile.Serialization)
	assert.Empty(t, profile.TagManifestsRequired)

	// BagIt Profile Info
	require.NotNil(t, profile.BagItProfileInfo)
	assert.Equal(t, "http://example.com/aptrust-bagit-profile_2.0.json", profile.BagItProfileInfo.BagItProfileIdentifier)
	assert.Equal(t, "support@aptrust.org", profile.BagItProfileInfo.ContactEmail)
	assert.Equal(t, "A. Diamond", profile.BagItProfileInfo.ContactName)
	assert.Equal(t, "BagIt profile for ingesting content into APTrust.", profile.BagItProfileInfo.ExternalDescription)
	assert.Equal(t, "aptrust.org", profile.BagItProfileInfo.SourceOrganization)
	assert.Equal(t, "2.0", profile.BagItProfileInfo.Version)

	// Required Tag Files
	require.NotNil(t, profile.TagFilesRequired)
	require.Equal(t, 3, len(profile.TagFilesRequired))

	bagit := profile.TagFilesRequired["bagit.txt"]
	require.NotNil(t, bagit)
	require.Equal(t, 2, len(bagit))
	require.NotNil(t, bagit["BagIt-Version"])
	assert.True(t, bagit["BagIt-Version"].Required)
	assert.False(t, bagit["BagIt-Version"].EmptyOk)

	baginfo := profile.TagFilesRequired["bag-info.txt"]
	require.NotNil(t, baginfo)

	aptrust := profile.TagFilesRequired["aptrust-info.txt"]
	require.NotNil(t, aptrust)
}
<commit_msg>Test DPN profile<commit_after>package core_test

import (
	"fmt"
	"github.com/APTrust/bagit/core"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"path/filepath"
	"runtime"
	"testing"
)

func getPathToProfile(profileName string) (string, error) {
	_, filename, _, ok := runtime.Caller(0)
	if !ok {
		return "", fmt.Errorf("Rumtime cannot get caller file name.")
	}
	absFileName, err := filepath.Abs(filename)
	if err != nil {
		return "", err
	}
	bagPath := filepath.Join(absFileName, "..", "..", "testdata", "profiles", profileName)
	return filepath.Abs(bagPath)
}

func TestLoadBagItProfile(t *testing.T) {
	aptrustFile, err := getPathToProfile("aptrust_bagit_profile_2.0.json")
	require.Nil(t, err)
	profile, err := core.LoadBagItProfile(aptrustFile)
	require.Nil(t, err)
	assert.EqualValues(t, []string{"0.97"}, profile.AcceptBagItVersion)
	assert.EqualValues(t, []string{"application/tar"}, profile.AcceptSerialization)
	assert.False(t, profile.AllowFetchTxt)
	assert.True(t, profile.AllowMiscTopLevelFiles)
	assert.True(t, profile.AllowMiscDirectories)
	assert.EqualValues(t, []string{"md5"}, profile.ManifestsRequired)
	assert.Equal(t, "required", profile.Serialization)
	assert.Empty(t, profile.TagManifestsRequired)

	// BagIt Profile Info
	require.NotNil(t, profile.BagItProfileInfo)
	assert.Equal(t, "http://example.com/aptrust-bagit-profile_2.0.json", profile.BagItProfileInfo.BagItProfileIdentifier)
	assert.Equal(t, "support@aptrust.org", profile.BagItProfileInfo.ContactEmail)
	assert.Equal(t, "A. Diamond", profile.BagItProfileInfo.ContactName)
	assert.Equal(t, "BagIt profile for ingesting content into APTrust.", profile.BagItProfileInfo.ExternalDescription)
	assert.Equal(t, "aptrust.org", profile.BagItProfileInfo.SourceOrganization)
	assert.Equal(t, "2.0", profile.BagItProfileInfo.Version)

	// Required Tag Files
	require.NotNil(t, profile.TagFilesRequired)
	require.Equal(t, 3, len(profile.TagFilesRequired))

	bagit := profile.TagFilesRequired["bagit.txt"]
	require.NotNil(t, bagit)
	require.Equal(t, 2, len(bagit))
	require.NotNil(t, bagit["BagIt-Version"])
	assert.True(t, bagit["BagIt-Version"].Required)
	assert.False(t, bagit["BagIt-Version"].EmptyOk)

	baginfo := profile.TagFilesRequired["bag-info.txt"]
	require.NotNil(t, baginfo)

	aptrust := profile.TagFilesRequired["aptrust-info.txt"]
	require.NotNil(t, aptrust)

	// Make sure this one parses, while we're at it.
	dpnFile, err := getPathToProfile("dpn_bagit_profile.json")
	require.Nil(t, err)
	dpnProfile, err := core.LoadBagItProfile(dpnFile)
	require.Nil(t, err)
	require.Equal(t, 3, len(dpnProfile.TagFilesRequired))
	require.Equal(t, 2, len(dpnProfile.TagFilesRequired["bagit.txt"]))
	require.Equal(t, 9, len(dpnProfile.TagFilesRequired["bag-info.txt"]))
	require.Equal(t, 11, len(dpnProfile.TagFilesRequired["dpn-tags/dpn-info.txt"]))
}
<|endoftext|>


<commit_before>package commands

import (
	"bytes"
	"errors"
	"io"
	"sort"

	cmds "github.com/ipfs/go-ipfs/commands"
	repo "github.com/ipfs/go-ipfs/repo"
	config "github.com/ipfs/go-ipfs/repo/config"
	"github.com/ipfs/go-ipfs/repo/fsrepo"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
)

type BootstrapOutput struct {
	Peers []string
}

var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multiaddr>/<peerID>')"

var BootstrapCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show or edit the list of bootstrap peers.",
		ShortDescription: `
Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
` + bootstrapSecurityWarning,
	},

	Run:        bootstrapListCmd.Run,
	Marshalers: bootstrapListCmd.Marshalers,
	Type:       bootstrapListCmd.Type,

	Subcommands: map[string]*cmds.Command{
		"list": bootstrapListCmd,
		"add":  bootstrapAddCmd,
		"rm":   bootstrapRemoveCmd,
	},
}

var bootstrapAddCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Add peers to the bootstrap list.",
		ShortDescription: `Outputs a list of peers that were added (that weren't already
in the bootstrap list).
` + bootstrapSecurityWarning,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
	},

	Options: []cmds.Option{
		cmds.BoolOption("default", "Add default bootstrap nodes."),
	},

	Run: func(req cmds.Request, res cmds.Response) {
		inputPeers, err := config.ParseBootstrapPeers(req.Arguments())
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		deflt, _, err := req.Option("default").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		if deflt {
			// parse separately for meaningful, correct error.
			defltPeers, err := config.DefaultBootstrapPeers()
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			inputPeers = append(inputPeers, defltPeers...)
		}

		if len(inputPeers) == 0 {
			res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient)
			return
		}

		added, err := bootstrapAdd(r, cfg, inputPeers)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(added)})
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, ok := res.Output().(*BootstrapOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			buf := new(bytes.Buffer)
			if err := bootstrapWritePeers(buf, "added ", v.Peers); err != nil {
				return nil, err
			}

			return buf, nil
		},
	},
}

var bootstrapRemoveCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Removes peers from the bootstrap list.",
		ShortDescription: `Outputs the list of peers that were removed.
` + bootstrapSecurityWarning,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
	},
	Options: []cmds.Option{
		cmds.BoolOption("all", "Remove all bootstrap peers."),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		input, err := config.ParseBootstrapPeers(req.Arguments())
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		all, _, err := req.Option("all").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		var removed []config.BootstrapPeer
		if all {
			removed, err = bootstrapRemoveAll(r, cfg)
		} else {
			removed, err = bootstrapRemove(r, cfg, input)
		}
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(removed)})
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, ok := res.Output().(*BootstrapOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			buf := new(bytes.Buffer)
			err := bootstrapWritePeers(buf, "removed ", v.Peers)
			return buf, err
		},
	},
}

var bootstrapListCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Show peers in the bootstrap list.",
		ShortDescription: "Peers are output in the format '<multiaddr>/<peerID>'.",
	},

	Run: func(req cmds.Request, res cmds.Response) {
		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		peers, err := cfg.BootstrapPeers()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(peers)})
		return
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: bootstrapMarshaler,
	},
}

func bootstrapMarshaler(res cmds.Response) (io.Reader, error) {
	v, ok := res.Output().(*BootstrapOutput)
	if !ok {
		return nil, u.ErrCast()
	}

	buf := new(bytes.Buffer)
	err := bootstrapWritePeers(buf, "", v.Peers)
	return buf, err
}

func bootstrapWritePeers(w io.Writer, prefix string, peers []string) error {

	sort.Stable(sort.StringSlice(peers))
	for _, peer := range peers {
		_, err := w.Write([]byte(peer + "\n"))
		if err != nil {
			return err
		}
	}
	return nil
}

func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
	addedMap := map[string]struct{}{}
	addedList := make([]config.BootstrapPeer, 0, len(peers))

	// re-add cfg bootstrap peers to rm dupes
	bpeers := cfg.Bootstrap
	cfg.Bootstrap = nil

	// add new peers
	for _, peer := range peers {
		s := peer.String()
		if _, found := addedMap[s]; found {
			continue
		}

		cfg.Bootstrap = append(cfg.Bootstrap, s)
		addedList = append(addedList, peer)
		addedMap[s] = struct{}{}
	}

	// add back original peers. in this order so that we output them.
	for _, s := range bpeers {
		if _, found := addedMap[s]; found {
			continue
		}

		cfg.Bootstrap = append(cfg.Bootstrap, s)
		addedMap[s] = struct{}{}
	}

	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return addedList, nil
}

func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
	removed := make([]config.BootstrapPeer, 0, len(toRemove))
	keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))

	peers, err := cfg.BootstrapPeers()
	if err != nil {
		return nil, err
	}

	for _, peer := range peers {
		found := false
		for _, peer2 := range toRemove {
			if peer.Equal(peer2) {
				found = true
				removed = append(removed, peer)
				break
			}
		}

		if !found {
			keep = append(keep, peer)
		}
	}
	cfg.SetBootstrapPeers(keep)

	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return removed, nil
}

func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer, error) {
	removed, err := cfg.BootstrapPeers()
	if err != nil {
		return nil, err
	}

	cfg.Bootstrap = nil
	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return removed, nil
}

const bootstrapSecurityWarning = `
SECURITY WARNING:

The bootstrap command manipulates the "bootstrap list", which contains
the addresses of bootstrap nodes. These are the *trusted peers* from
which to learn about other peers in the network. Only edit this list
if you understand the risks of adding or removing nodes from this list.

`
<commit_msg>Added Default to `bootstrap` cmd<commit_after>package commands

import (
	"bytes"
	"errors"
	"io"
	"sort"

	cmds "github.com/ipfs/go-ipfs/commands"
	repo "github.com/ipfs/go-ipfs/repo"
	config "github.com/ipfs/go-ipfs/repo/config"
	"github.com/ipfs/go-ipfs/repo/fsrepo"
	u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
)

type BootstrapOutput struct {
	Peers []string
}

var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multiaddr>/<peerID>')"

var BootstrapCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Show or edit the list of bootstrap peers.",
		ShortDescription: `
Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
` + bootstrapSecurityWarning,
	},

	Run:        bootstrapListCmd.Run,
	Marshalers: bootstrapListCmd.Marshalers,
	Type:       bootstrapListCmd.Type,

	Subcommands: map[string]*cmds.Command{
		"list": bootstrapListCmd,
		"add":  bootstrapAddCmd,
		"rm":   bootstrapRemoveCmd,
	},
}

var bootstrapAddCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Add peers to the bootstrap list.",
		ShortDescription: `Outputs a list of peers that were added (that weren't already
in the bootstrap list).
` + bootstrapSecurityWarning,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
	},

	Options: []cmds.Option{
		cmds.BoolOption("default", "Add default bootstrap nodes.").Default(false),
	},

	Run: func(req cmds.Request, res cmds.Response) {
		inputPeers, err := config.ParseBootstrapPeers(req.Arguments())
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		deflt, _, err := req.Option("default").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		if deflt {
			// parse separately for meaningful, correct error.
			defltPeers, err := config.DefaultBootstrapPeers()
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			inputPeers = append(inputPeers, defltPeers...)
		}

		if len(inputPeers) == 0 {
			res.SetError(errors.New("no bootstrap peers to add"), cmds.ErrClient)
			return
		}

		added, err := bootstrapAdd(r, cfg, inputPeers)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(added)})
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, ok := res.Output().(*BootstrapOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			buf := new(bytes.Buffer)
			if err := bootstrapWritePeers(buf, "added ", v.Peers); err != nil {
				return nil, err
			}

			return buf, nil
		},
	},
}

var bootstrapRemoveCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Removes peers from the bootstrap list.",
		ShortDescription: `Outputs the list of peers that were removed.
` + bootstrapSecurityWarning,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("peer", false, true, peerOptionDesc).EnableStdin(),
	},
	Options: []cmds.Option{
		cmds.BoolOption("all", "Remove all bootstrap peers.").Default(false),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		input, err := config.ParseBootstrapPeers(req.Arguments())
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		all, _, err := req.Option("all").Bool()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		var removed []config.BootstrapPeer
		if all {
			removed, err = bootstrapRemoveAll(r, cfg)
		} else {
			removed, err = bootstrapRemove(r, cfg, input)
		}
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(removed)})
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, ok := res.Output().(*BootstrapOutput)
			if !ok {
				return nil, u.ErrCast()
			}

			buf := new(bytes.Buffer)
			err := bootstrapWritePeers(buf, "removed ", v.Peers)
			return buf, err
		},
	},
}

var bootstrapListCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline:          "Show peers in the bootstrap list.",
		ShortDescription: "Peers are output in the format '<multiaddr>/<peerID>'.",
	},

	Run: func(req cmds.Request, res cmds.Response) {
		r, err := fsrepo.Open(req.InvocContext().ConfigRoot)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		defer r.Close()
		cfg, err := r.Config()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		peers, err := cfg.BootstrapPeers()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
		res.SetOutput(&BootstrapOutput{config.BootstrapPeerStrings(peers)})
		return
	},
	Type: BootstrapOutput{},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: bootstrapMarshaler,
	},
}

func bootstrapMarshaler(res cmds.Response) (io.Reader, error) {
	v, ok := res.Output().(*BootstrapOutput)
	if !ok {
		return nil, u.ErrCast()
	}

	buf := new(bytes.Buffer)
	err := bootstrapWritePeers(buf, "", v.Peers)
	return buf, err
}

func bootstrapWritePeers(w io.Writer, prefix string, peers []string) error {

	sort.Stable(sort.StringSlice(peers))
	for _, peer := range peers {
		_, err := w.Write([]byte(peer + "\n"))
		if err != nil {
			return err
		}
	}
	return nil
}

func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
	addedMap := map[string]struct{}{}
	addedList := make([]config.BootstrapPeer, 0, len(peers))

	// re-add cfg bootstrap peers to rm dupes
	bpeers := cfg.Bootstrap
	cfg.Bootstrap = nil

	// add new peers
	for _, peer := range peers {
		s := peer.String()
		if _, found := addedMap[s]; found {
			continue
		}

		cfg.Bootstrap = append(cfg.Bootstrap, s)
		addedList = append(addedList, peer)
		addedMap[s] = struct{}{}
	}

	// add back original peers. in this order so that we output them.
	for _, s := range bpeers {
		if _, found := addedMap[s]; found {
			continue
		}

		cfg.Bootstrap = append(cfg.Bootstrap, s)
		addedMap[s] = struct{}{}
	}

	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return addedList, nil
}

func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
	removed := make([]config.BootstrapPeer, 0, len(toRemove))
	keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))

	peers, err := cfg.BootstrapPeers()
	if err != nil {
		return nil, err
	}

	for _, peer := range peers {
		found := false
		for _, peer2 := range toRemove {
			if peer.Equal(peer2) {
				found = true
				removed = append(removed, peer)
				break
			}
		}

		if !found {
			keep = append(keep, peer)
		}
	}
	cfg.SetBootstrapPeers(keep)

	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return removed, nil
}

func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer, error) {
	removed, err := cfg.BootstrapPeers()
	if err != nil {
		return nil, err
	}

	cfg.Bootstrap = nil
	if err := r.SetConfig(cfg); err != nil {
		return nil, err
	}

	return removed, nil
}

const bootstrapSecurityWarning = `
SECURITY WARNING:

The bootstrap command manipulates the "bootstrap list", which contains
the addresses of bootstrap nodes. These are the *trusted peers* from
which to learn about other peers in the network. Only edit this list
if you understand the risks of adding or removing nodes from this list.

`
<|endoftext|>


<commit_before>package unixfs

import (
	"bytes"
	"fmt"
	"io"
	"sort"
	"text/tabwriter"
	"time"

	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	cmds "github.com/ipfs/go-ipfs/commands"
	core "github.com/ipfs/go-ipfs/core"
	path "github.com/ipfs/go-ipfs/path"
	unixfs "github.com/ipfs/go-ipfs/unixfs"
	unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
)

type LsLink struct {
	Name, Hash string
	Size       uint64
	Type       string
}

type LsObject struct {
	Hash  string
	Size  uint64
	Type  string
	Links []LsLink
}

type LsOutput struct {
	Arguments map[string]string
	Objects   map[string]*LsObject
}

var LsCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "List directory contents for Unix-filesystem objects",
		ShortDescription: `
Retrieves the object named by <ipfs-or-ipns-path> and displays the
contents with the following format:

  <hash> <type> <size> <name>

For files, the child size is the total size of the file contents.  For
directories, the child size is the IPFS link size.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from").EnableStdin(),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		node, err := req.Context().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		paths := req.Arguments()

		output := LsOutput{
			Arguments: map[string]string{},
			Objects:   map[string]*LsObject{},
		}

		for _, fpath := range paths {
			ctx := req.Context().Context
			merkleNode, err := core.Resolve(ctx, node, path.Path(fpath))
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			key, err := merkleNode.Key()
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			hash := key.B58String()
			output.Arguments[fpath] = hash

			if _, ok := output.Objects[hash]; ok {
				// duplicate argument for an already-listed node
				continue
			}

			unixFSNode, err := unixfs.FromBytes(merkleNode.Data)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			t := unixFSNode.GetType()

			output.Objects[hash] = &LsObject{
				Hash: key.String(),
				Type: t.String(),
				Size: unixFSNode.GetFilesize(),
			}

			switch t {
			default:
				res.SetError(fmt.Errorf("unrecognized type: %s", t), cmds.ErrImplementation)
				return
			case unixfspb.Data_File:
				break
			case unixfspb.Data_Directory:
				links := make([]LsLink, len(merkleNode.Links))
				output.Objects[hash].Links = links
				for i, link := range merkleNode.Links {
					getCtx, cancel := context.WithTimeout(ctx, time.Minute)
					defer cancel()
					link.Node, err = link.GetNode(getCtx, node.DAG)
					if err != nil {
						res.SetError(err, cmds.ErrNormal)
						return
					}
					d, err := unixfs.FromBytes(link.Node.Data)
					if err != nil {
						res.SetError(err, cmds.ErrNormal)
						return
					}
					t := d.GetType()
					lsLink := LsLink{
						Name: link.Name,
						Hash: link.Hash.B58String(),
						Type: t.String(),
					}
					if t == unixfspb.Data_File {
						lsLink.Size = d.GetFilesize()
					} else {
						lsLink.Size = link.Size
					}
					links[i] = lsLink
				}
			}
		}

		res.SetOutput(&output)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {

			output := res.Output().(*LsOutput)
			buf := new(bytes.Buffer)
			w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)

			nonDirectories := []string{}
			directories := []string{}
			for argument, hash := range output.Arguments {
				object, ok := output.Objects[hash]
				if !ok {
					return nil, fmt.Errorf("unresolved hash: %s", hash)
				}

				if object.Type == "Directory" {
					directories = append(directories, argument)
				} else {
					nonDirectories = append(nonDirectories, argument)
				}
			}
			sort.Strings(nonDirectories)
			sort.Strings(directories)

			for _, argument := range nonDirectories {
				fmt.Fprintf(w, "%s\n", argument)
			}

			seen := map[string]bool{}
			for i, argument := range directories {
				hash := output.Arguments[argument]
				if _, ok := seen[hash]; ok {
					continue
				}
				seen[hash] = true

				object := output.Objects[hash]
				if i > 0 || len(nonDirectories) > 0 {
					fmt.Fprintln(w)
				}
				if len(output.Arguments) > 1 {
					for _, arg := range directories[i:] {
						if output.Arguments[arg] == hash {
							fmt.Fprintf(w, "%s:\n", arg)
						}
					}
				}
				for _, link := range object.Links {
					fmt.Fprintf(w, "%s\n", link.Name)
				}
			}
			w.Flush()

			return buf, nil
		},
	},
	Type: LsOutput{},
}
<commit_msg>core/commands/unixfs/ls: Drop multi-column example from --help<commit_after>package unixfs

import (
	"bytes"
	"fmt"
	"io"
	"sort"
	"text/tabwriter"
	"time"

	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"

	cmds "github.com/ipfs/go-ipfs/commands"
	core "github.com/ipfs/go-ipfs/core"
	path "github.com/ipfs/go-ipfs/path"
	unixfs "github.com/ipfs/go-ipfs/unixfs"
	unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
)

type LsLink struct {
	Name, Hash string
	Size       uint64
	Type       string
}

type LsObject struct {
	Hash  string
	Size  uint64
	Type  string
	Links []LsLink
}

type LsOutput struct {
	Arguments map[string]string
	Objects   map[string]*LsObject
}

var LsCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "List directory contents for Unix-filesystem objects",
		ShortDescription: `
Retrieves the object named by <ipfs-or-ipns-path> and displays the
contents.

The JSON output contains size information.  For files, the child size
is the total size of the file contents.  For directories, the child
size is the IPFS link size.
`,
	},

	Arguments: []cmds.Argument{
		cmds.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from").EnableStdin(),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		node, err := req.Context().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		paths := req.Arguments()

		output := LsOutput{
			Arguments: map[string]string{},
			Objects:   map[string]*LsObject{},
		}

		for _, fpath := range paths {
			ctx := req.Context().Context
			merkleNode, err := core.Resolve(ctx, node, path.Path(fpath))
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			key, err := merkleNode.Key()
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			hash := key.B58String()
			output.Arguments[fpath] = hash

			if _, ok := output.Objects[hash]; ok {
				// duplicate argument for an already-listed node
				continue
			}

			unixFSNode, err := unixfs.FromBytes(merkleNode.Data)
			if err != nil {
				res.SetError(err, cmds.ErrNormal)
				return
			}

			t := unixFSNode.GetType()

			output.Objects[hash] = &LsObject{
				Hash: key.String(),
				Type: t.String(),
				Size: unixFSNode.GetFilesize(),
			}

			switch t {
			default:
				res.SetError(fmt.Errorf("unrecognized type: %s", t), cmds.ErrImplementation)
				return
			case unixfspb.Data_File:
				break
			case unixfspb.Data_Directory:
				links := make([]LsLink, len(merkleNode.Links))
				output.Objects[hash].Links = links
				for i, link := range merkleNode.Links {
					getCtx, cancel := context.WithTimeout(ctx, time.Minute)
					defer cancel()
					link.Node, err = link.GetNode(getCtx, node.DAG)
					if err != nil {
						res.SetError(err, cmds.ErrNormal)
						return
					}
					d, err := unixfs.FromBytes(link.Node.Data)
					if err != nil {
						res.SetError(err, cmds.ErrNormal)
						return
					}
					t := d.GetType()
					lsLink := LsLink{
						Name: link.Name,
						Hash: link.Hash.B58String(),
						Type: t.String(),
					}
					if t == unixfspb.Data_File {
						lsLink.Size = d.GetFilesize()
					} else {
						lsLink.Size = link.Size
					}
					links[i] = lsLink
				}
			}
		}

		res.SetOutput(&output)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {

			output := res.Output().(*LsOutput)
			buf := new(bytes.Buffer)
			w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)

			nonDirectories := []string{}
			directories := []string{}
			for argument, hash := range output.Arguments {
				object, ok := output.Objects[hash]
				if !ok {
					return nil, fmt.Errorf("unresolved hash: %s", hash)
				}

				if object.Type == "Directory" {
					directories = append(directories, argument)
				} else {
					nonDirectories = append(nonDirectories, argument)
				}
			}
			sort.Strings(nonDirectories)
			sort.Strings(directories)

			for _, argument := range nonDirectories {
				fmt.Fprintf(w, "%s\n", argument)
			}

			seen := map[string]bool{}
			for i, argument := range directories {
				hash := output.Arguments[argument]
				if _, ok := seen[hash]; ok {
					continue
				}
				seen[hash] = true

				object := output.Objects[hash]
				if i > 0 || len(nonDirectories) > 0 {
					fmt.Fprintln(w)
				}
				if len(output.Arguments) > 1 {
					for _, arg := range directories[i:] {
						if output.Arguments[arg] == hash {
							fmt.Fprintf(w, "%s:\n", arg)
						}
					}
				}
				for _, link := range object.Links {
					fmt.Fprintf(w, "%s\n", link.Name)
				}
			}
			w.Flush()

			return buf, nil
		},
	},
	Type: LsOutput{},
}
<|endoftext|>


<commit_before>package unixfs

import (
	"bytes"
	"fmt"
	"io"
	"sort"
	"text/tabwriter"

	cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"

	cmds "github.com/ipfs/go-ipfs/commands"
	core "github.com/ipfs/go-ipfs/core"
	e "github.com/ipfs/go-ipfs/core/commands/e"
	merkledag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"
	resolver "github.com/ipfs/go-ipfs/path/resolver"
	unixfs "github.com/ipfs/go-ipfs/unixfs"
	uio "github.com/ipfs/go-ipfs/unixfs/io"
	unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
)

type LsLink struct {
	Name, Hash string
	Size       uint64
	Type       string
}

type LsObject struct {
	Hash  string
	Size  uint64
	Type  string
	Links []LsLink
}

type LsOutput struct {
	Arguments map[string]string
	Objects   map[string]*LsObject
}

var LsCmd = &cmds.Command{
	Helptext: cmdkit.HelpText{
		Tagline: "List directory contents for Unix filesystem objects.",
		ShortDescription: `
Displays the contents of an IPFS or IPNS object(s) at the given path.

The JSON output contains size information. For files, the child size
is the total size of the file contents. For directories, the child
size is the IPFS link size.

This functionality is deprecated, and will be removed in future versions. If
possible, please use 'ipfs ls' instead.
`,
		LongDescription: `
Displays the contents of an IPFS or IPNS object(s) at the given path.

The JSON output contains size information. For files, the child size
is the total size of the file contents. For directories, the child
size is the IPFS link size.

The path can be a prefixless ref; in this case, we assume it to be an
/ipfs ref and not /ipns.

Example:

    > ipfs file ls QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ
    cat.jpg
    > ipfs file ls /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ
    cat.jpg

This functionality is deprecated, and will be removed in future versions. If
possible, please use 'ipfs ls' instead.
`,
	},

	Arguments: []cmdkit.Argument{
		cmdkit.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from.").EnableStdin(),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		node, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmdkit.ErrNormal)
			return
		}

		paths := req.Arguments()

		output := LsOutput{
			Arguments: map[string]string{},
			Objects:   map[string]*LsObject{},
		}

		for _, fpath := range paths {
			ctx := req.Context()

			resolver := &resolver.Resolver{
				DAG:         node.DAG,
				ResolveOnce: uio.ResolveUnixfsOnce,
			}

			merkleNode, err := core.Resolve(ctx, node.Namesys, resolver, path.Path(fpath))
			if err != nil {
				res.SetError(err, cmdkit.ErrNormal)
				return
			}

			c := merkleNode.Cid()

			hash := c.String()
			output.Arguments[fpath] = hash

			if _, ok := output.Objects[hash]; ok {
				// duplicate argument for an already-listed node
				continue
			}

			ndpb, ok := merkleNode.(*merkledag.ProtoNode)
			if !ok {
				res.SetError(merkledag.ErrNotProtobuf, cmdkit.ErrNormal)
				return
			}

			unixFSNode, err := unixfs.FromBytes(ndpb.Data())
			if err != nil {
				res.SetError(err, cmdkit.ErrNormal)
				return
			}

			t := unixFSNode.GetType()

			output.Objects[hash] = &LsObject{
				Hash: c.String(),
				Type: t.String(),
				Size: unixFSNode.GetFilesize(),
			}

			switch t {
			case unixfspb.Data_File:
				break
			case unixfspb.Data_Directory:
				links := make([]LsLink, len(merkleNode.Links()))
				output.Objects[hash].Links = links
				for i, link := range merkleNode.Links() {
					linkNode, err := link.GetNode(ctx, node.DAG)
					if err != nil {
						res.SetError(err, cmdkit.ErrNormal)
						return
					}
					lnpb, ok := linkNode.(*merkledag.ProtoNode)
					if !ok {
						res.SetError(merkledag.ErrNotProtobuf, cmdkit.ErrNormal)
						return
					}

					d, err := unixfs.FromBytes(lnpb.Data())
					if err != nil {
						res.SetError(err, cmdkit.ErrNormal)
						return
					}
					t := d.GetType()
					lsLink := LsLink{
						Name: link.Name,
						Hash: link.Cid.String(),
						Type: t.String(),
					}
					if t == unixfspb.Data_File {
						lsLink.Size = d.GetFilesize()
					} else {
						lsLink.Size = link.Size
					}
					links[i] = lsLink
				}
			case unixfspb.Data_Symlink:
				res.SetError(fmt.Errorf("cannot list symlinks yet"), cmdkit.ErrNormal)
				return
			default:
				res.SetError(fmt.Errorf("unrecognized type: %s", t), cmdkit.ErrImplementation)
				return
			}
		}

		res.SetOutput(&output)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, err := unwrapOutput(res.Output())
			if err != nil {
				return nil, err
			}

			output, ok := v.(*LsOutput)
			if !ok {
				return nil, e.TypeErr(output, v)
			}
			buf := new(bytes.Buffer)
			w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)

			nonDirectories := []string{}
			directories := []string{}
			for argument, hash := range output.Arguments {
				object, ok := output.Objects[hash]
				if !ok {
					return nil, fmt.Errorf("unresolved hash: %s", hash)
				}

				if object.Type == "Directory" {
					directories = append(directories, argument)
				} else {
					nonDirectories = append(nonDirectories, argument)
				}
			}
			sort.Strings(nonDirectories)
			sort.Strings(directories)

			for _, argument := range nonDirectories {
				fmt.Fprintf(w, "%s\n", argument)
			}

			seen := map[string]bool{}
			for i, argument := range directories {
				hash := output.Arguments[argument]
				if _, ok := seen[hash]; ok {
					continue
				}
				seen[hash] = true

				object := output.Objects[hash]
				if i > 0 || len(nonDirectories) > 0 {
					fmt.Fprintln(w)
				}
				if len(output.Arguments) > 1 {
					for _, arg := range directories[i:] {
						if output.Arguments[arg] == hash {
							fmt.Fprintf(w, "%s:\n", arg)
						}
					}
				}
				for _, link := range object.Links {
					fmt.Fprintf(w, "%s\n", link.Name)
				}
			}
			w.Flush()

			return buf, nil
		},
	},
	Type: LsOutput{},
}
<commit_msg>return a nice error when listing sharded directories<commit_after>package unixfs

import (
	"bytes"
	"fmt"
	"io"
	"sort"
	"text/tabwriter"

	cmdkit "gx/ipfs/QmceUdzxkimdYsgtX733uNgzf1DLHyBKN6ehGSp85ayppM/go-ipfs-cmdkit"

	cmds "github.com/ipfs/go-ipfs/commands"
	core "github.com/ipfs/go-ipfs/core"
	e "github.com/ipfs/go-ipfs/core/commands/e"
	merkledag "github.com/ipfs/go-ipfs/merkledag"
	path "github.com/ipfs/go-ipfs/path"
	resolver "github.com/ipfs/go-ipfs/path/resolver"
	unixfs "github.com/ipfs/go-ipfs/unixfs"
	uio "github.com/ipfs/go-ipfs/unixfs/io"
	unixfspb "github.com/ipfs/go-ipfs/unixfs/pb"
)

type LsLink struct {
	Name, Hash string
	Size       uint64
	Type       string
}

type LsObject struct {
	Hash  string
	Size  uint64
	Type  string
	Links []LsLink
}

type LsOutput struct {
	Arguments map[string]string
	Objects   map[string]*LsObject
}

var LsCmd = &cmds.Command{
	Helptext: cmdkit.HelpText{
		Tagline: "List directory contents for Unix filesystem objects.",
		ShortDescription: `
Displays the contents of an IPFS or IPNS object(s) at the given path.

The JSON output contains size information. For files, the child size
is the total size of the file contents. For directories, the child
size is the IPFS link size.

This functionality is deprecated, and will be removed in future versions. If
possible, please use 'ipfs ls' instead.
`,
		LongDescription: `
Displays the contents of an IPFS or IPNS object(s) at the given path.

The JSON output contains size information. For files, the child size
is the total size of the file contents. For directories, the child
size is the IPFS link size.

The path can be a prefixless ref; in this case, we assume it to be an
/ipfs ref and not /ipns.

Example:

    > ipfs file ls QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ
    cat.jpg
    > ipfs file ls /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ
    cat.jpg

This functionality is deprecated, and will be removed in future versions. If
possible, please use 'ipfs ls' instead.
`,
	},

	Arguments: []cmdkit.Argument{
		cmdkit.StringArg("ipfs-path", true, true, "The path to the IPFS object(s) to list links from.").EnableStdin(),
	},
	Run: func(req cmds.Request, res cmds.Response) {
		node, err := req.InvocContext().GetNode()
		if err != nil {
			res.SetError(err, cmdkit.ErrNormal)
			return
		}

		paths := req.Arguments()

		output := LsOutput{
			Arguments: map[string]string{},
			Objects:   map[string]*LsObject{},
		}

		for _, fpath := range paths {
			ctx := req.Context()

			resolver := &resolver.Resolver{
				DAG:         node.DAG,
				ResolveOnce: uio.ResolveUnixfsOnce,
			}

			merkleNode, err := core.Resolve(ctx, node.Namesys, resolver, path.Path(fpath))
			if err != nil {
				res.SetError(err, cmdkit.ErrNormal)
				return
			}

			c := merkleNode.Cid()

			hash := c.String()
			output.Arguments[fpath] = hash

			if _, ok := output.Objects[hash]; ok {
				// duplicate argument for an already-listed node
				continue
			}

			ndpb, ok := merkleNode.(*merkledag.ProtoNode)
			if !ok {
				res.SetError(merkledag.ErrNotProtobuf, cmdkit.ErrNormal)
				return
			}

			unixFSNode, err := unixfs.FromBytes(ndpb.Data())
			if err != nil {
				res.SetError(err, cmdkit.ErrNormal)
				return
			}

			t := unixFSNode.GetType()

			output.Objects[hash] = &LsObject{
				Hash: c.String(),
				Type: t.String(),
				Size: unixFSNode.GetFilesize(),
			}

			switch t {
			case unixfspb.Data_File:
				break
			case unixfspb.Data_HAMTShard:
				// We need a streaming ls API for this.
				res.SetError(fmt.Errorf("cannot list large directories yet"), cmdkit.ErrNormal)
				return
			case unixfspb.Data_Directory:
				links := make([]LsLink, len(merkleNode.Links()))
				output.Objects[hash].Links = links
				for i, link := range merkleNode.Links() {
					linkNode, err := link.GetNode(ctx, node.DAG)
					if err != nil {
						res.SetError(err, cmdkit.ErrNormal)
						return
					}
					lnpb, ok := linkNode.(*merkledag.ProtoNode)
					if !ok {
						res.SetError(merkledag.ErrNotProtobuf, cmdkit.ErrNormal)
						return
					}

					d, err := unixfs.FromBytes(lnpb.Data())
					if err != nil {
						res.SetError(err, cmdkit.ErrNormal)
						return
					}
					t := d.GetType()
					lsLink := LsLink{
						Name: link.Name,
						Hash: link.Cid.String(),
						Type: t.String(),
					}
					if t == unixfspb.Data_File {
						lsLink.Size = d.GetFilesize()
					} else {
						lsLink.Size = link.Size
					}
					links[i] = lsLink
				}
			case unixfspb.Data_Symlink:
				res.SetError(fmt.Errorf("cannot list symlinks yet"), cmdkit.ErrNormal)
				return
			default:
				res.SetError(fmt.Errorf("unrecognized type: %s", t), cmdkit.ErrImplementation)
				return
			}
		}

		res.SetOutput(&output)
	},
	Marshalers: cmds.MarshalerMap{
		cmds.Text: func(res cmds.Response) (io.Reader, error) {
			v, err := unwrapOutput(res.Output())
			if err != nil {
				return nil, err
			}

			output, ok := v.(*LsOutput)
			if !ok {
				return nil, e.TypeErr(output, v)
			}
			buf := new(bytes.Buffer)
			w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)

			nonDirectories := []string{}
			directories := []string{}
			for argument, hash := range output.Arguments {
				object, ok := output.Objects[hash]
				if !ok {
					return nil, fmt.Errorf("unresolved hash: %s", hash)
				}

				if object.Type == "Directory" {
					directories = append(directories, argument)
				} else {
					nonDirectories = append(nonDirectories, argument)
				}
			}
			sort.Strings(nonDirectories)
			sort.Strings(directories)

			for _, argument := range nonDirectories {
				fmt.Fprintf(w, "%s\n", argument)
			}

			seen := map[string]bool{}
			for i, argument := range directories {
				hash := output.Arguments[argument]
				if _, ok := seen[hash]; ok {
					continue
				}
				seen[hash] = true

				object := output.Objects[hash]
				if i > 0 || len(nonDirectories) > 0 {
					fmt.Fprintln(w)
				}
				if len(output.Arguments) > 1 {
					for _, arg := range directories[i:] {
						if output.Arguments[arg] == hash {
							fmt.Fprintf(w, "%s:\n", arg)
						}
					}
				}
				for _, link := range object.Links {
					fmt.Fprintf(w, "%s\n", link.Name)
				}
			}
			w.Flush()

			return buf, nil
		},
	},
	Type: LsOutput{},
}
<|endoftext|>


<commit_before>package main
import (
	"log"
	"net/http"
	"fmt"
	"io"
	"time"
)

const webBaseDir = "web"
const port = 8888

func ConnectHttpServer() {
	http.HandleFunc("/", render)
	log.Printf("http listening on port %d", port)
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func render(w http.ResponseWriter, r *http.Request) {
	requestedFile := r.URL.Path[1:]
	log.Printf("render: %s", requestedFile)

	f, err := http.Dir(webBaseDir).Open(requestedFile)
	defer f.Close()

	if err == nil {
		content := io.ReadSeeker(f)
		http.ServeContent(w, r, requestedFile, time.Now(), content)
		return
	}
	log.Printf("Error opening requested file %s: %v", requestedFile, err)
	// TODO return some sort of 500 error,
	// and return 404 only for when the file 'merely' can't be found..
	http.NotFound(w, r)
}<commit_msg>Handle default page<commit_after>package main
import (
	"log"
	"net/http"
	"fmt"
	"io"
	"time"
)

const webBaseDir = "web"
const port = 8888
const defaultPage = "index.html"

func ConnectHttpServer() {
	http.HandleFunc("/", render)
	log.Printf("http listening on port %d", port)
	http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}

func render(w http.ResponseWriter, r *http.Request) {
	requestedFile := r.URL.Path[1:]
	// TODO switch this to use debug logging
	log.Printf("render: '%s'", requestedFile)
	if requestedFile == "" {
		requestedFile = defaultPage
	}

	f, err := http.Dir(webBaseDir).Open(requestedFile)
	defer f.Close()

	if err == nil {
		content := io.ReadSeeker(f)
		http.ServeContent(w, r, requestedFile, time.Now(), content)
		return
	}
	log.Printf("Error opening requested file %s: %v", requestedFile, err)
	// TODO return some sort of 500 error,
	// and return 404 only for when the file 'merely' can't be found..
	http.NotFound(w, r)
}<|endoftext|>


<commit_before>// Copyright 2017 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/gt/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
package pwd

import (
	"crypto/md5"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"strconv"
	"time"
)

func PwGen(pass string) string {
	salt := strconv.FormatInt(time.Now().UnixNano()%9000+1000, 10)
	return Base64Encode(Sha1(Md5(pass)+salt) + salt)
}

func Base64Encode(s string) string {
	return base64.StdEncoding.EncodeToString([]byte(s))
}

func Base64Decode(s string) string {
	res, _ := base64.StdEncoding.DecodeString(s)
	return string(res)
}

func Sha1(s string) string {
	return fmt.Sprintf("%x", sha1.Sum([]byte(s)))
}

func Md5(s string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}

func PwCheck(pwd, saved string) bool {
	saved = Base64Decode(saved)
	if len(saved) < 4 {
		return false
	}
	salt := saved[len(saved)-4:]
	return Sha1(Md5(pwd)+salt)+salt == saved
}
<commit_msg>Fix golint<commit_after>// Copyright 2017 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-vgo/gt/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package pwd

import (
	"crypto/md5"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"strconv"
	"time"
)

func PwGen(pass string) string {
	salt := strconv.FormatInt(time.Now().UnixNano()%9000+1000, 10)
	return Base64Encode(Sha1(Md5(pass)+salt) + salt)
}

func Base64Encode(s string) string {
	return base64.StdEncoding.EncodeToString([]byte(s))
}

func Base64Decode(s string) string {
	res, _ := base64.StdEncoding.DecodeString(s)
	return string(res)
}

func Sha1(s string) string {
	return fmt.Sprintf("%x", sha1.Sum([]byte(s)))
}

func Md5(s string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}

func PwCheck(pwd, saved string) bool {
	saved = Base64Decode(saved)
	if len(saved) < 4 {
		return false
	}
	salt := saved[len(saved)-4:]
	return Sha1(Md5(pwd)+salt)+salt == saved
}
<|endoftext|>


<commit_before>package qr_test

import (
	"encoding/gob"
	"fmt"
	"math/rand"
	"os"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/alicebob/qr"
)

func init() {
	rand.Seed(time.Now().Unix())
}

func setupDataDir() string {
	os.RemoveAll("./d")
	if err := os.Mkdir("./d/", 0700); err != nil {
		panic(fmt.Sprintf("Can't make ./d/: %v", err))
	}
	return "./d"
}

func TestBasic(t *testing.T) {
	d := setupDataDir()

	q, err := qr.New(d, "test")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()
	for i := 0; i < 1000; i++ {
		q.Enqueue(i)
	}

	ret := make([]int, 1000)
	for i := range ret {
		select {
		case ii := <-q.Dequeue():
			ret[i] = ii.(int)
		case <-time.After(2 * time.Second):
			t.Fatalf("q should not be empty")
		}
	}

	select {
	case e := <-q.Dequeue():
		t.Fatalf("q should be empty, got a %#v", e)
	default:
		// ok
	}
}

func TestBlock(t *testing.T) {
	// Read should block until there is something.
	d := setupDataDir()
	q, err := qr.New(d, "test")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	ready := make(chan struct{})

	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		ready <- struct{}{}
		if got := <-q.Dequeue(); got != "hello world" {
			t.Errorf("Want hello, got %#v", got)
		}
	}()
	<-ready

	q.Enqueue("hello world")

	wg.Wait()
}

func TestBig(t *testing.T) {
	// Queue a lot of elements.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < eventCount; i++ {
		q.Enqueue(payload)
	}
	if have, want := q.FileCount(), 1; have != want {
		t.Errorf("have %d, want %d", have, want)
	}
	for i := 0; i < eventCount; i++ {
		if have, want := <-q.Dequeue(), payload; have != want {
			t.Fatalf("Want for %d: have: %#v, want %#v", i, have, want)
		}
	}
	if have, want := q.FileCount(), 0; have != want {
		t.Errorf("have %d, want %d", have, want)
	}
	q.Close()

	if have, want := fileCount(d), 0; have != want {
		t.Fatalf("Wrong number of files: have %d, have %d", have, want)
	}
}

func TestAsync(t *testing.T) {
	// Random sleep readers and writers.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
		wg         = sync.WaitGroup{}
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			q.Enqueue(payload)
			time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
		}
	}()

	// Reader is a little slower.
	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			if have, want := <-q.Dequeue(), payload; have != want {
				t.Fatalf("have %#v, want %#v", have, want)
			}
			time.Sleep(time.Duration(rand.Intn(150)) * time.Microsecond)
		}
	}()

	wg.Wait()
	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestMany(t *testing.T) {
	// Read and write a lot of messages, as fast as possible.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 1000000
		clients    = 10
		payload    = strings.Repeat("0xDEADBEEF", 30)
		wg         = sync.WaitGroup{}
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(100*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < clients; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < eventCount/clients; j++ {
				q.Enqueue(payload)
			}
		}()
	}
	wg.Wait()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			if got := <-q.Dequeue(); payload != got {
				t.Fatalf("Want for %d: %#v, got %#v", i, payload, got)
			}
		}
	}()
	wg.Wait()

	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestReopen(t *testing.T) {
	// Simple reopening.
	d := setupDataDir()
	q, err := qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}

	q.Enqueue("Message 1")
	q.Enqueue("Message 2")
	q.Close()

	q, err = qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	select {
	case <-q.Dequeue():
	case <-time.After(10 * time.Millisecond):
		t.Fatalf("nothing to read")
	}
	<-q.Dequeue()
	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestReopenBig(t *testing.T) {
	// Queue a lot of elements.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < eventCount; i++ {
		q.Enqueue(payload)
	}
	q.Close()

	q, err = qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < eventCount; i++ {
		if have, want := <-q.Dequeue(), payload; have != want {
			t.Fatalf("Want for %d: have: %#v, want %#v", i, have, want)
		}
	}
	q.Close()

	if have, want := fileCount(d), 0; have != want {
		t.Fatalf("Wrong number of files: have %d, have %d", have, want)
	}
}

func TestReadOnly(t *testing.T) {
	// Only reading doesn't block the close.
	d := setupDataDir()
	q, err := qr.New(d, "i")
	if err != nil {
		t.Fatal(err)
	}

	select {
	case v := <-q.Dequeue():
		t.Fatalf("Impossible read: %v", v)
	default:
	}

	q.Close()
}

func TestStruct(t *testing.T) {
	d := setupDataDir()
	q, err := qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	type s struct {
		X string
		Y int
	}
	gob.Register(s{})

	data := []s{
		{"Event", 1},
		{"alice", 2},
		{"bob", 3},
	}
	for _, d := range data {
		q.Enqueue(d)
	}
	for _, want := range data {
		if got := <-q.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}
}

func TestTwoStructs(t *testing.T) {
	d := setupDataDir()
	q1, err := qr.New(d, "s1")
	if err != nil {
		t.Fatal(err)
	}
	q2, err := qr.New(d, "s2")
	if err != nil {
		t.Fatal(err)
	}
	defer q1.Close()
	defer q2.Close()

	type s1 struct {
		X string
		Y int
	}
	gob.Register(s1{})

	type s2 struct {
		A float64
		B string
	}
	gob.Register(s2{})

	data1 := []s1{
		{"Event", 1},
		{"alice", 2},
		{"bob", 3},
	}

	data2 := []s2{
		{3.14, "pi"},
		{2.72, "e"},
	}

	for _, d1 := range data1 {
		q1.Enqueue(d1)
	}
	for _, d2 := range data2 {
		q2.Enqueue(d2)
	}

	for _, want := range data1 {
		if got := <-q1.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}
	for _, want := range data2 {
		if got := <-q2.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestTest(t *testing.T) {
	d := setupDataDir()
	q, err := qr.New(d, "xxx", qr.OptionTest("hello"))
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	type r struct {
		X string
		Y int
	}

	if _, err := qr.New(d, "xxx", qr.OptionTest(r{"hello", 1})); err == nil {
		t.Errorf("should have failed for unregistered struct")
	}

	gob.Register(r{})
	if _, err := qr.New(d, "xxx", qr.OptionTest(r{"hello", 1})); err != nil {
		t.Fatal(err)
	}
}

func TestInvalidPrefix(t *testing.T) {
	// Need a non-nil prefix.
	d := setupDataDir()
	for prefix, valid := range map[string]bool{
		"":        false,
		"foobar":  true,
		"foo/bar": false,
		"foo-bar": false,
	} {
		_, err := qr.New(d, prefix)
		if have, want := (err == nil), valid; have != want {
			t.Fatalf("prefix: %q, have: %t, want: %t", prefix, have, want)
		}
	}
}

// fileCount is a helper to count files in a directory.
func fileCount(dir string) int {
	fh, err := os.Open(dir)
	if err != nil {
		panic(err)
	}
	defer fh.Close()

	n, err := fh.Readdirnames(-1)
	if err != nil {
		panic(err)
	}
	return len(n)
}
<commit_msg>stabilize test<commit_after>package qr_test

import (
	"encoding/gob"
	"fmt"
	"math/rand"
	"os"
	"strings"
	"sync"
	"testing"
	"time"

	"github.com/alicebob/qr"
)

func init() {
	rand.Seed(time.Now().Unix())
}

func setupDataDir() string {
	os.RemoveAll("./d")
	if err := os.Mkdir("./d/", 0700); err != nil {
		panic(fmt.Sprintf("Can't make ./d/: %v", err))
	}
	return "./d"
}

func TestBasic(t *testing.T) {
	d := setupDataDir()

	q, err := qr.New(d, "test")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()
	for i := 0; i < 1000; i++ {
		q.Enqueue(i)
	}

	ret := make([]int, 1000)
	for i := range ret {
		select {
		case ii := <-q.Dequeue():
			ret[i] = ii.(int)
		case <-time.After(2 * time.Second):
			t.Fatalf("q should not be empty")
		}
	}

	select {
	case e := <-q.Dequeue():
		t.Fatalf("q should be empty, got a %#v", e)
	default:
		// ok
	}
}

func TestBlock(t *testing.T) {
	// Read should block until there is something.
	d := setupDataDir()
	q, err := qr.New(d, "test")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	ready := make(chan struct{})

	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		ready <- struct{}{}
		if got := <-q.Dequeue(); got != "hello world" {
			t.Errorf("Want hello, got %#v", got)
		}
	}()
	<-ready

	q.Enqueue("hello world")

	wg.Wait()
}

func TestBig(t *testing.T) {
	// Queue a lot of elements.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < eventCount; i++ {
		q.Enqueue(payload)
	}
	if have, wantMin := q.FileCount(), 1; have < wantMin {
		t.Errorf("have %d, want at least %d", have, wantMin)
	}
	for i := 0; i < eventCount; i++ {
		if have, want := <-q.Dequeue(), payload; have != want {
			t.Fatalf("Want for %d: have: %#v, want %#v", i, have, want)
		}
	}
	if have, want := q.FileCount(), 0; have != want {
		t.Errorf("have %d, want %d", have, want)
	}
	q.Close()

	if have, want := fileCount(d), 0; have != want {
		t.Fatalf("Wrong number of files: have %d, have %d", have, want)
	}
}

func TestAsync(t *testing.T) {
	// Random sleep readers and writers.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
		wg         = sync.WaitGroup{}
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			q.Enqueue(payload)
			time.Sleep(time.Duration(rand.Intn(100)) * time.Microsecond)
		}
	}()

	// Reader is a little slower.
	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			if have, want := <-q.Dequeue(), payload; have != want {
				t.Fatalf("have %#v, want %#v", have, want)
			}
			time.Sleep(time.Duration(rand.Intn(150)) * time.Microsecond)
		}
	}()

	wg.Wait()
	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestMany(t *testing.T) {
	// Read and write a lot of messages, as fast as possible.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 1000000
		clients    = 10
		payload    = strings.Repeat("0xDEADBEEF", 30)
		wg         = sync.WaitGroup{}
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(100*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < clients; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for j := 0; j < eventCount/clients; j++ {
				q.Enqueue(payload)
			}
		}()
	}
	wg.Wait()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for i := 0; i < eventCount; i++ {
			if got := <-q.Dequeue(); payload != got {
				t.Fatalf("Want for %d: %#v, got %#v", i, payload, got)
			}
		}
	}()
	wg.Wait()

	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestReopen(t *testing.T) {
	// Simple reopening.
	d := setupDataDir()
	q, err := qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}

	q.Enqueue("Message 1")
	q.Enqueue("Message 2")
	q.Close()

	q, err = qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	select {
	case <-q.Dequeue():
	case <-time.After(10 * time.Millisecond):
		t.Fatalf("nothing to read")
	}
	<-q.Dequeue()
	q.Close()

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestReopenBig(t *testing.T) {
	// Queue a lot of elements.
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	var (
		d          = setupDataDir()
		eventCount = 10000
		payload    = strings.Repeat("0xDEADBEEF", 300)
	)
	q, err := qr.New(d, "events", qr.OptionTimeout(10*time.Millisecond))
	if err != nil {
		t.Fatal(err)
	}

	for i := 0; i < eventCount; i++ {
		q.Enqueue(payload)
	}
	q.Close()

	q, err = qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	for i := 0; i < eventCount; i++ {
		if have, want := <-q.Dequeue(), payload; have != want {
			t.Fatalf("Want for %d: have: %#v, want %#v", i, have, want)
		}
	}
	q.Close()

	if have, want := fileCount(d), 0; have != want {
		t.Fatalf("Wrong number of files: have %d, have %d", have, want)
	}
}

func TestReadOnly(t *testing.T) {
	// Only reading doesn't block the close.
	d := setupDataDir()
	q, err := qr.New(d, "i")
	if err != nil {
		t.Fatal(err)
	}

	select {
	case v := <-q.Dequeue():
		t.Fatalf("Impossible read: %v", v)
	default:
	}

	q.Close()
}

func TestStruct(t *testing.T) {
	d := setupDataDir()
	q, err := qr.New(d, "events")
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	type s struct {
		X string
		Y int
	}
	gob.Register(s{})

	data := []s{
		{"Event", 1},
		{"alice", 2},
		{"bob", 3},
	}
	for _, d := range data {
		q.Enqueue(d)
	}
	for _, want := range data {
		if got := <-q.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}
}

func TestTwoStructs(t *testing.T) {
	d := setupDataDir()
	q1, err := qr.New(d, "s1")
	if err != nil {
		t.Fatal(err)
	}
	q2, err := qr.New(d, "s2")
	if err != nil {
		t.Fatal(err)
	}
	defer q1.Close()
	defer q2.Close()

	type s1 struct {
		X string
		Y int
	}
	gob.Register(s1{})

	type s2 struct {
		A float64
		B string
	}
	gob.Register(s2{})

	data1 := []s1{
		{"Event", 1},
		{"alice", 2},
		{"bob", 3},
	}

	data2 := []s2{
		{3.14, "pi"},
		{2.72, "e"},
	}

	for _, d1 := range data1 {
		q1.Enqueue(d1)
	}
	for _, d2 := range data2 {
		q2.Enqueue(d2)
	}

	for _, want := range data1 {
		if got := <-q1.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}
	for _, want := range data2 {
		if got := <-q2.Dequeue(); want != got {
			t.Errorf("Want %#v, got %#v", want, got)
		}
	}

	if got, want := fileCount(d), 0; got != want {
		t.Fatalf("Wrong number of files: got %d, want %d", got, want)
	}
}

func TestTest(t *testing.T) {
	d := setupDataDir()
	q, err := qr.New(d, "xxx", qr.OptionTest("hello"))
	if err != nil {
		t.Fatal(err)
	}
	defer q.Close()

	type r struct {
		X string
		Y int
	}

	if _, err := qr.New(d, "xxx", qr.OptionTest(r{"hello", 1})); err == nil {
		t.Errorf("should have failed for unregistered struct")
	}

	gob.Register(r{})
	if _, err := qr.New(d, "xxx", qr.OptionTest(r{"hello", 1})); err != nil {
		t.Fatal(err)
	}
}

func TestInvalidPrefix(t *testing.T) {
	// Need a non-nil prefix.
	d := setupDataDir()
	for prefix, valid := range map[string]bool{
		"":        false,
		"foobar":  true,
		"foo/bar": false,
		"foo-bar": false,
	} {
		_, err := qr.New(d, prefix)
		if have, want := (err == nil), valid; have != want {
			t.Fatalf("prefix: %q, have: %t, want: %t", prefix, have, want)
		}
	}
}

// fileCount is a helper to count files in a directory.
func fileCount(dir string) int {
	fh, err := os.Open(dir)
	if err != nil {
		panic(err)
	}
	defer fh.Close()

	n, err := fh.Readdirnames(-1)
	if err != nil {
		panic(err)
	}
	return len(n)
}
<|endoftext|>


<commit_before>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package state

import (
	"bytes"
	"fmt"
	"io"
	"math/big"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/logger/glog"
	"github.com/ethereum/go-ethereum/rlp"
	"github.com/ethereum/go-ethereum/trie"
)

var emptyCodeHash = crypto.Keccak256(nil)

type Code []byte

func (self Code) String() string {
	return string(self) //strings.Join(Disassemble(self), " ")
}

type Storage map[common.Hash]common.Hash

func (self Storage) String() (str string) {
	for key, value := range self {
		str += fmt.Sprintf("%X : %X\n", key, value)
	}

	return
}

func (self Storage) Copy() Storage {
	cpy := make(Storage)
	for key, value := range self {
		cpy[key] = value
	}

	return cpy
}

type StateObject struct {
	db   trie.Database // State database for storing state changes
	trie *trie.SecureTrie

	// Address belonging to this account
	address common.Address
	// The balance of the account
	balance *big.Int
	// The nonce of the account
	nonce uint64
	// The code hash if code is present (i.e. a contract)
	codeHash []byte
	// The code for this account
	code Code
	// Cached storage (flushed when updated)
	storage Storage

	// Mark for deletion
	// When an object is marked for deletion it will be delete from the trie
	// during the "update" phase of the state transition
	remove  bool
	deleted bool
	dirty   bool
}

func NewStateObject(address common.Address, db trie.Database) *StateObject {
	object := &StateObject{
		db:       db,
		address:  address,
		balance:  new(big.Int),
		dirty:    true,
		codeHash: emptyCodeHash,
		storage:  make(Storage),
	}
	object.trie, _ = trie.NewSecure(common.Hash{}, db)
	return object
}

func (self *StateObject) MarkForDeletion() {
	self.remove = true
	self.dirty = true

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v X\n", self.Address(), self.nonce, self.balance)
	}
}

func (c *StateObject) getAddr(addr common.Hash) common.Hash {
	var ret []byte
	rlp.DecodeBytes(c.trie.Get(addr[:]), &ret)
	return common.BytesToHash(ret)
}

func (c *StateObject) setAddr(addr, value common.Hash) {
	v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
	if err != nil {
		// if RLPing failed we better panic and not fail silently. This would be considered a consensus issue
		panic(err)
	}
	c.trie.Update(addr[:], v)
}

func (self *StateObject) Storage() Storage {
	return self.storage
}

func (self *StateObject) GetState(key common.Hash) common.Hash {
	value, exists := self.storage[key]
	if !exists {
		value = self.getAddr(key)
		if (value != common.Hash{}) {
			self.storage[key] = value
		}
	}

	return value
}

func (self *StateObject) SetState(key, value common.Hash) {
	self.storage[key] = value
	self.dirty = true
}

// Update updates the current cached storage to the trie
func (self *StateObject) Update() {
	for key, value := range self.storage {
		if (value == common.Hash{}) {
			self.trie.Delete(key[:])
			continue
		}
		self.setAddr(key, value)
	}
}

func (c *StateObject) AddBalance(amount *big.Int) {
	c.SetBalance(new(big.Int).Add(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

func (c *StateObject) SubBalance(amount *big.Int) {
	c.SetBalance(new(big.Int).Sub(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

func (c *StateObject) SetBalance(amount *big.Int) {
	c.balance = amount
	c.dirty = true
}

func (c *StateObject) St() Storage {
	return c.storage
}

// Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *StateObject) ReturnGas(gas, price *big.Int) {}

func (self *StateObject) Copy() *StateObject {
	stateObject := NewStateObject(self.Address(), self.db)
	stateObject.balance.Set(self.balance)
	stateObject.codeHash = common.CopyBytes(self.codeHash)
	stateObject.nonce = self.nonce
	stateObject.trie = self.trie
	stateObject.code = self.code
	stateObject.storage = self.storage.Copy()
	stateObject.remove = self.remove
	stateObject.dirty = self.dirty
	stateObject.deleted = self.deleted

	return stateObject
}

//
// Attribute accessors
//

func (self *StateObject) Balance() *big.Int {
	return self.balance
}

// Returns the address of the contract/account
func (c *StateObject) Address() common.Address {
	return c.address
}

func (self *StateObject) Trie() *trie.SecureTrie {
	return self.trie
}

func (self *StateObject) Root() []byte {
	return self.trie.Root()
}

func (self *StateObject) Code() []byte {
	return self.code
}

func (self *StateObject) SetCode(code []byte) {
	self.code = code
	self.codeHash = crypto.Keccak256(code)
	self.dirty = true
}

func (self *StateObject) SetNonce(nonce uint64) {
	self.nonce = nonce
	self.dirty = true
}

func (self *StateObject) Nonce() uint64 {
	return self.nonce
}

// Never called, but must be present to allow StateObject to be used
// as a vm.Account interface that also satisfies the vm.ContractRef
// interface. Interfaces are awesome.
func (self *StateObject) Value() *big.Int {
	panic("Value on StateObject should never be called")
}

func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
	// When iterating over the storage check the cache first
	for h, value := range self.storage {
		cb(h, value)
	}

	it := self.trie.Iterator()
	for it.Next() {
		// ignore cached values
		key := common.BytesToHash(self.trie.GetKey(it.Key))
		if _, ok := self.storage[key]; !ok {
			cb(key, common.BytesToHash(it.Value))
		}
	}
}

type extStateObject struct {
	Nonce    uint64
	Balance  *big.Int
	Root     common.Hash
	CodeHash []byte
}

// EncodeRLP implements rlp.Encoder.
func (c *StateObject) EncodeRLP(w io.Writer) error {
	return rlp.Encode(w, []interface{}{c.nonce, c.balance, c.Root(), c.codeHash})
}

// DecodeObject decodes an RLP-encoded state object.
func DecodeObject(address common.Address, db trie.Database, data []byte) (*StateObject, error) {
	var (
		obj = &StateObject{address: address, db: db, storage: make(Storage)}
		ext extStateObject
		err error
	)
	if err = rlp.DecodeBytes(data, &ext); err != nil {
		return nil, err
	}
	if obj.trie, err = trie.NewSecure(ext.Root, db); err != nil {
		return nil, err
	}
	if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
		if obj.code, err = db.Get(ext.CodeHash); err != nil {
			return nil, fmt.Errorf("can't get code for hash %x: %v", ext.CodeHash, err)
		}
	}
	obj.nonce = ext.Nonce
	obj.balance = ext.Balance
	obj.codeHash = ext.CodeHash
	return obj, nil
}
<commit_msg>core/state: short-circuit balance change if zero value<commit_after>// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package state

import (
	"bytes"
	"fmt"
	"io"
	"math/big"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/logger/glog"
	"github.com/ethereum/go-ethereum/rlp"
	"github.com/ethereum/go-ethereum/trie"
)

var emptyCodeHash = crypto.Keccak256(nil)

type Code []byte

func (self Code) String() string {
	return string(self) //strings.Join(Disassemble(self), " ")
}

type Storage map[common.Hash]common.Hash

func (self Storage) String() (str string) {
	for key, value := range self {
		str += fmt.Sprintf("%X : %X\n", key, value)
	}

	return
}

func (self Storage) Copy() Storage {
	cpy := make(Storage)
	for key, value := range self {
		cpy[key] = value
	}

	return cpy
}

type StateObject struct {
	db   trie.Database // State database for storing state changes
	trie *trie.SecureTrie

	// Address belonging to this account
	address common.Address
	// The balance of the account
	balance *big.Int
	// The nonce of the account
	nonce uint64
	// The code hash if code is present (i.e. a contract)
	codeHash []byte
	// The code for this account
	code Code
	// Cached storage (flushed when updated)
	storage Storage

	// Mark for deletion
	// When an object is marked for deletion it will be delete from the trie
	// during the "update" phase of the state transition
	remove  bool
	deleted bool
	dirty   bool
}

func NewStateObject(address common.Address, db trie.Database) *StateObject {
	object := &StateObject{
		db:       db,
		address:  address,
		balance:  new(big.Int),
		dirty:    true,
		codeHash: emptyCodeHash,
		storage:  make(Storage),
	}
	object.trie, _ = trie.NewSecure(common.Hash{}, db)
	return object
}

func (self *StateObject) MarkForDeletion() {
	self.remove = true
	self.dirty = true

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v X\n", self.Address(), self.nonce, self.balance)
	}
}

func (c *StateObject) getAddr(addr common.Hash) common.Hash {
	var ret []byte
	rlp.DecodeBytes(c.trie.Get(addr[:]), &ret)
	return common.BytesToHash(ret)
}

func (c *StateObject) setAddr(addr, value common.Hash) {
	v, err := rlp.EncodeToBytes(bytes.TrimLeft(value[:], "\x00"))
	if err != nil {
		// if RLPing failed we better panic and not fail silently. This would be considered a consensus issue
		panic(err)
	}
	c.trie.Update(addr[:], v)
}

func (self *StateObject) Storage() Storage {
	return self.storage
}

func (self *StateObject) GetState(key common.Hash) common.Hash {
	value, exists := self.storage[key]
	if !exists {
		value = self.getAddr(key)
		if (value != common.Hash{}) {
			self.storage[key] = value
		}
	}

	return value
}

func (self *StateObject) SetState(key, value common.Hash) {
	self.storage[key] = value
	self.dirty = true
}

// Update updates the current cached storage to the trie
func (self *StateObject) Update() {
	for key, value := range self.storage {
		if (value == common.Hash{}) {
			self.trie.Delete(key[:])
			continue
		}
		self.setAddr(key, value)
	}
}

func (c *StateObject) AddBalance(amount *big.Int) {
	if amount.Cmp(common.Big0) == 0 {
		return
	}
	c.SetBalance(new(big.Int).Add(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

func (c *StateObject) SubBalance(amount *big.Int) {
	if amount.Cmp(common.Big0) == 0 {
		return
	}
	c.SetBalance(new(big.Int).Sub(c.balance, amount))

	if glog.V(logger.Core) {
		glog.Infof("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
	}
}

func (c *StateObject) SetBalance(amount *big.Int) {
	c.balance = amount
	c.dirty = true
}

func (c *StateObject) St() Storage {
	return c.storage
}

// Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *StateObject) ReturnGas(gas, price *big.Int) {}

func (self *StateObject) Copy() *StateObject {
	stateObject := NewStateObject(self.Address(), self.db)
	stateObject.balance.Set(self.balance)
	stateObject.codeHash = common.CopyBytes(self.codeHash)
	stateObject.nonce = self.nonce
	stateObject.trie = self.trie
	stateObject.code = self.code
	stateObject.storage = self.storage.Copy()
	stateObject.remove = self.remove
	stateObject.dirty = self.dirty
	stateObject.deleted = self.deleted

	return stateObject
}

//
// Attribute accessors
//

func (self *StateObject) Balance() *big.Int {
	return self.balance
}

// Returns the address of the contract/account
func (c *StateObject) Address() common.Address {
	return c.address
}

func (self *StateObject) Trie() *trie.SecureTrie {
	return self.trie
}

func (self *StateObject) Root() []byte {
	return self.trie.Root()
}

func (self *StateObject) Code() []byte {
	return self.code
}

func (self *StateObject) SetCode(code []byte) {
	self.code = code
	self.codeHash = crypto.Keccak256(code)
	self.dirty = true
}

func (self *StateObject) SetNonce(nonce uint64) {
	self.nonce = nonce
	self.dirty = true
}

func (self *StateObject) Nonce() uint64 {
	return self.nonce
}

// Never called, but must be present to allow StateObject to be used
// as a vm.Account interface that also satisfies the vm.ContractRef
// interface. Interfaces are awesome.
func (self *StateObject) Value() *big.Int {
	panic("Value on StateObject should never be called")
}

func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
	// When iterating over the storage check the cache first
	for h, value := range self.storage {
		cb(h, value)
	}

	it := self.trie.Iterator()
	for it.Next() {
		// ignore cached values
		key := common.BytesToHash(self.trie.GetKey(it.Key))
		if _, ok := self.storage[key]; !ok {
			cb(key, common.BytesToHash(it.Value))
		}
	}
}

type extStateObject struct {
	Nonce    uint64
	Balance  *big.Int
	Root     common.Hash
	CodeHash []byte
}

// EncodeRLP implements rlp.Encoder.
func (c *StateObject) EncodeRLP(w io.Writer) error {
	return rlp.Encode(w, []interface{}{c.nonce, c.balance, c.Root(), c.codeHash})
}

// DecodeObject decodes an RLP-encoded state object.
func DecodeObject(address common.Address, db trie.Database, data []byte) (*StateObject, error) {
	var (
		obj = &StateObject{address: address, db: db, storage: make(Storage)}
		ext extStateObject
		err error
	)
	if err = rlp.DecodeBytes(data, &ext); err != nil {
		return nil, err
	}
	if obj.trie, err = trie.NewSecure(ext.Root, db); err != nil {
		return nil, err
	}
	if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
		if obj.code, err = db.Get(ext.CodeHash); err != nil {
			return nil, fmt.Errorf("can't get code for hash %x: %v", ext.CodeHash, err)
		}
	}
	obj.nonce = ext.Nonce
	obj.balance = ext.Balance
	obj.codeHash = ext.CodeHash
	return obj, nil
}
<|endoftext|>


<commit_before>// Package quobyte represents a golang API for the Quobyte Storage System
package quobyte

import (
	"net/http"
	"regexp"
)

// retry policy codes
const (
	RetryNever         string = "NEVER"
	RetryInteractive   string = "INTERACTIVE"
	RetryInfinitely    string = "INFINITELY"
	RetryOncePerTarget string = "ONCE_PER_TARGET"
)

type QuobyteClient struct {
	client         *http.Client
	url            string
	username       string
	password       string
	apiRetryPolicy string
}

func (client *QuobyteClient) SetAPIRetryPolicy(retry string) {
	client.apiRetryPolicy = retry
}

func (client *QuobyteClient) GetAPIRetryPolicy() string {
	return client.apiRetryPolicy
}

// NewQuobyteClient creates a new Quobyte API client
func NewQuobyteClient(url string, username string, password string) *QuobyteClient {
	return &QuobyteClient{
		client:         &http.Client{},
		url:            url,
		username:       username,
		password:       password,
		apiRetryPolicy: RetryInteractive,
	}
}

// CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
	var response volumeUUID

	if request.TenantID != "" && !IsValidUUID(request.TenantID) {
		tenantUUID, err := client.ResolveTeantanNameTOUUID(request.TenantID)
		if err != nil {
			return "", err
		}

		request.TenantID = tenantUUID
	}

	if err := client.sendRequest("createVolume", request, &response); err != nil {
		return "", err
	}

	return response.VolumeUUID, nil
}

// ResolveVolumeNameToUUID resolves a volume name to a UUID
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
	request := &resolveVolumeNameRequest{
		VolumeName:   volumeName,
		TenantDomain: tenant,
	}
	var response volumeUUID
	if err := client.sendRequest("resolveVolumeName", request, &response); err != nil {
		return "", err
	}

	return response.VolumeUUID, nil
}

// DeleteVolume deletes a Quobyte volume
func (client *QuobyteClient) DeleteVolume(UUID string) error {
	return client.sendRequest(
		"deleteVolume",
		&volumeUUID{
			VolumeUUID: UUID,
		},
		nil)
}

// DeleteVolumeByName deletes a volume by a given name
func (client *QuobyteClient) DeleteVolumeByName(volumeName, tenant string) error {
	uuid, err := client.ResolveVolumeNameToUUID(volumeName, tenant)
	if err != nil {
		return err
	}

	return client.DeleteVolume(uuid)
}

// GetClientList returns a list of all active clients
func (client *QuobyteClient) GetClientList(tenant string) (GetClientListResponse, error) {
	request := &getClientListRequest{
		TenantDomain: tenant,
	}

	var response GetClientListResponse
	if err := client.sendRequest("getClientListRequest", request, &response); err != nil {
		return response, err
	}

	return response, nil
}

// SetVolumeQuota sets a Quota to the specified Volume
func (client *QuobyteClient) SetVolumeQuota(volumeUUID string, quotaSize uint64) error {
	request := &setQuotaRequest{
		Quotas: []*quota{
			&quota{
				Consumer: []*consumingEntity{
					&consumingEntity{
						Type:       "VOLUME",
						Identifier: volumeUUID,
					},
				},
				Limits: []*resource{
					&resource{
						Type:  "LOGICAL_DISK_SPACE",
						Value: quotaSize,
					},
				},
			},
		},
	}

	return client.sendRequest("setQuota", request, nil)
}

// GetTenant returns the Tenant configuration for all specified tenants
func (client *QuobyteClient) GetTenant(tenantIDs []string) (GetTenantResponse, error) {
	request := &getTenantRequest{TenantIDs: tenantIDs}

	var response GetTenantResponse
	err := client.sendRequest("getTenant", request, &response)
	if err != nil {
		return response, err
	}

	return response, nil
}

// GetTenantMap returns a map that contains all tenant names and there ID's
func (client *QuobyteClient) GetTenantMap() (map[string]string, error) {
	result := map[string]string{}
	response, err := client.GetTenant([]string{})

	if err != nil {
		return result, err
	}

	for _, tenant := range response.Tenants {
		result[tenant.Name] = tenant.TenantID
	}

	return result, nil
}

// SetTenant creates a Tenant with the specified name
func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
	request := &setTenantRequest{
		&TenantDomainConfiguration{
			Name: tenantName,
		},
		retryPolicy{client.GetAPIRetryPolicy()},
	}

	var response setTenantResponse
	err := client.sendRequest("setTenant", request, &response)
	if err != nil {
		return "", err
	}

	return response.TenantID, nil
}

// IsValidUUID Validates given uuid
func IsValidUUID(uuid string) bool {
	r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
	return r.MatchString(uuid)
}

// ResolveTeantanNameTOUUID Returns UUID for given name, error if not found.
func (client *QuobyteClient) ResolveTeantanNameTOUUID(name string) (string, error) {
	request := &resolveTenantNameRequest{
		TenantName: name,
	}

	var response resolveTenantNameResponse
	err := client.sendRequest("resolveTenantNameRequest", request, &response)
	if err != nil {
		return "", err
	}
	return response.TenantID, nil
}
<commit_msg>Typo corrections<commit_after>// Package quobyte represents a golang API for the Quobyte Storage System
package quobyte

import (
	"log"
	"net/http"
	"regexp"
)

// retry policy codes
const (
	RetryNever         string = "NEVER"
	RetryInteractive   string = "INTERACTIVE"
	RetryInfinitely    string = "INFINITELY"
	RetryOncePerTarget string = "ONCE_PER_TARGET"
)

type QuobyteClient struct {
	client         *http.Client
	url            string
	username       string
	password       string
	apiRetryPolicy string
}

func (client *QuobyteClient) SetAPIRetryPolicy(retry string) {
	client.apiRetryPolicy = retry
}

func (client *QuobyteClient) GetAPIRetryPolicy() string {
	return client.apiRetryPolicy
}

// NewQuobyteClient creates a new Quobyte API client
func NewQuobyteClient(url string, username string, password string) *QuobyteClient {
	return &QuobyteClient{
		client:         &http.Client{},
		url:            url,
		username:       username,
		password:       password,
		apiRetryPolicy: RetryInteractive,
	}
}

// CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
	var response volumeUUID

	if request.TenantID != "" && !IsValidUUID(request.TenantID) {
		log.Printf("Tenant name resolution: Resolving  %s to UUID\n", request.TenantID)
		tenantUUID, err := client.ResolveTenantNameToUUID(request.TenantID)
		if err != nil {
			return "", err
		}

		request.TenantID = tenantUUID
	}

	if err := client.sendRequest("createVolume", request, &response); err != nil {
		return "", err
	}

	return response.VolumeUUID, nil
}

// ResolveVolumeNameToUUID resolves a volume name to a UUID
func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
	request := &resolveVolumeNameRequest{
		VolumeName:   volumeName,
		TenantDomain: tenant,
	}
	var response volumeUUID
	if err := client.sendRequest("resolveVolumeName", request, &response); err != nil {
		return "", err
	}

	return response.VolumeUUID, nil
}

// DeleteVolume deletes a Quobyte volume
func (client *QuobyteClient) DeleteVolume(UUID string) error {
	return client.sendRequest(
		"deleteVolume",
		&volumeUUID{
			VolumeUUID: UUID,
		},
		nil)
}

// DeleteVolumeByName deletes a volume by a given name
func (client *QuobyteClient) DeleteVolumeByName(volumeName, tenant string) error {
	uuid, err := client.ResolveVolumeNameToUUID(volumeName, tenant)
	if err != nil {
		return err
	}

	return client.DeleteVolume(uuid)
}

// GetClientList returns a list of all active clients
func (client *QuobyteClient) GetClientList(tenant string) (GetClientListResponse, error) {
	request := &getClientListRequest{
		TenantDomain: tenant,
	}

	var response GetClientListResponse
	if err := client.sendRequest("getClientListRequest", request, &response); err != nil {
		return response, err
	}

	return response, nil
}

// SetVolumeQuota sets a Quota to the specified Volume
func (client *QuobyteClient) SetVolumeQuota(volumeUUID string, quotaSize uint64) error {
	request := &setQuotaRequest{
		Quotas: []*quota{
			&quota{
				Consumer: []*consumingEntity{
					&consumingEntity{
						Type:       "VOLUME",
						Identifier: volumeUUID,
					},
				},
				Limits: []*resource{
					&resource{
						Type:  "LOGICAL_DISK_SPACE",
						Value: quotaSize,
					},
				},
			},
		},
	}

	return client.sendRequest("setQuota", request, nil)
}

// GetTenant returns the Tenant configuration for all specified tenants
func (client *QuobyteClient) GetTenant(tenantIDs []string) (GetTenantResponse, error) {
	request := &getTenantRequest{TenantIDs: tenantIDs}

	var response GetTenantResponse
	err := client.sendRequest("getTenant", request, &response)
	if err != nil {
		return response, err
	}

	return response, nil
}

// GetTenantMap returns a map that contains all tenant names and there ID's
func (client *QuobyteClient) GetTenantMap() (map[string]string, error) {
	result := map[string]string{}
	response, err := client.GetTenant([]string{})

	if err != nil {
		return result, err
	}

	for _, tenant := range response.Tenants {
		result[tenant.Name] = tenant.TenantID
	}

	return result, nil
}

// SetTenant creates a Tenant with the specified name
func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
	request := &setTenantRequest{
		&TenantDomainConfiguration{
			Name: tenantName,
		},
		retryPolicy{client.GetAPIRetryPolicy()},
	}

	var response setTenantResponse
	err := client.sendRequest("setTenant", request, &response)
	if err != nil {
		return "", err
	}

	return response.TenantID, nil
}

// IsValidUUID Validates given uuid
func IsValidUUID(uuid string) bool {
	r := regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
	return r.MatchString(uuid)
}

// ResolveTenantNameToUUID Returns UUID for given name, error if not found.
func (client *QuobyteClient) ResolveTenantNameToUUID(name string) (string, error) {
	request := &resolveTenantNameRequest{
		TenantName: name,
	}

	var response resolveTenantNameResponse
	err := client.sendRequest("resolveTenantName", request, &response)
	if err != nil {
		return "", err
	}
	return response.TenantID, nil
}
<|endoftext|>


<commit_before>package jlogutil

import (
	"errors"

	"github.com/fastly/jlog-go"
)

// JReader embeds a reader with a subscriber name.
type JReader struct {
	jlog.Reader
	subscriber string
}

// NewReader opens the jlog at the given path, attaches the given subscriber
// for reading and returns the opened jlog.
func NewReader(path, subscriber string) (*JReader, error) {
	log, err := jlog.NewReader(path, nil)
	if err != nil {
		return nil, err
	}
	subs, err := log.ListSubscribers()
	if err != nil {
		return nil, err
	}

	jreader := &JReader{Reader: log}

	for _, sub := range subs {
		if sub == subscriber {
			return nil, errors.New("subscriber already exists")
		}
	}

	err = log.AddSubscriber(subscriber, jlog.END)
	if err != nil {
		return nil, err
	}
	err = log.Open(subscriber)
	if err != nil {
		jreader.Close()
		return nil, err
	}
	jreader.subscriber = subscriber
	return jreader, nil
}

func (j *JReader) Reopen() error {
	j.Reader.Close()
	err := j.Open(j.subscriber)
	if err != nil {
		return err
	}
	return nil
}

// Removes the JReader's specific reader and closes the jlog.
func (j *JReader) Close() {
	j.RemoveSubscriber(j.subscriber)
	j.Reader.Close()
}
<commit_msg>move jlogutil to jlog-go<commit_after><|endoftext|>