]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
macfuse: rework fuse initialisation, integrate with 'tahoe'
authorrobk-tahoe <robk-tahoe@allmydata.com>
Wed, 20 Feb 2008 00:16:08 +0000 (17:16 -0700)
committerrobk-tahoe <robk-tahoe@allmydata.com>
Wed, 20 Feb 2008 00:16:08 +0000 (17:16 -0700)
this provides a variety of changes to the macfuse 'tahoefuse' implementation.
most notably it extends the 'tahoe' command available through the mac build
to provide a 'fuse' subcommand, which invokes tahoefuse.  this addresses
various aspects of main(argv) handling, sys.argv manipulation to provide an
appropriate command line syntax that meshes with the fuse library's built-
in command line parsing.

this provides a "tahoe fuse [dir_cap_name] [fuse_options] mountpoint"
command, where dir_cap_name is an optional name of a .cap file to be found
in ~/.tahoe/private defaulting to the standard root_dir.cap. fuse_options
if given are passed into the fuse system as its normal command line options
and the mountpoint is checked for existence before launching fuse.

the tahoe 'fuse' command is provided as an additional_command to the tahoe
runner in the case that it's launched from the mac .app binary.

this also includes a tweak to the TFS class which incorporates the ctime
and mtime of files into the tahoe fs model, if available.

mac/allmydata_tahoe.py
mac/macfuse/tahoefuse.py
src/allmydata/gui/macapp.py

index b87d5cd8f0a84aefd80a4ec41a95d3bdec5a3c3d..cd4c780ea672de26a7da9aec1810c54b8009d1b5 100644 (file)
@@ -5,6 +5,39 @@ _junk = depends # appease pyflakes
 
 import sys
 
+from twisted.python import usage
+
+class ReplOptions(usage.Options):
+    pass
+
+def repl(config, stdout, stderr):
+    import code
+    return code.interact()
+
+class DbgRunnerExtension(object):
+    subCommands = [
+        ["dbgrepl", None, ReplOptions, "Open a python interpreter"],
+        ]
+    dispatch = {
+        "dbgrepl": repl,
+        }
+
+class FuseOptions(usage.Options):
+    def parseOptions(self, args):
+        self.args = args
+
+def fuse(config, stdout, stderr):
+    import macfuse.tahoefuse
+    macfuse.tahoefuse.main(config.args)
+
+class FuseRunnerExtension(object):
+    subCommands = [
+        ["fuse", None, FuseOptions, "Mount a filesystem via fuse"],
+        ]
+    dispatch = {
+        "fuse": fuse,
+        }
+
 def main(argv):
     if len(argv) == 1:
         # then we were given no args; do default mac node startup
@@ -13,7 +46,12 @@ def main(argv):
     else:
         # given any cmd line args, do 'tahoe' cli behaviour
         from allmydata.scripts import runner
-        sys.exit(runner.runner(argv[1:], install_node_control=False))
+        #runner_extensions = [DbgRunnerExtension, FuseRunnerExtension, ]
+        runner_extensions = [FuseRunnerExtension, ]
+        sys.exit(runner.runner(argv[1:],
+                               install_node_control=False,
+                               additional_commands=runner_extensions,
+                               ))
 
 if __name__ == '__main__':
     main(sys.argv)
index d61a3ef340e222db76167e312eb66d508858e598..470898d9d6182399976083f020009edc2cab82b4 100644 (file)
@@ -6,6 +6,7 @@ from allmydata.scripts.common_http import do_http as do_http_req
 
 import base64
 import sha
+import sys
 import os
 import errno
 import stat
@@ -23,6 +24,8 @@ import traceback
 import simplejson
 import urllib
 
+USAGE = 'usage: tahoe fuse [dir_cap_name] [fuse_options] mountpoint'
+
 if not hasattr(fuse, '__version__'):
     raise RuntimeError, \
         "your fuse-py doesn't know of fuse.__version__, probably it's too old."
@@ -101,7 +104,7 @@ class TahoeFuseFile(object):
                 self.fname = self.tfs.cache.tmp_file(os.urandom(20))
                 if self.fnode is None:
                     log('TFF: [%s] open(%s) for write: no such file, creating new File' % (self.name, self.fname, ))
-                    self.fnode = File(0, None)
+                    self.fnode = File(0, None, None)
                     self.fnode.tmp_fname = self.fname # XXX kill this
                     self.parent.add_child(self.name, self.fnode)
                 elif hasattr(self.fnode, 'tmp_fname'):
@@ -208,8 +211,9 @@ class TahoeFuse(fuse.Fuse):
         log("TF: __init__(%r, %r)" % (args, kw))
 
         self.tfs = tfs
+        _tfs_ = tfs
         class MyFuseFile(TahoeFuseFile):
-            tfs = tfs
+            tfs = _tfs_
         self.file_class = MyFuseFile
         log("TF: file_class: %r" % (self.file_class,))
 
@@ -341,22 +345,24 @@ class TahoeFuse(fuse.Fuse):
         self.log("mkdir(%r, %r)" % (path, mode))
         self.tfs.mkdir(path)
 
