@cryptotaxi247 / kubo / commits / 6080944af

writing files inside ipns works now! also implemented resolve cli command

Jeromy committed Sep 26, 2014 at 12:08 UTC 6080944af992a0793df0917e55a86c8f8f5578c1
14 files changed +144 -28
cmd/ipfs/ipfs.go
+1
@@ -53,6 +53,7 @@ Use "ipfs help <command>" for more information about a command.
53 cmdIpfsServe,
54 cmdIpfsRun,
55 cmdIpfsPub,
56 + cmdIpfsResolve,
57 },
58 Flag: *flag.NewFlagSet("ipfs", flag.ExitOnError),
59 }
cmd/ipfs/resolve.go new
+54
@@ -0,0 +1,54 @@
1 +package main
2 +
3 +import (
4 + "fmt"
5 + "os"
6 + "time"
7 +
8 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/gonuts/flag"
9 + "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/commander"
10 + "github.com/jbenet/go-ipfs/core/commands"
11 + "github.com/jbenet/go-ipfs/daemon"
12 + u "github.com/jbenet/go-ipfs/util"
13 +)
14 +
15 +var cmdIpfsResolve = &commander.Command{
16 + UsageLine: "resolve",
17 + Short: "resolve an ipns link to a hash",
18 + Long: `ipfs resolve <hash>... - Resolve hash.
19 +
20 +`,
21 + Run: resolveCmd,
22 + Flag: *flag.NewFlagSet("ipfs-resolve", flag.ExitOnError),
23 +}
24 +
25 +func resolveCmd(c *commander.Command, inp []string) error {
26 + u.Debug = true
27 + if len(inp) < 1 {
28 + u.POut(c.Long)
29 + return nil
30 + }
31 + conf, err := getConfigDir(c.Parent)
32 + if err != nil {
33 + return err
34 + }
35 +
36 + cmd := daemon.NewCommand()
37 + cmd.Command = "resolve"
38 + cmd.Args = inp
39 + err = daemon.SendCommand(cmd, conf)
40 + if err != nil {
41 + now := time.Now()
42 + // Resolve requires working DHT
43 + n, err := localNode(conf, true)
44 + if err != nil {
45 + return err
46 + }
47 +
48 + took := time.Now().Sub(now)
49 + fmt.Printf("localNode creation took %s\n", took.String())
50 +
51 + return commands.Resolve(n, cmd.Args, cmd.Opts, os.Stdout)
52 + }
53 + return nil
54 +}
core/commands/publish.go
+2 -3
@@ -21,10 +21,9 @@ func Publish(n *core.IpfsNode, args []string, opts map[string]interface{}, out i
21 }
22
23 k := n.Identity.PrivKey
24 - val := u.Key(args[0])
24
25 pub := nsys.NewPublisher(n.DAG, n.Routing)
27 - err := pub.Publish(k, val)
26 + err := pub.Publish(k, args[0])
27 if err != nil {
28 return err
29 }
@@ -33,7 +32,7 @@ func Publish(n *core.IpfsNode, args []string, opts map[string]interface{}, out i
32 if err != nil {
33 return err
34 }
36 - fmt.Fprintf(out, "Published %s to %s\n", val, u.Key(hash).Pretty())
35 + fmt.Fprintf(out, "Published %s to %s\n", args[0], u.Key(hash).Pretty())
36
37 return nil
38 }
core/commands/resolve.go new
+18
@@ -0,0 +1,18 @@
1 +package commands
2 +
3 +import (
4 + "fmt"
5 + "io"
6 +
7 + "github.com/jbenet/go-ipfs/core"
8 +)
9 +
10 +func Resolve(n *core.IpfsNode, args []string, opts map[string]interface{}, out io.Writer) error {
11 + res, err := n.Namesys.Resolve(args[0])
12 + if err != nil {
13 + return err
14 + }
15 +
16 + fmt.Fprintf(out, "%s -> %s\n", args[0], res)
17 + return nil
18 +}
daemon/daemon.go
+2
@@ -133,6 +133,8 @@ func (dl *DaemonListener) handleConnection(conn net.Conn) {
133 err = commands.Pin(dl.node, command.Args, command.Opts, conn)
134 case "publish":
135 err = commands.Publish(dl.node, command.Args, command.Opts, conn)
136 + case "resolve":
137 + err = commands.Resolve(dl.node, command.Args, command.Opts, conn)
138 default:
139 err = fmt.Errorf("Invalid Command: '%s'", command.Command)
140 }
fuse/ipns/ipns_unix.go
+24 -10
@@ -2,6 +2,7 @@ package ipns
2
3 import (
4 "fmt"
5 + "io"
6 "io/ioutil"
7 "os"
8 "os/exec"
@@ -83,6 +84,11 @@ func CreateRoot(n *core.IpfsNode, keys []ci.PrivKey, ipfsroot string) (*Root, er
84 continue
85 }
86
87 + if !u.IsValidHash(pointsTo) {
88 + log.Critical("Got back bad data from namesys resolve! [%s]", pointsTo)
89 + return nil, nil
90 + }
91 +
92 node, err := n.Resolver.ResolvePath(pointsTo)
93 if err != nil {
94 log.Warning("Failed to resolve value from ipns entry in ipfs")
@@ -120,7 +126,7 @@ func (*Root) Attr() fuse.Attr {
126
127 // Lookup performs a lookup under this node.
128 func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
123 - log.Debug("ipns: Root Lookup: '%s'", name)
129 + log.Debug("ipns: Root Lookup: '%s' [intr = %s]", name, intr.String())
130 switch name {
131 case "mach_kernel", ".hidden", "._.":
132 // Just quiet some log noise on OS X.
@@ -139,14 +145,14 @@ func (s *Root) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
145 return nd, nil
146 }
147
142 - log.Debug("ipns: Falling back to resolution.")
148 + log.Debug("ipns: Falling back to resolution for [%s].", name)
149 resolved, err := s.Ipfs.Namesys.Resolve(name)
150 if err != nil {
151 log.Error("ipns: namesys resolve error: %s", err)
152 return nil, fuse.ENOENT
153 }
154
149 - return &Link{s.IpfsRoot + "/" + resolved}, nil
155 + return &Link{s.IpfsRoot + "/" + u.Key(resolved).Pretty()}, nil
156 }
157
158 // ReadDir reads a particular directory. Disallowed for root.
@@ -221,7 +227,7 @@ func (s *Node) Attr() fuse.Attr {
227
228 // Lookup performs a lookup under this node.
229 func (s *Node) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) {
224 - log.Debug("ipns node Lookup '%s'", name)
230 + log.Debug("ipns: node Lookup '%s'", name)
231 nd, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name})
232 if err != nil {
233 // todo: make this error more versatile.
@@ -276,7 +282,7 @@ func (n *Node) Write(req *fuse.WriteRequest, resp *fuse.WriteResponse, intr fs.I
282 if n.dataBuf == nil {
283 n.dataBuf = new(bytes.Buffer)
284 }
279 - log.Debug("ipns Node Write: flags = %s, offset = %d, size = %d", req.Flags.String(), req.Offset, len(req.Data))
285 + log.Debug("ipns: Node Write: flags = %s, offset = %d, size = %d", req.Flags.String(), req.Offset, len(req.Data))
286 if req.Offset == 0 {
287 n.dataBuf.Reset()
288 n.dataBuf.Write(req.Data)
@@ -298,11 +304,18 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
304 // but for now, since the buf is all in memory anyways...
305 err := imp.NewDagInNode(n.dataBuf, n.Nd)
306 if err != nil {
301 - log.Error("ipns Flush error: %s", err)
307 + log.Error("ipns: Flush error: %s", err)
308 // return fuse.EVERYBAD
309 return fuse.ENODATA
310 }
311
312 + read, err := mdag.NewDagReader(n.Nd, n.Ipfs.DAG)
313 + if err != nil {
314 + panic(err)
315 + }
316 +
317 + io.Copy(os.Stdout, read)
318 +
319 var root *Node
320 if n.nsRoot != nil {
321 root = n.nsRoot
@@ -312,13 +325,13 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
325
326 err = root.Nd.Update()
327 if err != nil {
315 - log.Error("ipns dag tree update failed: %s", err)
328 + log.Error("ipns: dag tree update failed: %s", err)
329 return fuse.ENODATA
330 }
331
332 err = n.Ipfs.DAG.AddRecursive(root.Nd)
333 if err != nil {
321 - log.Critical("ipns Dag Add Error: %s", err)
334 + log.Critical("ipns: Dag Add Error: %s", err)
335 }
336
337 n.changed = false
@@ -332,9 +345,9 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error {
345 }
346 log.Debug("Publishing changes!")
347
335 - err = n.Ipfs.Publisher.Publish(root.key, ndkey)
348 + err = n.Ipfs.Publisher.Publish(root.key, ndkey.Pretty())
349 if err != nil {
337 - log.Error("ipns Publish Failed: %s", err)
350 + log.Error("ipns: Publish Failed: %s", err)
351 }
352 }
353 return nil
@@ -433,5 +446,6 @@ func (l *Link) Attr() fuse.Attr {
446 }
447
448 func (l *Link) Readlink(req *fuse.ReadlinkRequest, intr fs.Intr) (string, fuse.Error) {
449 + log.Debug("ReadLink: %s", l.Target)
450 return l.Target, nil
451 }
importer/importer.go
+1 -1
@@ -67,7 +67,7 @@ func NewDagInNode(r io.Reader, n *dag.Node) error {
67
68 blkChan := DefaultSplitter.Split(r)
69 first := <-blkChan
70 - n.Data = first
70 + n.Data = dag.FilePBData(first)
71
72 for blk := range blkChan {
73 child := &dag.Node{Data: dag.WrapData(blk)}
namesys/nsresolver.go
+2
@@ -1,6 +1,8 @@
1 package namesys
2
3 type Resolver interface {
4 + // Resolve returns a base58 encoded string
5 Resolve(string) (string, error)
6 +
7 Matches(string) bool
8 }
namesys/publisher.go
+3 -3
@@ -25,8 +25,8 @@ func NewPublisher(dag *mdag.DAGService, route routing.IpfsRouting) *IpnsPublishe
25 }
26
27 // Publish accepts a keypair and a value,
28 -func (p *IpnsPublisher) Publish(k ci.PrivKey, value u.Key) error {
29 - log.Debug("namesys: Publish %s", value.Pretty())
28 +func (p *IpnsPublisher) Publish(k ci.PrivKey, value string) error {
29 + log.Debug("namesys: Publish %s", value)
30 ctx := context.TODO()
31 data, err := CreateEntryData(k, value)
32 if err != nil {
@@ -66,7 +66,7 @@ func (p *IpnsPublisher) Publish(k ci.PrivKey, value u.Key) error {
66 return nil
67 }
68
69 -func CreateEntryData(pk ci.PrivKey, val u.Key) ([]byte, error) {
69 +func CreateEntryData(pk ci.PrivKey, val string) ([]byte, error) {
70 entry := new(IpnsEntry)
71 sig, err := pk.Sign([]byte(val))
72 if err != nil {
namesys/resolve_test.go
+3 -5
@@ -7,9 +7,8 @@ import (
7 bs "github.com/jbenet/go-ipfs/blockservice"
8 ci "github.com/jbenet/go-ipfs/crypto"
9 mdag "github.com/jbenet/go-ipfs/merkledag"
10 - "github.com/jbenet/go-ipfs/net/swarm"
10 "github.com/jbenet/go-ipfs/peer"
12 - "github.com/jbenet/go-ipfs/routing/dht"
11 + mock "github.com/jbenet/go-ipfs/routing/mock"
12 u "github.com/jbenet/go-ipfs/util"
13 )
14
@@ -17,9 +16,8 @@ func TestRoutingResolve(t *testing.T) {
16 local := &peer.Peer{
17 ID: []byte("testID"),
18 }
20 - net := swarm.NewSwarm(local)
19 lds := ds.NewMapDatastore()
22 - d := dht.NewDHT(local, net, lds)
20 + d := mock.NewMockRouter(local, lds)
21
22 bserv, err := bs.NewBlockService(lds, nil)
23 if err != nil {
@@ -40,7 +38,7 @@ func TestRoutingResolve(t *testing.T) {
38 t.Fatal(err)
39 }
40
43 - err = pub.Publish(privk, u.Key("Hello"))
41 + err = pub.Publish(privk, "Hello")
42 if err != nil {
43 t.Fatal(err)
44 }
namesys/routing.go
+1
@@ -35,6 +35,7 @@ func (r *RoutingResolver) Matches(name string) bool {
35 }
36
37 func (r *RoutingResolver) Resolve(name string) (string, error) {
38 + log.Debug("RoutingResolve: '%s'", name)
39 ctx := context.TODO()
40 hash, err := mh.FromB58String(name)
41 if err != nil {
path/path.go
+15 -5
@@ -8,8 +8,11 @@ import (
8 mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
9 merkledag "github.com/jbenet/go-ipfs/merkledag"
10 u "github.com/jbenet/go-ipfs/util"
11 + "github.com/op/go-logging"
12 )
13
14 +var log = logging.MustGetLogger("path")
15 +
16 // Resolver provides path resolution to IPFS
17 // It has a pointer to a DAGService, which is uses to resolve nodes.
18 type Resolver struct {
@@ -20,7 +23,7 @@ type Resolver struct {
23 // path component as a hash (key) of the first node, then resolves
24 // all other components walking the links, with ResolveLinks.
25 func (s *Resolver) ResolvePath(fpath string) (*merkledag.Node, error) {
23 - u.DOut("Resolve: '%s'\n", fpath)
26 + log.Debug("Resolve: '%s'", fpath)
27 fpath = path.Clean(fpath)
28
29 parts := strings.Split(fpath, "/")
@@ -66,10 +69,12 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
69 for _, name := range names {
70
71 var next u.Key
72 + var nlink *merkledag.Link
73 // for each of the links in nd, the current object
74 for _, link := range nd.Links {
75 if link.Name == name {
76 next = u.Key(link.Hash)
77 + nlink = link
78 break
79 }
80 }
@@ -80,10 +85,15 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) (
85 return nil, fmt.Errorf("no link named %q under %s", name, h2)
86 }
87
83 - // fetch object for link and assign to nd
84 - nd, err = s.DAG.Get(next)
85 - if err != nil {
86 - return nd, err
88 + if nlink.Node == nil {
89 + // fetch object for link and assign to nd
90 + nd, err = s.DAG.Get(next)
91 + if err != nil {
92 + return nd, err
93 + }
94 + nlink.Node = nd
95 + } else {
96 + nd = nlink.Node
97 }
98 }
99 return
routing/dht/routing.go
+1 -1
@@ -18,7 +18,7 @@ import (
18 // PutValue adds value corresponding to given Key.
19 // This is the top level "Store" operation of the DHT
20 func (dht *IpfsDHT) PutValue(ctx context.Context, key u.Key, value []byte) error {
21 - log.Debug("[%s] PutValue %v %v", dht.self.ID.Pretty(), key.Pretty(), value)
21 + log.Debug("PutValue %s %v", key.Pretty(), value)
22 err := dht.putLocal(key, value)
23 if err != nil {
24 return err
util/util.go
+17
@@ -11,8 +11,17 @@ import (
11 ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"
12 b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
13 mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
14 + "github.com/op/go-logging"
15 )
16
17 +var format = "%{color}%{time} %{shortfile} %{level}: %{color:reset}%{message}"
18 +
19 +func init() {
20 + backend := logging.NewLogBackend(os.Stderr, "", 0)
21 + logging.SetBackend(backend)
22 + logging.SetFormatter(logging.MustStringFormatter(format))
23 +}
24 +
25 // Debug is a global flag for debugging.
26 var Debug bool
27
@@ -42,6 +51,14 @@ func Hash(data []byte) (mh.Multihash, error) {
51 return mh.Sum(data, mh.SHA2_256, -1)
52 }
53
54 +func IsValidHash(s string) bool {
55 + out := b58.Decode(s)
56 + if out == nil || len(out) == 0 {
57 + return false
58 + }
59 + return true
60 +}
61 +
62 // TildeExpansion expands a filename, which may begin with a tilde.
63 func TildeExpansion(filename string) (string, error) {
64 if strings.HasPrefix(filename, "~/") {