Commit 1909c94c authored by Christophe Dumez's avatar Christophe Dumez

- huge code cleanup


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@7404 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 93977fbd
...@@ -34,7 +34,6 @@ from Products.ERP5Type.Utils import convertToUpperCase ...@@ -34,7 +34,6 @@ from Products.ERP5Type.Utils import convertToUpperCase
from MethodObject import Method 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.PythonScripts.Utility import allow_class from Products.PythonScripts.Utility import allow_class
from tempfile import mktemp from tempfile import mktemp
from Products.ERP5.Document.BusinessTemplate import removeAll from Products.ERP5.Document.BusinessTemplate import removeAll
...@@ -129,7 +128,8 @@ try: ...@@ -129,7 +128,8 @@ try:
# 0x8 means that the CA is unknown. # 0x8 means that the CA is unknown.
return True, 0x8, permanent return True, 0x8, permanent
# Wrap objects defined in pysvn so that skins have access to attributes in the ERP5 way. # Wrap objects defined in pysvn so that skins
# have access to attributes in the ERP5 way.
class Getter(Method): class Getter(Method):
def __init__(self, key): def __init__(self, key):
self._key = key self._key = key
...@@ -164,15 +164,18 @@ try: ...@@ -164,15 +164,18 @@ try:
class Status(ObjectWrapper): class Status(ObjectWrapper):
# XXX Big Hack to fix a bug # XXX Big Hack to fix a bug
__allow_access_to_unprotected_subobjects__ = 1 __allow_access_to_unprotected_subobjects__ = 1
attribute_list = ('path', 'entry', 'is_versioned', 'is_locked', 'is_copied', 'is_switched', 'prop_status', 'text_status', 'repos_prop_status', 'repos_text_status') attribute_list = ('path', 'entry', 'is_versioned', 'is_locked', \
'is_copied', 'is_switched', 'prop_status', 'text_status', \
'repos_prop_status', 'repos_text_status')
initializeAccessors(Status) initializeAccessors(Status)
class Entry(ObjectWrapper): class Entry(ObjectWrapper):
attribute_list = ('checksum', 'commit_author', 'commit_revision', 'commit_time', attribute_list = ('checksum', 'commit_author', 'commit_revision', \
'conflict_new', 'conflict_old', 'conflict_work', 'copy_from_revision', 'commit_time', 'conflict_new', 'conflict_old', 'conflict_work', \
'copy_from_url', 'is_absent', 'is_copied', 'is_deleted', 'is_valid', 'copy_from_revision', 'copy_from_url', 'is_absent', 'is_copied', \
'kind', 'name', 'properties_time', 'property_reject_file', 'repos', 'is_deleted', 'is_valid', 'kind', 'name', 'properties_time', \
'revision', 'schedule', 'text_time', 'url', 'uuid') 'property_reject_file', 'repos', 'revision', 'schedule', \
'text_time', 'url', 'uuid')
class Revision(ObjectWrapper): class Revision(ObjectWrapper):
attribute_list = ('kind', 'date', 'number') attribute_list = ('kind', 'date', 'number')
...@@ -193,9 +196,10 @@ try: ...@@ -193,9 +196,10 @@ try:
self.client.callback_get_log_message = GetLogMessageCallback(obj) self.client.callback_get_log_message = GetLogMessageCallback(obj)
self.client.callback_get_login = GetLoginCallback(obj) self.client.callback_get_login = GetLoginCallback(obj)
self.client.callback_notify = NotifyCallback(obj) self.client.callback_notify = NotifyCallback(obj)
self.client.callback_ssl_server_trust_prompt = SSLServerTrustPromptCallback(obj) self.client.callback_ssl_server_trust_prompt = \
SSLServerTrustPromptCallback(obj)
self.creation_time = time.time() self.creation_time = time.time()
self.__dict__.update(kw) self.__dict__.update(**kw)
self.exception = None self.exception = None
def getLogMessage(self): def getLogMessage(self):
...@@ -218,7 +222,8 @@ try: ...@@ -218,7 +222,8 @@ try:
def checkin(self, path, log_message, recurse): def checkin(self, path, log_message, recurse):
try: try:
return self.client.checkin(path, log_message=log_message or 'none', recurse=recurse) return self.client.checkin(path, log_message=log_message \
or 'none', recurse=recurse)
except pysvn.ClientError, error: except pysvn.ClientError, error:
excep = self.getException() excep = self.getException()
if excep: if excep:
...@@ -237,17 +242,19 @@ try: ...@@ -237,17 +242,19 @@ try:
raise error raise error
def status(self, path, **kw): def status(self, path, **kw):
# Since plain Python classes are not convenient in Zope, convert the objects. # Since plain Python classes are not convenient in
# Zope, convert the objects.
status_list = [Status(x) for x in self.client.status(path, **kw)] status_list = [Status(x) for x in self.client.status(path, **kw)]
# XXX: seems that pysvn return a list that is upside-down, we reverse it... # XXX: seems that pysvn return a list that is
# upside-down, we reverse it...
status_list.reverse() status_list.reverse()
return status_list return status_list
def removeAllInList(self, list): def removeAllInList(self, path_list):
"""Remove all files and folders in list """Remove all files and folders in list
""" """
for file in list: for file_path in path_list:
removeAll(file) removeAll(file_path)
def diff(self, path, revision1, revision2): def diff(self, path, revision1, revision2):
tmp = mktemp() tmp = mktemp()
...@@ -255,9 +262,12 @@ try: ...@@ -255,9 +262,12 @@ try:
if not revision1 or not revision2: if not revision1 or not revision2:
diff = self.client.diff(tmp_path=tmp, url_or_path=path, recurse=False) diff = self.client.diff(tmp_path=tmp, url_or_path=path, recurse=False)
else: else:
diff = self.client.diff(tmp_path=tmp, url_or_path=path, recurse=False, revision1=pysvn.Revision(pysvn.opt_revision_kind.number,revision1), revision2=pysvn.Revision(pysvn.opt_revision_kind.number,revision2)) diff = self.client.diff(tmp_path=tmp, url_or_path=path, \
recurse=False, revision1 = pysvn.Revision(pysvn.opt_revision_kind\
.number,revision1), revision2=pysvn.Revision(pysvn\
.opt_revision_kind.number,revision2))
# clean up temp dir # clean up temp dir
self.activate().removeAllInList([tmp,]) self.activate().removeAllInList([tmp, ])
return diff return diff
def revert(self, path, recurse=False): def revert(self, path, recurse=False):
...@@ -299,8 +309,10 @@ try: ...@@ -299,8 +309,10 @@ try:
else: else:
raise error raise error
# transform entry to dict to make it more usable in zope # transform entry to dict to make it more usable in zope
members_tuple=('url', 'uuid', 'revision', 'kind', 'commit_author', 'commit_revision', 'commit_time',) members_tuple = ('url', 'uuid', 'revision', 'kind', \
entry_dict = dict([(member,getattr(entry,member)) for member in members_tuple]) 'commit_author', 'commit_revision', 'commit_time',)
entry_dict = dict([(member, getattr(entry, member)) \
for member in members_tuple])
entry_dict['revision'] = entry_dict['revision'].number entry_dict['revision'] = entry_dict['revision'].number
entry_dict['commit_revision'] = entry_dict['commit_revision'].number entry_dict['commit_revision'] = entry_dict['commit_revision'].number
entry_dict['commit_time'] = time.ctime(entry_dict['commit_time']) entry_dict['commit_time'] = time.ctime(entry_dict['commit_time'])
...@@ -318,9 +330,9 @@ try: ...@@ -318,9 +330,9 @@ try:
else: else:
raise error raise error
#Modify the list to make it more usable in zope #Modify the list to make it more usable in zope
for dict in dict_list: for dictionary in dict_list:
dict['created_rev']=dict['created_rev'].number dictionary['created_rev'] = dictionary['created_rev'].number
dict['time']=time.ctime(dict['time']) dictionary['time'] = time.ctime(dictionary['time'])
return dict_list return dict_list
def cleanup(self, path): def cleanup(self, path):
......
...@@ -35,7 +35,7 @@ from Products.ERP5Type.Document.Folder import Folder ...@@ -35,7 +35,7 @@ from Products.ERP5Type.Document.Folder import Folder
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Subversion import _dtmldir from Products.ERP5Subversion import _dtmldir
from Products.ERP5Subversion.SubversionClient import newSubversionClient from Products.ERP5Subversion.SubversionClient import newSubversionClient
import os, re, commands, time, exceptions import os, re, commands, time, exceptions, pysvn
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
...@@ -45,7 +45,8 @@ from cStringIO import StringIO ...@@ -45,7 +45,8 @@ from cStringIO import StringIO
from tempfile import mktemp from tempfile import mktemp
from shutil import copy from shutil import copy
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.ERP5.Document.BusinessTemplate import removeAll, TemplateConditionError from Products.ERP5.Document.BusinessTemplate import removeAll
from Products.ERP5.Document.BusinessTemplate import TemplateConditionError
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
from dircache import listdir from dircache import listdir
from OFS.Traversable import NotFound from OFS.Traversable import NotFound
...@@ -60,8 +61,13 @@ try: ...@@ -60,8 +61,13 @@ try:
set set
except NameError: except NameError:
from sets import Set as set from sets import Set as set
NBSP = ' '
NBSP_TAB = NBSP*8
class File(object): class File(object):
""" Class that represents a file in memory
"""
__slots__ = ('status','name') __slots__ = ('status','name')
# Constructor # Constructor
def __init__(self, name, status) : def __init__(self, name, status) :
...@@ -70,7 +76,9 @@ class File(object): ...@@ -70,7 +76,9 @@ class File(object):
## End of File Class ## End of File Class
class Dir(object): class Dir(object):
__slots__ = ('status','name','sub_dirs','sub_files') """ Class that reprensents a folder in memory
"""
__slots__ = ('status', 'name', 'sub_dirs', 'sub_files')
# Constructor # Constructor
def __init__(self, name, status) : def __init__(self, name, status) :
self.status = status self.status = status
...@@ -78,32 +86,40 @@ class Dir(object): ...@@ -78,32 +86,40 @@ class Dir(object):
self.sub_dirs = [] # list of sub directories self.sub_dirs = [] # list of sub directories
self.sub_files = [] # list of sub files self.sub_files = [] # list of sub files
# return a list of sub directories' names
def getSubDirsNameList(self) : def getSubDirsNameList(self) :
""" return a list of sub directories' names
"""
return [d.name for d in self.sub_dirs] return [d.name for d in self.sub_dirs]
# return directory in subdirs given its name
def getDirFromName(self, name): def getDirFromName(self, name):
for d in self.sub_dirs: """ return directory in subdirs given its name
if d.name == name: """
return d for directory in self.sub_dirs:
if directory.name == name:
return directory
def getObjectFromName(self, name): def getObjectFromName(self, name):
for d in self.sub_dirs: """ return dir object given its name
if d.name == name: """
return d for directory in self.sub_dirs:
for f in self.sub_files: if directory.name == name:
if f.name == name: return directory
return f for sub_file in self.sub_files:
if sub_file.name == name:
return sub_file
def getContent(self): def getContent(self):
""" return content for directory
"""
content = self.sub_dirs content = self.sub_dirs
content.extend(self.sub_files) content.extend(self.sub_files)
return content return content
## End of Dir Class ## End of Dir Class
class Error(exceptions.EnvironmentError): class Error(exceptions.EnvironmentError):
pass """ Simple Exception
"""
pass
class SubversionPreferencesError(Exception): class SubversionPreferencesError(Exception):
"""The base exception class for the Subversion preferences. """The base exception class for the Subversion preferences.
...@@ -121,37 +137,37 @@ class SubversionNotAWorkingCopyError(Exception): ...@@ -121,37 +137,37 @@ class SubversionNotAWorkingCopyError(Exception):
pass pass
def copytree(src, dst, symlinks=False): def copytree(src, dst, symlinks=False):
"""Recursively copy a directory tree using copy(). """Recursively copy a directory tree using copy().
If exception(s) occur, an Error is raised with a list of reasons. If exception(s) occur, an Error is raised with a list of reasons.
dst dir must exist dst dir must exist
If the optional symlinks flag is true, symbolic links in the If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic it is false, the contents of the files pointed to by symbolic
links are copied. links are copied.
Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved
""" """
names = listdir(src) names = listdir(src)
errors = [] errors = []
for name in names: for name in names:
srcname = os.path.join(src, name) srcname = os.path.join(src, name)
dstname = os.path.join(dst, name) dstname = os.path.join(dst, name)
try: try:
if symlinks and os.path.islink(srcname): if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname) linkto = os.readlink(srcname)
os.symlink(linkto, dstname) os.symlink(linkto, dstname)
elif os.path.isdir(srcname): elif os.path.isdir(srcname):
if not os.path.exists(dstname): if not os.path.exists(dstname):
os.makedirs(dstname) os.makedirs(dstname)
copytree(srcname, dstname, symlinks) copytree(srcname, dstname, symlinks)
else: else:
copy(srcname, dstname) copy(srcname, dstname)
except (IOError, os.error), why: except (IOError, os.error), why:
errors.append((srcname, dstname, 'Error: ' + str(why.strerror))) errors.append((srcname, dstname, 'Error: ' + str(why.strerror)))
if errors: if errors:
raise Error, errors raise Error, errors
def cacheWalk(top, topdown=True, onerror=None): def cacheWalk(top, topdown=True, onerror=None):
"""Directory tree generator. """Directory tree generator.
...@@ -162,30 +178,30 @@ def cacheWalk(top, topdown=True, onerror=None): ...@@ -162,30 +178,30 @@ def cacheWalk(top, topdown=True, onerror=None):
Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved
""" """
try: try:
# Note that listdir and error are globals in this module due # Note that listdir and error are globals in this module due
# to earlier import-*. # to earlier import-*.
names = listdir(top) names = listdir(top)
except error, err: except os.error, err:
if onerror is not None: if onerror is not None:
onerror(err) onerror(err)
return return
dirs, nondirs = [], [] dirs, nondirs = [], []
for name in names: for name in names:
if os.path.isdir(os.path.join(top, name)): if os.path.isdir(os.path.join(top, name)):
dirs.append(name) dirs.append(name)
else: else:
nondirs.append(name) nondirs.append(name)
if topdown: if topdown:
yield top, dirs, nondirs yield top, dirs, nondirs
for name in dirs: for name in dirs:
path = os.path.join(top, name) path = os.path.join(top, name)
if not os.path.islink(path): if not os.path.islink(path):
for x in cacheWalk(path, topdown, onerror): for elem in cacheWalk(path, topdown, onerror):
yield x yield elem
if not topdown: if not topdown:
yield top, dirs, nondirs yield top, dirs, nondirs
def colorizeTag(tag): def colorizeTag(tag):
...@@ -208,41 +224,43 @@ def colorizeTag(tag): ...@@ -208,41 +224,43 @@ def colorizeTag(tag):
elif 'key' in text: elif 'key' in text:
color = '#0C4F0C'#dark green color = '#0C4F0C'#dark green
else: else:
color='blue' color = 'blue'
return "<font color='%s'>%s</font>"%(color,text,) return "<font color='%s'>%s</font>" % (color, text, )
def colorize(text): def colorize(text):
"""Return HTML Code with syntax hightlighting """Return HTML Code with syntax hightlighting
""" """
# Escape xml before adding html tags # Escape xml before adding html tags
html = escape(text) html = escape(text)
html = html.replace(' ', '&nbsp;&nbsp;') html = html.replace(' ', NBSP)
html = html.replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;') html = html.replace('\t', NBSP_TAB)
# Colorize comments # Colorize comments
p = re.compile(r'#.*') pattern = re.compile(r'#.*')
html = p.sub(colorizeTag, html) html = pattern.sub(colorizeTag, html)
# Colorize tags # Colorize tags
p = re.compile(r'&lt;.*?&gt;') pattern = re.compile(r'&lt;.*?&gt;')
html = p.sub(colorizeTag, html) html = pattern.sub(colorizeTag, html)
# Colorize strings # Colorize strings
p = re.compile(r'\".*?\"') pattern = re.compile(r'\".*?\"')
html = p.sub(colorizeTag, html) html = pattern.sub(colorizeTag, html)
html = html.replace(os.linesep, os.linesep+"<br>") html = html.replace(os.linesep, os.linesep+"<br>")
return html return html
class DiffFile: class DiffFile:
"""
# Members : # Members :
# - path : path of the modified file - path : path of the modified file
# - children : sub codes modified - children : sub codes modified
# - old_revision - old_revision
# - new_revision - new_revision
"""
def __init__(self, raw_diff): def __init__(self, raw_diff):
if '@@' not in raw_diff: if '@@' not in raw_diff:
self.binary=True self.binary = True
return return
else: else:
self.binary=False self.binary = False
self.header = raw_diff.split('@@')[0][:-1] self.header = raw_diff.split('@@')[0][:-1]
# Getting file path in header # Getting file path in header
self.path = self.header.split('====')[0][:-1].strip() self.path = self.header.split('====')[0][:-1].strip()
...@@ -264,63 +282,74 @@ class DiffFile: ...@@ -264,63 +282,74 @@ class DiffFile:
if line: if line:
if line.startswith('@@') and not first: if line.startswith('@@') and not first:
self.children.append(CodeBlock(os.linesep.join(tmp))) self.children.append(CodeBlock(os.linesep.join(tmp)))
tmp = [line,] tmp = [line, ]
else: else:
first = False first = False
tmp.append(line) tmp.append(line)
self.children.append(CodeBlock(os.linesep.join(tmp))) self.children.append(CodeBlock(os.linesep.join(tmp)))
def toHTML(self): def toHTML(self):
""" return HTML diff
"""
# Adding header of the table # Adding header of the table
if self.binary: if self.binary:
return '<b>Folder or binary file or just no changes!</b><br><br><br>' return '<b>Folder or binary file or just no changes!</b><br><br><br>'
html = ''' html_list = []
html_list.append('''
<table style="text-align: left; width: 100%%;" border="0" cellpadding="0" cellspacing="0"> <table style="text-align: left; width: 100%%;" border="0" cellpadding="0" cellspacing="0">
<tbody> <tbody>
<tr height="18px"> <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>
<td style="background-color: black;" width="2"></td> <td style="background-color: black;" width="2"></td>
<td style="background-color: grey"><b><center>%s</center></b></td> <td style="background-color: grey"><b><center>%s</center></b></td>
</tr>'''%(self.old_revision, self.new_revision) </tr>''' % (self.old_revision, self.new_revision))
header_color = 'grey' header_color = 'grey'
child_html_text = '''<tr height="18px"><td style="background-color: %s">
&nbsp;</td><td style="background-color: black;" width="2"></td>
<td style="background-color: %s">&nbsp;</td></tr><tr height="18px">
<td style="background-color: rgb(68, 132, 255);"><b>Line %%s</b></td>
<td style="background-color: black;" width="2"></td>
<td style="background-color: rgb(68, 132, 255);"><b>Line %%s</b></td>
</tr>''' % (header_color, header_color)
for child in self.children: for child in self.children:
# Adding line number of the modification # Adding line number of the modification
html += '''<tr height="18px"><td style="background-color: %s">&nbsp;</td><td style="background-color: black;" width="2"></td><td style="background-color: %s">&nbsp;</td></tr> <tr height="18px"> html_list.append( child_html_text % (child.old_line, child.new_line) )
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
<td style="background-color: black;" width="2"></td>
<td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
</tr>'''%(header_color, header_color, child.old_line, child.new_line)
header_color = 'white' header_color = 'white'
# Adding diff of the modification # Adding diff of the modification
old_code_list = child.getOldCodeList() old_code_list = child.getOldCodeList()
new_code_list = child.getNewCodeList() new_code_list = child.getNewCodeList()
i=0 i = 0
for old_line_tuple in old_code_list: for old_line_tuple in old_code_list:
new_line_tuple = new_code_list[i] new_line_tuple = new_code_list[i]
new_line = new_line_tuple[0] or ' ' new_line = new_line_tuple[0] or ' '
old_line = old_line_tuple[0] or ' ' old_line = old_line_tuple[0] or ' '
i+=1 i += 1
html += ''' <tr height="18px"> html_list.append( '''<tr height="18px">
<td style="background-color: %s">%s</td> <td style="background-color: %s">%s</td>
<td style="background-color: black;" width="2"></td> <td style="background-color: black;" width="2"></td>
<td style="background-color: %s">%s</td> <td style="background-color: %s">%s</td>
</tr>'''%(old_line_tuple[1], escape(old_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'), new_line_tuple[1], escape(new_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')) </tr>'''%(old_line_tuple[1],
html += ''' </tbody> escape(old_line).replace(' ', NBSP).replace('\t', NBSP_TAB),
</table><br><br>''' new_line_tuple[1],
return html escape(new_line).replace(' ', NBSP).replace('\t', NBSP_TAB))
)
html_list.append(''' </tbody></table><br/><br/>''')
return '\n'.join(html_list)
# A code block contains several SubCodeBlocks
class CodeBlock: class CodeBlock:
# Members : """
# - old_line : line in old code (before modif) A code block contains several SubCodeBlocks
# - new line : line in new code (after modif) Members :
# - old_line : line in old code (before modif)
# Methods : - new line : line in new code (after modif)
# - getOldCodeList() : return code before modif
# - getNewCodeList() : return code after modif Methods :
# Note: the code returned is a list of tuples (code line, background color) - 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__(self, raw_diff): def __init__(self, raw_diff):
# Splitting body and header # Splitting body and header
...@@ -334,7 +363,7 @@ class CodeBlock: ...@@ -334,7 +363,7 @@ class CodeBlock:
# Splitting modifications in SubCodeBlocks # Splitting modifications in SubCodeBlocks
in_modif = False in_modif = False
self.children = [] self.children = []
tmp=[] tmp = []
for line in self.body.split(os.linesep): for line in self.body.split(os.linesep):
if line: if line:
if (line.startswith('+') or line.startswith('-')): if (line.startswith('+') or line.startswith('-')):
...@@ -342,33 +371,36 @@ class CodeBlock: ...@@ -342,33 +371,36 @@ class CodeBlock:
tmp.append(line) tmp.append(line)
else: else:
self.children.append(SubCodeBlock(os.linesep.join(tmp))) self.children.append(SubCodeBlock(os.linesep.join(tmp)))
tmp = [line,] tmp = [line, ]
in_modif = True in_modif = True
else: else:
if in_modif: if in_modif:
self.children.append(SubCodeBlock(os.linesep.join(tmp))) self.children.append(SubCodeBlock(os.linesep.join(tmp)))
tmp = [line,] tmp = [line, ]
in_modif = False in_modif = False
else: else:
tmp.append(line) tmp.append(line)
self.children.append(SubCodeBlock(os.linesep.join(tmp))) self.children.append(SubCodeBlock(os.linesep.join(tmp)))
# Return code before modification
def getOldCodeList(self): def getOldCodeList(self):
""" Return code before modification
"""
tmp = [] tmp = []
for child in self.children: for child in self.children:
tmp.extend(child.getOldCodeList()) tmp.extend(child.getOldCodeList())
return tmp return tmp
# Return code after modification
def getNewCodeList(self): def getNewCodeList(self):
""" Return code after modification
"""
tmp = [] tmp = []
for child in self.children: for child in self.children:
tmp.extend(child.getNewCodeList()) tmp.extend(child.getNewCodeList())
return tmp return tmp
# a SubCodeBlock contain 0 or 1 modification (not more)
class SubCodeBlock: class SubCodeBlock:
""" a SubCodeBlock contain 0 or 1 modification (not more)
"""
def __init__(self, code): def __init__(self, code):
self.body = code self.body = code
self.modification = self._getModif() self.modification = self._getModif()
...@@ -385,75 +417,92 @@ class SubCodeBlock: ...@@ -385,75 +417,92 @@ class SubCodeBlock:
self.color = 'rgb(83, 253, 74);'#light green self.color = 'rgb(83, 253, 74);'#light green
def _getModif(self): def _getModif(self):
""" Return type of modification :
addition, deletion, none
"""
nb_plus = 0 nb_plus = 0
nb_minus = 0 nb_minus = 0
for line in self.body.split(os.linesep): for line in self.body.split(os.linesep):
if line.startswith("-"): if line.startswith("-"):
nb_minus-=1 nb_minus -= 1
elif line.startswith("+"): elif line.startswith("+"):
nb_plus+=1 nb_plus += 1
if (nb_plus==0 and nb_minus==0): if (nb_plus == 0 and nb_minus == 0):
return 'none' return 'none'
if (nb_minus==0): if (nb_minus == 0):
return 'addition' return 'addition'
if (nb_plus==0): if (nb_plus == 0):
return 'deletion' return 'deletion'
return 'change' return 'change'
def _getOldCodeLength(self): def _getOldCodeLength(self):
""" Private function to return old code length
"""
nb_lines = 0 nb_lines = 0
for line in self.body.split(os.linesep): for line in self.body.split(os.linesep):
if not line.startswith("+"): if not line.startswith("+"):
nb_lines+=1 nb_lines += 1
return nb_lines return nb_lines
def _getNewCodeLength(self): def _getNewCodeLength(self):
""" Private function to return new code length
"""
nb_lines = 0 nb_lines = 0
for line in self.body.split(os.linesep): for line in self.body.split(os.linesep):
if not line.startswith("-"): if not line.startswith("-"):
nb_lines+=1 nb_lines += 1
return nb_lines return nb_lines
# Return code before modification
def getOldCodeList(self): def getOldCodeList(self):
if self.modification=='none': """ Return code before modification
"""
if self.modification == 'none':
old_code = [(x, 'white') for x in self.body.split(os.linesep)] old_code = [(x, 'white') for x in self.body.split(os.linesep)]
elif self.modification=='change': elif self.modification == 'change':
old_code = [self._getOldCodeList(x) for x in self.body.split(os.linesep) if self._getOldCodeList(x)[0]] old_code = [self._getOldCodeList(x) for x in self.body.split(os.linesep) \
if self._getOldCodeList(x)[0]]
# we want old_code_list and new_code_list to have the same length # we want old_code_list and new_code_list to have the same length
if(self.old_code_length < self.new_code_length): if(self.old_code_length < self.new_code_length):
filling = [(None, self.color)]*(self.new_code_length-self.old_code_length) filling = [(None, self.color)] * (self.new_code_length - \
self.old_code_length)
old_code.extend(filling) old_code.extend(filling)
else: # deletion or addition else: # deletion or addition
old_code = [self._getOldCodeList(x) for x in self.body.split(os.linesep)] old_code = [self._getOldCodeList(x) for x in self.body.split(os.linesep)]
return old_code return old_code
def _getOldCodeList(self, line): def _getOldCodeList(self, line):
""" Private function to return code before modification
"""
if line.startswith('+'): if line.startswith('+'):
return (None, self.color) return (None, self.color)
if line.startswith('-'): if line.startswith('-'):
return (' '+line[1:], self.color) return (' ' + line[1:], self.color)
return (line, self.color) return (line, self.color)
# Return code after modification
def getNewCodeList(self): def getNewCodeList(self):
if self.modification=='none': """ Return code after modification
"""
if self.modification == 'none':
new_code = [(x, 'white') for x in self.body.split(os.linesep)] new_code = [(x, 'white') for x in self.body.split(os.linesep)]
elif self.modification=='change': elif self.modification == 'change':
new_code = [self._getNewCodeList(x) for x in self.body.split(os.linesep) if self._getNewCodeList(x)[0]] new_code = [self._getNewCodeList(x) for x in self.body.split(os.linesep) \
if self._getNewCodeList(x)[0]]
# we want old_code_list and new_code_list to have the same length # we want old_code_list and new_code_list to have the same length
if(self.new_code_length < self.old_code_length): if(self.new_code_length < self.old_code_length):
filling = [(None, self.color)]*(self.old_code_length-self.new_code_length) filling = [(None, self.color)] * (self.old_code_length - \
self.new_code_length)
new_code.extend(filling) new_code.extend(filling)
else: # deletion or addition else: # deletion or addition
new_code = [self._getNewCodeList(x) for x in self.body.split(os.linesep)] new_code = [self._getNewCodeList(x) for x in self.body.split(os.linesep)]
return new_code return new_code
def _getNewCodeList(self, line): def _getNewCodeList(self, line):
""" Private function to return code after modification
"""
if line.startswith('-'): if line.startswith('-'):
return (None, self.color) return (None, self.color)
if line.startswith('+'): if line.startswith('+'):
return (' '+line[1:], self.color) return (' ' + line[1:], self.color)
return (line, self.color) return (line, self.color)
class SubversionTool(BaseTool, UniqueObject, Folder): class SubversionTool(BaseTool, UniqueObject, Folder):
...@@ -488,33 +537,36 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -488,33 +537,36 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
# Filter content (ZMI)) # Filter content (ZMI))
def __init__(self): def __init__(self):
return Folder.__init__(self, SubversionTool.id) return Folder.__init__(self, SubversionTool.id)
# Filter content (ZMI))
def filtered_meta_types(self, user=None): def filtered_meta_types(self, user=None):
# Filters the list of available meta types. """
all = SubversionTool.inheritedAttribute('filtered_meta_types')(self) Filter content (ZMI))
meta_types = [] Filters the list of available meta types.
for meta_type in self.all_meta_types(): """
if meta_type['name'] in self.allowed_types: all = SubversionTool.inheritedAttribute('filtered_meta_types')(self)
meta_types.append(meta_type) meta_types = []
return meta_types for meta_type in self.all_meta_types():
if meta_type['name'] in self.allowed_types:
meta_types.append(meta_type)
return meta_types
# path is the path in svn working copy # path is the path in svn working copy
# return edit_path in zodb to edit it # return edit_path in zodb to edit it
# return '#' if no zodb path is found # return '#' if no zodb path is found
def editPath(self, bt, path): def editPath(self, business_template, path):
"""Return path to edit file """Return path to edit file
path can be relative or absolute path can be relative or absolute
""" """
path = self.relativeToAbsolute(path, bt).replace('\\', '/') path = self.relativeToAbsolute(path, business_template).replace('\\', '/')
if 'bt' in path.split('/'): if 'bt' in path.split('/'):
# not in zodb # not in zodb
return '#' return '#'
# if file have been deleted then not in zodb # if file have been deleted then not in zodb
if not os.path.exists(path): if not os.path.exists(path):
return '#' return '#'
svn_path = self.getSubversionPath(bt).replace('\\', '/') svn_path = self.getSubversionPath(business_template).replace('\\', '/')
edit_path = path.replace(svn_path, '').strip() edit_path = path.replace(svn_path, '').strip()
if edit_path == '': if edit_path == '':
# not in zodb # not in zodb
...@@ -528,20 +580,25 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -528,20 +580,25 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
# remove file extension # remove file extension
edit_path = os.path.splitext(edit_path)[0] edit_path = os.path.splitext(edit_path)[0]
# Add beginning and end of url # Add beginning and end of url
edit_path = os.path.join(bt.REQUEST["BASE2"], edit_path, 'manage_main') edit_path = os.path.join(business_template.REQUEST["BASE2"], \
edit_path, 'manage_main')
return edit_path return edit_path
def _encodeLogin(self, realm, user, password): def _encodeLogin(self, realm, user, password):
# Encode login information. """ Encode login information.
"""
return b64encode(dumps((realm, user, password))) return b64encode(dumps((realm, user, password)))
def _decodeLogin(self, login): def _decodeLogin(self, login):
# Decode login information. """ Decode login information.
"""
return loads(b64decode(login)) return loads(b64decode(login))
def goToWorkingCopy(self, bt): def goToWorkingCopy(self, business_template):
working_path = self.getSubversionPath(bt) """ Change to business template directory
os.chdir(working_path) """
working_path = self.getSubversionPath(business_template)
os.chdir(working_path)
def setLogin(self, realm, user, password): def setLogin(self, realm, user, password):
"""Set login information. """Set login information.
...@@ -560,7 +617,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -560,7 +617,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
value = ','.join(login_list) value = ','.join(login_list)
expires = (DateTime() + 1).toZone('GMT').rfc822() expires = (DateTime() + 1).toZone('GMT').rfc822()
request.set(self.login_cookie_name, value) request.set(self.login_cookie_name, value)
response.setCookie(self.login_cookie_name, value, path = '/', expires = expires) response.setCookie(self.login_cookie_name, value, path = '/', \
expires = expires)
def _getLogin(self, target_realm): def _getLogin(self, target_realm):
request = self.REQUEST request = self.REQUEST
...@@ -572,12 +630,14 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -572,12 +630,14 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
return user, password return user, password
return None, None return None, None
def getHeader(self, bt, file): def getHeader(self, business_template, file_path):
file = self.relativeToAbsolute(file, bt) file_path = self.relativeToAbsolute(file_path, business_template)
header = "<b><a href='BusinessTemplate_viewSvnShowFile?file="+file+"'>" + file + "</a></b>" header = "<b><a href='BusinessTemplate_viewSvnShowFile?file=" + \
edit_path = self.editPath(bt, file) file_path + "'>" + file_path + "</a></b>"
edit_path = self.editPath(business_template, file_path)
if edit_path != '#': if edit_path != '#':
header += "&nbsp;&nbsp;<a href='"+self.editPath(bt, file)+"'><img src='imgs/edit.png' border='0'></a>" header += "&nbsp;&nbsp;<a href='"+self.editPath(business_template, \
file_path) + "'><img src='imgs/edit.png' border='0'></a>"
return header return header
def _encodeSSLTrust(self, trust_dict, permanent=False): def _encodeSSLTrust(self, trust_dict, permanent=False):
...@@ -595,41 +655,49 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -595,41 +655,49 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
def getPreferredUsername(self): def getPreferredUsername(self):
"""return username in preferences if set of the current username """return username in preferences if set of the current username
""" """
username = self.getPortalObject().portal_preferences.getPreferredSubversionUserName() username = self.getPortalObject().portal_preferences\
.getPreferredSubversionUserName()
if username is None or username.strip() == "": if username is None or username.strip() == "":
# not set in preferences, then we get the current username in zope # not set in preferences, then we get the current username in zope
username = self.portal_membership.getAuthenticatedMember().getUserName() username = self.portal_membership.getAuthenticatedMember().getUserName()
return username return username
def diffHTML(self, file_path, bt, revision1=None, revision2=None): def diffHTML(self, file_path, business_template, revision1=None, \
raw_diff = self.diff(file_path, bt, revision1, revision2) revision2=None):
""" Return HTML diff
"""
raw_diff = self.diff(file_path, business_template, revision1, revision2)
return DiffFile(raw_diff).toHTML() return DiffFile(raw_diff).toHTML()
# Display a file content in HTML with syntax highlighting def fileHTML(self, business_template, file_path):
def fileHTML(self, bt, file_path): """ Display a file content in HTML with syntax highlighting
file_path = self.relativeToAbsolute(file_path, bt) """
file = open(file_path, 'r') file_path = self.relativeToAbsolute(file_path, business_template)
input_file = open(file_path, 'r')
if os.path.exists(file_path): if os.path.exists(file_path):
if os.path.isdir(file_path): if os.path.isdir(file_path):
text = "<b>"+file_path+"</b><hr>" text = "<b>"+file_path+"</b><hr>"
text += file_path +" is a folder!" text += file_path +" is a folder!"
else: else:
head = "<b>"+file_path+"</b> <a href='"+self.editPath(bt, file_path)+"'><img src='imgs/edit.png' border='0'></a><hr>" head = "<b>"+file_path+"</b> <a href='" + \
text = head + colorize(file.read()) self.editPath(business_template, file_path) + \
"'><img src='imgs/edit.png' border='0'></a><hr>"
text = head + colorize(input_file.read())
else: else:
# see if tmp file is here (svn deleted file) # see if tmp file is here (svn deleted file)
if file_path[-1]==os.sep: if file_path[-1] == os.sep:
file_path=file_path[:-1] file_path = file_path[:-1]
filename = file_path.split(os.sep)[-1] filename = file_path.split(os.sep)[-1]
tmp_path = os.sep.join(file_path.split(os.sep)[:-1]) tmp_path = os.sep.join(file_path.split(os.sep)[:-1])
tmp_path = os.path.join(tmp_path,'.svn','text-base',filename+'.svn-base') tmp_path = os.path.join(tmp_path, '.svn', 'text-base', \
filename+'.svn-base')
if os.path.exists(tmp_path): if os.path.exists(tmp_path):
head = "<b>"+tmp_path+"</b> (svn temporary file)<hr>" head = "<b>"+tmp_path+"</b> (svn temporary file)<hr>"
text = head + colorize(file.read()) text = head + colorize(input_file.read())
else : # does not exist else : # does not exist
text = "<b>"+file_path+"</b><hr>" text = "<b>"+file_path+"</b><hr>"
text += file_path +" does not exist!" text += file_path +" does not exist!"
file.close() input_file.close()
return text return text
security.declareProtected(Permissions.ManagePortal, 'acceptSSLServer') security.declareProtected(Permissions.ManagePortal, 'acceptSSLServer')
...@@ -648,9 +716,12 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -648,9 +716,12 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
value = ','.join(trust_list) value = ','.join(trust_list)
expires = (DateTime() + 1).toZone('GMT').rfc822() expires = (DateTime() + 1).toZone('GMT').rfc822()
request.set(self.ssl_trust_cookie_name, value) request.set(self.ssl_trust_cookie_name, value)
response.setCookie(self.ssl_trust_cookie_name, value, path = '/', expires = expires) response.setCookie(self.ssl_trust_cookie_name, value, path = '/', \
expires = expires)
def acceptSSLPerm(self, trust_dict): def acceptSSLPerm(self, trust_dict):
""" Accept SSL server permanently
"""
self.acceptSSLServer(self, trust_dict, True) self.acceptSSLServer(self, trust_dict, True)
def _trustSSLServer(self, target_trust_dict): def _trustSSLServer(self, target_trust_dict):
...@@ -671,71 +742,78 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -671,71 +742,78 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
return newSubversionClient(self, **kw) return newSubversionClient(self, **kw)
security.declareProtected('Import/Export objects', 'getSubversionPath') security.declareProtected('Import/Export objects', 'getSubversionPath')
# with_name : with business template name at the end of the path def getSubversionPath(self, business_template, with_name=True):
def getSubversionPath(self, bt, with_name=True): """
# return the working copy path corresponding to return the working copy path corresponding to
# the given business template browsing the given business template browsing
# working copy list in preferences (looking working copy list in preferences (looking
# only at first level of directories) only at first level of directories)
wc_list = self.getPortalObject().portal_preferences.getPreferredSubversionWorkingCopyList()
with_name : with business template name at the end of the path
"""
wc_list = self.getPortalObject().portal_preferences\
.getPreferredSubversionWorkingCopyList()
if not wc_list: if not wc_list:
wc_list = self.getPortalObject().portal_preferences.default_site_preference.getPreferredSubversionWorkingCopyList() wc_list = self.getPortalObject().portal_preferences.\
default_site_preference.getPreferredSubversionWorkingCopyList()
if not wc_list: if not wc_list:
raise SubversionPreferencesError, 'Please set at least one Subversion Working Copy in preferences first.' raise SubversionPreferencesError, \
'Please set at least one Subversion Working Copy in preferences first.'
if len(wc_list) == 0 : if len(wc_list) == 0 :
raise SubversionPreferencesError, 'Please set at least one Subversion Working Copy in preferences first.' raise SubversionPreferencesError, \
bt_name = bt.getTitle() 'Please set at least one Subversion Working Copy in preferences first.'
for wc in wc_list: bt_name = business_template.getTitle()
wc = self._getWorkingPath(wc) for working_copy in wc_list:
if not os.path.exists(os.path.join(wc, '.svn')): working_copy = self._getWorkingPath(working_copy)
raise SubversionNotAWorkingCopyError, "You must check out working copies in this directory: "+wc+" or choose another path in portal preferences." if not os.path.exists(os.path.join(working_copy, '.svn')):
if bt_name in listdir(wc) : raise SubversionNotAWorkingCopyError, \
wc_path = os.path.join(wc, bt_name) "You must check out working copies in this directory: " + \
working_copy + " or choose another path in portal preferences."
if bt_name in listdir(working_copy) :
wc_path = os.path.join(working_copy, bt_name)
if os.path.isdir(wc_path): if os.path.isdir(wc_path):
if with_name: if with_name:
return wc_path return wc_path
else: else:
return os.sep.join(wc_path.split(os.sep)[:-1]) return os.sep.join(wc_path.split(os.sep)[:-1])
raise SubversionUnknownBusinessTemplateError, "Could not find '"+bt_name+"' at first level of working copies." raise SubversionUnknownBusinessTemplateError, "Could not find '"+\
bt_name+"' at first level of working copies."
def getTopWorkingPath(self):
return self.top_working_path
def _getWorkingPath(self, path): def _getWorkingPath(self, path):
#if path[0] != '/': """ Check if the given path is reachable (allowed)
# path = os.path.join(self.top_working_path, path) """
#path = os.path.abspath(path)
if not path.startswith(self.top_working_path): if not path.startswith(self.top_working_path):
raise Unauthorized, 'unauthorized access to path %s' % path raise Unauthorized, 'unauthorized access to path %s' % path
return path return path
security.declareProtected('Import/Export objects', 'update') security.declareProtected('Import/Export objects', 'update')
def update(self, bt): def update(self, business_template):
"""Update a working copy. """Update a working copy.
""" """
path = self._getWorkingPath(self.getSubversionPath(bt)) path = self._getWorkingPath(self.getSubversionPath(business_template))
client = self._getClient() client = self._getClient()
# Revert local changes in working copy first to import a "pure" BT after update # Revert local changes in working copy first
# to import a "pure" BT after update
self.revert(path=path, recurse=True) self.revert(path=path, recurse=True)
# Update from SVN # Update from SVN
client.update(path) client.update(path)
# Import in zodb # Import in zodb
return self.importBT(bt) return self.importBT(business_template)
security.declareProtected('Import/Export objects', 'updatewc') security.declareProtected('Import/Export objects', 'updatewc')
def updatewc(self, bt): def updatewc(self, business_template):
"""Update a working copy. """Update a working copy.
""" """
path = self._getWorkingPath(self.getSubversionPath(bt)) path = self._getWorkingPath(self.getSubversionPath(business_template))
client = self._getClient() client = self._getClient()
# Update from SVN # Update from SVN
client.update(path) client.update(path)
security.declareProtected('Import/Export objects', 'switch') security.declareProtected('Import/Export objects', 'switch')
def switch(self, bt, url): def switch(self, business_template, url):
"""switch SVN repository for a working copy. """switch SVN repository for a working copy.
""" """
path = self._getWorkingPath(self.getSubversionPath(bt)) path = self._getWorkingPath(self.getSubversionPath(business_template))
client = self._getClient() client = self._getClient()
if url[-1] == '/' : if url[-1] == '/' :
url = url[:-1] url = url[:-1]
...@@ -744,51 +822,58 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -744,51 +822,58 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
security.declareProtected('Import/Export objects', 'add') security.declareProtected('Import/Export objects', 'add')
# path can be a list or not (relative or absolute) # path can be a list or not (relative or absolute)
def add(self, path, bt=None): def add(self, path, business_template=None):
"""Add a file or a directory. """Add a file or a directory.
""" """
if bt is not None: if business_template is not None:
if isinstance(path, list) : if isinstance(path, list) :
path = [self._getWorkingPath(self.relativeToAbsolute(x, bt)) for x in path] path = [self._getWorkingPath(self.relativeToAbsolute(x, \
business_template)) for x in path]
else: else:
path = self._getWorkingPath(self.relativeToAbsolute(path, bt)) path = self._getWorkingPath(self.relativeToAbsolute(path, \
business_template))
client = self._getClient() client = self._getClient()
return client.add(path) return client.add(path)
security.declareProtected('Import/Export objects', 'info') security.declareProtected('Import/Export objects', 'info')
def info(self, bt): def info(self, business_template):
"""return info of working copy """return info of working copy
""" """
working_copy = self._getWorkingPath(self.getSubversionPath(bt)) working_copy = self._getWorkingPath(self\
.getSubversionPath(business_template))
client = self._getClient() client = self._getClient()
return client.info(working_copy) return client.info(working_copy)
security.declareProtected('Import/Export objects', 'log') security.declareProtected('Import/Export objects', 'log')
# path can be absolute or relative # path can be absolute or relative
def log(self, path, bt): def log(self, path, business_template):
"""return log of a file or dir """return log of a file or dir
""" """
client = self._getClient() client = self._getClient()
return client.log(self._getWorkingPath(self.relativeToAbsolute(path, bt))) return client.log(self._getWorkingPath(self\
.relativeToAbsolute(path, business_template)))
security.declareProtected('Import/Export objects', 'cleanup') security.declareProtected('Import/Export objects', 'cleanup')
def cleanup(self, bt): def cleanup(self, business_template):
"""remove svn locks in working copy """remove svn locks in working copy
""" """
working_copy = self._getWorkingPath(self.getSubversionPath(bt)) working_copy = self._getWorkingPath(self\
.getSubversionPath(business_template))
client = self._getClient() client = self._getClient()
return client.cleanup(working_copy) return client.cleanup(working_copy)
security.declareProtected('Import/Export objects', 'remove') security.declareProtected('Import/Export objects', 'remove')
# path can be a list or not (relative or absolute) # path can be a list or not (relative or absolute)
def remove(self, path, bt=None): def remove(self, path, business_template=None):
"""Remove a file or a directory. """Remove a file or a directory.
""" """
if bt is not None: if business_template is not None:
if isinstance(path, list) : if isinstance(path, list) :
path = [self._getWorkingPath(self.relativeToAbsolute(x, bt)) for x in path] path = [self._getWorkingPath(self\
.relativeToAbsolute(x, business_template)) for x in path]
else: else:
path = self._getWorkingPath(self.relativeToAbsolute(path, bt)) path = self._getWorkingPath(self.relativeToAbsolute(path, \
business_template))
client = self._getClient() client = self._getClient()
return client.remove(path) return client.remove(path)
...@@ -801,35 +886,40 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -801,35 +886,40 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
security.declareProtected('Import/Export objects', 'ls') security.declareProtected('Import/Export objects', 'ls')
# path can be relative or absolute # path can be relative or absolute
def ls(self, path, bt): def ls(self, path, business_template):
"""Display infos about a file. """Display infos about a file.
""" """
client = self._getClient() client = self._getClient()
return client.ls(self._getWorkingPath(self.relativeToAbsolute(path, bt))) return client.ls(self._getWorkingPath(self\
.relativeToAbsolute(path, business_template)))
security.declareProtected('Import/Export objects', 'diff') security.declareProtected('Import/Export objects', 'diff')
# path can be relative or absolute # path can be relative or absolute
def diff(self, path, bt, revision1=None, revision2=None): def diff(self, path, business_template, revision1=None, revision2=None):
"""Make a diff for a file or a directory. """Make a diff for a file or a directory.
""" """
client = self._getClient() client = self._getClient()
return client.diff(self._getWorkingPath(self.relativeToAbsolute(path, bt)), revision1, revision2) return client.diff(self._getWorkingPath(self.relativeToAbsolute(path, \
business_template)), revision1, revision2)
security.declareProtected('Import/Export objects', 'revert') security.declareProtected('Import/Export objects', 'revert')
# path can be absolute or relative # path can be absolute or relative
def revert(self, path, bt=None, recurse=False): def revert(self, path, business_template=None, recurse=False):
"""Revert local changes in a file or a directory. """Revert local changes in a file or a directory.
""" """
client = self._getClient() client = self._getClient()
if not isinstance(path, list) : if not isinstance(path, list) :
path = [self._getWorkingPath(self.relativeToAbsolute(path, bt))] path = [self._getWorkingPath(self.relativeToAbsolute(path, \
if bt is not None: business_template))]
path = [self._getWorkingPath(self.relativeToAbsolute(x, bt)) for x in path] if business_template is not None:
path = [self._getWorkingPath(self.relativeToAbsolute(x, \
business_template)) for x in path]
client.revert(path, recurse) client.revert(path, recurse)
security.declareProtected('Import/Export objects', 'revertZODB') security.declareProtected('Import/Export objects', 'revertZODB')
# path can be absolute or relative # path can be absolute or relative
def revertZODB(self, bt, added_files=None, other_files=None, recurse=False): def revertZODB(self, business_template, added_files=None, \
other_files=None, recurse=False):
"""Revert local changes in a file or a directory """Revert local changes in a file or a directory
in ZODB and on hard drive in ZODB and on hard drive
""" """
...@@ -841,13 +931,13 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -841,13 +931,13 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
if not other_files : if not other_files :
other_files = [] other_files = []
if not isinstance(added_files, list) : if not isinstance(added_files, list) :
added_files=[added_files] added_files = [added_files]
if not isinstance(other_files, list) : if not isinstance(other_files, list) :
other_files=[other_files] other_files = [other_files]
# Reinstall removed or modified files # Reinstall removed or modified files
for p in other_files : for path in other_files :
path_list = self._getWorkingPath(p).split(os.sep) path_list = self._getWorkingPath(path).split(os.sep)
if 'bt' not in path_list: if 'bt' not in path_list:
if len(path_list) > 2 : if len(path_list) > 2 :
tmp = os.sep.join(path_list[2:]) tmp = os.sep.join(path_list[2:])
...@@ -856,8 +946,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -856,8 +946,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
object_to_update[tmp] = 'install' object_to_update[tmp] = 'install'
path_added_list = [] path_added_list = []
# remove added files # remove added files
for p in added_files : for path in added_files :
path_list = self._getWorkingPath(p).split(os.sep) path_list = self._getWorkingPath(path).split(os.sep)
if 'bt' not in path_list: if 'bt' not in path_list:
if len(path_list) > 2 : if len(path_list) > 2 :
tmp = os.sep.join(path_list[2:]) tmp = os.sep.join(path_list[2:])
...@@ -866,7 +956,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -866,7 +956,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
path_added_list.append(tmp) path_added_list.append(tmp)
## hack to remove objects ## hack to remove objects
# Create a temporary bt with objects to delete # Create a temporary bt with objects to delete
tmp_bt = getToolByName(bt, 'portal_templates').newContent(portal_type="Business Template") tmp_bt = getToolByName(business_template, 'portal_templates')\
.newContent(portal_type="Business Template")
tmp_bt.setTemplatePathList(path_added_list) tmp_bt.setTemplatePathList(path_added_list)
tmp_bt.setTitle('tmp_bt_revert') tmp_bt.setTitle('tmp_bt_revert')
# Build bt # Build bt
...@@ -876,57 +967,67 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -876,57 +967,67 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
tmp_bt.install() tmp_bt.install()
tmp_bt.uninstall() tmp_bt.uninstall()
# Remove it from portal template # Remove it from portal template
bt.portal_templates.manage_delObjects(ids=tmp_bt.getId()) business_template.portal_templates.manage_delObjects(ids=tmp_bt.getId())
#revert changes #revert changes
added_files.extend(other_files) added_files.extend(other_files)
to_revert = [self.relativeToAbsolute(x, bt) for x in added_files] to_revert = [self.relativeToAbsolute(x, business_template) \
for x in added_files]
if len(to_revert) != 0 : if len(to_revert) != 0 :
client.revert(to_revert, recurse) client.revert(to_revert, recurse)
# Partially reinstall installed bt # Partially reinstall installed bt
installed_bt = bt.portal_templates.getInstalledBusinessTemplate( bt.getTitle()) installed_bt = business_template.portal_templates\
.getInstalledBusinessTemplate(business_template.getTitle())
installed_bt.reinstall(object_to_update=object_to_update, force=0) installed_bt.reinstall(object_to_update=object_to_update, force=0)
security.declareProtected('Import/Export objects', 'resolved') security.declareProtected('Import/Export objects', 'resolved')
# path can be absolute or relative # path can be absolute or relative
def resolved(self, path, bt): def resolved(self, path, business_template):
"""remove conflicted status """remove conflicted status
""" """
client = self._getClient() client = self._getClient()
if isinstance(path, list) : if isinstance(path, list) :
path = [self._getWorkingPath(self.relativeToAbsolute(x, bt)) for x in path] path = [self._getWorkingPath(self.relativeToAbsolute(x, \
business_template)) for x in path]
else: else:
path = self._getWorkingPath(self.relativeToAbsolute(path, bt)) path = self._getWorkingPath(self.relativeToAbsolute(path, \
business_template))
return client.resolved(path) return client.resolved(path)
def relativeToAbsolute(self, path, bt) : def relativeToAbsolute(self, path, business_template):
""" Return an absolute path given the absolute one
and the business template
"""
if path[0] == os.sep: if path[0] == os.sep:
# already absolute # already absolute
return path return path
# relative path # relative path
if path.split(os.sep)[0] == bt.getTitle(): if path.split(os.sep)[0] == business_template.getTitle():
return os.path.join(self.getSubversionPath(bt, False), path) return os.path.join(self.getSubversionPath(business_template, \
False), path)
else: else:
return os.path.join(self.getSubversionPath(bt), path) return os.path.join(self.getSubversionPath(business_template), path)
security.declareProtected('Import/Export objects', 'checkin') security.declareProtected('Import/Export objects', 'checkin')
# path can be relative or absolute (can be a list of paths too) # path can be relative or absolute (can be a list of paths too)
def checkin(self, path, bt, log_message=None, recurse=True): def checkin(self, path, business_template, log_message=None, recurse=True):
"""Commit local changes. """Commit local changes.
""" """
if isinstance(path, list) : if isinstance(path, list) :
path = [self._getWorkingPath(self.relativeToAbsolute(x, bt)) for x in path] path = [self._getWorkingPath(self.relativeToAbsolute(x, \
business_template)) for x in path]
else: else:
path = self._getWorkingPath(self.relativeToAbsolute(path, bt)) path = self._getWorkingPath(self.relativeToAbsolute(path, \
business_template))
client = self._getClient() client = self._getClient()
return client.checkin(path, log_message, recurse) return client.checkin(path, log_message, recurse)
security.declareProtected('Import/Export objects', 'getLastChangelog') security.declareProtected('Import/Export objects', 'getLastChangelog')
def getLastChangelog(self, bt): def getLastChangelog(self, business_template):
"""Return last changelog of a business template """Return last changelog of a business template
""" """
bt_path = self._getWorkingPath(self.getSubversionPath(bt)) bt_path = self._getWorkingPath(self.getSubversionPath(business_template))
changelog_path = bt_path + os.sep + 'bt' + os.sep + 'change_log' changelog_path = bt_path + os.sep + 'bt' + os.sep + 'change_log'
changelog="" changelog = ""
if os.path.exists(changelog_path): if os.path.exists(changelog_path):
changelog_file = open(changelog_path, 'r') changelog_file = open(changelog_path, 'r')
changelog_lines = changelog_file.readlines() changelog_lines = changelog_file.readlines()
...@@ -934,7 +1035,7 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -934,7 +1035,7 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
for line in changelog_lines: for line in changelog_lines:
if line.strip() == '': if line.strip() == '':
break break
changelog+=line changelog += line
return changelog return changelog
...@@ -952,10 +1053,10 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -952,10 +1053,10 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
client = self._getClient() client = self._getClient()
status_list = client.status(self._getWorkingPath(path), **kw) status_list = client.status(self._getWorkingPath(path), **kw)
unversioned_list = [] unversioned_list = []
for statusObj in status_list: for status_obj in status_list:
if str(statusObj.getTextStatus()) == "unversioned": if str(status_obj.getTextStatus()) == "unversioned":
my_dict = {} my_dict = {}
my_dict['uid'] = statusObj.getPath() my_dict['uid'] = status_obj.getPath()
unversioned_list.append(my_dict) unversioned_list.append(my_dict)
return unversioned_list return unversioned_list
...@@ -966,35 +1067,39 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -966,35 +1067,39 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
client = self._getClient() client = self._getClient()
status_list = client.status(self._getWorkingPath(path), **kw) status_list = client.status(self._getWorkingPath(path), **kw)
conflicted_list = [] conflicted_list = []
for statusObj in status_list: for status_obj in status_list:
if str(statusObj.getTextStatus()) == "conflicted": if str(status_obj.getTextStatus()) == "conflicted":
my_dict = {} my_dict = {}
my_dict['uid'] = statusObj.getPath() my_dict['uid'] = status_obj.getPath()
conflicted_list.append(my_dict) conflicted_list.append(my_dict)
return conflicted_list return conflicted_list
security.declareProtected('Import/Export objects', 'removeAllInList') security.declareProtected('Import/Export objects', 'removeAllInList')
def removeAllInList(self, list): def removeAllInList(self, path_list):
"""Remove all files and folders in list """Remove all files and folders in list
""" """
for file in list: for file_path in path_list:
removeAll(file) removeAll(file_path)
def getModifiedTree(self, bt, show_unmodified=False) : def getModifiedTree(self, business_template, show_unmodified=False) :
""" Return tree of files returned by svn status
"""
# Get subversion path without business template name at the end # Get subversion path without business template name at the end
bt_path = self._getWorkingPath(self.getSubversionPath(bt, False)) bt_path = self._getWorkingPath(self.getSubversionPath(business_template, \
False))
if bt_path[-1] != '/': if bt_path[-1] != '/':
bt_path += '/' bt_path += '/'
# Business template root directory is the root of the tree # Business template root directory is the root of the tree
root = Dir(bt.getTitle(), "normal") root = Dir(business_template.getTitle(), "normal")
somethingModified = False something_modified = False
# We browse the files returned by svn status # We browse the files returned by svn status
for status_obj in self.status(os.path.join(bt_path, bt.getTitle())) : for status_obj in self.status(os.path.join(bt_path, \
business_template.getTitle())) :
# can be (normal, added, modified, deleted, conflicted, unversioned) # can be (normal, added, modified, deleted, conflicted, unversioned)
status = str(status_obj.getTextStatus()) status = str(status_obj.getTextStatus())
if (show_unmodified or status != "normal") and status != "unversioned": if (show_unmodified or status != "normal") and status != "unversioned":
somethingModified = True something_modified = True
# Get object path # Get object path
full_path = status_obj.getPath() full_path = status_obj.getPath()
relative_path = full_path.replace(bt_path, '') relative_path = full_path.replace(bt_path, '')
...@@ -1005,11 +1110,11 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1005,11 +1110,11 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
# First we add the directories present in the path to the tree # First we add the directories present in the path to the tree
# if it does not already exist # if it does not already exist
for d in relative_path.split(os.sep)[1:-1] : for directory in relative_path.split(os.sep)[1:-1] :
if d : if directory :
if d not in parent.getSubDirsNameList() : if directory not in parent.getSubDirsNameList() :
parent.sub_dirs.append(Dir(d, "normal")) parent.sub_dirs.append(Dir(directory, "normal"))
parent = parent.getDirFromName(d) parent = parent.getDirFromName(directory)
# Consider the whole path which can be a folder or a file # Consider the whole path which can be a folder or a file
# We add it the to the tree if it does not already exist # We add it the to the tree if it does not already exist
...@@ -1026,51 +1131,65 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1026,51 +1131,65 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
else : else :
# add new file to the tree # add new file to the tree
parent.sub_files.append(File(filename, str(status))) parent.sub_files.append(File(filename, str(status)))
return somethingModified and root return something_modified and root
def extractBT(self, bt): def extractBT(self, business_template):
# first update working copy """
#self.updatewc(bt) Extract business template to hard drive
bt.build() and do svn add/del stuff comparing it
svn_path = self._getWorkingPath(self.getSubversionPath(bt) + os.sep) to local working copy
"""
business_template.build()
svn_path = self._getWorkingPath(self.getSubversionPath(business_template) \
+ os.sep)
path = mktemp() + os.sep path = mktemp() + os.sep
try: try:
bt.export(path=path, local=1) business_template.export(path=path, local=1)
# svn del deleted files # svn del deleted files
self.deleteOldFiles(svn_path, path, bt) self.deleteOldFiles(svn_path, path)
# add new files and copy # add new files and copy
self.addNewFiles(svn_path, path, bt) self.addNewFiles(svn_path, path)
self.goToWorkingCopy(bt) self.goToWorkingCopy(business_template)
except (pysvn.ClientError, NotFound, AttributeError, AttributeError, Error), error: except (pysvn.ClientError, NotFound, AttributeError, \
AttributeError, Error), error:
# Clean up # Clean up
removeAll(path) removeAll(path)
raise error raise error
# Clean up # Clean up
self.activate().removeAllInList([path,]) self.activate().removeAllInList([path, ])
def importBT(self, bt): def importBT(self, business_template):
return bt.download(self._getWorkingPath(self.getSubversionPath(bt))) """
Import business template from local
working copy
"""
return business_template.download(self._getWorkingPath(self\
.getSubversionPath(business_template)))
# Get a list of files and keep only parents # Get a list of files and keep only parents
# Necessary before recursively commit removals # Necessary before recursively commit removals
def cleanChildrenInList(self, list): def cleanChildrenInList(self, path_list):
res = list """
for file in list: Get a list of files and keep only parents
res = [x for x in res if file == x or file not in x] Necessary before recursively commit removals
"""
res = path_list
for file_path in path_list:
res = [x for x in res if file_path == x or file_path not in x]
return res return res
# return a set with directories present in the directory # return a set with directories present in the directory
def getSetDirsForDir(self, directory): def getSetDirsForDir(self, directory):
dir_set = set() dir_set = set()
for root, dirs, files in cacheWalk(directory): for root, dirs, _ in cacheWalk(directory):
# don't visit SVN directories # don't visit SVN directories
if '.svn' in dirs: if '.svn' in dirs:
dirs.remove('.svn') dirs.remove('.svn')
# get Directories # get Directories
for name in dirs: for name in dirs:
i = root.replace(directory, '').count(os.sep) i = root.replace(directory, '').count(os.sep)
f = os.path.join(root, name) path = os.path.join(root, name)
dir_set.add((i, f.replace(directory,''))) dir_set.add((i, path.replace(directory,'')))
return dir_set return dir_set
# return a set with files present in the directory # return a set with files present in the directory
...@@ -1083,8 +1202,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1083,8 +1202,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
# get Files # get Files
for name in files: for name in files:
i = root.replace(directory, '').count(os.sep) i = root.replace(directory, '').count(os.sep)
f = os.path.join(root, name) path = os.path.join(root, name)
dir_set.add((i, f.replace(directory,''))) dir_set.add((i, path.replace(directory,'')))
return dir_set return dir_set
# return files present in new_dir but not in old_dir # return files present in new_dir but not in old_dir
...@@ -1109,22 +1228,24 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1109,22 +1228,24 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
new_set = self.getSetDirsForDir(new_dir) new_set = self.getSetDirsForDir(new_dir)
return new_set.difference(old_set) return new_set.difference(old_set)
# svn del files that have been removed in new dir def deleteOldFiles(self, old_dir, new_dir):
def deleteOldFiles(self, old_dir, new_dir, bt): """ svn del files that have been removed in new dir
"""
# detect removed files # detect removed files
files_set = self.getNewFiles(new_dir, old_dir) files_set = self.getNewFiles(new_dir, old_dir)
# detect removed directories # detect removed directories
dirs_set = self.getNewDirs(new_dir, old_dir) dirs_set = self.getNewDirs(new_dir, old_dir)
# svn del # svn del
list = [x for x in files_set] path_list = [x for x in files_set]
list.sort() path_list.sort()
self.remove([os.path.join(old_dir, x[1]) for x in list]) self.remove([os.path.join(old_dir, x[1]) for x in path_list])
list = [x for x in dirs_set] path_list = [x for x in dirs_set]
list.sort() path_list.sort()
self.remove([os.path.join(old_dir, x[1]) for x in list]) self.remove([os.path.join(old_dir, x[1]) for x in path_list])
# copy files and add new files def addNewFiles(self, old_dir, new_dir):
def addNewFiles(self, old_dir, new_dir, bt): """ copy files and add new files
"""
# detect created files # detect created files
files_set = self.getNewFiles(old_dir, new_dir) files_set = self.getNewFiles(old_dir, new_dir)
# detect created directories # detect created directories
...@@ -1132,21 +1253,27 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1132,21 +1253,27 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
# Copy files # Copy files
copytree(new_dir, old_dir) copytree(new_dir, old_dir)
# svn add # svn add
list = [x for x in dirs_set] path_list = [x for x in dirs_set]
list.sort() path_list.sort()
self.add([os.path.join(old_dir, x[1]) for x in list]) self.add([os.path.join(old_dir, x[1]) for x in path_list])
list = [x for x in files_set] path_list = [x for x in files_set]
list.sort() path_list.sort()
self.add([os.path.join(old_dir, x[1]) for x in list]) self.add([os.path.join(old_dir, x[1]) for x in path_list])
def treeToXML(self, item, bt) : def treeToXML(self, item, business_template) :
""" Convert tree in memory to XML
"""
output = "<?xml version='1.0' encoding='iso-8859-1'?>"+ os.linesep output = "<?xml version='1.0' encoding='iso-8859-1'?>"+ os.linesep
output += "<tree id='0'>" + os.linesep output += "<tree id='0'>" + os.linesep
output = self._treeToXML(item, output, bt.getTitle(), True) output = self._treeToXML(item, output, business_template.getTitle(), True)
output += "</tree>" + os.linesep output += "</tree>" + os.linesep
return output return output
def _treeToXML(self, item, output, relative_path, first) : def _treeToXML(self, item, output, relative_path, first) :
"""
Private function to convert recursively tree
in memory to XML
"""
# Choosing a color coresponding to the status # Choosing a color coresponding to the status
status = item.status status = item.status
if status == 'added' : if status == 'added' :
...@@ -1170,7 +1297,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder): ...@@ -1170,7 +1297,8 @@ class SubversionTool(BaseTool, UniqueObject, Folder):
'im1="folder_open.png" im2="folder.png">'%(item.name, 'im1="folder_open.png" im2="folder.png">'%(item.name,
relative_path, color) + os.linesep relative_path, color) + os.linesep
for it in item.getContent(): for it in item.getContent():
output = self._treeToXML(item.getObjectFromName(it.name), output, os.path.join(relative_path,it.name),first) output = self._treeToXML(item.getObjectFromName(it.name), output, \
os.path.join(relative_path,it.name),first)
output += '</item>' + os.linesep output += '</item>' + os.linesep
else : else :
output += '<item text="%s" id="%s" aCol="%s" im0="document.png"/>'\ output += '<item text="%s" id="%s" aCol="%s" im0="document.png"/>'\
......
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