-def main(tfs):
-
-    usage = "Userspace tahoe fs: cache a tahoe tree and present via fuse\n" + fuse.Fuse.fusage
-
+def launch_tahoe_fuse(tfs, argv):
+    sys.argv = ['tahoe fuse'] + list(argv)
     server = TahoeFuse(tfs, version="%prog " + fuse.__version__,
-                       usage=usage,
+                       usage=USAGE,
                        dash_s_do='setsingle')
     server.parse(errex=1)
     server.main()
 
 
-def getbasedir():
-    f = file(os.path.expanduser("~/.tahoe/private/root_dir.cap"), 'rb')
-    bd = f.read().strip()
-    f.close()
-    return bd
+def getbasedir(cap_name='root_dir'):
+    fname = os.path.expanduser("~/.tahoe/private/%s.cap" % (cap_name,))
+    if os.path.exists(fname):
+        f = file(fname, 'rb')
+        bd = f.read().strip()
+        f.close()
+        return bd
+    else:
+        return None
 
 def getnodeurl():
     f = file(os.path.expanduser("~/.tahoe/node.url"), 'rb')
@@ -437,17 +443,34 @@ class Directory(object):
         return s
 
 class File(object):
-    def __init__(self, size, ro_uri):
+    def __init__(self, size, ro_uri, metadata):
         self.size = size
         if ro_uri:
             ro_uri = str(ro_uri)
         self.ro_uri = ro_uri
+        self.metadata = metadata or {}
 
     def __repr__(self):
         return "<File %s>" % (fingerprint(self.ro_uri) or [self.tmp_fname],)
 
     def pprint(self, prefix='', printed=None):
-        return "         %s (%s)" % (prefix, self.size, )
+        times, remainder = self.get_times()
+        return "         %s (%s) %s %s" % (prefix, self.size, times, remainder)
+
+    def get_times(self):
+        rem = self.metadata.copy()
+        now = time.time()
+        times = {}
+        for T in ['c', 'm']:
+            t = rem.pop('%stime'%T, None)
+            if not t:
+                t = 'none'
+            elif (now-t) < 86400:
+                t = time.strftime('%a:%H:%M:%S', time.localtime(t))
+            else:
+                t = time.strftime('%Y:%b:%d:%H:%M', time.localtime(t))
+            times[T] = t
+        return times, rem
 
     def get_stat(self):
         if hasattr(self, 'tmp_fname'):
@@ -521,7 +544,7 @@ class TFS(object):
                 cobj = self.dir_for(name, cattrs.get('ro_uri'), cattrs.get('rw_uri'))
             else:
                 assert ctype == "filenode"
-                cobj = File(cattrs.get('size'), cattrs.get('ro_uri'))
+                cobj = File(cattrs.get('size'), cattrs.get('ro_uri'), cattrs.get('metadata'))
             dirobj.children[name] = cobj
 
     def dir_for(self, name, ro_uri, rw_uri):
@@ -646,14 +669,45 @@ class FileCache(object):
 def print_tree():
     log('tree:\n' + _tfs.pprint())
 
-if __name__ == '__main__':
-    log("\n\nmain()")
-    tfs = TFS(getnodeurl(), getbasedir())
+def main(argv):
+    log("\n\nmain(%s)" % (argv,))
+
+    if not argv:
+        argv = ['--help']
+    if len(argv) == 1 and argv[0] in ['-h', '--help', '--version']:
+        #print USAGE
+        launch_tahoe_fuse(None, argv)
+        return -2
+
+    if not argv[0].startswith('-'):
+        cap_name = argv[0]
+        basedir = getbasedir(cap_name)
+        if basedir is None:
+            print 'root dir named "%s" not found.' % (cap_name,)
+            return -2
+        argv = argv[1:]
+    else:
+        basedir = getbasedir() # default 'root_dir'
+
+    if argv[-1].startswith('-'):
+        print 'mountpoint not given'
+        return -2
+    mountpoint = os.path.abspath(argv[-1])
+    if not os.path.exists(mountpoint):
+        #raise OSError(2, 'No such file or directory: "%s"' % (mountpoint,))
+        print 'No such file or directory: "%s"' % (mountpoint,)
+        return -2
+
+    nodeurl = getnodeurl()
+
+    tfs = TFS(nodeurl, basedir)
     print tfs.pprint()
 
     # make tfs instance accesible to print_tree() for dbg
     global _tfs
     _tfs = tfs
 
-    main(tfs)
+    launch_tahoe_fuse(tfs, argv)
 
+if __name__ == '__main__':
+    main(sys.argv)
index 6a99e37ec8f84716e6122aec8566ff521a840c37..d8eee3e799667e5e3a1c8c25012b45d09c5160cf 100644 (file)
@@ -283,16 +283,3 @@ class MacGuiApp(wx.App):
     def on_account_page(self, event):
         webbrowser.open(DEFAULT_SERVER_URL + ACCOUNT_PAGE)
 
-
-def main(argv):
-    if len(argv) == 1:
-        # then we were given no args; do default mac node startup
-        sys.exit(run_macapp())
-    else:
-        # given any cmd line args, do 'tahoe' cli behaviour
-        from allmydata.scripts import runner
-        sys.exit(runner.runner(argv[1:], install_node_control=False))
-
-if __name__ == '__main__':
-    main(sys.argv)
-