diff --git a/cmd/cammount/cammount.go b/cmd/cammount/cammount.go index 433b7e0ff..ba912f6fb 100644 --- a/cmd/cammount/cammount.go +++ b/cmd/cammount/cammount.go @@ -36,6 +36,7 @@ import ( "camlistore.org/pkg/cacher" "camlistore.org/pkg/client" "camlistore.org/pkg/fs" + "camlistore.org/pkg/search" "camlistore.org/third_party/code.google.com/p/rsc/fuse" ) @@ -46,7 +47,7 @@ var ( ) func usage() { - fmt.Fprint(os.Stderr, "usage: cammount [opts] [ [|]]\n") + fmt.Fprint(os.Stderr, "usage: cammount [opts] [ [||]]\n") flag.PrintDefaults() os.Exit(2) } @@ -101,12 +102,26 @@ func main() { } } else { cl = client.NewOrFail() // automatic from flags + cl.SetHTTPClient(&http.Client{Transport: cl.TransportForConfig(nil)}) + var ok bool root, ok = blob.Parse(rootArg) + if !ok { - log.Fatalf("Error parsing root blobref: %q\n", rootArg) + // not a blobref, check for root name instead + req := &search.WithAttrRequest{N: 1, Attr: "camliRoot", Value: rootArg} + wres, err := cl.GetPermanodesWithAttr(req) + + if err != nil { + log.Fatal("could not query search") + } + + if wres.WithAttr != nil { + root = wres.WithAttr[0].Permanode + } else { + log.Fatalf("root specified is not a blobref or name of a root: %q\n", rootArg) + } } - cl.SetHTTPClient(&http.Client{Transport: cl.TransportForConfig(nil)}) } } else { cl = client.NewOrFail() // automatic from flags @@ -120,12 +135,12 @@ func main() { defer diskCacheFetcher.Clean() if root.Valid() { var err error - camfs, err = fs.NewRootedCamliFileSystem(diskCacheFetcher, root) + camfs, err = fs.NewRootedCamliFileSystem(cl, diskCacheFetcher, root) if err != nil { log.Fatalf("Error creating root with %v: %v", root, err) } } else { - camfs = fs.NewCamliFileSystem(cl, diskCacheFetcher) + camfs = fs.NewDefaultCamliFileSystem(cl, diskCacheFetcher) } if *debug { diff --git a/pkg/fs/fs.go b/pkg/fs/fs.go index a116f26d2..7f5c83cc7 100644 --- a/pkg/fs/fs.go +++ b/pkg/fs/fs.go @@ -67,9 +67,9 @@ func newCamliFileSystem(fetcher blob.SeekFetcher) *CamliFileSystem { } } -// NewCamliFileSystem returns a filesystem with a generic base, from which users -// can navigate by blobref, tag, date, etc. -func NewCamliFileSystem(client *client.Client, fetcher blob.SeekFetcher) *CamliFileSystem { +// NewDefaultCamliFileSystem returns a filesystem with a generic base, from which +// users can navigate by blobref, tag, date, etc. +func NewDefaultCamliFileSystem(client *client.Client, fetcher blob.SeekFetcher) *CamliFileSystem { if client == nil || fetcher == nil { panic("nil argument") } @@ -79,21 +79,20 @@ func NewCamliFileSystem(client *client.Client, fetcher blob.SeekFetcher) *CamliF return fs } -// NewRootedCamliFileSystem returns a CamliFileSystem with root as its -// base. -func NewRootedCamliFileSystem(fetcher blob.SeekFetcher, root blob.Ref) (*CamliFileSystem, error) { +// NewRootedCamliFileSystem returns a CamliFileSystem with a node based on a blobref +// as its base. +func NewRootedCamliFileSystem(cli *client.Client, fetcher blob.SeekFetcher, root blob.Ref) (*CamliFileSystem, error) { fs := newCamliFileSystem(fetcher) + fs.client = cli + + n, err := fs.newNodeFromBlobRef(root) - blob, err := fs.fetchSchemaMeta(root) if err != nil { return nil, err } - if blob.Type() != "directory" { - return nil, fmt.Errorf("Blobref must be of a directory, got a %v", blob.Type()) - } - n := &node{fs: fs, blobref: root, meta: blob} - n.populateAttr() + fs.root = n + return fs, nil } @@ -347,6 +346,27 @@ func (fs *CamliFileSystem) fetchSchemaMeta(br blob.Ref) (*schema.Blob, error) { return blob, nil } +// consolated logic for determining a node to mount based on an arbitrary blobref +func (fs *CamliFileSystem) newNodeFromBlobRef(root blob.Ref) (fuse.Node, error) { + blob, err := fs.fetchSchemaMeta(root) + if err != nil { + return nil, err + } + + switch blob.Type() { + case "directory": + n := &node{fs: fs, blobref: root, meta: blob} + n.populateAttr() + return n, nil + + case "permanode": + // other mutDirs listed in the default fileystem have names and are displayed + return &mutDir{fs: fs, permanode: root, name: "-"}, nil + } + + return nil, fmt.Errorf("Blobref must be of a directory or permanode got a %v", blob.Type()) +} + type notImplementDirNode struct{ noXattr } func (notImplementDirNode) Attr() fuse.Attr {