fuseosc: do not throw exception when no connectivity available
[opensuse:osc.git] / fuse / fuseosc
1 #!/usr/bin/python
2
3 import osc
4 import osc.conf
5 import osc.core
6 import sys
7 import fuse
8 import stat
9 import os
10 import errno
11 import tempfile
12
13 fuse.fuse_python_api = (0, 2)
14
15 projects = []
16 cache = {}
17
18 class EmptyStat(fuse.Stat):
19     def __init__(self):
20         self.st_mode = 0
21         self.st_ino = 0
22         self.st_dev = 0
23         self.st_nlink = 0
24         self.st_uid = 0
25         self.st_gid = 0
26         self.st_size = 0
27         self.st_atime = 0
28         self.st_mtime = 0
29         self.st_ctime = 0
30
31 class CacheEntry(object):
32     def __init__(self):
33         self.stat = None
34         self.handle = None
35         self.tmpname = None
36
37 class oscFS(fuse.Fuse):
38
39     def __init__(self, *args, **kw):
40         fuse.Fuse.__init__(self, *args, **kw)
41         print 'OK'
42
43     def getattr(self, path):
44         st = EmptyStat()
45         # path is project
46         if path == '/' or path in projects or len(filter(lambda x: x.startswith(path), projects)) > 0:
47             st.st_mode = stat.S_IFDIR | 0555
48             st.st_nlink = 2
49             return st
50         # path is package
51         if os.path.dirname(path) in projects:
52             st.st_mode = stat.S_IFDIR | 0555
53             st.st_nlink = 2
54             return st
55         # path is file
56         if cache.has_key(path):
57             return cache[path].stat
58         else:
59             return -errno.ENOENT
60
61     def readdir(self, path, offset):
62         yield fuse.Direntry('.')
63         yield fuse.Direntry('..')
64
65         if os.path.dirname(path) in projects: # path is package
66             prj = os.path.dirname(path).replace('/','')
67             pkg = os.path.basename(path)
68             for f in osc.core.meta_get_filelist(osc.conf.config['apiurl'], prj, pkg, verbose=True):
69                 st = EmptyStat()
70                 st.st_mode = stat.S_IFREG | 0444
71                 st.st_size = f.size
72                 st.st_atime = f.mtime
73                 st.st_ctime = f.mtime
74                 st.st_mtime = f.mtime
75                 cache[path + '/' + f.name] = CacheEntry()
76                 cache[path + '/' + f.name].stat = st
77                 yield fuse.Direntry(f.name)
78             return
79
80         if path in projects: # path is project
81             prj = path.replace('/','')
82             for p in osc.core.meta_get_packagelist(osc.conf.config['apiurl'], prj):
83                 yield fuse.Direntry(p)
84
85         else: # path is project structure
86             if (path != '/'):
87                 path += '/'
88             l = len(path)
89             for d in set( map(lambda x: x[l:].split('/')[0], filter(lambda x: x.startswith(path), projects) ) ) :
90                 yield fuse.Direntry(d)
91
92     def mythread ( self ):
93         print '*** mythread'
94         return -errno.ENOSYS
95
96     def chmod ( self, path, mode ):
97         print '*** chmod', path, oct(mode)
98         return -errno.ENOSYS
99
100     def chown ( self, path, uid, gid ):
101         print '*** chown', path, uid, gid
102         return -errno.ENOSYS
103
104     def fsync ( self, path, isFsyncFile ):
105         print '*** fsync', path, isFsyncFile
106         return -errno.ENOSYS
107
108     def link ( self, targetPath, linkPath ):
109         print '*** link', targetPath, linkPath
110         return -errno.ENOSYS
111
112     def mkdir ( self, path, mode ):
113         print '*** mkdir', path, oct(mode)
114         return -errno.ENOSYS
115
116     def mknod ( self, path, mode, dev ):
117         print '*** mknod', path, oct(mode), dev
118         return -errno.ENOSYS
119
120     def open ( self, path, flags ):
121         file = os.path.basename(path)
122         d = os.path.dirname(path)
123         pkg = os.path.basename(d)
124         prj = os.path.dirname(d).replace('/','')
125         if not cache.has_key(path):
126             return -errno.ENOENT
127         if cache[path].stat == None:
128             return -errno.ENOENT
129         tmp = tempfile.mktemp(prefix = 'oscfs_')
130         osc.core.get_source_file(osc.conf.config['apiurl'], prj, pkg, file, tmp)
131         cache[path].handle = open(tmp, 'r')
132         cache[path].tmpname = tmp
133
134     def read ( self, path, length, offset ):
135         if not cache.has_key(path):
136             return -errno.EACCES
137         f = cache[path].handle
138         f.seek(offset)
139         return f.read(length)
140
141     def readlink ( self, path ):
142         print '*** readlink', path
143         return -errno.ENOSYS
144
145     def release ( self, path, flags ):
146         if cache.has_key(path):
147             cache[path].handle.close()
148             cache[path].handle = None
149             os.unlink(f.cache[path].tmpname)
150             cache[path].tmpname = None
151
152     def rename ( self, oldPath, newPath ):
153         print '*** rename', oldPath, newPath
154         return -errno.ENOSYS
155
156     def rmdir ( self, path ):
157         print '*** rmdir', path
158         return -errno.ENOSYS
159
160     def statfs ( self ):
161         print '*** statfs'
162         return -errno.ENOSYS
163
164     def symlink ( self, targetPath, linkPath ):
165         print '*** symlink', targetPath, linkPath
166         return -errno.ENOSYS
167
168     def truncate ( self, path, size ):
169         print '*** truncate', path, size
170         return -errno.ENOSYS
171
172     def unlink ( self, path ):
173         print '*** unlink', path
174         return -errno.ENOSYS
175
176     def utime ( self, path, times ):
177         print '*** utime', path, times
178         return -errno.ENOSYS
179
180     def write ( self, path, buf, offset ):
181         print '*** write', path, buf, offset
182         return -errno.ENOSYS
183
184 def fill_projects():
185     try:
186         for prj in osc.core.meta_get_project_list(osc.conf.config['apiurl']):
187             projects.append( '/' + prj.replace(':', ':/') )
188     except:
189         print 'failed'
190         sys.exit(1)
191
192 if __name__ == '__main__':
193     print 'Loading config ...',
194     osc.conf.get_config()
195     print 'OK'
196     print 'Getting projects list ...',
197     fill_projects()
198     print 'OK'
199     print 'Starting FUSE ...',
200     oscfs = oscFS( version = '%prog ' + fuse.__version__, usage = '', dash_s_do = 'setsingle')
201     oscfs.flags = 0
202     oscfs.multithreaded = 0
203     oscfs.parse(values = oscfs, errex = 1)
204     oscfs.main()