Expose SHA1s as extended attributes.
Change-Id: I71b1fbd6dd3ae475ac4f67e4a570445d2b5ddc3a
diff --git a/fs/gitilesfs.go b/fs/gitilesfs.go
index 91d1a93..616b9f7 100644
--- a/fs/gitilesfs.go
+++ b/fs/gitilesfs.go
@@ -120,7 +120,18 @@
return fuse.OK
}
-// TODO(hanwen): implement extended attributes to read the SHA1.
+const xattrName = "user.gitsha1"
+
+func (n *gitilesNode) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
+ if attribute != xattrName {
+ return nil, fuse.ENODATA
+ }
+ return []byte(n.id.String()), fuse.OK
+}
+
+func (n *gitilesNode) ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status) {
+ return []string{xattrName}, fuse.OK
+}
func (n *gitilesNode) Open(flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
if n.root.handleLessIO {
@@ -216,6 +227,10 @@
return nodefs.NewDataFile(d.data), fuse.OK
}
+func (d *dataNode) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
+ return nil, fuse.ENODATA
+}
+
func (n *dataNode) Deletable() bool { return false }
func newDataNode(c []byte) nodefs.Node {
@@ -239,6 +254,10 @@
func (r *gitilesRoot) Deletable() bool { return false }
+func (n *gitilesRoot) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
+ return nil, fuse.ENODATA
+}
+
func (r *gitilesRoot) OnMount(fsConn *nodefs.FileSystemConnector) {
if err := r.onMount(fsConn); err != nil {
log.Printf("onMount: %v", err)
diff --git a/fs/gitilesfs_test.go b/fs/gitilesfs_test.go
index b19789c..49dc122 100644
--- a/fs/gitilesfs_test.go
+++ b/fs/gitilesfs_test.go
@@ -190,6 +190,23 @@
} else if string(got) != want {
t.Errorf("got %q, want %q", got, want)
}
+
+ data := make([]byte, 1024)
+ sz, err := syscall.Listxattr(filepath.Join(fix.mntDir, "AUTHORS"), data)
+ if err != nil {
+ t.Fatalf("Listxattr: %v", err)
+ }
+ if got, want := string(data[:sz]), xattrName+"\000"; got != want {
+ t.Errorf("got xattrs %q, want %q", got, want)
+ }
+
+ sz, err = syscall.Getxattr(filepath.Join(fix.mntDir, "AUTHORS"), xattrName, data)
+ if err != nil {
+ t.Fatalf("Getxattr: %v", err)
+ }
+ if got, want := "787d767f94fd634ed29cd69ec9f93bab2b25f5d4", string(data[:sz]); got != want {
+ t.Errorf("got %q, want %q", got, want)
+ }
}
func TestGitilesFS(t *testing.T) {
diff --git a/fs/manifestfs.go b/fs/manifestfs.go
index 3d5bce5..a6c8898 100644
--- a/fs/manifestfs.go
+++ b/fs/manifestfs.go
@@ -23,6 +23,7 @@
"github.com/google/gitfs/cache"
"github.com/google/gitfs/gitiles"
"github.com/google/gitfs/manifest"
+ "github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
git "github.com/libgit2/git2go"
)
@@ -45,6 +46,10 @@
func (r *manifestFSRoot) Deletable() bool { return false }
+func (r *manifestFSRoot) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
+ return nil, fuse.ENODATA
+}
+
// NewManifestFS creates a Manifest FS root node.
func NewManifestFS(service *gitiles.Service, cache *cache.Cache, opts ManifestOptions) (nodefs.Node, error) {
xml, err := opts.Manifest.MarshalXML()
diff --git a/fs/multifs.go b/fs/multifs.go
index 57e9f98..97babe9 100644
--- a/fs/multifs.go
+++ b/fs/multifs.go
@@ -56,6 +56,10 @@
func (r *multiManifestFSRoot) Deletable() bool { return false }
+func (r *multiManifestFSRoot) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
+ return nil, fuse.ENODATA
+}
+
type configNode struct {
nodefs.Node
root *multiManifestFSRoot