// GetDAG will fill out all of the links of the given Node. // It returns a channel of nodes, which the caller can receive // all the child nodes of 'root' on, in proper order. func GetDAG(ctx context.Context, ds DAGService, root node.Node) []NodeGetter { var cids []*cid.Cid for _, lnk := range root.Links() { cids = append(cids, lnk.Cid) } return GetNodes(ctx, ds, cids) }
func (t *traversal) shouldSkip(n node.Node) (bool, error) { if t.opts.SkipDuplicates { k := n.Cid() if _, found := t.seen[k.KeyString()]; found { return true, nil } t.seen[k.KeyString()] = struct{}{} } return false, nil }
// Pin the given node, optionally recursive func (p *pinner) Pin(ctx context.Context, node node.Node, recurse bool) error { p.lock.Lock() defer p.lock.Unlock() c := node.Cid() if recurse { if p.recursePin.Has(c) { return nil } if p.directPin.Has(c) { p.directPin.Remove(c) } // fetch entire graph err := mdag.FetchGraph(ctx, c, p.dserv) if err != nil { return err } p.recursePin.Add(c) } else { if _, err := p.dserv.Get(ctx, c); err != nil { return err } if p.recursePin.Has(c) { return fmt.Errorf("%s already pinned recursively", c.String()) } p.directPin.Add(c) } return nil }
func (rw *RefWriter) writeRefsSingle(n node.Node) (int, error) { c := n.Cid() if rw.skip(c) { return 0, nil } count := 0 for _, l := range n.Links() { lc := l.Cid if rw.skip(lc) { continue } if err := rw.WriteEdge(c, lc, l.Name); err != nil { return count, err } count++ } return count, nil }
func ResolveUnixfsOnce(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) { pbnd, ok := nd.(*dag.ProtoNode) if !ok { lnk, _, err := nd.ResolveLink([]string{name}) return lnk, err } upb, err := ft.FromBytes(pbnd.Data()) if err != nil { // Not a unixfs node, use standard object traversal code lnk, _, err := nd.ResolveLink([]string{name}) return lnk, err } switch upb.GetType() { /* case ft.THAMTShard: s, err := hamt.NewHamtFromDag(ds, nd) if err != nil { return nil, err } // TODO: optimized routine on HAMT for returning a dag.Link to avoid extra disk hits out, err := s.Find(ctx, name) if err != nil { return nil, err } return dag.MakeLink(out) */ default: lnk, _, err := nd.ResolveLink([]string{name}) return lnk, err } }
func (rw *RefWriter) writeRefsRecursive(n node.Node) (int, error) { nc := n.Cid() var count int for i, ng := range dag.GetDAG(rw.Ctx, rw.DAG, n) { lc := n.Links()[i].Cid if rw.skip(lc) { continue } if err := rw.WriteEdge(nc, lc, n.Links()[i].Name); err != nil { return count, err } nd, err := ng.Get(rw.Ctx) if err != nil { return count, err } c, err := rw.writeRefsRecursive(nd) count += c if err != nil { return count, err } } return count, nil }
func (t *Batch) Add(nd node.Node) (*cid.Cid, error) { t.blocks = append(t.blocks, nd) t.size += len(nd.RawData()) if t.size > t.MaxSize { return nd.Cid(), t.Commit() } return nd.Cid(), nil }
// NewDagReader creates a new reader object that reads the data represented by // the given node, using the passed in DAGService for data retreival func NewDagReader(ctx context.Context, n node.Node, serv mdag.DAGService) (*DagReader, error) { switch n := n.(type) { case *mdag.RawNode: return &DagReader{ buf: NewRSNCFromBytes(n.RawData()), }, nil case *mdag.ProtoNode: pb := new(ftpb.Data) if err := proto.Unmarshal(n.Data(), pb); err != nil { return nil, err } switch pb.GetType() { case ftpb.Data_Directory: // Dont allow reading directories return nil, ErrIsDir case ftpb.Data_File, ftpb.Data_Raw: return NewDataFileReader(ctx, n, pb, serv), nil case ftpb.Data_Metadata: if len(n.Links()) == 0 { return nil, errors.New("incorrectly formatted metadata object") } child, err := n.Links()[0].GetNode(ctx, serv) if err != nil { return nil, err } childpb, ok := child.(*mdag.ProtoNode) if !ok { return nil, mdag.ErrNotProtobuf } return NewDagReader(ctx, childpb, serv) case ftpb.Data_Symlink: return nil, ErrCantReadSymlinks default: return nil, ft.ErrUnrecognizedType } default: return nil, fmt.Errorf("unrecognized node type") } }
func (adder *Adder) addNode(node node.Node, path string) error { // patch it into the root if path == "" { path = node.Cid().String() } dir := gopath.Dir(path) if dir != "." { if err := mfs.Mkdir(adder.mr, dir, true, false); err != nil { return err } } if err := mfs.PutNode(adder.mr, path, node); err != nil { return err } if !adder.Silent { return outputDagnode(adder.Out, path, node) } return nil }
// from core/commands/object.go func getOutput(dagnode node.Node) (*Object, error) { c := dagnode.Cid() output := &Object{ Hash: c.String(), Links: make([]Link, len(dagnode.Links())), } for i, link := range dagnode.Links() { output.Links[i] = Link{ Name: link.Name, Size: link.Size, } } return output, nil }
func assertCanGet(t *testing.T, ds DAGService, n node.Node) { if _, err := ds.Get(context.Background(), n.Cid()); err != nil { t.Fatal(err) } }
func ResolveSingle(ctx context.Context, ds dag.DAGService, nd node.Node, name string) (*node.Link, error) { lnk, _, err := nd.ResolveLink([]string{name}) return lnk, err }
func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) { // TODO(cryptix): move me to ServeHTTP and pass into all handlers ctx, cancel := context.WithCancel(i.node.Context()) defer cancel() rootPath, err := path.ParsePath(r.URL.Path) if err != nil { webError(w, "putHandler: IPFS path not valid", err, http.StatusBadRequest) return } rsegs := rootPath.Segments() if rsegs[0] == ipnsPathPrefix { webError(w, "putHandler: updating named entries not supported", errors.New("WritableGateway: ipns put not supported"), http.StatusBadRequest) return } var newnode node.Node if rsegs[len(rsegs)-1] == "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" { newnode = ft.EmptyDirNode() } else { putNode, err := i.newDagFromReader(r.Body) if err != nil { webError(w, "putHandler: Could not create DAG from request", err, http.StatusInternalServerError) return } newnode = putNode } var newPath string if len(rsegs) > 1 { newPath = path.Join(rsegs[2:]) } var newcid *cid.Cid rnode, err := core.Resolve(ctx, i.node.Namesys, i.node.Resolver, rootPath) switch ev := err.(type) { case path.ErrNoLink: // ev.Node < node where resolve failed // ev.Name < new link // but we need to patch from the root c, err := cid.Decode(rsegs[1]) if err != nil { webError(w, "putHandler: bad input path", err, http.StatusBadRequest) return } rnode, err := i.node.DAG.Get(ctx, c) if err != nil { webError(w, "putHandler: Could not create DAG from request", err, http.StatusInternalServerError) return } pbnd, ok := rnode.(*dag.ProtoNode) if !ok { webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest) return } e := dagutils.NewDagEditor(pbnd, i.node.DAG) err = e.InsertNodeAtPath(ctx, newPath, newnode, ft.EmptyDirNode) if err != nil { webError(w, "putHandler: InsertNodeAtPath failed", err, http.StatusInternalServerError) return } nnode, err := e.Finalize(i.node.DAG) if err != nil { webError(w, "putHandler: could not get node", err, http.StatusInternalServerError) return } newcid = nnode.Cid() case nil: pbnd, ok := rnode.(*dag.ProtoNode) if !ok { webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest) return } pbnewnode, ok := newnode.(*dag.ProtoNode) if !ok { webError(w, "Cannot read non protobuf nodes through gateway", dag.ErrNotProtobuf, http.StatusBadRequest) return } // object set-data case pbnd.SetData(pbnewnode.Data()) newcid, err = i.node.DAG.Add(pbnd) if err != nil { nnk := newnode.Cid() rk := pbnd.Cid() webError(w, fmt.Sprintf("putHandler: Could not add newnode(%q) to root(%q)", nnk.String(), rk.String()), err, http.StatusInternalServerError) return } default: log.Warningf("putHandler: unhandled resolve error %T", ev) webError(w, "could not resolve root DAG", ev, http.StatusInternalServerError) return } i.addUserHeaders(w) // ok, _now_ write user's headers. w.Header().Set("IPFS-Hash", newcid.String()) http.Redirect(w, r, gopath.Join(ipfsPathPrefix, newcid.String(), newPath), http.StatusCreated) }