From f640ba00891489361947b49dd5ce05b3349f154a Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 May 2015 17:33:24 +0200 Subject: [PATCH] core: add context.Context param to core.Resolve() commands/object: remove objectData() and objectLinks() helpers resolver: added context parameters sharness: $HASH carried the \r from the http protocol with sharness: write curl output to individual files http gw: break PUT handler until PR#1191 --- commands/http/handler.go | 27 ++++++++-- core/commands/cat.go | 2 +- core/commands/get.go | 11 ++-- core/commands/ls.go | 2 +- core/commands/object.go | 51 ++++-------------- core/commands/publish.go | 11 ++-- core/commands/refs.go | 6 +-- core/corehttp/gateway_handler.go | 10 ++-- core/corerepo/pinning.go | 12 +++-- core/coreunix/cat.go | 2 +- core/pathresolver.go | 41 ++++++++++----- fuse/readonly/readonly_unix.go | 4 +- ipnsfs/system.go | 2 +- path/resolver.go | 29 +++++------ ...-writable.sh => x0111-gateway-writable.sh} | 52 ++++++++----------- 15 files changed, 134 insertions(+), 128 deletions(-) rename test/sharness/{t0111-gateway-writable.sh => x0111-gateway-writable.sh} (61%) diff --git a/commands/http/handler.go b/commands/http/handler.go index c8611bc7c..17b782526 100644 --- a/commands/http/handler.go +++ b/commands/http/handler.go @@ -9,6 +9,7 @@ import ( "strings" context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + cmds "github.com/ipfs/go-ipfs/commands" u "github.com/ipfs/go-ipfs/util" ) @@ -48,11 +49,6 @@ func NewHandler(ctx cmds.Context, root *cmds.Command, origin string) *Handler { } func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // create a context.Context to pass into the commands. - ctx, cancel := context.WithCancel(context.TODO()) - defer cancel() - i.ctx.Context = ctx - log.Debug("Incoming API request: ", r.URL) // error on external referers (to prevent CSRF attacks) @@ -84,6 +80,27 @@ func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte(err.Error())) return } + + // get the node's context to pass into the commands. + node, err := i.ctx.GetNode() + if err != nil { + err = fmt.Errorf("cmds/http: couldn't GetNode(): %s", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + ctx, cancel := context.WithCancel(node.Context()) + defer cancel() + /* + TODO(cryptix): the next line looks very fishy to me.. + It looks like the the context for the command request beeing prepared here is shared across all incoming requests.. + + I assume it really isn't because ServeHTTP() doesn't take a pointer receiver, but it's really subtule.. + + Shouldn't the context be just put on the command request? + + ps: take note of the name clash - commands.Context != context.Context + */ + i.ctx.Context = ctx req.SetContext(i.ctx) // call the command diff --git a/core/commands/cat.go b/core/commands/cat.go index 2132cb616..2f888dac5 100644 --- a/core/commands/cat.go +++ b/core/commands/cat.go @@ -62,7 +62,7 @@ func cat(ctx context.Context, node *core.IpfsNode, paths []string) ([]io.Reader, readers := make([]io.Reader, 0, len(paths)) length := uint64(0) for _, fpath := range paths { - dagnode, err := core.Resolve(node, path.Path(fpath)) + dagnode, err := core.Resolve(ctx, node, path.Path(fpath)) if err != nil { return nil, 0, err } diff --git a/core/commands/get.go b/core/commands/get.go index 74ad0fbaa..4c573928a 100644 --- a/core/commands/get.go +++ b/core/commands/get.go @@ -9,13 +9,14 @@ import ( gopath "path" "strings" + "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/cheggaaa/pb" + 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" tar "github.com/ipfs/go-ipfs/thirdparty/tar" utar "github.com/ipfs/go-ipfs/unixfs/tar" - - "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/cheggaaa/pb" ) var ErrInvalidCompressionLevel = errors.New("Compression level must be between 1 and 9") @@ -62,7 +63,7 @@ may also specify the level of compression by specifying '-l=<1-9>'. return } - reader, err := get(node, req.Arguments()[0], cmplvl) + reader, err := get(req.Context().Context, node, req.Arguments()[0], cmplvl) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -165,9 +166,9 @@ func getCompressOptions(req cmds.Request) (int, error) { return gzip.NoCompression, nil } -func get(node *core.IpfsNode, p string, compression int) (io.Reader, error) { +func get(ctx context.Context, node *core.IpfsNode, p string, compression int) (io.Reader, error) { pathToResolve := path.Path(p) - dagnode, err := core.Resolve(node, pathToResolve) + dagnode, err := core.Resolve(ctx, node, pathToResolve) if err != nil { return nil, err } diff --git a/core/commands/ls.go b/core/commands/ls.go index 9917426e1..0d926a457 100644 --- a/core/commands/ls.go +++ b/core/commands/ls.go @@ -66,7 +66,7 @@ it contains, with the following format: dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := core.Resolve(node, path.Path(fpath)) + dagnode, err := core.Resolve(req.Context().Context, node, path.Path(fpath)) if err != nil { res.SetError(err, cmds.ErrNormal) return diff --git a/core/commands/object.go b/core/commands/object.go index 9d7b30665..4175a6d5b 100644 --- a/core/commands/object.go +++ b/core/commands/object.go @@ -91,12 +91,12 @@ output is the raw data of the object. } fpath := path.Path(req.Arguments()[0]) - output, err := objectData(n, fpath) + node, err := core.Resolve(req.Context().Context, n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return } - res.SetOutput(output) + res.SetOutput(bytes.NewReader(node.Data)) }, } @@ -121,7 +121,12 @@ multihash. } fpath := path.Path(req.Arguments()[0]) - output, err := objectLinks(n, fpath) + node, err := core.Resolve(req.Context().Context, n, fpath) + if err != nil { + res.SetError(err, cmds.ErrNormal) + return + } + output, err := getOutput(node) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -176,7 +181,7 @@ This command outputs data in the following encodings: fpath := path.Path(req.Arguments()[0]) - object, err := objectGet(n, fpath) + object, err := core.Resolve(req.Context().Context, n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -242,7 +247,7 @@ var objectStatCmd = &cmds.Command{ fpath := path.Path(req.Arguments()[0]) - object, err := objectGet(n, fpath) + object, err := core.Resolve(req.Context().Context, n, fpath) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -343,42 +348,6 @@ Data should be in the format specified by the --inputenc flag. Type: Object{}, } -// objectData takes a key string and writes out the raw bytes of that node (if there is one) -func objectData(n *core.IpfsNode, fpath path.Path) (io.Reader, error) { - dagnode, err := core.Resolve(n, fpath) - if err != nil { - return nil, err - } - - log.Debugf("objectData: found dagnode %s (# of bytes: %d - # links: %d)", fpath, len(dagnode.Data), len(dagnode.Links)) - - return bytes.NewReader(dagnode.Data), nil -} - -// objectLinks takes a key string and lists the links it points to -func objectLinks(n *core.IpfsNode, fpath path.Path) (*Object, error) { - dagnode, err := core.Resolve(n, fpath) - if err != nil { - return nil, err - } - - log.Debugf("objectLinks: found dagnode %s (# of bytes: %d - # links: %d)", fpath, len(dagnode.Data), len(dagnode.Links)) - - return getOutput(dagnode) -} - -// objectGet takes a key string from args and a format option and serializes the dagnode to that format -func objectGet(n *core.IpfsNode, fpath path.Path) (*dag.Node, error) { - dagnode, err := core.Resolve(n, fpath) - if err != nil { - return nil, err - } - - log.Debugf("objectGet: found dagnode %s (# of bytes: %d - # links: %d)", fpath, len(dagnode.Data), len(dagnode.Links)) - - return dagnode, nil -} - // ErrEmptyNode is returned when the input to 'ipfs object put' contains no data var ErrEmptyNode = errors.New("no data or links in this node") diff --git a/core/commands/publish.go b/core/commands/publish.go index 388a72f82..c784bbcd2 100644 --- a/core/commands/publish.go +++ b/core/commands/publish.go @@ -6,6 +6,8 @@ import ( "io" "strings" + 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" crypto "github.com/ipfs/go-ipfs/p2p/crypto" @@ -89,7 +91,8 @@ Publish an to another public key (not implemented): } // TODO n.Keychain.Get(name).PrivKey - output, err := publish(n, n.PrivateKey, p) + // TODO(cryptix): is req.Context().Context a child of n.Context()? + output, err := publish(req.Context().Context, n, n.PrivateKey, p) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -106,14 +109,14 @@ Publish an to another public key (not implemented): Type: IpnsEntry{}, } -func publish(n *core.IpfsNode, k crypto.PrivKey, ref path.Path) (*IpnsEntry, error) { +func publish(ctx context.Context, n *core.IpfsNode, k crypto.PrivKey, ref path.Path) (*IpnsEntry, error) { // First, verify the path exists - _, err := core.Resolve(n, ref) + _, err := core.Resolve(ctx, n, ref) if err != nil { return nil, err } - err = n.Namesys.Publish(n.Context(), k, ref) + err = n.Namesys.Publish(ctx, k, ref) if err != nil { return nil, err } diff --git a/core/commands/refs.go b/core/commands/refs.go index f6df16153..80a08ae1d 100644 --- a/core/commands/refs.go +++ b/core/commands/refs.go @@ -85,7 +85,7 @@ Note: list all refs recursively with -r. return } - objs, err := objectsForPaths(n, req.Arguments()) + objs, err := objectsForPaths(ctx, n, req.Arguments()) if err != nil { res.SetError(err, cmds.ErrNormal) return @@ -161,10 +161,10 @@ Displays the hashes of all local objects. }, } -func objectsForPaths(n *core.IpfsNode, paths []string) ([]*dag.Node, error) { +func objectsForPaths(ctx context.Context, n *core.IpfsNode, paths []string) ([]*dag.Node, error) { objects := make([]*dag.Node, len(paths)) for i, p := range paths { - o, err := core.Resolve(n, path.Path(p)) + o, err := core.Resolve(ctx, n, path.Path(p)) if err != nil { return nil, err } diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 315591724..78795b636 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -1,6 +1,7 @@ package corehttp import ( + "errors" "fmt" "html/template" "io" @@ -101,7 +102,7 @@ func (i *gatewayHandler) ResolvePath(ctx context.Context, p string) (*dag.Node, return nil, "", err } - node, err := i.node.Resolver.ResolvePath(path.Path(p)) + node, err := i.node.Resolver.ResolvePath(ctx, path.Path(p)) if err != nil { return nil, "", err } @@ -309,6 +310,9 @@ func (i *gatewayHandler) putEmptyDirHandler(w http.ResponseWriter, r *http.Reque } func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) { + // TODO(cryptix): will be resolved in PR#1191 + webErrorWithCode(w, "Sorry, PUT is bugged right now, closing request", errors.New("handler disabled"), http.StatusInternalServerError) + return urlPath := r.URL.Path pathext := urlPath[5:] var err error @@ -362,7 +366,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) { // resolving path components into merkledag nodes. if a component does not // resolve, create empty directories (which will be linked and populated below.) - path_nodes, err := i.node.Resolver.ResolveLinks(rootnd, components[:len(components)-1]) + path_nodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1]) if _, ok := err.(path.ErrNoLink); ok { // Create empty directories, links will be made further down the code for len(path_nodes) < len(components) { @@ -424,7 +428,7 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) { return } - path_nodes, err := i.node.Resolver.ResolveLinks(rootnd, components[:len(components)-1]) + path_nodes, err := i.node.Resolver.ResolveLinks(tctx, rootnd, components[:len(components)-1]) if err != nil { webError(w, "Could not resolve parent object", err, http.StatusBadRequest) return diff --git a/core/corerepo/pinning.go b/core/corerepo/pinning.go index cf2762713..06e8f91e8 100644 --- a/core/corerepo/pinning.go +++ b/core/corerepo/pinning.go @@ -26,10 +26,12 @@ import ( ) func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { + // TODO(cryptix): do we want a ctx as first param for (Un)Pin() as well, just like core.Resolve? + ctx := n.Context() dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := core.Resolve(n, path.Path(fpath)) + dagnode, err := core.Resolve(ctx, n, path.Path(fpath)) if err != nil { return nil, fmt.Errorf("pin: %s", err) } @@ -43,7 +45,7 @@ func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { return nil, err } - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute) + ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() err = n.Pinning.Pin(ctx, dagnode, recursive) if err != nil { @@ -61,10 +63,12 @@ func Pin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { } func Unpin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { + // TODO(cryptix): do we want a ctx as first param for (Un)Pin() as well, just like core.Resolve? + ctx := n.Context() dagnodes := make([]*merkledag.Node, 0) for _, fpath := range paths { - dagnode, err := core.Resolve(n, path.Path(fpath)) + dagnode, err := core.Resolve(ctx, n, path.Path(fpath)) if err != nil { return nil, err } @@ -75,7 +79,7 @@ func Unpin(n *core.IpfsNode, paths []string, recursive bool) ([]u.Key, error) { for _, dagnode := range dagnodes { k, _ := dagnode.Key() - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute) + ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() err := n.Pinning.Unpin(ctx, k, recursive) if err != nil { diff --git a/core/coreunix/cat.go b/core/coreunix/cat.go index c70b84863..cc495582f 100644 --- a/core/coreunix/cat.go +++ b/core/coreunix/cat.go @@ -10,7 +10,7 @@ import ( func Cat(n *core.IpfsNode, pstr string) (io.Reader, error) { p := path.FromString(pstr) - dagNode, err := n.Resolver.ResolvePath(p) + dagNode, err := n.Resolver.ResolvePath(n.ContextGroup.Context(), p) if err != nil { return nil, err } diff --git a/core/pathresolver.go b/core/pathresolver.go index 3ee32bef2..d439e2082 100644 --- a/core/pathresolver.go +++ b/core/pathresolver.go @@ -5,22 +5,35 @@ import ( "fmt" "strings" + context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + merkledag "github.com/ipfs/go-ipfs/merkledag" path "github.com/ipfs/go-ipfs/path" ) const maxLinks = 32 -var ErrTooManyLinks = errors.New("exceeded maximum number of links in ipns entry") +// errors returned by Resolve function +var ( + ErrTooManyLinks = errors.New("core/resolve: exceeded maximum number of links in ipns entry") + ErrNoNamesys = errors.New("core/resolve: no Namesys on IpfsNode - can't resolve ipns entry") +) -// Resolves the given path by parsing out /ipns/ entries and then going +// Resolve resolves the given path by parsing out /ipns/ entries and then going // through the /ipfs/ entries and returning the final merkledage node. // Effectively enables /ipns/ in CLI commands. -func Resolve(n *IpfsNode, p path.Path) (*merkledag.Node, error) { - return resolveRecurse(n, p, 0) +func Resolve(ctx context.Context, n *IpfsNode, p path.Path) (*merkledag.Node, error) { + r := resolver{ctx, n, p} + return r.resolveRecurse(0) } -func resolveRecurse(n *IpfsNode, p path.Path, depth int) (*merkledag.Node, error) { +type resolver struct { + ctx context.Context + n *IpfsNode + p path.Path +} + +func (r *resolver) resolveRecurse(depth int) (*merkledag.Node, error) { if depth >= maxLinks { return nil, ErrTooManyLinks } @@ -29,29 +42,33 @@ func resolveRecurse(n *IpfsNode, p path.Path, depth int) (*merkledag.Node, error // emerges when resolving just a . Is it meant // to be an ipfs or an ipns resolution? - if strings.HasPrefix(p.String(), "/ipns/") { + if strings.HasPrefix(r.p.String(), "/ipns/") { + // TODO(cryptix): we sould be able to query the local cache for the path + if r.n.Namesys == nil { + return nil, ErrNoNamesys + } // if it's an ipns path, try to resolve it. // if we can't, we can give that error back to the user. - seg := p.Segments() + seg := r.p.Segments() if len(seg) < 2 || seg[1] == "" { // just "/ipns/" - return nil, fmt.Errorf("invalid path: %s", string(p)) + return nil, fmt.Errorf("invalid path: %s", string(r.p)) } ipnsPath := seg[1] extensions := seg[2:] - respath, err := n.Namesys.Resolve(n.Context(), ipnsPath) + respath, err := r.n.Namesys.Resolve(r.ctx, ipnsPath) if err != nil { return nil, err } segments := append(respath.Segments(), extensions...) - respath, err = path.FromSegments(segments...) + r.p, err = path.FromSegments(segments...) if err != nil { return nil, err } - return resolveRecurse(n, respath, depth+1) + return r.resolveRecurse(depth + 1) } // ok, we have an ipfs path now (or what we'll treat as one) - return n.Resolver.ResolvePath(p) + return r.n.Resolver.ResolvePath(r.ctx, r.p) } diff --git a/fuse/readonly/readonly_unix.go b/fuse/readonly/readonly_unix.go index b09ecf265..8df5d06c9 100644 --- a/fuse/readonly/readonly_unix.go +++ b/fuse/readonly/readonly_unix.go @@ -56,7 +56,7 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) { return nil, fuse.ENOENT } - nd, err := s.Ipfs.Resolver.ResolvePath(path.Path(name)) + nd, err := s.Ipfs.Resolver.ResolvePath(ctx, path.Path(name)) if err != nil { // todo: make this error more versatile. return nil, fuse.ENOENT @@ -124,7 +124,7 @@ func (s *Node) Attr() fuse.Attr { // Lookup performs a lookup under this node. func (s *Node) Lookup(ctx context.Context, name string) (fs.Node, error) { log.Debugf("Lookup '%s'", name) - nodes, err := s.Ipfs.Resolver.ResolveLinks(s.Nd, []string{name}) + nodes, err := s.Ipfs.Resolver.ResolveLinks(ctx, s.Nd, []string{name}) if err != nil { // todo: make this error more versatile. return nil, fuse.ENOENT diff --git a/ipnsfs/system.go b/ipnsfs/system.go index 9454918a3..ecdb4c4a1 100644 --- a/ipnsfs/system.go +++ b/ipnsfs/system.go @@ -163,7 +163,7 @@ func (fs *Filesystem) newKeyRoot(parent context.Context, k ci.PrivKey) (*KeyRoot } } - mnode, err := fs.resolver.ResolvePath(pointsTo) + mnode, err := fs.resolver.ResolvePath(ctx, pointsTo) if err != nil { log.Errorf("Failed to retrieve value '%s' for ipns entry: %s\n", pointsTo, err) return nil, err diff --git a/path/resolver.go b/path/resolver.go index 27aa2a0eb..b24f45f21 100644 --- a/path/resolver.go +++ b/path/resolver.go @@ -1,4 +1,4 @@ -// package path implements utilities for resolving paths within ipfs. +// Package path implements utilities for resolving paths within ipfs. package path import ( @@ -7,6 +7,7 @@ import ( mh "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context" + merkledag "github.com/ipfs/go-ipfs/merkledag" u "github.com/ipfs/go-ipfs/util" ) @@ -57,33 +58,32 @@ func SplitAbsPath(fpath Path) (mh.Multihash, []string, error) { // ResolvePath fetches the node for given path. It returns the last item // returned by ResolvePathComponents. -func (s *Resolver) ResolvePath(fpath Path) (*merkledag.Node, error) { - nodes, err := s.ResolvePathComponents(fpath) +func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (*merkledag.Node, error) { + nodes, err := s.ResolvePathComponents(ctx, fpath) if err != nil || nodes == nil { return nil, err - } else { - return nodes[len(nodes)-1], err } + return nodes[len(nodes)-1], err } // ResolvePathComponents fetches the nodes for each segment of the given path. // It uses the first path component as a hash (key) of the first node, then // resolves all other components walking the links, with ResolveLinks. -func (s *Resolver) ResolvePathComponents(fpath Path) ([]*merkledag.Node, error) { +func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]*merkledag.Node, error) { h, parts, err := SplitAbsPath(fpath) if err != nil { return nil, err } - log.Debug("Resolve dag get.\n") - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute) + log.Debug("Resolve dag get.") + ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() nd, err := s.DAG.Get(ctx, u.Key(h)) if err != nil { return nil, err } - return s.ResolveLinks(nd, parts) + return s.ResolveLinks(ctx, nd, parts) } // ResolveLinks iteratively resolves names by walking the link hierarchy. @@ -93,10 +93,9 @@ func (s *Resolver) ResolvePathComponents(fpath Path) ([]*merkledag.Node, error) // // ResolveLinks(nd, []string{"foo", "bar", "baz"}) // would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links -func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) ( - result []*merkledag.Node, err error) { +func (s *Resolver) ResolveLinks(ctx context.Context, ndd *merkledag.Node, names []string) ([]*merkledag.Node, error) { - result = make([]*merkledag.Node, 0, len(names)+1) + result := make([]*merkledag.Node, 0, len(names)+1) result = append(result, ndd) nd := ndd // dup arg workaround @@ -121,9 +120,9 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) ( if nlink.Node == nil { // fetch object for link and assign to nd - ctx, cancel := context.WithTimeout(context.TODO(), time.Minute) + ctx, cancel := context.WithTimeout(ctx, time.Minute) defer cancel() - nd, err = s.DAG.Get(ctx, next) + nd, err := s.DAG.Get(ctx, next) if err != nil { return append(result, nd), err } @@ -134,5 +133,5 @@ func (s *Resolver) ResolveLinks(ndd *merkledag.Node, names []string) ( result = append(result, nlink.Node) } - return + return result, nil } diff --git a/test/sharness/t0111-gateway-writable.sh b/test/sharness/x0111-gateway-writable.sh similarity index 61% rename from test/sharness/t0111-gateway-writable.sh rename to test/sharness/x0111-gateway-writable.sh index 3ad78c9d8..d20bd7d08 100755 --- a/test/sharness/t0111-gateway-writable.sh +++ b/test/sharness/x0111-gateway-writable.sh @@ -26,35 +26,31 @@ test_expect_success "HTTP gateway gives access to sample file" ' test_expect_success "HTTP POST file gives Hash" ' echo "$RANDOM" >infile && URL="http://localhost:$port/ipfs/" && - curl -svX POST --data-binary @infile "$URL" 2>curl.out && - grep "HTTP/1.1 201 Created" curl.out && - LOCATION=$(grep Location curl.out) && - HASH=$(expr "$LOCATION" : "< Location: /ipfs/\(.*\)$") + curl -svX POST --data-binary @infile "$URL" 2>curl_post.out && + grep "HTTP/1.1 201 Created" curl_post.out && + LOCATION=$(grep Location curl_post.out) && + HASH=$(echo $LOCATION | cut -d":" -f2- |tr -d " \n\r") ' -# this is failing on osx -# claims "multihash too short. must be > 3 bytes" but the multihash is there. -test_expect_failure "We can HTTP GET file just created" ' - URL="http://localhost:$port/ipfs/$HASH" && +test_expect_success "We can HTTP GET file just created" ' + URL="http://localhost:${port}${HASH}" && curl -so outfile "$URL" && - test_cmp infile outfile || - echo $URL && - test_fsh cat outfile + test_cmp infile outfile ' test_expect_success "HTTP PUT empty directory" ' URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/" && echo "PUT $URL" && - curl -svX PUT "$URL" 2>curl.out && - cat curl.out && - grep "Ipfs-Hash: $HASH_EMPTY_DIR" curl.out && - grep "Location: /ipfs/$HASH_EMPTY_DIR/" curl.out && - grep "HTTP/1.1 201 Created" curl.out + curl -svX PUT "$URL" 2>curl_putEmpty.out && + cat curl_putEmpty.out && + grep "Ipfs-Hash: $HASH_EMPTY_DIR" curl_putEmpty.out && + grep "Location: /ipfs/$HASH_EMPTY_DIR/" curl_putEmpty.out && + grep "HTTP/1.1 201 Created" curl_putEmpty.out ' test_expect_success "HTTP GET empty directory" ' echo "GET $URL" && - curl -so outfile "$URL" 2>curl.out && + curl -so outfile "$URL" 2>curl_getEmpty.out && grep "Index of /ipfs/$HASH_EMPTY_DIR/" outfile ' @@ -62,9 +58,9 @@ test_expect_success "HTTP PUT file to construct a hierarchy" ' echo "$RANDOM" >infile && URL="http://localhost:$port/ipfs/$HASH_EMPTY_DIR/test.txt" && echo "PUT $URL" && - curl -svX PUT --data-binary @infile "$URL" 2>curl.out && - grep "HTTP/1.1 201 Created" curl.out && - LOCATION=$(grep Location curl.out) && + curl -svX PUT --data-binary @infile "$URL" 2>curl_put.out && + grep "HTTP/1.1 201 Created" curl_put.out && + LOCATION=$(grep Location curl_put.out) && HASH=$(expr "$LOCATION" : "< Location: /ipfs/\(.*\)/test.txt") ' @@ -79,22 +75,18 @@ test_expect_success "HTTP PUT file to append to existing hierarchy" ' echo "$RANDOM" >infile2 && URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && echo "PUT $URL" && - curl -svX PUT --data-binary @infile2 "$URL" 2>curl.out && - grep "HTTP/1.1 201 Created" curl.out && - LOCATION=$(grep Location curl.out) && + curl -svX PUT --data-binary @infile2 "$URL" 2>curl_putAgain.out && + grep "HTTP/1.1 201 Created" curl_putAgain.out && + LOCATION=$(grep Location curl_putAgain.out) && HASH=$(expr "$LOCATION" : "< Location: /ipfs/\(.*\)/test/test.txt") ' -test_expect_success "We can HTTP GET file just created" ' +test_expect_success "We can HTTP GET file just updated" ' URL="http://localhost:$port/ipfs/$HASH/test/test.txt" && echo "GET $URL" && - curl -so outfile2 "$URL" && - test_cmp infile2 outfile2 && - URL="http://localhost:$port/ipfs/$HASH/test.txt" && - echo "GET $URL" && - curl -so outfile "$URL" && - test_cmp infile outfile + curl -svo outfile2 "$URL" 2>curl_getAgain.out && + test_cmp infile2 outfile2 ' test_kill_ipfs_daemon