2 A read-only svn fs showing all the revisions in subdirectories.
4 from objectfs import ObjectFs, SymLink
5 from handler import Handler
6 from pysvn.ra import connect
7 from pysvn.date import decode
8 import errno, posixpath, time
11 #USE_SYMLINKS = 0 # they are wrong if the original file had another path
13 # use getfattr -d filename to see the node's attributes, which include
14 # information like the revision at which the file was last modified
18 def __init__(self, svnurl):
20 self.ra = connect(svnurl)
21 self.head = self.ra.get_latest_rev()
24 for rev in range(1, self.head+1):
33 return SymLink(str(self.head))
36 return TopLevelDir(self.ra, rev, rev, '')
40 def __init__(self, ra, rev, last_changed_rev, path):
43 self.last_changed_rev = last_changed_rev
47 return '<%s %d/%s>' % (self.__class__.__name__, self.rev, self.path)
51 rev, props, entries = self.ra.get_dir(self.path, self.rev,
53 for key, stats in entries.items():
54 yield key, getnode(self.ra, self.rev,
55 posixpath.join(self.path, key), stats)
58 def __init__(self, ra, rev, last_changed_rev, path, size):
59 Node.__init__(self, ra, rev, last_changed_rev, path)
66 checksum, rev, props, data = self.ra.get_file(self.path, self.rev,
71 class TopLevelDir(Dir):
73 for item in Dir.listdir(self):
75 yield 'svn:log', Log(self.ra, self.rev)
79 def __init__(self, ra, rev):
83 def getlogentry(self):
86 except AttributeError:
87 logentries = self.ra.log('', startrev=self.rev, endrev=self.rev)
89 [self.logentry] = logentries
95 return len(self.read())
98 logentry = self.getlogentry()
100 return 'r%d | (no change here)\n' % (self.rev,)
101 datetuple = time.gmtime(decode(logentry.date))
102 date = time.strftime("%c", datetuple)
103 return 'r%d | %s | %s\n\n%s' % (self.rev,
112 ## def getnode(ra, rev, path, stats):
113 ## committed_rev = stats['svn:entry:committed-rev']
114 ## if committed_rev == rev:
115 ## kind = stats['svn:entry:kind']
116 ## if kind == 'file':
117 ## return File(ra, rev, path, stats['svn:entry:size'])
118 ## elif kind == 'dir':
119 ## return Dir(ra, rev, path)
121 ## raise IOError(errno.EINVAL, "kind %r" % (kind,))
123 ## depth = path.count('/')
124 ## return SymLink('../' * depth + '../%d/%s' % (committed_rev, path))
126 def getnode(ra, rev, path, stats):
127 last_changed_rev = stats['svn:entry:committed-rev']
128 kind = stats['svn:entry:kind']
130 return File(ra, rev, last_changed_rev, path,
131 stats['svn:entry:size'])
133 return Dir(ra, rev, last_changed_rev, path)
135 raise IOError(errno.EINVAL, "kind %r" % (kind,))
138 if __name__ == '__main__':
140 svnurl, mountpoint = sys.argv[1:]
141 handler = Handler(mountpoint, ObjectFs(Root(svnurl)))
142 handler.loop_forever()