Commit dfe0fa26 authored by Jérome Perrin's avatar Jérome Perrin

Changes from 0.8.1.6

These changes were from http://www.nexedi.org/static/packages/source/erp5diff-0.8.1.6.tar.gz
parent fc4c404b
0.8.1.6 (unreleased) 0.8.1.6 (2015/04/23)
-------------------- --------------------
* Bug fix * Disable _removeStrictEqualsSubNodeList that can make a wrong result
* Add support of deletion/addition for tailed text nodes
0.8.1.5 (2011/08/08) 0.8.1.5 (2011/08/08)
-------------------- --------------------
......
...@@ -13,7 +13,7 @@ def read(name): ...@@ -13,7 +13,7 @@ def read(name):
return open(name).read() return open(name).read()
long_description=( long_description=(
read('README.rst') read('README')
+ '\n' + + '\n' +
read('CHANGES.txt') read('CHANGES.txt')
) )
......
...@@ -202,6 +202,7 @@ class ERP5Diff: ...@@ -202,6 +202,7 @@ class ERP5Diff:
for child in element: for child in element:
clone_node = deepcopy(child) clone_node = deepcopy(child)
update_element.append(clone_node) update_element.append(clone_node)
else:
update_element.text = element.text update_element.text = element.text
root.append(update_element) root.append(update_element)
...@@ -214,16 +215,6 @@ class ERP5Diff: ...@@ -214,16 +215,6 @@ class ERP5Diff:
update_element.text = text update_element.text = text
root.append(update_element) root.append(update_element)
def _xupdateInsertAfterTextNode(self, element, path, nsmap=None):
"""insert new tail text node
"""
root = self._getResultRoot()
insert_element = etree.Element('{%s}insert-after' % self._ns, nsmap=nsmap)
insert_element.attrib['select'] = path
text_element = etree.SubElement(insert_element, '{%s}text' % self._ns, nsmap=nsmap)
text_element.text = element.tail
root.append(insert_element)
def _xupdateRemoveElement(self, path, nsmap=None): def _xupdateRemoveElement(self, path, nsmap=None):
""" """
Remove an element at 'path'. Remove an element at 'path'.
...@@ -498,6 +489,9 @@ class ERP5Diff: ...@@ -498,6 +489,9 @@ class ERP5Diff:
-old_element (to remove) -old_element (to remove)
-new_element (to insert) -new_element (to insert)
""" """
# XXX we do nothing here for now
return old_list, new_list, {}
# XXX because the implementation below can return a wrong result
old_candidate_list = old_list[:] old_candidate_list = old_list[:]
new_candidate_list = new_list[:] new_candidate_list = new_list[:]
misplaced_node_dict = {} misplaced_node_dict = {}
...@@ -616,28 +610,20 @@ class ERP5Diff: ...@@ -616,28 +610,20 @@ class ERP5Diff:
self._testAttributes(old_node, new_node, child_path) self._testAttributes(old_node, new_node, child_path)
if not old_ignore_text and len(old_element): if not old_ignore_text and len(old_element):
# Mixed Content # Mixed Content
if ((old_node.text and old_node.text.strip()) or (new_node.text\ if old_node.text and old_node.text.strip() and new_node.text\
and new_node.text.strip())) and old_node.text != new_node.text\ and new_node.text.strip() and old_node.text != new_node.text:
and (self._checkIgnoreText(new_node) == self._checkIgnoreText(old_node)): text_path = child_path + '/text()[%i]' % (new_node.getparent().index(new_node))
text_path = child_path + '/text()[1]'
self._xupdateUpdateTextNode(new_node, new_node.text, self._xupdateUpdateTextNode(new_node, new_node.text,
text_path, nsmap=new_element.nsmap) text_path, nsmap=new_element.nsmap)
if ((old_node.tail and old_node.tail.strip()) or (new_node.tail\ if old_node.tail and old_node.tail.strip() and new_node.tail\
and new_node.tail.strip())) and old_node.tail != new_node.tail: and new_node.tail.strip() and old_node.tail != new_node.tail:
if old_node.tail:
# case 1: edit existing text node, usage of position should works to reach
# expected text node
position = 1 position = 1
position += len([sibling for sibling in old_node.itersiblings(preceding=True) if sibling.tail]) if new_node.getparent().text:
if old_node.getparent().text:
position += 1 position += 1
position += len([sibling for sibling in old_node.itersiblings(preceding=True) if sibling.tail])
text_path = path + '/text()[%i]' % (position) text_path = path + '/text()[%i]' % (position)
self._xupdateUpdateTextNode(new_node, new_node.tail, self._xupdateUpdateTextNode(new_node, new_node.tail,
text_path, nsmap=new_element.nsmap) text_path, nsmap=new_element.nsmap)
else:
# case 2: Means adding a new text node, the position is ambiguous,
# so use insert-after instead
self._xupdateInsertAfterTextNode(new_node, child_path, nsmap=new_element.nsmap)
self._compareChildNodes(old_node, new_node, child_path) self._compareChildNodes(old_node, new_node, child_path)
new_start = new_current + 1 new_start = new_current + 1
if new_current in new_object_left_index_set: if new_current in new_object_left_index_set:
......
...@@ -611,9 +611,6 @@ class TestERP5Diff(unittest.TestCase): ...@@ -611,9 +611,6 @@ class TestERP5Diff(unittest.TestCase):
<workflow_action id="edit_workflow"> <workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.426 GMT+9</time> <time type="date">2009/08/28 19:12:34.426 GMT+9</time>
</workflow_action> </workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.424 GMT+9</time>
</workflow_action>
</object> </object>
</erp5> </erp5>
""" """
...@@ -636,17 +633,67 @@ class TestERP5Diff(unittest.TestCase): ...@@ -636,17 +633,67 @@ class TestERP5Diff(unittest.TestCase):
</erp5> </erp5>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]"/> <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]/time">2009/08/28 19:12:34.430 GMT+9</xupdate:update>
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]"/> <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]/time">2009/08/28 19:12:34.428 GMT+9</xupdate:update>
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]"/> <xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]/time">2009/08/28 19:12:34.426 GMT+9</xupdate:update>
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][8]"/> <xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][5]"/>
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][6]"/>
<xupdate:remove select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][7]"/>
</xupdate:modifications>
"""
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_test_remove_element_with_same_id_bis(self):
"""21. Modify two elements that have same id
"""
old_xml = """
<erp5>
<object portal_type="Person" id="313730">
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.424 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.432 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.434 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.436 GMT+9</time>
</workflow_action>
</object>
</erp5>
"""
new_xml = """
<erp5>
<object portal_type="Person" id="313730">
<workflow_action id="edit_workflow">
<time type="date">2009/08/28 19:12:34.424 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/29 19:12:34.432 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/30 19:12:34.434 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2009/08/31 19:12:34.436 GMT+9</time>
</workflow_action>
</object>
</erp5>
"""
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][2]/time">2009/08/29 19:12:34.432 GMT+9</xupdate:update>
<xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][3]/time">2009/08/30 19:12:34.434 GMT+9</xupdate:update>
<xupdate:update select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]/time">2009/08/31 19:12:34.436 GMT+9</xupdate:update>
</xupdate:modifications> </xupdate:modifications>
""" """
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_modify_attributes_of_sequential_objects(self): def test_modify_attributes_of_sequential_objects(self):
"""21. Modify attributes of sequencial objects """22. Modify attributes of sequencial objects
""" """
old_xml = """ old_xml = """
...@@ -684,7 +731,7 @@ class TestERP5Diff(unittest.TestCase): ...@@ -684,7 +731,7 @@ class TestERP5Diff(unittest.TestCase):
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_nodes_with_qnames(self): def test_nodes_with_qnames(self):
"""22. Modify nodes with Qualified Names """23. Modify nodes with Qualified Names
ERP5Diff should create xpath valid expression with correct prefix ERP5Diff should create xpath valid expression with correct prefix
""" """
old_xml = """ old_xml = """
...@@ -744,7 +791,7 @@ class TestERP5Diff(unittest.TestCase): ...@@ -744,7 +791,7 @@ class TestERP5Diff(unittest.TestCase):
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_attibutes_with_qnames(self): def test_attibutes_with_qnames(self):
"""23. Modify nodes with Qualified Names """24. Modify nodes with Qualified Names
Works on Attributes specially Works on Attributes specially
""" """
...@@ -770,7 +817,7 @@ class TestERP5Diff(unittest.TestCase): ...@@ -770,7 +817,7 @@ class TestERP5Diff(unittest.TestCase):
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_attibutes_with_qnames_at_root_level(self): def test_attibutes_with_qnames_at_root_level(self):
"""24. Modify nodes with Qualified Names at root level """25. Modify nodes with Qualified Names at root level
Work on Attributes specially Work on Attributes specially
""" """
old_xml = """ old_xml = """
...@@ -796,8 +843,8 @@ class TestERP5Diff(unittest.TestCase): ...@@ -796,8 +843,8 @@ class TestERP5Diff(unittest.TestCase):
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_reoder_nodes_to_the_end(self): def test_reorder_nodes_to_the_end(self):
"""25. Reorder some nodes to the end of list """26. Reorder some nodes to the end of list
""" """
old_xml = """ old_xml = """
<ul> <ul>
...@@ -826,18 +873,17 @@ class TestERP5Diff(unittest.TestCase): ...@@ -826,18 +873,17 @@ class TestERP5Diff(unittest.TestCase):
</ul> </ul>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/ul/li[3]"/> <xupdate:update select="/ul/li[3]">5</xupdate:update>
<xupdate:remove select="/ul/li[4]"/> <xupdate:update select="/ul/li[4]">6</xupdate:update>
<xupdate:insert-after select="/ul/li[7]"> <xupdate:update select="/ul/li[5]">7</xupdate:update>
<xupdate:element name="li">3</xupdate:element> <xupdate:update select="/ul/li[6]">3</xupdate:update>
<xupdate:element name="li">4</xupdate:element> <xupdate:update select="/ul/li[7]">4</xupdate:update>
</xupdate:insert-after>
</xupdate:modifications> </xupdate:modifications>
""" """
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_reoder_nodes_form_the_end(self): def test_reorder_nodes_form_the_end(self):
"""26. Reorder some nodes from the end of list """26. Reorder some nodes from the end of list
""" """
old_xml = """ old_xml = """
...@@ -867,18 +913,18 @@ class TestERP5Diff(unittest.TestCase): ...@@ -867,18 +913,18 @@ class TestERP5Diff(unittest.TestCase):
</ul> </ul>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/ul/li[7]"/> <xupdate:update select="/ul/li[3]">7</xupdate:update>
<xupdate:remove select="/ul/li[8]"/> <xupdate:update select="/ul/li[4]">8</xupdate:update>
<xupdate:insert-after select="/ul/li[2]"> <xupdate:update select="/ul/li[5]">3</xupdate:update>
<xupdate:element name="li">7</xupdate:element> <xupdate:update select="/ul/li[6]">4</xupdate:update>
<xupdate:element name="li">8</xupdate:element> <xupdate:update select="/ul/li[7]">5</xupdate:update>
</xupdate:insert-after> <xupdate:update select="/ul/li[8]">6</xupdate:update>
</xupdate:modifications> </xupdate:modifications>
""" """
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_reoder_nodes_at_the_beginning(self): def test_test_reorder_nodes_at_the_beginning(self):
"""27. Reorder some nodes at the beginning """27. Reorder some nodes at the beginning
""" """
old_xml = """ old_xml = """
...@@ -908,12 +954,12 @@ class TestERP5Diff(unittest.TestCase): ...@@ -908,12 +954,12 @@ class TestERP5Diff(unittest.TestCase):
</ul> </ul>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/ul/li[5]"/> <xupdate:update select="/ul/li[1]">5</xupdate:update>
<xupdate:remove select="/ul/li[6]"/> <xupdate:update select="/ul/li[2]">6</xupdate:update>
<xupdate:append child="first()"> <xupdate:update select="/ul/li[3]">1</xupdate:update>
<xupdate:element name="li">5</xupdate:element> <xupdate:update select="/ul/li[4]">2</xupdate:update>
<xupdate:element name="li">6</xupdate:element> <xupdate:update select="/ul/li[5]">3</xupdate:update>
</xupdate:append> <xupdate:update select="/ul/li[6]">4</xupdate:update>
</xupdate:modifications> </xupdate:modifications>
""" """
...@@ -949,12 +995,14 @@ class TestERP5Diff(unittest.TestCase): ...@@ -949,12 +995,14 @@ class TestERP5Diff(unittest.TestCase):
</ul> </ul>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:remove select="/ul/li[2]"/> <xupdate:update select="/ul/li[2]">4</xupdate:update>
<xupdate:remove select="/ul/li[3]"/> <xupdate:update select="/ul/li[3]">5</xupdate:update>
<xupdate:insert-after select="/ul/li[9]"> <xupdate:update select="/ul/li[4]">6</xupdate:update>
<xupdate:element name="li">2</xupdate:element> <xupdate:update select="/ul/li[5]">7</xupdate:update>
<xupdate:element name="li">3</xupdate:element> <xupdate:update select="/ul/li[6]">8</xupdate:update>
</xupdate:insert-after> <xupdate:update select="/ul/li[7]">9</xupdate:update>
<xupdate:update select="/ul/li[8]">2</xupdate:update>
<xupdate:update select="/ul/li[9]">3</xupdate:update>
</xupdate:modifications> </xupdate:modifications>
""" """
...@@ -1076,10 +1124,6 @@ class TestERP5Diff(unittest.TestCase): ...@@ -1076,10 +1124,6 @@ class TestERP5Diff(unittest.TestCase):
<node>AAA<blank/>BBB</node> <node>AAA<blank/>BBB</node>
<node>AAA<blank/>BBB</node> <node>AAA<blank/>BBB</node>
<node>AAA<blank/>BBB<blank/>BBB</node>CCC <node>AAA<blank/>BBB<blank/>BBB</node>CCC
<a_node/>AAA
<b_node/>
<b_node/>
<node/>
</ul> </ul>
""" """
new_xml = """ new_xml = """
...@@ -1088,10 +1132,6 @@ class TestERP5Diff(unittest.TestCase): ...@@ -1088,10 +1132,6 @@ class TestERP5Diff(unittest.TestCase):
<node>C<blank/>BBB</node> <node>C<blank/>BBB</node>
<node>AAA<blank/>D</node> <node>AAA<blank/>D</node>
<node>AAA<blank/>BBB<blank/>E</node>F <node>AAA<blank/>BBB<blank/>E</node>F
<a_node/>
<b_node/>
<b_node/>G
<node>BBB<blank/>H</node>
</ul> </ul>
""" """
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"> expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
...@@ -1100,121 +1140,8 @@ class TestERP5Diff(unittest.TestCase): ...@@ -1100,121 +1140,8 @@ class TestERP5Diff(unittest.TestCase):
<xupdate:update select="/ul/node[2]/text()[1]">C</xupdate:update> <xupdate:update select="/ul/node[2]/text()[1]">C</xupdate:update>
<xupdate:update select="/ul/node[3]/text()[2]">D</xupdate:update> <xupdate:update select="/ul/node[3]/text()[2]">D</xupdate:update>
<xupdate:update select="/ul/text()[2]">F <xupdate:update select="/ul/text()[2]">F
</xupdate:update> </xupdate:update>
<xupdate:update select="/ul/node[4]/text()[3]">E</xupdate:update> <xupdate:update select="/ul/node[4]/text()[3]">E</xupdate:update>
<xupdate:update select="/ul/text()[3]"/>
<xupdate:insert-after select="/ul/b_node[2]">
<xupdate:text>G
</xupdate:text>
</xupdate:insert-after>
<xupdate:update select="/ul/node[5]">BBB<blank/>H</xupdate:update>
</xupdate:modifications>
"""
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
def test_insert_element_with_same_id(self):
"""31. Insert elements with the same ids with the proper
indexes
"""
old_xml = """<erp5>
<object portal_type="Person" id="313730">
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:12:58.767616 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:0.092858 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:4.909007 GMT+9</time>
</workflow_action>
</object>
</erp5>
"""
new_xml = """<erp5>
<object portal_type="Person" id="313730">
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:06:58.767616 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:12:58.767616 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:0.092858 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:3.767616 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:4.909007 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:4.999999 GMT+9</time>
</workflow_action>
<workflow_action id="edit_workflow">
<time type="date">2011/11/22 18:13:14.767616 GMT+9</time>
</workflow_action>
</object>
</erp5>
"""
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:insert-before select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][1]">
<xupdate:element name="workflow_action">
<xupdate:attribute name="id">edit_workflow</xupdate:attribute>
<time type="date">2011/11/22 18:06:58.767616 GMT+9</time>
</xupdate:element>
</xupdate:insert-before>
<xupdate:insert-before select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][4]">
<xupdate:element name="workflow_action">
<xupdate:attribute name="id">edit_workflow</xupdate:attribute>
<time type="date">2011/11/22 18:13:3.767616 GMT+9</time>
</xupdate:element>
</xupdate:insert-before>
<xupdate:insert-after select="/erp5/object[@id='313730']/workflow_action[@id='edit_workflow'][5]">
<xupdate:element name="workflow_action">
<xupdate:attribute name="id">edit_workflow</xupdate:attribute>
<time type="date">2011/11/22 18:13:4.999999 GMT+9</time>
</xupdate:element>
<xupdate:element name="workflow_action">
<xupdate:attribute name="id">edit_workflow</xupdate:attribute>
<time type="date">2011/11/22 18:13:14.767616 GMT+9</time>
</xupdate:element>
</xupdate:insert-after>
</xupdate:modifications>
"""
def test_part_of_repeated_elements_updated(self):
"""32. Update a part of repeated elements
"""
old_xml = """<erp5>
<object portal_type="Text" gid="0123456789">
<base_data type="data">
<block_data>a</block_data>
<block_data>b</block_data>
<block_data>b</block_data>
<block_data>b</block_data>
<block_data>c</block_data>
</base_data>
</object>
</erp5>
"""
new_xml = """<erp5>
<object portal_type="Text" gid="0123456789">
<base_data type="data">
<block_data>a</block_data>
<block_data>d</block_data>
<block_data>b</block_data>
<block_data>b</block_data>
<block_data>c</block_data>
</base_data>
</object>
</erp5>
"""
expected_result_string = """<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0">
<xupdate:update select="/erp5/object[@gid='0123456789']/base_data/block_data[2]">d</xupdate:update>
</xupdate:modifications> </xupdate:modifications>
""" """
self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string) self._assertERP5DiffWorks(old_xml, new_xml, expected_result_string)
......
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