Commit c07213ca authored by Christophe Dumez's avatar Christophe Dumez

- HTML Diff is now working (looks like viewcvs)


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@6356 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 1a88de33
...@@ -34,6 +34,7 @@ from MethodObject import Method ...@@ -34,6 +34,7 @@ from MethodObject import Method
from Globals import InitializeClass from Globals import InitializeClass
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from zLOG import LOG
try: try:
import pysvn import pysvn
...@@ -229,7 +230,11 @@ try: ...@@ -229,7 +230,11 @@ try:
def diff(self, path): def diff(self, path):
self._getPreferences() self._getPreferences()
os.system('mkdir -p /tmp/tmp-svn/') os.system('mkdir -p /tmp/tmp-svn/')
return self.client.diff('/tmp/tmp-svn',path) return self.client.diff(tmp_path='/tmp/tmp-svn/', url_or_path=path, recurse=False)
def revert(self, path):
self._getPreferences()
return self.client.revert(path)
def newSubversionClient(container, **kw): def newSubversionClient(container, **kw):
return SubversionClient(**kw).__of__(container) return SubversionClient(**kw).__of__(container)
......
...@@ -34,7 +34,7 @@ from Products.ERP5Type import Permissions ...@@ -34,7 +34,7 @@ from Products.ERP5Type import Permissions
from Products.ERP5Subversion import _dtmldir from Products.ERP5Subversion import _dtmldir
from zLOG import LOG, WARNING, INFO from zLOG import LOG, WARNING, INFO
from Products.ERP5Subversion.SubversionClient import newSubversionClient from Products.ERP5Subversion.SubversionClient import newSubversionClient
import os import os, re
from DateTime import DateTime from DateTime import DateTime
from cPickle import dumps, loads from cPickle import dumps, loads
from App.config import getConfiguration from App.config import getConfiguration
...@@ -74,6 +74,221 @@ class Dir : ...@@ -74,6 +74,221 @@ class Dir :
return d return d
## End of Dir Class ## End of Dir Class
class DiffFile:
# Members :
# - path : path of the modified file
# - children : sub codes modified
# - old_revision
# - new_revision
def __init__(this, raw_diff):
this.header = raw_diff.split('@@')[0][:-1]
# Getting file path in header
this.path = this.header.split('====')[0][:-1].strip()
# Getting revisions in header
for line in this.header.split('\n'):
if line.startswith('--- '):
tmp = re.search('\\([\w\s]+\\)$', line)
this.old_revision = tmp.string[tmp.start():tmp.end()][1:-1].strip()
if line.startswith('+++ '):
tmp = re.search('\\([\w\s]+\\)$', line)
this.new_revision = tmp.string[tmp.start():tmp.end()][1:-1].strip()
# Splitting the body from the header
this.body = '\n'.join(raw_diff.strip().split('\n')[4:])
# Now splitting modifications
this.children = []
first = True
tmp = []
for line in this.body.split('\n'):
if line:
if line.startswith('@@') and not first:
this.children.append(CodeBlock('\n'.join(tmp)))
tmp = [line,]
else:
first = False
tmp.append(line)
this.children.append(CodeBlock('\n'.join(tmp)))
def _escape(this, data):
"""
Escape &, <, and > in a string of data.
This is a copy of the xml.sax.saxutils.escape function.
"""
# must do ampersand first
if data:
#data = data.replace("&", "&amp;")
data = data.replace(">", "&gt;")
data = data.replace("<", "&lt;")
return data
def toHTML(this):
# Adding header of the table
html = '''<font color='black'><b>%s</b><br>
<hr><br>
<table style="text-align: left; width: 100%%;" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr height="18px">
<td style="background-color: grey"><b><center>%s</center></b></td>
<td style="background-color: grey"><b><center>%s</center></b></td>
</tr>'''%(this.path, this.old_revision, this.new_revision)
First = True
for child in this.children:
# Adding line number of the modification
if First:
html += '''<tr height="18px"><td style="background-color: grey">&nbsp;</td><td style="background-color: grey">&nbsp;</td></tr> <tr>
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
</tr>'''%(child.old_line, child.new_line)
First = False
else:
html += '''<tr height="18px"><td style="background-color: white">&nbsp;</td><td style="background-color: white">&nbsp;</td></tr> <tr>
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
</tr>'''%(child.old_line, child.new_line)
# Adding diff of the modification
old_code_list = child.getOldCodeList()
new_code_list = child.getNewCodeList()
i=0
for old_line_tuple in old_code_list:
new_line_tuple = new_code_list[i]
if new_line_tuple[0]:
new_line = new_line_tuple[0]
else:
new_line = ' '
if old_line_tuple[0]:
old_line = old_line_tuple[0]
else:
old_line = ' '
i+=1
html += ''' <tr height="18px">
<td style="background-color: %s">%s</td>
<td style="background-color: %s">%s</td>
</tr>'''%(old_line_tuple[1], this._escape(old_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'), new_line_tuple[1], this._escape(new_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
html += ''' </tbody>
</table></font><br><br>'''
return html
# A code block contains several SubCodeBlocks
class CodeBlock:
# Members :
# - old_line : line in old code (before modif)
# - new line : line in new code (after modif)
#
# Methods :
# - getOldCodeList() : return code before modif
# - getNewCodeList() : return code after modif
# Note: the code returned is a list of tuples (code line, background color)
def __init__(this, raw_diff):
# Splitting body and header
this.body = '\n'.join(raw_diff.split('\n')[1:])
this.header = raw_diff.split('\n')[0]
# Getting modifications lines
tmp = re.search('^@@ -\d+', this.header)
this.old_line = tmp.string[tmp.start():tmp.end()][4:]
tmp = re.search('\+\d+,', this.header)
this.new_line = tmp.string[tmp.start():tmp.end()][1:-1]
# Splitting modifications in SubCodeBlocks
in_modif = False
this.children = []
tmp=[]
for line in this.body.split('\n'):
if line:
if (line.startswith('+') or line.startswith('-')):
if in_modif:
tmp.append(line)
else:
this.children.append(SubCodeBlock('\n'.join(tmp)))
tmp = [line,]
in_modif = True
else:
if in_modif:
this.children.append(SubCodeBlock('\n'.join(tmp)))
tmp = [line,]
in_modif = False
else:
tmp.append(line)
this.children.append(SubCodeBlock('\n'.join(tmp)))
# Return code before modification
def getOldCodeList(this):
tmp = []
for child in this.children:
tmp.extend(child.getOldCodeList())
return tmp
# Return code after modification
def getNewCodeList(this):
tmp = []
for child in this.children:
tmp.extend(child.getNewCodeList())
return tmp
# a SubCodeBlock contain 0 or 1 modification (not more)
class SubCodeBlock:
def __init__(this, code):
this.body=code
this.modification=this._getModif()
# Choosing background color
if this.modification == 'none':
this.color = 'white'
elif this.modification == 'change':
this.color = 'rgb(253, 228, 6);'#light orange
elif this.modification == 'deletion':
this.color = 'rgb(253, 117, 74);'#light red
else:
this.color = 'rgb(83, 253, 74);'#light green
def _getModif(this):
nb_plus = 0
nb_minus = 0
for line in this.body.split('\n'):
if line.startswith("-"):
nb_minus-=1
elif line.startswith("+"):
nb_plus+=1
if (nb_plus!=0 and nb_minus==0):
return 'addition'
if (nb_plus==0 and nb_minus!=0):
return 'deletion'
if (nb_plus==0 and nb_minus==0):
return 'none'
return 'change'
# Return code before modification
def getOldCodeList(this):
if this.modification=='none':
return [(x, 'white') for x in this.body.split('\n')]
elif this.modification=='change':
return [this._getOldCodeList(x) for x in this.body.split('\n') if this._getOldCodeList(x)[0]]
else: # deletion or addition
return [this._getOldCodeList(x) for x in this.body.split('\n')]
def _getOldCodeList(this, line):
if line.startswith('+'):
return (None, this.color)
if line.startswith('-'):
return (' '+line[1:], this.color)
return (line, this.color)
# Return code after modification
def getNewCodeList(this):
if this.modification=='none':
return [(x, 'white') for x in this.body.split('\n')]
elif this.modification=='change':
return [this._getNewCodeList(x) for x in this.body.split('\n') if this._getNewCodeList(x)[0]]
else: # deletion or addition
return [this._getNewCodeList(x) for x in this.body.split('\n')]
def _getNewCodeList(this, line):
if line.startswith('-'):
return (None, this.color)
if line.startswith('+'):
return (' '+line[1:], this.color)
return (line, this.color)
class SubversionTool(UniqueObject, Folder): class SubversionTool(UniqueObject, Folder):
"""The SubversionTool provides a Subversion interface to ERP5. """The SubversionTool provides a Subversion interface to ERP5.
""" """
...@@ -193,6 +408,10 @@ class SubversionTool(UniqueObject, Folder): ...@@ -193,6 +408,10 @@ class SubversionTool(UniqueObject, Folder):
trust_item_list, permanent = loads(b64decode(login)) trust_item_list, permanent = loads(b64decode(login))
return dict(trust_item_list), permanent return dict(trust_item_list), permanent
def diffHTML(self, file_path):
raw_diff = self.diff(file_path)
return DiffFile(raw_diff).toHTML()
security.declareProtected(Permissions.ManagePortal, 'acceptSSLServer') security.declareProtected(Permissions.ManagePortal, 'acceptSSLServer')
def acceptSSLServer(self, trust_dict, permanent=False): def acceptSSLServer(self, trust_dict, permanent=False):
"""Accept a SSL server. """Accept a SSL server.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment