Skip to content

Commit

Permalink
writing files inside ipns works now! also implemented resolve cli com…
Browse files Browse the repository at this point in the history
…mand
  • Loading branch information
whyrusleeping authored and jbenet committed Oct 1, 2014
1 parent 006b68b commit 6080944
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 28 deletions.
1 change: 1 addition & 0 deletions cmd/ipfs/ipfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Use "ipfs help <command>" for more information about a command.
cmdIpfsServe,
cmdIpfsRun,
cmdIpfsPub,
cmdIpfsResolve,
},
Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
}
Expand Down
54 changes: 54 additions & 0 deletions cmd/ipfs/resolve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"fmt"
"os"
"time"

"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
"github.com/jbenet/go-ipfs/core/commands"
"github.com/jbenet/go-ipfs/daemon"
u "github.com/jbenet/go-ipfs/util"
)

var cmdIpfsResolve = &commander.Command{
UsageLine: "resolve",
Short: "resolve an ipns link to a hash",
Long: `ipfs resolve <hash>... - Resolve hash.
`,
Run: resolveCmd,
Flag: *flag.NewFlagSet("ipfs-resolve", flag.ExitOnError),
}

func resolveCmd(c *commander.Command, inp []string) error {
u.Debug = true
if len(inp) < 1 {
u.POut(c.Long)
return nil
}
conf, err := getConfigDir(c.Parent)
if err != nil {
return err
}

cmd := daemon.NewCommand()
cmd.Command = "resolve"
cmd.Args = inp
err = daemon.SendCommand(cmd, conf)
if err != nil {
now := time.Now()
// Resolve requires working DHT
n, err := localNode(conf, true)
if err != nil {
return err
}

took := time.Now().Sub(now)
fmt.Printf("localNode creation took %s\n", took.String())

return commands.Resolve(n, cmd.Args, cmd.Opts, os.Stdout)
}
return nil
}
5 changes: 2 additions & 3 deletions core/commands/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ func Publish(n *core.IpfsNode, args []string, opts map[string]interface{}, out i
}

k := n.Identity.PrivKey
val := u.Key(args[0])

pub := nsys.NewPublisher(n.DAG, n.Routing)
err := pub.Publish(k, val)
err := pub.Publish(k, args[0])
if err != nil {
return err
}
Expand All @@ -33,7 +32,7 @@ func Publish(n *core.IpfsNode, args []string, opts map[string]interface{}, out i
if err != nil {
return err
}
fmt.Fprintf(out, "Published %s to %s\n", val, u.Key(hash).Pretty())
fmt.Fprintf(out, "Published %s to %s\n", args[0], u.Key(hash).Pretty())

return nil
}
18 changes: 18 additions & 0 deletions core/commands/resolve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package commands

import (
"fmt"
"io"

"github.com/jbenet/go-ipfs/core"
)

func Resolve(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
res, err := n.Namesys.Resolve(args[0])
if err != nil {
return err
}

fmt.Fprintf(out, "%s -> %s\n", args[0], res)
return nil
}
2 changes: 2 additions & 0 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ func (dl *DaemonListener) handleConnection(conn net.Conn) {
err = commands.Pin(dl.node, command.Args, command.Opts, conn)
case "publish":
err = commands.Publish(dl.node, command.Args, command.Opts, conn)
case "resolve":
err = commands.Resolve(dl.node, command.Args, command.Opts, conn)
default:
err = fmt.Errorf("Invalid Command: '%s'", command.Command)
}
Expand Down
34 changes: 24 additions & 10 deletions fuse/ipns/ipns_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ipns

