Modified: subversion/branches/ra-git/subversion/tests/cmdline/mod_dav_svn_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/mod_dav_svn_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/mod_dav_svn_tests.py Tue Oct 11 09:11:50 2016 @@ -25,7 +25,14 @@ ###################################################################### # General modules -import logging, httplib, base64 +import os, logging, base64, functools + +try: + # Python <3.0 + import httplib +except ImportError: + # Python >=3.0 + import http.client as httplib logger = logging.getLogger() @@ -41,6 +48,92 @@ Issue = svntest.testcase.Issue_deco Wimp = svntest.testcase.Wimp_deco ###################################################################### +# Helper routines + +def compare(lhs, rhs): + """Implements cmp() for Python 2 and 3 alike""" + if lhs == None: + if rhs == None: + return 0 + else: + return -1 + else: + if rhs == None: + return 1 + else: + return (lhs > rhs) - (lhs < rhs) + +def compare_dict(lhs, rhs): + """Implements dictionary comparison for Python 2 and 3 alike""" + lhs_sorted = sorted(lhs, key=lambda x:sorted(x.keys())) + rhs_sorted = sorted(rhs, key=lambda x:sorted(x.keys())) + return (lhs_sorted > rhs_sorted) - (lhs_sorted < rhs_sorted) + +def compare_xml_elem(a, b): + """Recursively compare two xml.etree.ElementTree.Element objects. + Return a 3-tuple made out of (cmp, elem_a, elem_b), where cmp is + the integer result of the comparison (negative, zero or positive), + and elem_a and elem_b point to mismatching elements. Iff cmp is + zero, elem_a and elem_b are None. """ + + # Compare tags, attributes, inner text, tail attribute and the + # number of child elements. + res = compare(a.tag, b.tag) + if res != 0: + return res, a, b + # Don't care about the order of the attributes. + res = compare_dict(a.attrib, b.attrib) + if res != 0: + return res, a, b + res = compare(a.text, b.text) + if res != 0: + return res, a, b + res = compare(a.tail, b.tail) + if res != 0: + return res, a, b + res = compare(len(a), len(b)) + if res != 0: + return res, a, b + + # Prior to recursing, order child elements using the same comparator. + # Right now we don't care about the order of the elements. For instance, + # <D:response>'s in PROPFIND *need* to be compared without a particular + # order, since the server returns them in an unstable order of the hash + # iteration. + def sortcmp(x, y): + return compare_xml_elem(x, y)[0] + + a_children = sorted(list(a), key=functools.cmp_to_key(sortcmp)) + b_children = sorted(list(b), key=functools.cmp_to_key(sortcmp)) + + for a_child, b_child in zip(a_children, b_children): + res = compare_xml_elem(a_child, b_child) + if res[0] != 0: + return res + + # Elements are equal. + return 0, None, None + +def verify_xml_response(expected_xml, actual_xml): + """Parse and compare two XML responses, raise svntest.Failure + in case EXPECTED_XML doesn't match ACTUAL_XML. """ + + import xml.etree.ElementTree as ET + + expected_root = ET.fromstring(expected_xml) + actual_root = ET.fromstring(actual_xml) + res, expected_elem, actual_elem = compare_xml_elem(expected_root, + actual_root) + if res != 0: + # The actual response doesn't match our expectations; dump it for + # debugging purposes, and highlight the mismatching xml element. + logger.warn("Response:\n%s" % actual_xml) + raise svntest.Failure("Unexpected response part\n" + " Expected: '%s'\n Actual: '%s'\n" + % (ET.tostring(expected_elem), + ET.tostring(actual_elem))) + +###################################################################### # Tests @SkipUnless(svntest.main.is_ra_type_dav) @@ -50,7 +143,7 @@ def cache_control_header(sbox): sbox.build(create_wc=False, read_only=True) headers = { - 'Authorization': 'Basic ' + base64.b64encode('jconstant:rayjandom'), + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), } h = svntest.main.create_http_connection(sbox.repo_url) @@ -142,6 +235,411 @@ def cache_control_header(sbox): r.read() +@SkipUnless(svntest.main.is_ra_type_dav) +def simple_propfind(sbox): + "verify simple PROPFIND responses" + + sbox.build(create_wc=False, read_only=True) + repo_uripath = '/' + svntest.wc.svn_uri_quote( + svntest.main.pristine_greek_repos_dir.replace(os.path.sep, '/')) + h = svntest.main.create_http_connection(sbox.repo_url) + + # PROPFIND /repos/!svn/rvr/1, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<prop><resourcetype xmlns="DAV:"/></prop>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype><D:collection/></lp1:resourcetype>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + # PROPFIND /repos/!svn/rvr/1, Depth = 1 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '1', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<prop><resourcetype xmlns="DAV:"/></prop>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype><D:collection/></lp1:resourcetype>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/A/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype><D:collection/></lp1:resourcetype>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/iota</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype/>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + # PROPFIND /repos/!svn/rvr/1/A/B/F, Depth = 1 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '1', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<prop><resourcetype xmlns="DAV:"/></prop>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1/A/B/F', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/A/B/F/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype><D:collection/></lp1:resourcetype>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + # PROPFIND /repos/!svn/rvr/1/iota, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<prop><resourcetype xmlns="DAV:"/></prop>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1/iota', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/iota</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype/>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + +@SkipUnless(svntest.main.is_ra_type_dav) +def propfind_multiple_props(sbox): + "verify multi-prop PROPFIND response" + + sbox.build(create_wc=False, read_only=True) + repo_uripath = '/' + svntest.wc.svn_uri_quote( + svntest.main.pristine_greek_repos_dir.replace(os.path.sep, '/')) + h = svntest.main.create_http_connection(sbox.repo_url) + + # PROPFIND /repos/!svn/rvr/1/iota, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8" ?>\n' + '<D:propfind xmlns:D="DAV:">\n' + '<D:prop xmlns:S="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:resourcetype/>\n' + '<S:md5-checksum/>\n' + '</D:prop>\n' + '</D:propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1/iota', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" ' + 'xmlns:ns1="http://subversion.tigris.org/xmlns/dav/" ' + 'xmlns:ns0="DAV:">\n' + '<D:response xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/iota</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype/>\n' + '<lp2:md5-checksum>' + '2d18c5e57e84c5b8a5e9a6e13fa394dc' + '</lp2:md5-checksum>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + +@SkipUnless(svntest.main.is_ra_type_dav) +def propfind_404(sbox): + "verify PROPFIND for non-existing property" + + sbox.build(create_wc=False, read_only=True) + repo_uripath = '/' + svntest.wc.svn_uri_quote( + svntest.main.pristine_greek_repos_dir.replace(os.path.sep, '/')) + h = svntest.main.create_http_connection(sbox.repo_url) + + # PROPFIND /repos/!svn/rvr/1, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<prop><nonexistingprop xmlns="DAV:"/></prop>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:g0="DAV:">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<g0:nonexistingprop/>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 404 Not Found</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + +@SkipUnless(svntest.main.is_ra_type_dav) +def propfind_allprop(sbox): + "verify allprop PROPFIND response" + + sbox.build() + repo_uripath = '/' + svntest.wc.svn_uri_quote( + sbox.repo_dir.replace(os.path.sep, '/')) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + # Ensure stable date and uuid + svntest.main.run_svnadmin('setuuid', sbox.repo_dir, + 'd7130b12-92f6-45c9-9217-b9f0472c3fab') + svntest.actions.run_and_verify_svn(None, [], + 'propset', '--revprop', '-r', '1', + 'svn:date', '2015-01-01T00:00:00.0Z', + sbox.wc_dir) + + h = svntest.main.create_http_connection(sbox.repo_url) + + # PROPFIND /repos/!svn/rvr/1, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<allprop/>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/1', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:S="http://subversion.tigris.org/xmlns/svn/" ' + 'xmlns:C="http://subversion.tigris.org/xmlns/custom/" ' + 'xmlns:V="http://subversion.tigris.org/xmlns/dav/" ' + 'xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/1/</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<lp1:resourcetype><D:collection/></lp1:resourcetype>\n' + '<lp1:getcontenttype>' + + 'text/html; charset=UTF-8' + + '</lp1:getcontenttype>\n' + '<lp1:getetag>W/"1//"</lp1:getetag>\n' + '<lp1:creationdate>2015-01-01T00:00:00.0Z</lp1:creationdate>\n' + '<lp1:getlastmodified>' + + 'Thu, 01 Jan 2015 00:00:00 GMT' + + '</lp1:getlastmodified>\n' + '<lp1:checked-in>' + '<D:href>' + repo_uripath + '/!svn/ver/1/</D:href>' + '</lp1:checked-in>\n' + '<lp1:version-controlled-configuration>' + '<D:href>' + repo_uripath + '/!svn/vcc/default</D:href>' + '</lp1:version-controlled-configuration>\n' + '<lp1:version-name>1</lp1:version-name>\n' + '<lp1:creator-displayname>jrandom</lp1:creator-displayname>\n' + '<lp2:baseline-relative-path/>\n' + '<lp2:repository-uuid>' + + 'd7130b12-92f6-45c9-9217-b9f0472c3fab' + + '</lp2:repository-uuid>\n' + '<lp2:deadprop-count>0</lp2:deadprop-count>\n' + '<D:lockdiscovery/>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + + +@SkipUnless(svntest.main.is_ra_type_dav) +def propfind_propname(sbox): + "verify propname PROPFIND response" + + sbox.build() + sbox.simple_propset('a', 'b', 'iota') + sbox.simple_commit() + repo_uripath = '/' + svntest.wc.svn_uri_quote( + sbox.repo_dir.replace(os.path.sep, '/')) + + h = svntest.main.create_http_connection(sbox.repo_url) + + # PROPFIND /repos/!svn/rvr/2/iota, Depth = 0 + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + 'Depth': '0', + } + req_body = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<propfind xmlns="DAV:">\n' + '<propname/>\n' + '</propfind>\n' + ) + h.request('PROPFIND', sbox.repo_url + '/!svn/rvr/2/iota', req_body, headers) + r = h.getresponse() + if r.status != httplib.MULTI_STATUS: + raise svntest.Failure('Unexpected status: %d %s' % (r.status, r.reason)) + + expected_response = ( + '<?xml version="1.0" encoding="utf-8"?>\n' + '<D:multistatus xmlns:D="DAV:" xmlns:ns0="DAV:">\n' + '<D:response xmlns:S="http://subversion.tigris.org/xmlns/svn/" ' + 'xmlns:C="http://subversion.tigris.org/xmlns/custom/" ' + 'xmlns:V="http://subversion.tigris.org/xmlns/dav/" ' + 'xmlns:lp1="DAV:" ' + 'xmlns:lp2="http://subversion.tigris.org/xmlns/dav/">\n' + '<D:href>' + repo_uripath + '/!svn/rvr/2/iota</D:href>\n' + '<D:propstat>\n' + '<D:prop>\n' + '<C:a/>\n' + '<lp1:resourcetype/>\n' + '<lp1:getcontentlength/>\n' + '<lp1:getcontenttype/>\n' + '<lp1:getetag/>\n' + '<lp1:creationdate/>\n' + '<lp1:getlastmodified/>\n' + '<lp1:checked-in/>\n' + '<lp1:version-controlled-configuration/>\n' + '<lp1:version-name/>\n' + '<lp1:creator-displayname/>\n' + '<lp2:baseline-relative-path/>\n' + '<lp2:md5-checksum/>\n' + '<lp2:repository-uuid/>\n' + '<lp2:deadprop-count/>\n' + '<lp2:sha1-checksum/>\n' + '<D:supportedlock/>\n' + '<D:lockdiscovery/>\n' + '</D:prop>\n' + '<D:status>HTTP/1.1 200 OK</D:status>\n' + '</D:propstat>\n' + '</D:response>\n' + '</D:multistatus>\n' + ) + actual_response = r.read() + verify_xml_response(expected_response, actual_response) + ######################################################################## # Run the tests @@ -149,6 +647,11 @@ def cache_control_header(sbox): # list all tests here, starting with None: test_list = [ None, cache_control_header, + simple_propfind, + propfind_multiple_props, + propfind_404, + propfind_allprop, + propfind_propname, ] serial_only = True
Modified: subversion/branches/ra-git/subversion/tests/cmdline/move_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/move_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/move_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/move_tests.py Tue Oct 11 09:11:50 2016 @@ -237,7 +237,7 @@ def build_simple_file_move_tests(sbox, s copied='+', wc_rev='-')}) mc = {} mc['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) mc['status'].tweak(source, status='D ', moved_to=dest) @@ -250,7 +250,7 @@ def build_simple_file_move_tests(sbox, s working['output'] = svntest.verify.ExpectedOutput( [ "Breaking move with source path '%s'\n" % source_path, - "Resolved conflicted state of '%s'\n" % source_path, + "Tree conflict at '%s' marked as resolved.\n" % source_path, ] ) working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -280,15 +280,15 @@ def build_simple_file_move_tests(sbox, s test['up_status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) test['up_status'].tweak(source, status='! ', treeconflict='C', wc_rev=None) test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-')}) - # mine-conflict doen't work. + # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't say it broke the move it should. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) # move is broken now working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -323,13 +323,13 @@ def build_simple_file_move_tests(sbox, s test['up_status'].add({dest: Item(status='A ', copied='+', wc_rev='-')}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Broke the move but doesn't notify that it does. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) # XXX: Not sure this status is really correct here working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -362,13 +362,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't say what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -403,14 +403,14 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} working['accept'] = 'working' # XXX: Doesn't say what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -468,13 +468,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't say what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -508,13 +508,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't say what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -548,13 +548,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Didn't tell us what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -588,13 +588,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't tell you what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -628,13 +628,13 @@ def build_simple_file_move_tests(sbox, s wc_rev='-', moved_from=source)}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} # XXX: Doesn't tell you what it did. working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % dest_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % dest_path, match_all=False ) # working converts the move into a replacement working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -670,7 +670,7 @@ def build_simple_file_move_tests(sbox, s # TODO: Should check that the output includes that the update was applied to # the destination mc['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) mc['status'].tweak(source, status='D ', moved_to=dest) @@ -682,7 +682,7 @@ def build_simple_file_move_tests(sbox, s working['output'] = svntest.verify.ExpectedOutput( [ "Breaking move with source path '%s'\n" % source_path, - "Resolved conflicted state of '%s'\n" % source_path + "Tree conflict at '%s' marked as resolved.\n" % source_path ] ) # XXX: working breaks the move? Is that right? @@ -718,7 +718,7 @@ def build_simple_file_move_tests(sbox, s # TODO: Should check that the output includes that the update was applied to # the destination mc['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) mc['status'].tweak(source, status='D ', moved_to=dest) @@ -730,7 +730,7 @@ def build_simple_file_move_tests(sbox, s working['output'] = svntest.verify.ExpectedOutput( [ "Breaking move with source path '%s'\n" % source_path, - "Resolved conflicted state of '%s'\n" % source_path + "Tree conflict at '%s' marked as resolved.\n" % source_path ] ) # XXX: working breaks the move? Is that right? @@ -766,7 +766,7 @@ def build_simple_file_move_tests(sbox, s # TODO: Should check that the output includes that the update was applied to # the destination mc['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) mc['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) mc['status'].tweak(source, status='D ', moved_to=dest) @@ -778,7 +778,7 @@ def build_simple_file_move_tests(sbox, s working['output'] = svntest.verify.ExpectedOutput( [ "Breaking move with source path '%s'\n" % source_path, - "Resolved conflicted state of '%s'\n" % source_path + "Tree conflict at '%s' marked as resolved.\n" % source_path ] ) # XXX: working breaks the move? Is that right? @@ -815,12 +815,12 @@ def build_simple_file_move_tests(sbox, s treeconflict='C')}) # mine-conflict doesn't work. mc = {} - mc['error'] = svntest.verify.RegexOutput(".*: .*: W155027:.*", match_all=False) + mc['error'] = svntest.verify.RegexOutput(".*: .*: W195024:.*", match_all=False) mc['status'] = test['up_status'] mc['disk'] = test['up_disk'] working = {} working['output'] = svntest.verify.ExpectedOutput( - "Resolved conflicted state of '%s'\n" % source_path, match_all=False + "Tree conflict at '%s' marked as resolved.\n" % source_path, match_all=False ) # move is broken now working['status'] = svntest.actions.get_virginal_state(wc_dir, test['end_rev']) @@ -1250,7 +1250,7 @@ def nested_replaces(sbox): svntest.actions.run_and_verify_status(wc_dir, r2_status) svntest.main.run_svn(None, 'commit', '-m', 'r2: juggle the tree', wc_dir) - expected_output = svntest.verify.UnorderedRegexListOutput(map(re.escape, [ + escaped = svntest.main.ensure_list(map(re.escape, [ ' R /A (from /X/Y/Z:1)', ' A /A/B (from /A/B:1)', ' R /A/B/C (from /X:1)', @@ -1259,9 +1259,9 @@ def nested_replaces(sbox): ' R /X/Y/Z (from /A:1)', ' D /X/Y/Z/B', ' D /A/B/C/Y', - ]) + [ - '^-', '^r2', '^-', '^Changed paths:', - ]) + ])) + expected_output = svntest.verify.UnorderedRegexListOutput(escaped + + [ '^-', '^r2', '^-', '^Changed paths:', ]) svntest.actions.run_and_verify_svn(expected_output, [], 'log', '-qvr2', repo_url) @@ -1609,7 +1609,7 @@ def move_conflict_details(sbox): " C %s\n" % sbox.ospath('B/F'), " C %s\n" % sbox.ospath('B/lambda'), "Updated to revision 2.\n", - "Resolved conflicted state of '%s'\n" % sbox.ospath('A/B') + "Tree conflict at '%s' marked as resolved.\n" % sbox.ospath('A/B') ] svntest.actions.run_and_verify_svn(expected_output, [], 'resolve', sbox.ospath('A/B'), Modified: subversion/branches/ra-git/subversion/tests/cmdline/patch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/patch_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/patch_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/patch_tests.py Tue Oct 11 09:11:50 2016 @@ -1581,6 +1581,9 @@ def patch_no_svn_eol_style(sbox): else: crlf = '\r\n' + # Strict EOL style matching breaks Windows tests at least with Python 2 + keep_eol_style = not svntest.main.is_os_windows() + eols = [crlf, '\015', '\n', '\012'] for target_eol in eols: for patch_eol in eols: @@ -1657,13 +1660,13 @@ def patch_no_svn_eol_style(sbox): expected_skip = wc.State('', { }) - svntest.actions.run_and_verify_patch(wc_dir, - patch_file_path, - expected_output, - expected_disk, - expected_status, - expected_skip, - [], True, True) + svntest.actions.run_and_verify_patch2(wc_dir, + patch_file_path, + expected_output, + expected_disk, + expected_status, + expected_skip, + [], True, True, keep_eol_style) expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], @@ -1685,6 +1688,9 @@ def patch_with_svn_eol_style(sbox): else: crlf = '\r\n' + # Strict EOL style matching breaks Windows tests at least with Python 2 + keep_eol_style = not svntest.main.is_os_windows() + eols = [crlf, '\015', '\n', '\012'] eol_styles = ['CRLF', 'CR', 'native', 'LF'] rev = 1 @@ -1771,15 +1777,16 @@ def patch_with_svn_eol_style(sbox): expected_skip = wc.State('', { }) - svntest.actions.run_and_verify_patch(wc_dir, - patch_file_path, - expected_output, - expected_disk, - expected_status, - expected_skip, - None, # expected err - 1, # check-props - 1) # dry-run + svntest.actions.run_and_verify_patch2(wc_dir, + patch_file_path, + expected_output, + expected_disk, + expected_status, + expected_skip, + None, # expected err + 1, # check-props + 1, # dry-run + keep_eol_style) # keep-eol-style expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], 'revert', '-R', wc_dir) @@ -1800,6 +1807,9 @@ def patch_with_svn_eol_style_uncommitted else: crlf = '\r\n' + # Strict EOL style matching breaks Windows tests at least with Python 2 + keep_eol_style = not svntest.main.is_os_windows() + eols = [crlf, '\015', '\n', '\012'] eol_styles = ['CRLF', 'CR', 'native', 'LF'] for target_eol, target_eol_style in zip(eols, eol_styles): @@ -1880,15 +1890,16 @@ def patch_with_svn_eol_style_uncommitted expected_skip = wc.State('', { }) - svntest.actions.run_and_verify_patch(wc_dir, - patch_file_path, - expected_output, - expected_disk, - expected_status, - expected_skip, - None, # expected err - 1, # check-props - 1) # dry-run + svntest.actions.run_and_verify_patch2(wc_dir, + patch_file_path, + expected_output, + expected_disk, + expected_status, + expected_skip, + None, # expected err + 1, # check-props + 1, # dry-run + keep_eol_style) # keep-eol-style expected_output = ["Reverted '" + mu_path + "'\n"] svntest.actions.run_and_verify_svn(expected_output, [], 'revert', '-R', wc_dir) @@ -3461,7 +3472,7 @@ def patch_one_property(sbox, trailing_eo 1, # dry-run '--strip', '3') - svntest.actions.check_prop('k', wc_dir, [value]) + svntest.actions.check_prop('k', wc_dir, [value.encode()]) def patch_strip_cwd(sbox): "patch --strip propchanges cwd" @@ -4518,7 +4529,7 @@ def patch_empty_file(sbox): "--- lf.txt\t(revision 2)\n", "+++ lf.txt\t(working copy)\n", "@@ -1 +1 @@\n", - "\n" + "-\n" "+replacement\n", # patch a new file 'new.txt\n' @@ -4553,7 +4564,7 @@ def patch_empty_file(sbox): # Current result: lf.txt patched ok, new created, empty succeeds with offset. expected_disk = svntest.main.greek_state.copy() expected_disk.add({ - 'lf.txt' : Item(contents="\n"), + 'lf.txt' : Item(contents="replacement\n"), 'new.txt' : Item(contents="new file\n"), 'empty.txt' : Item(contents="replacement\n"), }) @@ -5788,7 +5799,7 @@ def patch_binary_file(sbox): # Make the file binary by putting some non ascii chars inside or propset # will return a warning - sbox.simple_append('iota', '\0\202\203\204\205\206\207nsomething\nelse\xFF') + sbox.simple_append('iota', b'\0\202\203\204\205\206\207nsomething\nelse\xFF') sbox.simple_propset('svn:mime-type', 'application/binary', 'iota') expected_output = [ @@ -5827,8 +5838,8 @@ def patch_binary_file(sbox): expected_disk.tweak('iota', props={'svn:mime-type':'application/binary'}, contents = - 'This is the file \'iota\'.\n' - '\0\202\203\204\205\206\207nsomething\nelse\xFF') + b'This is the file \'iota\'.\n' + + b'\0\202\203\204\205\206\207nsomething\nelse\xFF') expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.tweak('iota', status='MM') expected_skip = wc.State('', { }) @@ -7528,6 +7539,288 @@ def patch_move_and_change(sbox): [], True, True, '--reverse-diff') +@Issue(4609) +def missing_trailing_context(sbox): + "missing trailing context" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/mu', + 'a\n' + 'b\n' + 'c\n' + 'd\n' + 'e\n', + truncate=True) + sbox.simple_commit() + sbox.simple_update() + + # The hunk is expected to have two lines of trailing context but + # only has one. + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 2)\n", + "+++ A/mu\t(working copy)\n", + "@@ -1,5 +1,5 @@\n", + " a\n", + " b\n", + "-c\n", + "+cc\n", + " d\n", + ] + patch_file_path = sbox.get_tempname('my.patch') + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), 'wb') + + # GNU patch will apply the hunk with fuzz 1 and modify only the 'c' line. + # Our patch file finds the length mismatch and applies a penalty. + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -1,4 +1,4 @@ with fuzz 1\n', + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents = + 'a\n' + 'b\n' + 'cc\n' + 'd\n' + 'e\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 2) + expected_status.tweak('A/mu', status='M ') + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, patch_file_path, + expected_output, expected_disk, + expected_status, expected_skip) + + # Try reverse patch + expected_disk.tweak('A/mu', contents = + 'a\n' + 'b\n' + 'c\n' + 'd\n' + 'e\n') + expected_status.tweak('A/mu', status=' ') + svntest.actions.run_and_verify_patch(wc_dir, patch_file_path, + expected_output, expected_disk, + expected_status, expected_skip, + [], False, True, '--reverse-diff') + + # The hunk is expected to have two lines of trailing context but + # only has one. + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 2)\n", + "+++ A/mu\t(working copy)\n", + "@@ -1,4 +1,4 @@\n", + " a\n", + " b\n", + "-c\n", + "+cc\n", + " d\n", + " e\n", + ] + patch_file_path = sbox.get_tempname('my2.patch') + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), 'wb') + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -1,5 +1,5 @@ with fuzz 1\n', + ] + expected_disk.tweak('A/mu', contents = + 'a\n' + 'b\n' + 'cc\n' + 'd\n' + 'e\n') + expected_status.tweak('A/mu', status='M ') + svntest.actions.run_and_verify_patch(wc_dir, patch_file_path, + expected_output, expected_disk, + expected_status, expected_skip) + + # Try reverse patch + expected_disk.tweak('A/mu', contents = + 'a\n' + 'b\n' + 'c\n' + 'd\n' + 'e\n') + expected_status.tweak('A/mu', status=' ') + svntest.actions.run_and_verify_patch(wc_dir, patch_file_path, + expected_output, expected_disk, + expected_status, expected_skip, + [], False, True, '--reverse-diff') + +def patch_missed_trail(sbox): + "apply a patch to an empty file" + + sbox.build() + wc_dir = sbox.wc_dir + + patch_file_path = sbox.get_tempname('my.patch') + svntest.main.file_write(patch_file_path, ''.join([ + # Add a line to a file with just '\n' with bad header (should be +1,2) + "Index: lf.txt\n", + "===================================================================\n", + "--- lf.txt\t(revision 2)\n", + "+++ lf.txt\t(working copy)\n", + "@@ -1 +1 @@\n", + "\n" + "+replacement\n", + ])) + + sbox.simple_add_text('\n', 'lf.txt') + sbox.simple_commit() + + expected_output = [ + 'U %s\n' % sbox.ospath('lf.txt'), + '> applied hunk @@ -1,1 +1,2 @@ with fuzz 1\n', + ] + + # Current result: lf.txt patched ok, new created, empty succeeds with offset. + expected_disk = svntest.main.greek_state.copy() + expected_disk.add({ + 'lf.txt' : Item(contents="\nreplacement\n"), + }) + expected_skip = wc.State(wc_dir, {}) + expected_status = None + + svntest.actions.run_and_verify_patch(wc_dir, patch_file_path, + expected_output, expected_disk, + expected_status, expected_skip) + +def patch_merge(sbox): + "patching a specific merge" + + sbox.build() + wc_dir = sbox.wc_dir + repo_url = sbox.repo_url + + sbox.simple_add_text('A\n' + 'B\n' + 'C\n' + 'J\n' + 'K\n' + 'L', 'new.txt') + sbox.simple_commit() + + remote_patch = sbox.get_tempname('remote.patch') + svntest.main.file_write(remote_patch, + '--- new.txt\t(revision 6)\n' + '+++ new.txt\t(revision 7)\n' + '@@ -1,6 +1,9 @@\n' + ' A\n' + ' B\n' + '-C\n' + '+ C\n' + '+D\n' + '+E\n' + '+F\n' + ' J\n' + ' K\n' + ' L\n' + '\ No newline at end of file', mode='wb') + + expected_skip = wc.State('', { }) + expected_output = wc.State(wc_dir, { + 'new.txt' : Item(status='U '), + }) + svntest.actions.run_and_verify_patch(wc_dir, remote_patch, + expected_output, None, + None, expected_skip) + sbox.simple_commit() + sbox.simple_update(revision=2) + + local_patch = sbox.get_tempname('local.patch') + svntest.main.file_write(local_patch, + '--- new.txt\t(revision 3)\n' + '+++ new.txt\t(revision 4)\n' + '@@ -1,6 +1,9 @@\n' + ' A\n' + ' B\n' + ' C\n' + '+D\n' + '+E\n' + '+F\n' + ' J\n' + ' K\n' + ' L\n' + '\ No newline at end of file', mode='wb') + + svntest.actions.run_and_verify_patch(wc_dir, local_patch, + expected_output, None, + None, expected_skip) + + expected_disk = svntest.main.greek_state.copy() + expected_disk.add({ + 'new.txt' : Item(contents='A\n' + 'B\n' + '<<<<<<< .mine\n' + 'C\n' + 'D\n' + 'E\n' + 'F\n' + '||||||| .r2\n' + 'C\n' + '=======\n' + ' C\n' + 'D\n' + 'E\n' + 'F\n' + '>>>>>>> .r3\n' + 'J\n' + 'K\n' + 'L'), + 'new.txt.mine' : Item(contents="A\nB\nC\nD\nE\nF\nJ\nK\nL"), + 'new.txt.r2' : Item(contents="A\nB\nC\nJ\nK\nL"), + 'new.txt.r3' : Item(contents="A\nB\n C\nD\nE\nF\nJ\nK\nL"), + }) + expected_output.tweak('new.txt', status='C ') + svntest.actions.run_and_verify_update(wc_dir, expected_output, expected_disk, + None, []) + + # Revert to base position + sbox.simple_revert('new.txt') + sbox.simple_update(revision=2) + + # And now do the same thing as a merge instead of an update + expected_output.tweak('new.txt', status='U ') + svntest.actions.run_and_verify_patch(wc_dir, local_patch, + expected_output, None, + None, expected_skip) + + expected_output.tweak('new.txt', status='C ') + expected_disk = svntest.main.greek_state.copy() + expected_disk.add({ + 'new.txt' : Item(contents='A\n' + 'B\n' + '<<<<<<< .working\n' + 'C\n' + 'D\n' + 'E\n' + 'F\n' + '||||||| .merge-left.r2\n' + 'C\n' + '=======\n' + ' C\n' + 'D\n' + 'E\n' + 'F\n' + '>>>>>>> .merge-right.r3\n' + 'J\n' + 'K\n' + 'L'), + 'new.txt.working' : Item(contents="A\nB\nC\nD\nE\nF\nJ\nK\nL"), + 'new.txt.merge-left.r2' : Item(contents="A\nB\nC\nJ\nK\nL"), + 'new.txt.merge-right.r3' : Item(contents="A\nB\n C\nD\nE\nF\nJ\nK\nL"), + }) + + svntest.actions.run_and_verify_merge(wc_dir, 2, 3, repo_url, repo_url, + expected_output, None, None, + expected_disk, None, + expected_skip) + ######################################################################## #Run the tests @@ -7608,6 +7901,9 @@ test_list = [ None, patch_add_one_line, patch_with_mergeinfo, patch_move_and_change, + missing_trailing_context, + patch_missed_trail, + patch_merge, ] if __name__ == '__main__': Modified: subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/prop_tests.py Tue Oct 11 09:11:50 2016 @@ -750,7 +750,7 @@ def copy_inherits_special_props(sbox): # copied file. if os.name == 'posix': sbox.simple_propset('svn:executable', 'on', 'new_file1.bin') - os.chmod(new_path1, 0644) + os.chmod(new_path1, svntest.main.S_ALL_READ | stat.S_IWUSR) # Commit the file sbox.simple_commit() @@ -894,41 +894,42 @@ def prop_value_conversions(sbox): # part of the prop value and it doesn't get converted in the pipe. # Check svn:mime-type - svntest.actions.check_prop('svn:mime-type', iota_path, ['text/html']) - svntest.actions.check_prop('svn:mime-type', mu_path, ['text/html']) + svntest.actions.check_prop('svn:mime-type', iota_path, [b'text/html']) + svntest.actions.check_prop('svn:mime-type', mu_path, [b'text/html']) # Check svn:eol-style - svntest.actions.check_prop('svn:eol-style', iota_path, ['native']) - svntest.actions.check_prop('svn:eol-style', mu_path, ['native']) + svntest.actions.check_prop('svn:eol-style', iota_path, [b'native']) + svntest.actions.check_prop('svn:eol-style', mu_path, [b'native']) # Check svn:ignore + linesep = os.linesep.encode() svntest.actions.check_prop('svn:ignore', A_path, - ['*.o'+os.linesep, 'foo.c'+os.linesep]) + [b'*.o'+linesep, b'foo.c'+linesep]) svntest.actions.check_prop('svn:ignore', B_path, - ['*.o'+os.linesep, 'foo.c'+os.linesep]) + [b'*.o'+linesep, b'foo.c'+linesep]) # Check svn:externals svntest.actions.check_prop('svn:externals', A_path, - ['foo http://foo.com/repos'+os.linesep]) + [b'foo http://foo.com/repos'+linesep]) svntest.actions.check_prop('svn:externals', B_path, - ['foo http://foo.com/repos'+os.linesep]) + [b'foo http://foo.com/repos'+linesep]) # Check svn:keywords - svntest.actions.check_prop('svn:keywords', iota_path, ['Rev Date']) - svntest.actions.check_prop('svn:keywords', mu_path, ['Rev Date']) + svntest.actions.check_prop('svn:keywords', iota_path, [b'Rev Date']) + svntest.actions.check_prop('svn:keywords', mu_path, [b'Rev Date']) # Check svn:executable - svntest.actions.check_prop('svn:executable', iota_path, ['*']) - svntest.actions.check_prop('svn:executable', lambda_path, ['*']) - svntest.actions.check_prop('svn:executable', mu_path, ['*']) + svntest.actions.check_prop('svn:executable', iota_path, [b'*']) + svntest.actions.check_prop('svn:executable', lambda_path, [b'*']) + svntest.actions.check_prop('svn:executable', mu_path, [b'*']) # Check other props - svntest.actions.check_prop('svn:some-prop', lambda_path, ['bar']) - svntest.actions.check_prop('svn:some-prop', mu_path, [' bar baz']) - svntest.actions.check_prop('svn:some-prop', iota_path, ['bar'+os.linesep]) - svntest.actions.check_prop('some-prop', lambda_path, ['bar']) - svntest.actions.check_prop('some-prop', mu_path,[' bar baz']) - svntest.actions.check_prop('some-prop', iota_path, ['bar\n']) + svntest.actions.check_prop('svn:some-prop', lambda_path, [b'bar']) + svntest.actions.check_prop('svn:some-prop', mu_path, [b' bar baz']) + svntest.actions.check_prop('svn:some-prop', iota_path, [b'bar'+linesep]) + svntest.actions.check_prop('some-prop', lambda_path, [b'bar']) + svntest.actions.check_prop('some-prop', mu_path,[b' bar baz']) + svntest.actions.check_prop('some-prop', iota_path, [b'bar\n']) #---------------------------------------------------------------------- @@ -958,10 +959,10 @@ def binary_props(sbox): mu_path_bak = sbox.ospath('A/mu', wc_dir=wc_backup) # Property value convenience vars. - prop_zb = "This property has a zer\000 byte." - prop_ff = "This property has a form\014feed." - prop_xml = "This property has an <xml> tag." - prop_binx = "This property has an <xml> tag and a zer\000 byte." + prop_zb = b"This property has a zer\000 byte." + prop_ff = b"This property has a form\014feed." + prop_xml = b"This property has an <xml> tag." + prop_binx = b"This property has an <xml> tag and a zer\000 byte." # Set some binary properties. svntest.actions.set_prop('prop_zb', prop_zb, B_path, ) @@ -1673,11 +1674,11 @@ def added_moved_file(sbox): svntest.main.run_svn(None, 'mv', foo_path, foo2_path) # should still have the property - svntest.actions.check_prop('someprop', foo2_path, ['someval']) + svntest.actions.check_prop('someprop', foo2_path, [b'someval']) # the property should get committed, too sbox.simple_commit() - svntest.actions.check_prop('someprop', foo2_url, ['someval']) + svntest.actions.check_prop('someprop', foo2_url, [b'someval']) # Issue 2220, deleting a non-existent property should error @@ -2087,7 +2088,7 @@ def atomic_over_ra(sbox): PASSES_WITHOUT_BPV(None, s1) # Value of "flower" is 's1'. - svntest.actions.check_prop('flower', repo_url, [s1], 0) + svntest.actions.check_prop('flower', repo_url, [s1.encode()], 0) # Test for issue #3721 'redirection of svn propget output corrupted with # large property values' Modified: subversion/branches/ra-git/subversion/tests/cmdline/relocate_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/relocate_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/relocate_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/relocate_tests.py Tue Oct 11 09:11:50 2016 @@ -350,15 +350,20 @@ def relocate_with_relative_externals(sbo sbox.build() wc_dir = sbox.wc_dir + repo_dir = sbox.repo_dir + repo_url = sbox.repo_url # Add a relative external. change_external(os.path.join(wc_dir, 'A', 'B'), "^/A/D/G G-ext\n../D/H H-ext", commit=True) svntest.actions.run_and_verify_svn(None, [], 'update', wc_dir) + # A second wc not at the repository root + other_wc = sbox.add_wc_path('other') + svntest.main.safe_rmtree(other_wc, 1) + svntest.actions.run_and_verify_svn(None, [], 'checkout', + repo_url + '/A/B', other_wc) # Move our repository to another location. - repo_dir = sbox.repo_dir - repo_url = sbox.repo_url other_repo_dir, other_repo_url = sbox.add_repo_path('other') svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0) svntest.main.safe_rmtree(repo_dir, 1) @@ -374,6 +379,46 @@ def relocate_with_relative_externals(sbo svntest.actions.run_and_verify_info([{ 'URL' : '.*.other/A/D/H$' }], os.path.join(wc_dir, 'A', 'B', 'H-ext')) + # Relocate with prefix too long to be valid for externals. + svntest.actions.run_and_verify_svn(None, [], 'relocate', + repo_url + '/A/B', + other_repo_url + '/A/B', + other_wc) + + svntest.actions.run_and_verify_info([{ 'URL' : '.*.other/A/D/G$' }], + os.path.join(other_wc, 'G-ext')) + svntest.actions.run_and_verify_info([{ 'URL' : '.*.other/A/D/H$' }], + os.path.join(other_wc, 'H-ext')) + +def prefix_partial_component(sbox): + """prefix with a partial component""" + + sbox.build() + wc_dir = sbox.wc_dir + repo_dir = sbox.repo_dir + repo_url = sbox.repo_url + other1_repo_dir, other1_repo_url = sbox.add_repo_path('xxxother') + other2_repo_dir, other2_repo_url = sbox.add_repo_path('yyyother') + + # Relocate to 'xxxother'. + svntest.main.copy_repos(repo_dir, other1_repo_dir, 1, 0) + svntest.main.safe_rmtree(repo_dir, 1) + svntest.actions.run_and_verify_svn(None, [], 'relocate', + repo_url, other1_repo_url, wc_dir) + svntest.actions.run_and_verify_info([{ 'URL' : '.*.xxxother$' }], + wc_dir) + + # Now relocate from 'xxx' to 'yyy' omitting 'other'. + svntest.main.copy_repos(other1_repo_dir, other2_repo_dir, 1, 0) + svntest.main.safe_rmtree(other1_repo_url, 1) + svntest.actions.run_and_verify_svn(None, [], 'relocate', + other1_repo_url[:-5], + other2_repo_url[:-5], + wc_dir) + svntest.actions.run_and_verify_info([{ 'URL' : '.*.yyyother$' }], + wc_dir) + + ######################################################################## # Run the tests @@ -385,6 +430,7 @@ test_list = [ None, single_file_relocate, relocate_with_switched_children, relocate_with_relative_externals, + prefix_partial_component, ] if __name__ == '__main__': Modified: subversion/branches/ra-git/subversion/tests/cmdline/resolve_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/resolve_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/resolve_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/resolve_tests.py Tue Oct 11 09:11:50 2016 @@ -598,6 +598,76 @@ def multi_range_merge_with_accept(sbox): svntest.main.run_svn(None, 'merge', '-c4,3', '^/iota', 'iota', '--accept=theirs-conflict') +#---------------------------------------------------------------------- + +# Test for issue #4647 'auto resolution mine-full fails on binary file' +@Issue(4647) +@XFail() +def automatic_binary_conflict_resolution(sbox): + "resolve -R --accept [base | mf | tf] binary file" + + sbox.build() + wc_dir = sbox.wc_dir + + # Some paths we'll care about + A_COPY_path = os.path.join(wc_dir, "A_COPY") + + # Add a binary file to the project in revision 2. + theta_contents = open(os.path.join(sys.path[0], "theta.bin"), 'rb').read() + theta_path = sbox.ospath('A/theta') + svntest.main.file_write(theta_path, theta_contents, 'wb') + svntest.main.run_svn(None, 'add', theta_path) + svntest.main.run_svn(None, 'commit', '-m', 'log msg', wc_dir) + + # Branch A to A_COPY in revision 3. + svntest.main.run_svn(None, 'copy', wc_dir + "/A", A_COPY_path) + svntest.main.run_svn(None, 'commit', '-m', 'log msg', wc_dir) + + # Modify the binary file on trunk and in the branch, so that both versions + # differ. + theta_branch_path = sbox.ospath('A_COPY/theta') + svntest.main.file_append_binary(theta_path, theta_contents) + svntest.main.run_svn(None, 'commit', '-m', 'log msg', wc_dir) + svntest.main.file_append_binary(theta_branch_path, theta_contents) + svntest.main.file_append_binary(theta_branch_path, theta_contents) + svntest.main.run_svn(None, 'commit', '-m', 'log msg', wc_dir) + + # Run an svn update now to prevent mixed-revision working copy [1:4] error. + svntest.main.run_svn(None, 'update', wc_dir) + + + def do_binary_conflicting_merge(): + svntest.actions.run_and_verify_svn(None, [], + 'revert', '--recursive', A_COPY_path) + svntest.main.run_svn(None, 'merge', sbox.repo_url + "/A/theta", + wc_dir + "/A_COPY/theta") + + # Test 'svn resolve -R --accept base' + # Regression until r1758160 + do_binary_conflicting_merge() + svntest.actions.run_and_verify_resolve([theta_branch_path], + '-R', '--accept', 'base', + A_COPY_path) + + # Test 'svn resolve -R --accept theirs-full' + do_binary_conflicting_merge() + svntest.actions.run_and_verify_resolve([theta_branch_path], + '-R', '--accept', 'tf', + A_COPY_path) + + # Test 'svn resolve -R --accept working' + # Equivalent to 'svn resolved' + do_binary_conflicting_merge() + svntest.actions.run_and_verify_resolve([theta_branch_path], + '-R', '--accept', 'working', + A_COPY_path) + + # Test 'svn resolve -R --accept mine-full' + # There is no '.mine' for binary file conflicts. Same handling as 'working' + do_binary_conflicting_merge() + svntest.actions.run_and_verify_resolve([theta_branch_path], + '-R', '--accept', 'mine-full', + A_COPY_path) ######################################################################## # Run the tests @@ -611,6 +681,7 @@ test_list = [ None, resolved_on_deleted_item, theirs_conflict_in_subdir, multi_range_merge_with_accept, + automatic_binary_conflict_resolution, ] if __name__ == '__main__': Modified: subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/revert_tests.py Tue Oct 11 09:11:50 2016 @@ -1132,7 +1132,7 @@ def revert_permissions_only(sbox): check_executability(path, False) - os.chmod(sbox.ospath('A/B/E/alpha'), 0444) # read-only + os.chmod(sbox.ospath('A/B/E/alpha'), svntest.main.S_ALL_READ) # read-only is_readonly(sbox.ospath('A/B/E/alpha')) expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/alpha')] svntest.actions.run_and_verify_svn(expected_output, [], @@ -1140,7 +1140,7 @@ def revert_permissions_only(sbox): is_writable(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): - os.chmod(sbox.ospath('A/B/E/beta'), 0777) # executable + os.chmod(sbox.ospath('A/B/E/beta'), svntest.main.S_ALL_RWX) # executable is_executable(sbox.ospath('A/B/E/beta')) expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/beta')] svntest.actions.run_and_verify_svn(expected_output, [], @@ -1165,7 +1165,7 @@ def revert_permissions_only(sbox): expected_output, expected_status) - os.chmod(sbox.ospath('A/B/E/alpha'), 0666) # not read-only + os.chmod(sbox.ospath('A/B/E/alpha'), svntest.main.S_ALL_RW) # not read-only is_writable(sbox.ospath('A/B/E/alpha')) expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/alpha')] svntest.actions.run_and_verify_svn(expected_output, [], @@ -1173,7 +1173,7 @@ def revert_permissions_only(sbox): is_readonly(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): - os.chmod(sbox.ospath('A/B/E/beta'), 0666) # not executable + os.chmod(sbox.ospath('A/B/E/beta'), svntest.main.S_ALL_RW) # not executable is_non_executable(sbox.ospath('A/B/E/beta')) expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E/beta')] svntest.actions.run_and_verify_svn(expected_output, [], Modified: subversion/branches/ra-git/subversion/tests/cmdline/schedule_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/schedule_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/schedule_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/schedule_tests.py Tue Oct 11 09:11:50 2016 @@ -26,7 +26,7 @@ ###################################################################### # General modules -import os, logging +import os, logging, stat logger = logging.getLogger() @@ -198,11 +198,11 @@ def add_executable(sbox): 'propget', "svn:executable", file_ospath) test_cases = [ - ("all_exe", 0777, 1), - ("none_exe", 0666, 0), - ("user_exe", 0766, 1), - ("group_exe", 0676, 0), - ("other_exe", 0667, 0), + ("all_exe", svntest.main.S_ALL_RWX, 1), + ("none_exe", svntest.main.S_ALL_RW, 0), + ("user_exe", svntest.main.S_ALL_RW | stat.S_IXUSR, 1), + ("group_exe", svntest.main.S_ALL_RW | stat.S_IXGRP, 0), + ("other_exe", svntest.main.S_ALL_RW | stat.S_IXOTH, 0), ] for test_case in test_cases: runTest(sbox.wc_dir, *test_case) Modified: subversion/branches/ra-git/subversion/tests/cmdline/special_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/tests/cmdline/special_tests.py?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/tests/cmdline/special_tests.py (original) +++ subversion/branches/ra-git/subversion/tests/cmdline/special_tests.py Tue Oct 11 09:11:50 2016 @@ -25,7 +25,7 @@ ###################################################################### # General modules -import sys, os, re, copy +import sys, os, re, copy, stat # Our testing module import svntest @@ -972,7 +972,7 @@ def replace_symlinks(sbox): 'A/D/Hx/psi.sh', ]: file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n') - os.chmod(wc(p), 0775) + os.chmod(wc(p), svntest.main.S_ALL_RW | stat.S_IXUSR) sbox.simple_add(p) if not svntest.main.is_posix_os(): sbox.simple_propset('svn:executable', 'X', p)