Оказывается, формат дампа SVN очень легко анализировать. Если я сгенерирую его с помощью svnadmin dump --deltas
, тогда файл дампа будет содержать дельты для каждой модификации файла, и я могу разумно принять размер дельты (в байтах) за расстояние редактирования.
На случай, если кто-нибудь зайдет сюда, вот простой скрипт Python, который берет файл дампа svn и распечатывает файл XML, содержащий все свойства. Размеры редактирования содержатся в //path/Text-content-length
записях.
def read_defs(f):
res = {}
while True:
l = f.readline()
if l in ['','\n']: break
s = l.split(': ',1)
if len(s)!=2: assert False, 'Bad definition line '+l
res[s[0]] = (s[1][:-1] if s[1].endswith('\n') else s[1])
if len(res)==0 and l=='': return None
return res
def read_props(f):
res = {}
lastkey = None
while True:
l = f.readline()
if l.startswith('PROPS-END'): break
ln = int(l.split()[1])
l2 = f.read(ln); f.readline()
if l.startswith('K'):
lastkey = l2; res[l2] = None
elif l.startswith('V'):
res[lastkey] = l2
else:
assert False, 'Unexpected prop entry '+l
return res
def parsedump(f):
print '<?xml version="1.0"?>'
print '<log>'
inrevision,inpaths = False,False
while True:
d = read_defs(f)
if d is None: break
p = read_props(f) if 'Prop-content-length' in d else {}
if 'Revision-number' in d:
if inpaths: print '</paths>'; inpaths=False
if inrevision: print '</logentry>'
print '<logentry revision="'+d['Revision-number']+'">'
inrevision = True
for k,v in p.iteritems(): print '<'+k+'>'+v+'</'+k+'>'
elif 'Node-path' in d:
if not inpaths: print '<paths>'; inpaths=True
print '<path>'
for k,v in d.iteritems(): print '<'+k+'>'+v+'</'+k+'>'
for k,v in p.iteritems(): print '<'+k+'>'+v+'</'+k+'>'
print '</path>'
cl = (int(d['Content-length']) if 'Content-length' in d else 0)
pcl = (int(d['Prop-content-length']) if 'Prop-content-length' in d else 0)
f.seek(cl-pcl,1)
if inpaths: print '</paths>'
if inrevision: print '</logentry>'
print '</log>'
import sys
if __name__=='__main__':
if len(sys.argv)==0:
print 'Usage: svndump2xml FILENAME\nConverts FILENAME to xml, and prints to standard output'
sys.exit(0)
filename = sys.argv[1]
with open(filename,'rb') as f:
parsedump(f)