func setup_dir(t testing.TB, chunkStore chunks.Store, dirents []*wire.Dirent) *wire.Dirent { blob, err := blobs.Open( chunkStore, blobs.EmptyManifest("dir"), ) if err != nil { t.Fatalf("unexpected blob open error: %v", err) } w := snap.NewWriter(blob) for _, de := range dirents { err := w.Add(de) if err != nil { t.Fatalf("unexpected add error: %v", err) } } manifest, err := blob.Save() if err != nil { t.Fatalf("unexpected save error: %v", err) } var de wire.Dirent de.Type.Dir = &wire.Dir{ Manifest: wirecas.FromBlob(manifest), } return &de }
// snapshot records a snapshot of the directory and stores it in wde func (d *dir) snapshot(tx *bolt.Tx, out *wiresnap.Dir, intr fs.Intr) error { // NOT HOLDING THE LOCK, accessing database snapshot ONLY // TODO move bucket lookup to caller? bucket := d.fs.bucket(tx).Bucket(bucketDir) if bucket == nil { return errors.New("dir bucket missing") } manifest := blobs.EmptyManifest("dir") blob, err := blobs.Open(d.fs.chunkStore, manifest) if err != nil { return err } w := snap.NewWriter(blob) c := bucket.Cursor() prefix := pathToKey(d.inode, "") for k, v := c.Seek(prefix); k != nil; k, v = c.Next() { if !bytes.HasPrefix(k, prefix) { // past the end of the directory break } name := string(k[len(prefix):]) de, err := d.unmarshalDirent(v) if err != nil { return err } sde := wiresnap.Dirent{ Name: name, } switch { case de.Type.File != nil: // TODO d.reviveNode would do blobs.Open and that's a bit // too much work; rework the apis sde.Type.File = &wiresnap.File{ Manifest: de.Type.File.Manifest, } case de.Type.Dir != nil: child, err := d.reviveDir(de, name) if err != nil { return err } sde.Type.Dir = &wiresnap.Dir{} err = child.snapshot(tx, sde.Type.Dir, intr) if err != nil { return err } default: return errors.New("TODO") } err = w.Add(&sde) if err != nil { return err } } manifest, err = blob.Save() if err != nil { return err } out.Manifest = wirecas.FromBlob(manifest) out.Align = w.Align() return nil }