import (
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
Expand Down Expand Up @@ -83,6 +84,11 @@ func CreateRoot(n *core.IpfsNode, keys []ci.PrivKey, ipfsroot string) (*Root, er
continue
}

if !u.IsValidHash(pointsTo) {
log.Critical("Got back bad data from namesys resolve! [%s]", pointsTo)
return nil, nil
}

node, err := n.Resolver.ResolvePath(pointsTo)
if err != nil {
log.Warning("Failed to resolve value from ipns entry in ipfs")
Expand Down Expand Up @@ -120,7 +126,7 @@ func (*Root) Attr() fuse.Attr {

// Lookup performs a lookup under this node.
func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
log.Debug("ipns: Root Lookup: '%s'", name)
log.Debug("ipns: Root Lookup: '%s' [intr = %s]", name, intr.String())
switch name {
case "mach_kernel", ".hidden", "._.":
// Just quiet some log noise on OS X.
Expand All @@ -139,14 +145,14 @@ func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
return nd, nil
}

log.Debug("ipns: Falling back to resolution.")
log.Debug("ipns: Falling back to resolution for [%s].", name)
resolved, err := s.Ipfs.Namesys.Resolve(name)
if err != nil {
log.Error("ipns: namesys resolve error: %s", err)
return nil, fuse.ENOENT
}

return &Link{s.IpfsRoot + "/" + resolved}, nil
return &Link{s.IpfsRoot + "/" + u.Key(resolved).Pretty()}, nil
}

// ReadDir reads a particular directory. Disallowed for root.
Expand Down Expand Up @@ -221,7 +227,7 @@ func (s *Node) Attr() fuse.Attr {

// Lookup performs a lookup under this node.
func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
log.Debug("ipns node Lookup '%s'", name)
log.Debug("ipns: node Lookup '%s'", name)
nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
if err != nil {
// todo: make this error more versatile.
Expand Down Expand Up @@ -276,7 +282,7 @@ func (n *Node) Write(req *fuse.WriteRequest, resp *fuse.WriteResponse, intr fs.I
if n.dataBuf == nil {
n.dataBuf = new(bytes.Buffer)
}
log.Debug("ipns Node Write: flags = %s, offset = %d, size = %d", req.Flags.String(), req.Offset, len(req.Data))
log.Debug("ipns: Node Write: flags = %s, offset = %d, size = %d", req.Flags.String(), req.Offset, len(req.Data))
if req.Offset == 0 {
n.dataBuf.Reset()
n.dataBuf.Write(req.Data)
Expand All @@ -298,11 +304,18 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
// but for now, since the buf is all in memory anyways...
err := imp.NewDagInNode(n.dataBuf, n.Nd)
if err != nil {
log.Error("ipns Flush error: %s", err)
log.Error("ipns: Flush error: %s", err)
// return fuse.EVERYBAD
return fuse.ENODATA
}

read, err := mdag.NewDagReader(n.Nd, n.Ipfs.DAG)
if err != nil {
panic(err)
}

io.Copy(os.Stdout, read)

var root *Node
if n.nsRoot != nil {
root = n.nsRoot
Expand All @@ -312,13 +325,13 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {

err = root.Nd.Update()
if err != nil {
log.Error("ipns dag tree update failed: %s", err)
log.Error("ipns: dag tree update failed: %s", err)
return fuse.ENODATA
}

err = n.Ipfs.DAG.AddRecursive(root.Nd)
if err != nil {
log.Critical("ipns Dag Add Error: %s", err)
log.Critical("ipns: Dag Add Error: %s", err)
}

n.changed = false
Expand All @@ -332,9 +345,9 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
}
log.Debug("Publishing changes!")

err = n.Ipfs.Publisher.Publish(root.key, ndkey)
err = n.Ipfs.Publisher.Publish(root.key, ndkey.Pretty())
if err != nil {
log.Error("ipns Publish Failed: %s", err)
log.Error("ipns: Publish Failed: %s", err)
}
}
return nil
Expand Down Expand Up @@ -433,5 +446,6 @@ func (l *Link) Attr() fuse.Attr {
}

func (l *Link) Readlink(req *fuse.ReadlinkRequest, intr fs.Intr) (string, fuse.Error) {
log.Debug("ReadLink: %s", l.Target)
return l.Target, nil
}
2 changes: 1 addition & 1 deletion importer/importer.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func NewDagInNode(r io.Reader, n *dag.Node) error {

blkChan := DefaultSplitter.Split(r)
first := <-blkChan
n.Data = first
n.Data = dag.FilePBData(first)

for blk := range blkChan {
child := &dag.Node{Data: dag.WrapData(blk)}
Expand Down
2 changes: 2 additions & 0 deletions namesys/nsresolver.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package namesys

type Resolver interface {
// Resolve returns a base58 encoded string
Resolve(string) (string, error)

Matches(string) bool
}
6 changes: 3 additions & 3 deletions namesys/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func NewPublisher(dag *mdag.DAGService, route routing.IpfsRouting) *IpnsPublishe
}

// Publish accepts a keypair and a value,
func (p *IpnsPublisher) Publish(k ci.PrivKey, value u.Key) error {
log.Debug("namesys: Publish %s", value.Pretty())
func (p *IpnsPublisher) Publish(k ci.PrivKey, value string) error {
log.Debug("namesys: Publish %s", value)
ctx := context.TODO()
data, err := CreateEntryData(k, value)
if err != nil {
Expand Down Expand Up @@ -66,7 +66,7 @@ func (p *IpnsPublisher) Publish(k ci.PrivKey, value u.Key) error {
return nil
}

func CreateEntryData(pk ci.PrivKey, val u.Key) ([]byte, error) {
func CreateEntryData(pk ci.PrivKey, val string) ([]byte, error) {
entry := new(IpnsEntry)
sig, err := pk.Sign([]byte(val))
if err != nil {
Expand Down
8 changes: 3 additions & 5 deletions namesys/resolve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ import (
bs "github.com/jbenet/go-ipfs/blockservice"
ci "github.com/jbenet/go-ipfs/crypto"
mdag "github.com/jbenet/go-ipfs/merkledag"
"github.com/jbenet/go-ipfs/net/swarm"
"github.com/jbenet/go-ipfs/peer"
"github.com/jbenet/go-ipfs/routing/dht"
mock "github.com/jbenet/go-ipfs/routing/mock"
u "github.com/jbenet/go-ipfs/util"
)

func TestRoutingResolve(t *testing.T) {
local := &peer.Peer{
ID: []byte("testID"),
}
net := swarm.NewSwarm(local)
lds := ds.NewMapDatastore()
d := dht.NewDHT(local, net, lds)
d := mock.NewMockRouter(local, lds)

bserv, err := bs.NewBlockService(lds, nil)
if err != nil {
Expand All @@ -40,7 +38,7 @@ func TestRoutingResolve(t *testing.T) {
t.Fatal(err)
}

err = pub.Publish(privk, u.Key("Hello"))
err = pub.Publish(privk, "Hello")
if err != nil {
t.Fatal(err)
}
Expand Down
1 change: 1 addition & 0 deletions namesys/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (r *RoutingResolver) Matches(name string) bool {
}

func (r *RoutingResolver) Resolve(name string) (string, error) {
log.Debug("RoutingResolve: '%s'", name)
ctx := context.TODO()
hash, err := mh.FromB58String(name)
if err != nil {
Expand Down
20 changes: 15 additions & 5 deletions path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
merkledag "github.com/jbenet/go-ipfs/merkledag"
u "github.com/jbenet/go-ipfs/util"
"github.com/op/go-logging"
)

var log = logging.MustGetLogger("path")

// Resolver provides path resolution to IPFS
// It has a pointer to a DAGService, which is uses to resolve nodes.
type Resolver struct {
Expand All @@ -20,7 +23,7 @@ type Resolver struct {
// path component as a hash (key) of the first node, then resolves
// all other components walking the links, with ResolveLinks.
func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
u.DOut("Resolve: '%s'\n", fpath)
log.Debug("Resolve: '%s'", fpath)
fpath = path.Clean(fpath)

parts := strings.Split(fpath, "/")
Expand Down Expand Up @@ -66,10 +69,12 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
for _, name := range names {

var next u.Key
var nlink *merkledag.Link
// for each of the links in nd, the current object
for _, link := range nd.Links {
if link.Name == name {
next = u.Key(link.Hash)
nlink = link
break
}
}
Expand All @@ -80,10 +85,15 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
return nil, fmt.Errorf("no link named %q under %s", name, h2)
}

// fetch object for link and assign to nd
nd, err = s.DAG.Get(next)
if err != nil {
return nd, err
if nlink.Node == nil {
// fetch object for link and assign to nd
nd, err = s.DAG.Get(next)
if err != nil {
return nd, err
}
nlink.Node = nd
} else {
nd = nlink.Node
}
}
return
Expand Down
2 changes: 1 addition & 1 deletion routing/dht/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
// PutValue adds value corresponding to given Key.
// This is the top level "Store" operation of the DHT
func (dht *IpfsDHT) PutValue(ctx context.Context, key u.Key, value []byte) error {
log.Debug("[%s] PutValue %v %v", dht.self.ID.Pretty(), key.Pretty(), value)
log.Debug("PutValue %s %v", key.Pretty(), value)
err := dht.putLocal(key, value)
if err != nil {
return err
Expand Down
Loading

0 comments on commit 6080944

Please sign in to comment.