Add Linkfile and Copyfile support to Manifest FS.
Change-Id: Iee24760742ffb3b5546c9b400c9fc5d314528733
diff --git a/fs/gitilesfs.go b/fs/gitilesfs.go
index c89554e..37a3cc1 100644
--- a/fs/gitilesfs.go
+++ b/fs/gitilesfs.go
@@ -51,6 +51,28 @@
lazyRepo *cache.LazyRepo
}
+type linkNode struct {
+ nodefs.Node
+ linkTarget []byte
+}
+
+func newLinkNode(target string) *linkNode {
+ return &linkNode{
+ Node: nodefs.NewDefaultNode(),
+ linkTarget: []byte(target),
+ }
+}
+
+func (n *linkNode) GetAttr(out *fuse.Attr, file nodefs.File, context *fuse.Context) (code fuse.Status) {
+ out.Size = uint64(len(n.linkTarget))
+ out.Mode = fuse.S_IFLNK
+ return fuse.OK
+}
+
+func (n *linkNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
+ return n.linkTarget, fuse.OK
+}
+
// gitilesNode represents a read-only blob in the FUSE filesystem.
type gitilesNode struct {
nodefs.Node
diff --git a/fs/gitilesfs_test.go b/fs/gitilesfs_test.go
index 4fe8124..ff22bd1 100644
--- a/fs/gitilesfs_test.go
+++ b/fs/gitilesfs_test.go
@@ -23,8 +23,10 @@
"net/http"
"os"
"path/filepath"
+ "reflect"
"regexp"
"strings"
+ "syscall"
"testing"
"github.com/google/gitfs/cache"
@@ -60,7 +62,10 @@
<default revision="master"
remote="aosp"
sync-j="4" />
- <project path="build/kati" name="platform/build/kati" groups="pdk,tradefed" revision="ce34badf691d36e8048b63f89d1a86ee5fa4325c" />
+ <project path="build/kati" name="platform/build/kati" groups="pdk,tradefed" revision="ce34badf691d36e8048b63f89d1a86ee5fa4325c">
+ <copyfile dest="build/copydest" src="AUTHORS" />
+ <linkfile dest="build/linkdest" src="AUTHORS" />
+ </project>
</manifest>`
var testGitiles = map[string]string{
@@ -319,6 +324,25 @@
if string(contents) != want {
t.Fatalf("got %q, want %q", contents, want)
}
+
+ copyPath := filepath.Join(mntDir, "build", "copydest")
+ if copyFI, err := os.Lstat(copyPath); err != nil {
+ t.Errorf("Lstat(%s): %v", copyPath, err)
+ } else {
+ copyStat := copyFI.Sys().(*syscall.Stat_t)
+ origStat := fi.Sys().(*syscall.Stat_t)
+
+ if !reflect.DeepEqual(copyStat, origStat) {
+ t.Errorf("got stat %v, want %v", copyStat, origStat)
+ }
+ }
+
+ linkPath := filepath.Join(mntDir, "build", "linkdest")
+ if got, err := os.Readlink(linkPath); err != nil {
+ t.Errorf("Readlink(%s): %v", linkPath, err)
+ } else if want := "kati/AUTHORS"; got != want {
+ t.Errorf("Readlink(%s) = %q, want %q", linkPath, got, want)
+ }
}
// TODO(hanwen): factor common setup into a testFixture struct.
@@ -358,7 +382,7 @@
}
opts := MultiFSOptions{}
- fs := NewMultiFS(cache, service, opts)
+ fs := NewMultiFS(service, cache, opts)
mntDir := d + "/mnt"
if err := os.Mkdir(mntDir, 0755); err != nil {
diff --git a/fs/manifestfs.go b/fs/manifestfs.go
index 8c241d5..2e72a01 100644
--- a/fs/manifestfs.go
+++ b/fs/manifestfs.go
@@ -129,6 +129,48 @@
}
}
+ // Do Linkfile, Copyfile after setting up the repos, so we
+ // have directories to attach the copy/link nodes to.
+ for _, p := range fs.options.Manifest.Project {
+ for _, cp := range p.Copyfile {
+ srcNode, left := fsConn.Node(fs.Inode(), filepath.Join(p.Path, cp.Src))
+ if len(left) > 0 {
+ return fmt.Errorf("Copyfile(%s): source %s does not exist", p.Name, cp.Src)
+ }
+
+ dir, left := fsConn.Node(fs.Inode(), cp.Dest)
+ switch len(left) {
+ case 0:
+ return fmt.Errorf("Copyfile(%s): dest %s already exists.", p.Name, cp.Dest)
+ case 1:
+ default:
+ return fmt.Errorf("Copyfile(%s): directory for dest %s does not exist.", p.Name, cp.Dest)
+ }
+
+ dir.AddChild(left[0], srcNode)
+ }
+
+ for _, lf := range p.Linkfile {
+ dir, left := fsConn.Node(fs.Inode(), lf.Dest)
+ switch len(left) {
+ case 0:
+ return fmt.Errorf("Linkfile(%s): dest %s already exists.", p.Name, lf.Dest)
+ case 1:
+ default:
+ return fmt.Errorf("Linkfile(%s): directory for dest %s does not exist.", p.Name, lf.Dest)
+ }
+
+ src := filepath.Join(p.Path, lf.Src)
+ rel, err := filepath.Rel(filepath.Dir(lf.Dest), src)
+ if err != nil {
+ return err
+ }
+
+ node := newLinkNode(filepath.Join(rel))
+ dir.NewChild(left[0], false, node)
+ }
+ }
+
return nil
}
@@ -187,5 +229,3 @@
}
return resmap, nil
}
-
-// TODO(hanwen): support LinkFile and CopyFile directives.