]> arthur.barton.de Git - bup.git/blob - cmd/fuse-cmd.py
Git: Ignore two more generated files
[bup.git] / cmd / fuse-cmd.py
1 #!/bin/sh
2 """": # -*-python-*-
3 bup_python="$(dirname "$0")/bup-python" || exit $?
4 exec "$bup_python" "$0" ${1+"$@"}
5 """
6 # end of bup preamble
7
8 import sys, os, errno
9
10 from bup import options, git, vfs, xstat
11 from bup.helpers import buglvl, log
12
13 try:
14     import fuse
15 except ImportError:
16     log('error: cannot find the python "fuse" module; please install it\n')
17     sys.exit(1)
18
19
20 cache = {}
21 def cache_get(top, path):
22     parts = path.split('/')
23     cache[('',)] = top
24     c = None
25     max = len(parts)
26     if buglvl >= 1:
27         log('cache: %r\n' % cache.keys())
28     for i in range(max):
29         pre = parts[:max-i]
30         if buglvl >= 1:
31             log('cache trying: %r\n' % pre)
32         c = cache.get(tuple(pre))
33         if c:
34             rest = parts[max-i:]
35             for r in rest:
36                 if buglvl >= 1:
37                     log('resolving %r from %r\n' % (r, c.fullname()))
38                 c = c.lresolve(r)
39                 key = tuple(pre + [r])
40                 if buglvl >= 1:
41                     log('saving: %r\n' % (key,))
42                 cache[key] = c
43             break
44     assert(c)
45     return c
46
47
48 class BupFs(fuse.Fuse):
49     def __init__(self, top, meta=False, verbose=0):
50         fuse.Fuse.__init__(self)
51         self.top = top
52         self.meta = meta
53         self.verbose = verbose
54     
55     def getattr(self, path):
56         if self.verbose > 0:
57             log('--getattr(%r)\n' % path)
58         try:
59             node = cache_get(self.top, path)
60             st = fuse.Stat(st_mode=node.mode,
61                            st_nlink=node.nlinks(),
62                            # Until/unless we store the size in m.
63                            st_size=node.size())
64             if self.meta:
65                 m = node.metadata()
66                 if m:
67                     st.st_mode = m.mode
68                     st.st_uid = m.uid
69                     st.st_gid = m.gid
70                     st.st_atime = max(0, xstat.fstime_floor_secs(m.atime))
71                     st.st_mtime = max(0, xstat.fstime_floor_secs(m.mtime))
72                     st.st_ctime = max(0, xstat.fstime_floor_secs(m.ctime))
73             return st
74         except vfs.NoSuchFile:
75             return -errno.ENOENT
76
77     def readdir(self, path, offset):
78         if self.verbose > 0:
79             log('--readdir(%r)\n' % path)
80         node = cache_get(self.top, path)
81         yield fuse.Direntry('.')
82         yield fuse.Direntry('..')
83         for sub in node.subs():
84             yield fuse.Direntry(sub.name)
85
86     def readlink(self, path):
87         if self.verbose > 0:
88             log('--readlink(%r)\n' % path)
89         node = cache_get(self.top, path)
90         return node.readlink()
91
92     def open(self, path, flags):
93         if self.verbose > 0:
94             log('--open(%r)\n' % path)
95         node = cache_get(self.top, path)
96         accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
97         if (flags & accmode) != os.O_RDONLY:
98             return -errno.EACCES
99         node.open()
100
101     def release(self, path, flags):
102         if self.verbose > 0:
103             log('--release(%r)\n' % path)
104
105     def read(self, path, size, offset):
106         if self.verbose > 0:
107             log('--read(%r)\n' % path)
108         n = cache_get(self.top, path)
109         o = n.open()
110         o.seek(offset)
111         return o.read(size)
112
113
114 if not hasattr(fuse, '__version__'):
115     raise RuntimeError, "your fuse module is too old for fuse.__version__"
116 fuse.fuse_python_api = (0, 2)
117
118
119 optspec = """
120 bup fuse [-d] [-f] <mountpoint>
121 --
122 f,foreground  run in foreground
123 d,debug       run in the foreground and display FUSE debug information
124 o,allow-other allow other users to access the filesystem
125 meta          report original metadata for paths when available
126 v,verbose     increase log output (can be used more than once)
127 """
128 o = options.Options(optspec)
129 (opt, flags, extra) = o.parse(sys.argv[1:])
130
131 if len(extra) != 1:
132     o.fatal("exactly one argument expected")
133
134 git.check_repo_or_die()
135 top = vfs.RefList(None)
136 f = BupFs(top, meta=opt.meta, verbose=opt.verbose)
137 f.fuse_args.mountpoint = extra[0]
138 if opt.debug:
139     f.fuse_args.add('debug')
140 if opt.foreground:
141     f.fuse_args.setmod('foreground')
142 print f.multithreaded
143 f.multithreaded = False
144 if opt.allow_other:
145     f.fuse_args.add('allow_other')
146
147 f.main()