3 # Copyright (c) 2008-2009 Pavol Rusnak <prusnak@suse.cz>
5 # Permission is hereby granted, free of charge, to any person
6 # obtaining a copy of this software and associated documentation
7 # files (the "Software"), to deal in the Software without
8 # restriction, including without limitation the rights to use,
9 # copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the
11 # Software is furnished to do so, subject to the following
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 # OTHER DEALINGS IN THE SOFTWARE.
33 # allow loading module from working copy if osc is not installed
34 sys.path.append(os.path.abspath(os.path.dirname(sys.argv[0]) + '/../osc'))
43 fuse.fuse_python_api = (0, 2)
48 class EmptyStat(fuse.Stat):
61 class CacheEntry(object):
67 class oscFS(fuse.Fuse):
69 def __init__(self, *args, **kw):
70 fuse.Fuse.__init__(self, *args, **kw)
73 def getattr(self, path):
76 if path == '/' or path in projects or len(filter(lambda x: x.startswith(path), projects)) > 0:
77 st.st_mode = stat.S_IFDIR | 0555
81 if os.path.dirname(path) in projects:
82 st.st_mode = stat.S_IFDIR | 0555
86 if cache.has_key(path):
87 return cache[path].stat
91 def readdir(self, path, offset):
92 yield fuse.Direntry('.')
93 yield fuse.Direntry('..')
95 if os.path.dirname(path) in projects: # path is package
96 prj = os.path.dirname(path).replace('/','')
97 pkg = os.path.basename(path)
98 for f in osc.core.meta_get_filelist(osc.conf.config['apiurl'], prj, pkg, verbose=True):
100 st.st_mode = stat.S_IFREG | 0444
102 st.st_atime = f.mtime
103 st.st_ctime = f.mtime
104 st.st_mtime = f.mtime
105 cache[path + '/' + f.name] = CacheEntry()
106 cache[path + '/' + f.name].stat = st
107 yield fuse.Direntry(f.name)
110 if path in projects: # path is project
111 prj = path.replace('/','')
112 for p in osc.core.meta_get_packagelist(osc.conf.config['apiurl'], prj):
113 yield fuse.Direntry(p)
115 else: # path is project structure
119 for d in set( map(lambda x: x[l:].split('/')[0], filter(lambda x: x.startswith(path), projects) ) ) :
120 yield fuse.Direntry(d)
122 def mythread ( self ):
126 def chmod ( self, path, mode ):
127 print '*** chmod', path, oct(mode)
130 def chown ( self, path, uid, gid ):
131 print '*** chown', path, uid, gid
134 def fsync ( self, path, isFsyncFile ):
135 print '*** fsync', path, isFsyncFile
138 def link ( self, targetPath, linkPath ):
139 print '*** link', targetPath, linkPath
142 def mkdir ( self, path, mode ):
143 print '*** mkdir', path, oct(mode)
146 def mknod ( self, path, mode, dev ):
147 print '*** mknod', path, oct(mode), dev
150 def open ( self, path, flags ):
151 file = os.path.basename(path)
152 d = os.path.dirname(path)
153 pkg = os.path.basename(d)
154 prj = os.path.dirname(d).replace('/','')
155 if not cache.has_key(path):
157 if cache[path].stat == None:
159 tmp = tempfile.mktemp(prefix = 'oscfs_')
160 osc.core.get_source_file(osc.conf.config['apiurl'], prj, pkg, file, tmp)
161 cache[path].handle = open(tmp, 'r')
162 cache[path].tmpname = tmp
164 def read ( self, path, length, offset ):
165 if not cache.has_key(path):
167 f = cache[path].handle
169 return f.read(length)
171 def readlink ( self, path ):
172 print '*** readlink', path
175 def release ( self, path, flags ):
176 if cache.has_key(path):
177 cache[path].handle.close()
178 cache[path].handle = None
179 os.unlink(f.cache[path].tmpname)
180 cache[path].tmpname = None
182 def rename ( self, oldPath, newPath ):
183 print '*** rename', oldPath, newPath
186 def rmdir ( self, path ):
187 print '*** rmdir', path
194 def symlink ( self, targetPath, linkPath ):
195 print '*** symlink', targetPath, linkPath
198 def truncate ( self, path, size ):
199 print '*** truncate', path, size
202 def unlink ( self, path ):
203 print '*** unlink', path
206 def utime ( self, path, times ):
207 print '*** utime', path, times
210 def write ( self, path, buf, offset ):
211 print '*** write', path, buf, offset
216 for prj in osc.core.meta_get_project_list(osc.conf.config['apiurl']):
217 projects.append( '/' + prj.replace(':', ':/') )
222 if __name__ == '__main__':
223 print 'Loading config ...',
224 osc.conf.get_config()
226 print 'Getting projects list ...',
229 print 'Starting FUSE ...',
230 oscfs = oscFS( version = '%prog ' + fuse.__version__, usage = '', dash_s_do = 'setsingle')
232 oscfs.multithreaded = 0
233 oscfs.parse(values = oscfs, errex = 1)