]> arthur.barton.de Git - bup.git/blob - cmd/fuse-cmd.py
vfs: supply ctime/mtime for the root of each commit.
[bup.git] / cmd / fuse-cmd.py
1 #!/usr/bin/env python
2 import sys, os, stat, errno, fuse, re, time, tempfile
3 from bup import options, git, vfs
4 from bup.helpers import *
5
6
7 class Stat(fuse.Stat):
8     def __init__(self):
9         self.st_mode = 0
10         self.st_ino = 0
11         self.st_dev = 0
12         self.st_nlink = 0
13         self.st_uid = 0
14         self.st_gid = 0
15         self.st_size = 0
16         self.st_atime = 0
17         self.st_mtime = 0
18         self.st_ctime = 0
19
20
21 cache = {}
22 def cache_get(top, path):
23     parts = path.split('/')
24     cache[('',)] = top
25     c = None
26     max = len(parts)
27     #log('cache: %r\n' % cache.keys())
28     for i in range(max):
29         pre = parts[:max-i]
30         #log('cache trying: %r\n' % pre)
31         c = cache.get(tuple(pre))
32         if c:
33             rest = parts[max-i:]
34             for r in rest:
35                 #log('resolving %r from %r\n' % (r, c.fullname()))
36                 c = c.lresolve(r)
37                 key = tuple(pre + [r])
38                 #log('saving: %r\n' % (key,))
39                 cache[key] = c
40             break
41     assert(c)
42     return c
43         
44     
45
46 class BupFs(fuse.Fuse):
47     def __init__(self, top):
48         fuse.Fuse.__init__(self)
49         self.top = top
50     
51     def getattr(self, path):
52         log('--getattr(%r)\n' % path)
53         try:
54             node = cache_get(self.top, path)
55             st = Stat()
56             st.st_mode = node.mode
57             st.st_nlink = node.nlinks()
58             st.st_size = node.size()
59             st.st_mtime = node.mtime
60             st.st_ctime = node.ctime
61             st.st_atime = node.atime
62             return st
63         except vfs.NoSuchFile:
64             return -errno.ENOENT
65
66     def readdir(self, path, offset):
67         log('--readdir(%r)\n' % path)
68         node = cache_get(self.top, path)
69         yield fuse.Direntry('.')
70         yield fuse.Direntry('..')
71         for sub in node.subs():
72             yield fuse.Direntry(sub.name)
73
74     def readlink(self, path):
75         log('--readlink(%r)\n' % path)
76         node = cache_get(self.top, path)
77         return node.readlink()
78
79     def open(self, path, flags):
80         log('--open(%r)\n' % path)
81         node = cache_get(self.top, path)
82         accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
83         if (flags & accmode) != os.O_RDONLY:
84             return -errno.EACCES
85         node.open()
86
87     def release(self, path, flags):
88         log('--release(%r)\n' % path)
89
90     def read(self, path, size, offset):
91         log('--read(%r)\n' % path)
92         n = cache_get(self.top, path)
93         return n.readbytes(offset, size)
94
95
96 if not hasattr(fuse, '__version__'):
97     raise RuntimeError, "your fuse module is too old for fuse.__version__"
98 fuse.fuse_python_api = (0, 2)
99
100
101 optspec = """
102 bup fuse [-d] [-f] <mountpoint>
103 --
104 d,debug   increase debug level
105 f,foreground  run in foreground
106 """
107 o = options.Options('bup fuse', optspec)
108 (opt, flags, extra) = o.parse(sys.argv[1:])
109
110 if len(extra) != 1:
111     o.fatal("exactly one argument expected")
112
113 git.check_repo_or_die()
114 top = vfs.RefList(None)
115 f = BupFs(top)
116 f.fuse_args.mountpoint = extra[0]
117 if opt.debug:
118     f.fuse_args.add('debug')
119 if opt.foreground:
120     f.fuse_args.setmod('foreground')
121 print f.multithreaded
122 f.multithreaded = False
123 f.fuse_args.add('allow_other')
124
125 f.main()