]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - contrib/fuse/impl_b/pyfuse/pysvnfs.py
43694f57e50260b946181ffa3b2e487bc3d15aee
[tahoe-lafs/tahoe-lafs.git] / contrib / fuse / impl_b / pyfuse / pysvnfs.py
1 from kernel import *
2 import errno, posixpath, weakref
3 from time import time as now
4 from stat import S_IFDIR, S_IFREG, S_IFMT
5 from cStringIO import StringIO
6 from handler import Handler
7 from pathfs import PathFs
8 from pysvn.ra_filesystem import SvnRepositoryFilesystem
9 import pysvn.date
10
11
12 class SvnFS(PathFs):
13
14     def __init__(self, svnurl, root=''):
15         super(SvnFS, self).__init__(root)
16         self.svnurl = svnurl
17         self.openfiles = weakref.WeakValueDictionary()
18         self.creationtimes = {}
19         self.do_open()
20
21     def do_open(self, rev='HEAD'):
22         self.fs = SvnRepositoryFilesystem(svnurl, rev)
23
24     def do_commit(self, msg):
25         rev = self.fs.commit(msg)
26         if rev is None:
27             print '* no changes.'
28         else:
29             print '* checked in revision %d.' % (rev,)
30         self.do_open()
31
32     def do_status(self, path=''):
33         print '* status'
34         result = []
35         if path and not path.endswith('/'):
36             path += '/'
37         for delta in self.fs._compute_deltas():
38             if delta.path.startswith(path):
39                 if delta.oldrev is None:
40                     c = 'A'
41                 elif delta.newrev is None:
42                     c = 'D'
43                 else:
44                     c = 'M'
45                 result.append('    %s  %s\n' % (c, delta.path[len(path):]))
46         return ''.join(result)
47
48     def getattr(self, path):
49         stat = self.fs.stat(path)
50         if stat['svn:entry:kind'] == 'dir':
51             s = S_IFDIR
52             mode = 0777
53         else:
54             s = S_IFREG
55             mode = 0666
56         try:
57             time = pysvn.date.decode(stat['svn:entry:committed-date'])
58         except KeyError:
59             try:
60                 time = self.creationtimes[path]
61             except KeyError:
62                 time = self.creationtimes[path] = now()
63         return self.mkattr(path,
64                            size    = stat.get('svn:entry:size', 0),
65                            st_kind = s,
66                            mode    = mode,
67                            time    = time)
68
69     def setattr(self, path, mode, uid, gid, size, atime, mtime):
70         if size is not None:
71             data = self.fs.read(path)
72             if size < len(data):
73                 self.fs.write(path, data[:size])
74             elif size > len(data):
75                 self.fs.write(path, data + '\x00' * (size - len(data)))
76
77     def listdir(self, path):
78         for name in self.fs.listdir(path):
79             kind = self.fs.check_path(posixpath.join(path, name))
80             if kind == 'dir':
81                 yield name, TYPE_DIR
82             else:
83                 yield name, TYPE_REG
84
85     def check_path(self, path):
86         kind = self.fs.check_path(path)
87         return kind is not None
88
89     def open(self, path, mode):
90         try:
91             of = self.openfiles[path]
92         except KeyError:
93             of = self.openfiles[path] = OpenFile(self.fs.read(path))
94         return of, FOPEN_KEEP_CACHE
95
96     def modified(self, path):
97         try:
98             of = self.openfiles[path]
99         except KeyError:
100             pass
101         else:
102             self.fs.write(path, of.f.getvalue())
103
104     def mknod_path(self, path, mode):
105         self.fs.add(path)
106
107     def mkdir_path(self, path, mode):
108         self.fs.mkdir(path)
109
110     def unlink_path(self, path):
111         self.fs.unlink(path)
112
113     def rmdir_path(self, path):
114         self.fs.rmdir(path)
115
116     def rename_path(self, oldpath, newpath):
117         kind = self.fs.check_path(oldpath)
118         if kind is None:
119             return False
120         self.fs.move(oldpath, newpath, kind)
121         return True
122
123     def getxattrs(self, path):
124         return XAttrs(self, path)
125
126
127 class OpenFile:
128     def __init__(self, data=''):
129         self.f = StringIO()
130         self.f.write(data)
131         self.f.seek(0)
132
133     def seek(self, pos):
134         self.f.seek(pos)
135
136     def read(self, sz):
137         return self.f.read(sz)
138
139     def write(self, buf):
140         self.f.write(buf)
141
142
143 class XAttrs:
144     def __init__(self, svnfs, path):
145         self.svnfs = svnfs
146         self.path = path
147
148     def keys(self):
149         return []
150
151     def __getitem__(self, key):
152         if key == 'status':
153             return self.svnfs.do_status(self.path)
154         raise KeyError(key)
155
156     def __setitem__(self, key, value):
157         if key == 'commit' and self.path == '':
158             self.svnfs.do_commit(value)
159         elif key == 'update' and self.path == '':
160             if self.svnfs.fs.modified():
161                 raise IOError(errno.EPERM, "there are local changes")
162             if value == '':
163                 rev = 'HEAD'
164             else:
165                 try:
166                     rev = int(value)
167                 except ValueError:
168                     raise IOError(errno.EPERM, "invalid revision number")
169             self.svnfs.do_open(rev)
170         else:
171             raise KeyError(key)
172
173     def __delitem__(self, key):
174         raise KeyError(key)
175
176
177 if __name__ == '__main__':
178     import sys
179     svnurl, mountpoint = sys.argv[1:]
180     handler = Handler(mountpoint, SvnFS(svnurl))
181     handler.loop_forever()