#!/usr/bin/python
import sys
import os
import re
import stringutils
import syslog
from difflib_2_5 import HtmlDiff
from svnlook import SvnLook
class Revision:
"""Wraps subversion revision into an object"""
def __init__(self, repository, revision, line_length = 80, subject_length = 100):
self.repository = repository
self.revision = int(revision)
self.line_length = line_length
self.subject_length = subject_length
self.svnlook = SvnLook(repository, revision)
self.changed_files = None
self.info = None
self.author = None
def getDiffForFile(self, change, file):
"""Returns html diff for a given file, comparing last and
previous revisions"""
if change == 'A':
new = self.svnlook.readFileForVersion(file, self.revision)
old = "NEW"
elif change == 'D':
new = "DELETED"
old = self.svnlook.readFileForVersion(file, self.revision - 1)
else:
new = self.svnlook.readFileForVersion(file, self.revision)
old = self.svnlook.readFileForVersion(file, self.revision - 1)
diff = HtmlDiff(2, self.line_length)
table = diff.make_table(old.split('\n'), new.split('\n'));
return table
def getDiffsForAllFiles(self):
"""Returns html diff tables for all files present in a given revision"""
files = self.getChangedFiles()
result = ""
for (change, file) in files:
result += "\n
" + file + "
\n";
result += self.getDiffForFile(change, file)
return result
def getChangedFiles(self):
return self._filterUnsupportedFiles(self.svnlook.processChangedFiles(self._getRawChangedFiles()))
def getAuthor(self):
"""Returns author of the revision"""
if not self.author:
self.author = self.svnlook._svnlook("author").replace("\n",'')
return self.author
def getDescription(self):
"""Returns description of the revision (more than just svnlook info!)"""
description = self._getSvnInfo()
description += "\n\n" + self._getRawChangedFiles()
return description
def getDescriptionSnippet(self):
"""Returns snippet of the description of a revision"""
info = self._getSvnInfo()
lines = info.split("\n")
description = "%d: " % self.revision
description += " ".join(lines[3:])
return stringutils.generateSnippet(description, length=self.subject_length)
def getTextForAllFiles(self):
"""Returns content of all files in revision"""
files = self.getChangedFiles()
result = ""
for (change, file) in files:
result += self._formatTextHeader(file)
if change != 'D':
result += self._enumerateLines(self.readFileForVersion(file, self.revision))
else:
result += "DELETED"
return result
def _getRawChangedFiles(self):
if not self.changed_files:
self.changed_files = self.svnlook.getRawChangedFiles()
return self.changed_files
def _getSvnInfo(self):
if not self.info:
self.info = self.svnlook._svnlook("info")
return self.info
def _formatTextHeader(self, file):
return "\n\n****** " + file + " ******\n\n"
def _enumerateLines(self, text):
lines = text.split("\n")
line_num = 1
result = ""
for line in lines:
result += ("%4d " % line_num) + line + "\n"
line_num += 1
return result
def _filterUnsupportedFiles(self, files):
sup_files = []
supported_files = \
re.compile('^\S*(html|xml|php|js|css|py|txt|c|cc|cpp|ini|cf|conf|java|sql|jsp|tmpl|readme|properties)$')
for (change, file) in files:
if supported_files.match(file.lower()):
sup_files.append((change, file))
return sup_files