18600: Fix Snapshot/Splice at collectionfs root.
authorTom Clegg <tom@curii.com>
Sun, 6 Mar 2022 07:31:39 +0000 (02:31 -0500)
committerTom Clegg <tom@curii.com>
Mon, 7 Mar 2022 07:00:22 +0000 (02:00 -0500)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

sdk/go/arvados/fs_base.go
sdk/go/arvados/fs_collection.go
sdk/go/arvados/fs_collection_test.go

index 387b6a737ff334cba74cb44dc83761a88fd56571..bebb74261e4767dd917a919f170fd47312c7939d 100644 (file)
@@ -463,14 +463,14 @@ func (fs *fileSystem) openFile(name string, flag int, perm os.FileMode) (*fileha
        default:
                return nil, fmt.Errorf("invalid flags 0x%x", flag)
        }
-       if !writable && parent.IsDir() {
+       if parent.IsDir() {
                // A directory can be opened via "foo/", "foo/.", or
                // "foo/..".
                switch name {
                case ".", "":
-                       return &filehandle{inode: parent}, nil
+                       return &filehandle{inode: parent, readable: readable, writable: writable}, nil
                case "..":
-                       return &filehandle{inode: parent.Parent()}, nil
+                       return &filehandle{inode: parent.Parent(), readable: readable, writable: writable}, nil
                }
        }
        createMode := flag&os.O_CREATE != 0
@@ -766,7 +766,7 @@ func Splice(fs FileSystem, target string, newsubtree *Subtree) error {
                f, err = fs.OpenFile(target, os.O_CREATE|os.O_WRONLY, 0700)
        }
        if err != nil {
-               return err
+               return fmt.Errorf("open %s: %w", target, err)
        }
        defer f.Close()
        return f.Splice(newsubtree)
index 0c5819721e0cb4e8762d6c1e1e3b70427a46a7da..f4dae746e2a72a1a6384857749cf7261f5465917 100644 (file)
@@ -1565,7 +1565,7 @@ func (dn *dirnode) snapshot() (*dirnode, error) {
 func (dn *dirnode) Splice(repl inode) error {
        repl, err := repl.Snapshot()
        if err != nil {
-               return err
+               return fmt.Errorf("cannot copy snapshot: %w", err)
        }
        switch repl := repl.(type) {
        default:
@@ -1599,7 +1599,7 @@ func (dn *dirnode) Splice(repl inode) error {
                defer dn.Unlock()
                _, err = dn.parent.Child(dn.fileinfo.name, func(inode) (inode, error) { return repl, nil })
                if err != nil {
-                       return err
+                       return fmt.Errorf("error replacing filenode: dn.parent.Child(): %w", err)
                }
                repl.fs = dn.fs
        }
index fab91d1f77dc37f3708380db3796400ff01dfca5..b221aaa083a12fd1f13fd3eaec3d9c0f85ae61b5 100644 (file)
@@ -1441,6 +1441,30 @@ func (s *CollectionFSSuite) TestEdgeCaseManifests(c *check.C) {
        }
 }
 
+func (s *CollectionFSSuite) TestSnapshotSplice(c *check.C) {
+       filedata1 := "hello snapshot+splice world\n"
+       fs, err := (&Collection{}).FileSystem(s.client, s.kc)
+       c.Assert(err, check.IsNil)
+       {
+               f, err := fs.OpenFile("file1", os.O_CREATE|os.O_RDWR, 0700)
+               c.Assert(err, check.IsNil)
+               _, err = f.Write([]byte(filedata1))
+               c.Assert(err, check.IsNil)
+               err = f.Close()
+               c.Assert(err, check.IsNil)
+       }
+
+       snap, err := Snapshot(fs, "/")
+       c.Assert(err, check.IsNil)
+       err = Splice(fs, "dir1", snap)
+       c.Assert(err, check.IsNil)
+       f, err := fs.Open("dir1/file1")
+       c.Assert(err, check.IsNil)
+       buf, err := io.ReadAll(f)
+       c.Assert(err, check.IsNil)
+       c.Check(string(buf), check.Equals, filedata1)
+}
+
 func (s *CollectionFSSuite) TestRefreshSignatures(c *check.C) {
        filedata1 := "hello refresh signatures world\n"
        fs, err := (&Collection{}).FileSystem(s.client, s.kc)