Modified: subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/lock_tests.py Sat May 23 14:16:56 2020 @@ -1001,7 +1001,7 @@ def lock_and_exebit1(sbox): if (not gamma_stat & mode_r or gamma_stat & mode_w or not gamma_stat & mode_x): - logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'") + logger.warn("Committing a file with 'svn:needs-lock, svn:executable'") logger.warn("after unlocking modified file's permissions") raise svntest.Failure @@ -1065,7 +1065,7 @@ def lock_and_exebit2(sbox): if (not gamma_stat & mode_r or gamma_stat & mode_w or not gamma_stat & mode_x): - logger.warn("Commiting a file with 'svn:needs-lock, svn:executable'") + logger.warn("Committing a file with 'svn:needs-lock, svn:executable'") logger.warn("did not set the file to read-only, executable") raise svntest.Failure @@ -1454,7 +1454,7 @@ def lock_path_not_in_head(sbox): svntest.actions.run_and_verify_svn(None, [], 'up', '-r1', wc_dir) expected_lock_fail_err_re = "svn: warning: W160042: " \ "(Path .* doesn't exist in HEAD revision)" - # Issue #3524 These lock attemtps were triggering an assert over ra_serf: + # Issue #3524 These lock attempts were triggering an assert over ra_serf: # # working_copies\lock_tests-37>svn lock A\D # ..\..\..\subversion\libsvn_client\ra.c:275: (apr_err=235000) @@ -1571,7 +1571,8 @@ def cp_isnt_ro(sbox): mu2_path = sbox.ospath('A/mu2') mu3_path = sbox.ospath('A/mu3') kappa_path = sbox.ospath('kappa') - open(kappa_path, 'w').write("This is the file 'kappa'.\n") + with open(kappa_path, 'w') as f: + f.write("This is the file 'kappa'.\n") ## added file sbox.simple_add('kappa') @@ -1834,7 +1835,7 @@ def commit_stolen_lock(sbox): # When removing directories, the locks of contained files were not # correctly removed from the working copy database, thus they later # magically reappeared when new files or directories with the same -# pathes were added. +# paths were added. @Issue(4364) def drop_locks_on_parent_deletion(sbox): "drop locks when the parent is deleted" @@ -1855,7 +1856,7 @@ def drop_locks_on_parent_deletion(sbox): [], expected_status) - # now re-add entities to the deleted pathes. + # now re-add entities to the deleted paths. sbox.simple_mkdir('A/B') sbox.simple_add_text('new file replacing old file', 'A/B/lambda') sbox.simple_add_text('file replacing former dir', 'A/B/F') @@ -2251,7 +2252,6 @@ def dav_lock_refresh(sbox): if r.status != httplib.OK: raise svntest.Failure('Lock refresh failed: %d %s' % (r.status, r.reason)) -@SkipUnless(svntest.main.is_ra_type_dav) def delete_locked_file_with_percent(sbox): "lock and delete a file called 'a %( ) .txt'"
Modified: subversion/branches/addremove/subversion/tests/cmdline/log_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/log_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/log_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/log_tests.py Sat May 23 14:16:56 2020 @@ -1592,7 +1592,7 @@ def merge_sensitive_log_added_mergeinfo_ # a merge results in added explicit mergeinfo on a path, but that # path previously inherited mergeinfo (rather than had no explicit # or inherited mergeinfo). See issue #3235, specifically - # http://subversion.tigris.org/issues/show_bug.cgi?id=3235#desc8. + # https://issues.apache.org/jira/browse/SVN-3235#desc8. sbox.build() wc_dir = sbox.wc_dir @@ -1752,7 +1752,7 @@ def merge_sensitive_log_added_mergeinfo_ def merge_sensitive_log_propmod_merge_inheriting_path(sbox): "log -g and simple propmod to merge-inheriting path" - # Issue #3285 (http://subversion.tigris.org/issues/show_bug.cgi?id=3285) + # Issue #3285 (https://issues.apache.org/jira/browse/SVN-3285) sbox.build() wc_dir = sbox.wc_dir @@ -2094,7 +2094,7 @@ def merge_sensitive_log_copied_path_inhe svntest.main.run_svn(None, 'move', old_gamma_path, new_gamma_path) sbox.simple_commit(message='Move file') - # 'svn log -g --stop-on-copy ^/A/C/gamma' hould return *only* r5 + # 'svn log -g --stop-on-copy ^/A/C/gamma' should return *only* r5 # Previously this test failed because the change in gamma's inherited # mergeinfo between r4 and r5, due to the move, was understood as a merge: # @@ -2166,13 +2166,13 @@ def log_diff(sbox): + [ "@@ -1 +1,2 @@\n", " This is the file 'beta'.\n", "+9\n", - "\ No newline at end of file\n", + "\\ No newline at end of file\n", ] ] r8diff = [ make_diff_header('A2/D/G/rho', 'nonexistent', 'revision 8') + [ "@@ -0,0 +1 @@\n", "+88\n", - "\ No newline at end of file\n", + "\\ No newline at end of file\n", ] ] log_chain = parse_log_output(output, with_diffs=True) @@ -2779,6 +2779,42 @@ def log_on_deleted_deep(sbox): '', '-q', '-c', '1-2') +@XFail() +@Issue(4711) +def log_with_merge_history_and_search(sbox): + "log --use-merge-history --search" + + sbox.build() + + # r2: create branch + sbox.simple_repo_copy('A', 'A2') # r2 + + # r3: mod in trunk + sbox.simple_append('A/mu', 'line 2') + sbox.simple_commit(message='r3: mod') + sbox.simple_update() + + # r4: merge + svntest.main.run_svn(None, 'merge', sbox.repo_url + '/A', sbox.ospath('A2')) + sbox.simple_commit(message='r4: merge') + sbox.simple_update() + + # Helper function + def count(haystack, needle): + """Return the number of times the string NEEDLE occurs in the string + HAYSTACK.""" + return len(haystack.split(needle)) - 1 + + # Check the output is valid + # ### Since the test is currently XFail, we only smoke test the output. + # ### When fixing this test to PASS, extend this validation. + _, output, _ = svntest.main.run_svn(None, 'log', '--xml', '-g', + '--search', "this will have no matches", + sbox.ospath('A2')) + + output = '\n'.join(output) + if count(output, "<logentry") != count(output, "</logentry"): + raise svntest.Failure("Apparently invalid XML in " + repr(output)) ######################################################################## # Run the tests @@ -2830,6 +2866,7 @@ test_list = [ None, merge_sensitive_log_xml_reverse_merges, log_revision_move_copy, log_on_deleted_deep, + log_with_merge_history_and_search, ] if __name__ == '__main__': Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/merge_authz_tests.py Sat May 23 14:16:56 2020 @@ -97,7 +97,7 @@ def mergeinfo_and_skipped_paths(sbox): wc_disk, wc_status = set_up_branch(sbox, False, 3) # Create a restrictive authz where part of the merge source and part - # of the target are inaccesible. + # of the target are inaccessible. write_restrictive_svnserve_conf(sbox.repo_dir) write_authz_file(sbox, {"/" : svntest.main.wc_author +"=rw", # Make a directory in the merge source inaccessible. @@ -342,7 +342,7 @@ def mergeinfo_and_skipped_paths(sbox): # this. # # Merge -c5 -c8 to the restricted WC's A_COPY_2/D/H. r5 gets merged first - # but is a no-op, r8 get's merged next and is operative so the mergeinfo + # but is a no-op, r8 gets merged next and is operative so the mergeinfo # should be updated on the merge target to reflect both merges. expected_output = wc.State(A_COPY_2_H_path, { 'omega' : Item(status='U '), @@ -486,7 +486,7 @@ def mergeinfo_and_skipped_paths(sbox): def merge_fails_if_subtree_is_deleted_on_src(sbox): "merge fails if subtree is deleted on src" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2876. ## + ## See https://issues.apache.org/jira/browse/SVN-2876. ## # Create a WC sbox.build() @@ -613,7 +613,7 @@ def reintegrate_fails_if_no_root_access( # should be able to reintegrate, regardless of what authorization # they have to parents of the source and target. # - # See http://subversion.tigris.org/issues/show_bug.cgi?id=3242#desc78 + # See https://issues.apache.org/jira/browse/SVN-3242#desc78 # Some paths we'll care about wc_dir = sbox.wc_dir Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/merge_automatic_tests.py Sat May 23 14:16:56 2020 @@ -1163,7 +1163,7 @@ def effective_sync_results_in_reintegrat # Now try an explicit --reintegrate merge from ^/branch to A. # This should work because since the resolution of - # http://subversion.tigris.org/issues/show_bug.cgi?id=3577 + # https://issues.apache.org/jira/browse/SVN-3577 # if B is *effectively* synced with A, then B can be reintegrated # to A. sbox.simple_update() Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/merge_reintegrate_tests.py Sat May 23 14:16:56 2020 @@ -1363,7 +1363,7 @@ def reintegrate_with_subtree_mergeinfo(s # how can any prop changes be merged to it? The answer is that # the merge code does some quiet housekeeping, merging gamma_moved's # inherited mergeinfo into its incoming mergeinfo, see - # http://subversion.tigris.org/issues/show_bug.cgi?id=4309 + # https://issues.apache.org/jira/browse/SVN-4309 # This test is not covering issue #4309 so we let the current # behavior pass. # r17 - B) Synch merge from A to A_COPY Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/merge_tests.py Sat May 23 14:16:56 2020 @@ -697,7 +697,7 @@ def simple_property_merges(sbox): def merge_similar_unrelated_trees(sbox): "merging similar trees ancestrally unrelated" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=1249. ## + ## See https://issues.apache.org/jira/browse/SVN-1249. ## sbox.build() wc_dir = sbox.wc_dir @@ -3939,7 +3939,7 @@ def avoid_repeated_merge_on_subtree_with check_props=True) # Test for part of Issue #2821, see - # http://subversion.tigris.org/issues/show_bug.cgi?id=2821#desc22 + # https://issues.apache.org/jira/browse/SVN-2821#desc22 # # Revert all local changes. svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir) @@ -4794,7 +4794,7 @@ def mergeinfo_inheritance_and_discontinu # Merge r2:6 into A_COPY/D # # A_COPY/D should inherit the mergeinfo '/A:4' from A_COPY - # combine it with the discontinous merges performed directly on + # combine it with the discontinuous merges performed directly on # it (A/D/ 2:3 and A/D 4:6) resulting in '/A/D:3-6'. expected_output = wc.State(D_COPY_path, { 'H/psi' : Item(status='U '), @@ -4966,11 +4966,11 @@ def merge_to_switched_path(sbox): A_COPY_D_G_rho_path = sbox.ospath('A_COPY/D/G/rho') expected = svntest.verify.UnorderedOutput( - ["A " + os.path.join(G_COPY_path, "pi") + "\n", - "A " + os.path.join(G_COPY_path, "rho") + "\n", - "A " + os.path.join(G_COPY_path, "tau") + "\n", - "Checked out revision 6.\n", - "A " + G_COPY_path + "\n"]) + ["A " + G_COPY_path + "\n", + "A " + os.path.join(G_COPY_path, "pi") + "\n", + "A " + os.path.join(G_COPY_path, "rho") + "\n", + "A " + os.path.join(G_COPY_path, "tau") + "\n", + ]) # r7 - Copy A/D/G to A/D/G_COPY and commit. svntest.actions.run_and_verify_svn(expected, [], 'copy', @@ -6007,7 +6007,7 @@ def foreign_repos_does_not_update_mergei def avoid_reflected_revs(sbox): "avoid repeated merges for cyclic merging" - # See <http://subversion.tigris.org/issues/show_bug.cgi?id=2897>. + # See <https://issues.apache.org/jira/browse/SVN-2897>. # # This test cherry-picks some changes (all of them, in fact) from the # parent branch 'A' to the child branch 'A_COPY', and then tries to @@ -8294,7 +8294,7 @@ def cherry_picking(sbox): def propchange_of_subdir_raises_conflict(sbox): "merge of propchange on subdir raises conflict" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2969. ## + ## See https://issues.apache.org/jira/browse/SVN-2969. ## # Create a WC with a single branch sbox.build() @@ -8515,7 +8515,7 @@ def reverse_merge_prop_add_on_child(sbox def merge_target_with_non_inheritable_mergeinfo(sbox): "merge target with non inheritable mergeinfo" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2970. ## + ## See https://issues.apache.org/jira/browse/SVN-2970. ## # Create a WC with a single branch sbox.build() @@ -8547,7 +8547,7 @@ def merge_target_with_non_inheritable_me expected_output = wc.State(A_COPY_B_path, { 'lambda' : Item(status='U '), }) - # Issue #3642 http://subversion.tigris.org/issues/show_bug.cgi?id=3642 + # Issue #3642 https://issues.apache.org/jira/browse/SVN-3642 # # We don't expect A_COPY/B/F to have mergeinfo recorded on it because # not only is it unaffected by the merge at depth immediates, it could @@ -8820,7 +8820,7 @@ def merge_from_renamed_branch_fails_whil #Merge r4 from A/RENAMED_C to A/C #Merge r2:5 from A/RENAMED_C to A/C <-- This fails tracked via #3032. - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3032. ## + ## See https://issues.apache.org/jira/browse/SVN-3032. ## # Create a WC with a single branch sbox.build() @@ -9250,7 +9250,7 @@ def new_subtrees_should_not_break_merge( # so we expect only subtree merges on A_COPY/D, A_COPY_D_H, and # A_COPY/D/H/nu. The fact that A/D/H/nu doesn't exist at r6 should not cause # the merge to fail -- see - # http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc7. + # https://issues.apache.org/jira/browse/SVN-3067#desc7. expected_output = wc.State(A_COPY_path, { 'D/H/omega': Item(status='U '), }) @@ -10495,7 +10495,7 @@ def reverse_merge_away_all_mergeinfo(sbo # Another test for issue #3067: 'subtrees with intersecting mergeinfo, # that don't exist at the start of a merge range shouldn't break the # merge'. Specifically see -# http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5 +# https://issues.apache.org/jira/browse/SVN-3067#desc5 @SkipUnless(server_has_mergeinfo) @Issues(3138,3067,4217) def dont_merge_revs_into_subtree_that_predate_it(sbox): @@ -10614,7 +10614,7 @@ def dont_merge_revs_into_subtree_that_pr # Cherry harvest all eligible revisions from 'A/D/H' to 'H_COPY'. # # This is where we see the problem described in - # http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc5. + # https://issues.apache.org/jira/browse/SVN-3067#desc5. # # Use run_and_verify_svn() because run_and_verify_merge*() require # explicit revision ranges. @@ -11786,7 +11786,7 @@ def subtree_source_missing_in_requested_ # Another test for issue #3067: 'subtrees that don't exist at the start # or end of a merge range shouldn't break the merge' # -# See http://subversion.tigris.org/issues/show_bug.cgi?id=3067#desc34 +# See https://issues.apache.org/jira/browse/SVN-3067#desc34 @Issue(3067) @SkipUnless(server_has_mergeinfo) def subtrees_with_empty_mergeinfo(sbox): @@ -12848,6 +12848,39 @@ def natural_history_filtering(sbox): # the revisions on 'trunk' which occurred after 'branch2' was copied as # these are not part of 'branch2's natural history. + def path_join(head, tail): + if not head: return tail + if not tail: return head + return head + '/' + tail + + def greek_file_item(path): + if path[-1:].islower(): + basename = re.sub('.*/', '', path) + return Item("This is the file '" + basename + "'.\n") + return Item() + + A_paths = [ + "", + "B", + "B/lambda", + "B/E", + "B/E/alpha", + "B/E/beta", + "B/F", + "mu", + "C", + "D", + "D/gamma", + "D/G", + "D/G/pi", + "D/G/rho", + "D/G/tau", + "D/H", + "D/H/chi", + "D/H/omega", + "D/H/psi", + ] + sbox.build() wc_dir = sbox.wc_dir @@ -12861,68 +12894,16 @@ def natural_history_filtering(sbox): # r7: Make a second 'branch': Copy A to A_COPY_2 expected = svntest.verify.UnorderedOutput( - ["A " + os.path.join(A_COPY_2_path, "B") + "\n", - "A " + os.path.join(A_COPY_2_path, "B", "lambda") + "\n", - "A " + os.path.join(A_COPY_2_path, "B", "E") + "\n", - "A " + os.path.join(A_COPY_2_path, "B", "E", "alpha") + "\n", - "A " + os.path.join(A_COPY_2_path, "B", "E", "beta") + "\n", - "A " + os.path.join(A_COPY_2_path, "B", "F") + "\n", - "A " + os.path.join(A_COPY_2_path, "mu") + "\n", - "A " + os.path.join(A_COPY_2_path, "C") + "\n", - "A " + os.path.join(A_COPY_2_path, "D") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "gamma") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "G") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "G", "pi") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "G", "rho") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "G", "tau") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "H") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "H", "chi") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "H", "omega") + "\n", - "A " + os.path.join(A_COPY_2_path, "D", "H", "psi") + "\n", - "Checked out revision 6.\n", - "A " + A_COPY_2_path + "\n"]) - wc_status.add({ - "A_COPY_2" + "/B" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/B/lambda" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/B/E" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/B/E/alpha" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/B/E/beta" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/B/F" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/mu" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/C" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/gamma" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/G" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/G/pi" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/G/rho" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/G/tau" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/H" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/H/chi" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/H/omega" : Item(status=' ', wc_rev=7), - "A_COPY_2" + "/D/H/psi" : Item(status=' ', wc_rev=7), - "A_COPY_2" : Item(status=' ', wc_rev=7), - }) - wc_disk.add({ - "A_COPY_2" : Item(), - "A_COPY_2" + '/B' : Item(), - "A_COPY_2" + '/B/lambda' : Item("This is the file 'lambda'.\n"), - "A_COPY_2" + '/B/E' : Item(), - "A_COPY_2" + '/B/E/alpha' : Item("This is the file 'alpha'.\n"), - "A_COPY_2" + '/B/E/beta' : Item("New content"), - "A_COPY_2" + '/B/F' : Item(), - "A_COPY_2" + '/mu' : Item("This is the file 'mu'.\n"), - "A_COPY_2" + '/C' : Item(), - "A_COPY_2" + '/D' : Item(), - "A_COPY_2" + '/D/gamma' : Item("This is the file 'gamma'.\n"), - "A_COPY_2" + '/D/G' : Item(), - "A_COPY_2" + '/D/G/pi' : Item("This is the file 'pi'.\n"), - "A_COPY_2" + '/D/G/rho' : Item("New content"), - "A_COPY_2" + '/D/G/tau' : Item("This is the file 'tau'.\n"), - "A_COPY_2" + '/D/H' : Item(), - "A_COPY_2" + '/D/H/chi' : Item("New content"), - "A_COPY_2" + '/D/H/omega' : Item("This is the file 'omega'.\n"), - "A_COPY_2" + '/D/H/psi' : Item("New content"), - }) + [ "A " + sbox.ospath(path_join("A_COPY_2", p)) + "\n" + for p in A_paths ]) + wc_status.add( + { path_join("A_COPY_2", p) : Item(status=' ', wc_rev=7) + for p in A_paths }) + wc_disk.add( + { path_join("A_COPY_2", p) : + Item("New content") if p in ['B/E/beta', 'D/G/rho', 'D/H/chi', 'D/H/psi'] + else greek_file_item(p) + for p in A_paths }) svntest.actions.run_and_verify_svn(expected, [], 'copy', sbox.repo_url + "/A", A_COPY_2_path) @@ -13305,7 +13286,7 @@ def no_self_referential_filtering_on_add # how can any prop changes be merged to it? The answer is that # the merge code does some quiet housekeeping, merging C_MOVED's # inherited mergeinfo into its incoming mergeinfo, see - # http://subversion.tigris.org/issues/show_bug.cgi?id=4309 + # https://issues.apache.org/jira/browse/SVN-4309 # This test is not covering issue #4309 so we let the current # behavior pass. expected_mergeinfo_output = wc.State(A_COPY_2_path, { @@ -13374,13 +13355,13 @@ def no_self_referential_filtering_on_add #---------------------------------------------------------------------- # Test for issue #3324 -# http://subversion.tigris.org/issues/show_bug.cgi?id=3324 +# https://issues.apache.org/jira/browse/SVN-3324 @Issue(3324) @SkipUnless(server_has_mergeinfo) def merge_range_prior_to_rename_source_existence(sbox): "merge prior to rename src existence still dels src" - # Replicate a merge bug found while synching up a feature branch on the + # Replicate a merge bug found while syncing up a feature branch on the # Subversion repository with trunk. See r874121 of # http://svn.apache.org/repos/asf/subversion/branches/ignore-mergeinfo, in which # a move was merged to the target, but the delete half of the move @@ -13881,7 +13862,7 @@ def dont_merge_gaps_in_history(sbox): #---------------------------------------------------------------------- # Test for issue #3432 'Merge can record mergeinfo from natural history -# gaps'. See http://subversion.tigris.org/issues/show_bug.cgi?id=3432 +# gaps'. See https://issues.apache.org/jira/browse/SVN-3432 @Issue(3432) @SkipUnless(server_has_mergeinfo) def handle_gaps_in_implicit_mergeinfo(sbox): @@ -15122,7 +15103,7 @@ def foreign_repos_del_and_props(sbox): #---------------------------------------------------------------------- # Test for issue #3642 'immediate depth merges don't create proper subtree -# mergeinfo'. See http://subversion.tigris.org/issues/show_bug.cgi?id=3642 +# mergeinfo'. See https://issues.apache.org/jira/browse/SVN-3642 @Issue(3642) def immediate_depth_merge_creates_minimal_subtree_mergeinfo(sbox): "no spurious mergeinfo from immediate depth merges" @@ -15817,7 +15798,7 @@ def subtree_merges_inherit_invalid_worki #---------------------------------------------------------------------- # Test for issue #3686 'executable flag not correctly set on merge' -# See http://subversion.tigris.org/issues/show_bug.cgi?id=3686 +# See https://issues.apache.org/jira/browse/SVN-3686 @Issue(3686) @SkipUnless(server_has_mergeinfo) @SkipUnless(svntest.main.is_posix_os) Modified: subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/merge_tree_conflict_tests.py Sat May 23 14:16:56 2020 @@ -540,7 +540,7 @@ def merge_add_over_versioned_file_confli def mergeinfo_recording_in_skipped_merge(sbox): "mergeinfo recording in skipped merge" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2829. ## + ## See https://issues.apache.org/jira/browse/SVN-2829. ## # Create a WC with a single branch sbox.build() @@ -705,7 +705,7 @@ def del_differing_file(sbox): def tree_conflicts_and_obstructions(sbox): "tree conflicts and obstructions" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3146. ## + ## See https://issues.apache.org/jira/browse/SVN-3146. ## sbox.build() wc_dir = sbox.wc_dir Modified: subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/mergeinfo_tests.py Sat May 23 14:16:56 2020 @@ -196,7 +196,7 @@ def mergeinfo_on_unknown_url(sbox): # Test for issue #3126 'svn mergeinfo shows too few or too many # eligible revisions'. Specifically -# http://subversion.tigris.org/issues/show_bug.cgi?id=3126#desc5. +# https://issues.apache.org/jira/browse/SVN-3126#desc5. @SkipUnless(server_has_mergeinfo) @Issue(3126) def non_inheritable_mergeinfo(sbox): Modified: subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/mod_authz_svn_tests.py Sat May 23 14:16:56 2020 @@ -167,7 +167,7 @@ def anon(sbox): write_authz_file(sbox) - anon_tests = ( + anon_tests = ( { 'path': '', 'status': 301 }, { 'path': '/', 'status': 200 }, { 'path': '/repos', 'status': 301 }, Modified: subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py Sat May 23 14:16:56 2020 @@ -102,7 +102,7 @@ def compare_xml_elem(a, b): # 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)) @@ -640,6 +640,53 @@ def propfind_propname(sbox): actual_response = r.read() verify_xml_response(expected_response, actual_response) +@SkipUnless(svntest.main.is_ra_type_dav) +def last_modified_header(sbox): + "verify 'Last-Modified' header on 'external' GETs" + + sbox.build(create_wc=False, read_only=True) + + headers = { + 'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(), + } + + h = svntest.main.create_http_connection(sbox.repo_url) + + # GET /repos/iota + # Expect to see a Last-Modified header. + h.request('GET', sbox.repo_url + '/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + svntest.verify.compare_and_display_lines(None, 'Last-Modified', + svntest.verify.RegexOutput('.+'), + r.getheader('Last-Modified')) + r.read() + + # HEAD /repos/iota + # Expect to see a Last-Modified header. + h.request('HEAD', sbox.repo_url + '/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + svntest.verify.compare_and_display_lines(None, 'Last-Modified', + svntest.verify.RegexOutput('.+'), + r.getheader('Last-Modified')) + r.read() + + # GET /repos/!svn/rvr/1/iota + # There should not be a Last-Modified header (it's costly and not useful, + # see r1724790) + h.request('GET', sbox.repo_url + '/!svn/rvr/1/iota', None, headers) + r = h.getresponse() + if r.status != httplib.OK: + raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason)) + last_modified = r.getheader('Last-Modified') + if last_modified: + raise svntest.Failure('Unexpected Last-Modified header: %s' % last_modified) + r.read() + + ######################################################################## # Run the tests @@ -652,6 +699,7 @@ test_list = [ None, propfind_404, propfind_allprop, propfind_propname, + last_modified_header, ] serial_only = True Propchange: subversion/branches/addremove/subversion/tests/cmdline/mod_dav_svn_tests.py ------------------------------------------------------------------------------ svn:executable = * Modified: subversion/branches/addremove/subversion/tests/cmdline/move_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/move_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/move_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/move_tests.py Sat May 23 14:16:56 2020 @@ -125,7 +125,7 @@ def move_file_test(sbox, source, dest, m start_disk: validate the on disk state after the start update against this. start_status: validate the wc status after the start update against this. end_rev: revision to update to, bringing in some update you want to test. - up_output: validate the output of the end update agianst this. + up_output: validate the output of the end update against this. up_disk: validate the on disk state after the end update against this. up_status: validate the wc status after the end update against this. revert_paths: validate the paths reverted. @@ -793,7 +793,7 @@ def build_simple_file_move_tests(sbox, s # move and update with incoming identical move (r16-17) # XXX: It'd be really nice if we actually recognized this and the wc - # showed no conflict at all on udpate. + # showed no conflict at all on update. test = {} test['start_rev'] = 16 test['end_rev'] = 17 @@ -883,7 +883,7 @@ def build_simple_file_move_func(sbox, so # # Each test must return on success or raise on failure. # -# See http://wiki.apache.org/subversion/LocalMoves +# See https://cwiki.apache.org/confluence/display/SVN/LocalMoves def lateral_move_file_test(sbox): "lateral (rename) move of a file test" @@ -1261,7 +1261,7 @@ def nested_replaces(sbox): ' D /A/B/C/Y', ])) expected_output = svntest.verify.UnorderedRegexListOutput(escaped - + [ '^-', '^r2', '^-', '^Changed paths:', ]) + + [ '^--*', '^r2.*', '^--*', '^Changed paths:', ]) svntest.actions.run_and_verify_svn(expected_output, [], 'log', '-qvr2', repo_url) @@ -1755,7 +1755,7 @@ def move_conflict_markers(sbox): }) expected_disk.remove('iota', 'iota.prej', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', - 'A/B/E/dir_conflicts.prej', + 'A/B/E/dir_conflicts.prej', 'A/B/E/beta.prej') expected_disk.add({ 'A/iotb' : Item(contents="This is the file 'iota'.\n"), Modified: subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/patch_tests.py Sat May 23 14:16:56 2020 @@ -4246,7 +4246,7 @@ def patch_git_with_index_line(sbox): "+++ b/src/tools/ConsoleRunner/hi.txt\n", "@@ -0,0 +1 @@\n", "+hihihihihihi\n", - "\ No newline at end of file\n", + "\\ No newline at end of file\n", ] svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) @@ -4413,7 +4413,7 @@ def patch_replace_dir_with_file_and_vv(s "+++ A/D\t(working copy)\n", "@@ -0,0 +1 @@\n", "+New file\n", - "\ No newline at end of file\n", + "\\ No newline at end of file\n", # Add iota as directory "Index: iota\n", @@ -4426,7 +4426,7 @@ def patch_replace_dir_with_file_and_vv(s "Added: k\n", "## -0,0 +1 ##\n", "+v\n", - "\ No newline at end of property\n", + "\\ No newline at end of property\n", ])) expected_output = wc.State(wc_dir, { @@ -6541,7 +6541,7 @@ def patch_prop_madness(sbox): "Property: del_n\n" "## -1,1 +0,0 ##\n" "-no-eol\n" - "\ No newline at end of property\n" + "\\ No newline at end of property\n" % (sbox.path('iota'), sbox.path('iota'))), }) @@ -7791,6 +7791,225 @@ def patch_merge(sbox): expected_disk, None, expected_skip) +def patch_mergeinfo_in_regular_prop_format(sbox): + "patch mergeinfo in regular prop format" + + sbox.build() + wc_dir = sbox.wc_dir + strip_count = wc_dir.count(os.path.sep)+1 + + sbox.simple_copy('A/B/E', 'E') + sbox.simple_append('A/B/E/alpha', 'extra\nlines\n') + sbox.simple_commit() + + sbox.simple_propset('a', 'A', 'E') # 'a' < 'svn:mergeinfo' + sbox.simple_propset('z', 'Z', 'E') # 'z' > 'svn:mergeinfo' + + svntest.actions.run_and_verify_svn(None, [], + 'merge', '^/A/B/E', sbox.ospath('E')) + # Rename 'svn:mergeinfo' to 'svn_mergeinfo' so that 'diff' doesn't + # pretty-print it; then rename it back before we run it through 'patch'. + # (Alternatively, we could disable pretty-printing when we implement a + # command-line switch to do so.) + mergeinfo_value = sbox.simple_propget('svn:mergeinfo', 'E') + sbox.simple_propdel('svn:mergeinfo', 'E') + sbox.simple_propset('svn_mergeinfo', mergeinfo_value, 'E') + + _, diff, _ = svntest.actions.run_and_verify_svn(None, [], + 'diff', wc_dir) + diff = re.sub('svn_mergeinfo', 'svn:mergeinfo', ''.join(diff)) + + sbox.simple_revert('E', 'E/alpha') + + patch = sbox.get_tempname('recurse.patch') + svntest.main.file_write(patch, diff, mode='wb') + + expected_output = wc.State(wc_dir, { + 'E' : Item(status=' U'), + 'E/alpha' : Item(status='U '), + }) + expected_skip = wc.State(wc_dir, {}) + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.add({ + 'E' : Item(status=' M', wc_rev='2'), + 'E/alpha' : Item(status='M ', wc_rev='2'), + 'E/beta' : Item(status=' ', wc_rev='2'), + }) + expected_status.tweak('A/B/E/alpha', wc_rev=2) + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/B/E/alpha', contents="This is the file 'alpha'.\nextra\nlines\n") + expected_disk.add({ + 'E' : Item(props={'a': 'A', + # here is the correctly patched mergeinfo + 'svn:mergeinfo': '/A/B/E:2', + 'z': 'Z'}), + 'E/beta' : Item(contents="This is the file 'beta'.\n"), + 'E/alpha' : Item(contents="This is the file 'alpha'.\nextra\nlines\n"), + }) + + svntest.actions.run_and_verify_patch(wc_dir, patch, + expected_output, expected_disk, + expected_status, expected_skip, + [], True, True, + '--strip', strip_count) + +@XFail() +def patch_empty_prop(sbox): + "patch empty prop" + sbox.build(empty=True) + was_cwd = os.getcwd() + os.chdir(sbox.wc_dir) + sbox.wc_dir = '' + wc_dir = '' + + # start with a file with an empty prop + sbox.simple_add_text('', 'f') + sbox.simple_propset('p', '', 'f') + sbox.simple_commit() + + # a patch that modifies the prop to a non-empty value + unidiff_patch = [ + "--- f\n", + "+++ f\n", + "\n", + "Property changes on: f\n", + "___________________________________________________________________\n", + "Modified: p\n", + "## -0,0 +1 ##\n", + "+v\n", + ] + + trailing_eol = False + if trailing_eol: + value = "v\n" + else: + value = "v" + unidiff_patch += ['\ No newline at end of property\n'] + + patch_file_path = sbox.get_tempname('my.patch') + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch), 'wb') + + expected_output = [ + ' U %s\n' % sbox.ospath('f'), + ] + + expected_disk = svntest.wc.State(wc_dir, {}) + expected_disk.add({'f': Item(props={'p' : value})}) + expected_status = svntest.wc.State(wc_dir, {}) + expected_status.add({'f': Item(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, + None, # expected err + 1, # check-props + False, # dry-run + ) + + svntest.actions.check_prop('p', wc_dir, [value.encode()]) + + os.chdir(was_cwd) + +# Test that 'patch' can apply a patch that modifies properties on the root +# of a WC and/or the root of a repository. This test uses the format of +# diff output produced by 'svn diff --git' in svn <= 1.10.0: paths are given +# as 'a/' and 'b/' and 'Property changes on: ' (with no following '.'). +# +# See dev@ email thread 2018-07-09 from Dmitry Pavlenko, +# '[PATCH] can't "svn patch" working copy root if the patch is in --git format', +# https://lists.apache.org/thread.html/d1d9811ca36fac8cabb9339634840099e22811beac505be2ea59f19f@%3Cdev.subversion.apache.org%3E +@XFail() +def patch_git_wcroot(sbox): + "patch working copy root" + sbox.build(empty=True) + wc_dir = sbox.wc_dir + + git_patch = [ "Index: .\n", + "===================================================================\n", + "diff --git a/ b/\n", + "--- a/ (revision 0)\n", + "+++ b/ (working copy)\n", + "Property changes on: \n", + "___________________________________________________________________\n", + "Added: p\n", + "## -0,0 +1 ##\n", + "+v\n", + "\\ No newline at end of property\n", + ] + value = 'v' + + patch_file_path = sbox.get_tempname('my.patch') + svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb') + + expected_output = wc.State(wc_dir, { + '.' : Item(status=' U'), + }) + expected_disk = svntest.wc.State('', {}) + expected_disk.add({'': Item(props={'p' : value })}) + expected_status = svntest.wc.State(wc_dir, {}) + expected_status.add({'': Item(status=' M', wc_rev='0')}) + 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 + True, # check-props + False, # dry-run + ) + + svntest.actions.check_prop('p', wc_dir, [value.encode()]) + +# Test that 'patch' can apply a patch that modifies properties on the root +# of a WC and/or the root of a repository. This test performs a round-trip +# through 'diff --git' and 'patch' rather than assuming any particular +# variant of the patch format. +# +# See dev@ email thread 2018-07-09 from Dmitry Pavlenko, +# '[PATCH] can't "svn patch" working copy root if the patch is in --git format', +# https://lists.apache.org/thread.html/d1d9811ca36fac8cabb9339634840099e22811beac505be2ea59f19f@%3Cdev.subversion.apache.org%3E +@XFail() +def patch_git_wcroot2(sbox): + "patch working copy root" + sbox.build(empty=True) + wc_dir = sbox.wc_dir + + value = 'v' + sbox.simple_propset('p', value, '') + exit_code, git_patch, err_output = svntest.main.run_svn(None, 'diff', + '--git', wc_dir) + + patch_file_path = sbox.get_tempname('my.patch') + svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb') + + sbox.simple_revert('') + + expected_output = wc.State(wc_dir, { + '.' : Item(status=' U'), + }) + expected_disk = svntest.wc.State('', {}) + expected_disk.add({'': Item(props={'p' : value })}) + expected_status = svntest.wc.State(wc_dir, {}) + expected_status.add({'': Item(status=' M', wc_rev='0')}) + 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 + True, # check-props + False, # dry-run + ) + + svntest.actions.check_prop('p', wc_dir, [value.encode()]) + ######################################################################## #Run the tests @@ -7874,6 +8093,10 @@ test_list = [ None, missing_trailing_context, patch_missed_trail, patch_merge, + patch_mergeinfo_in_regular_prop_format, + patch_empty_prop, + patch_git_wcroot, + patch_git_wcroot2, ] if __name__ == '__main__': Modified: subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/prop_tests.py Sat May 23 14:16:56 2020 @@ -1768,7 +1768,7 @@ def rm_of_replaced_file(sbox): 'proplist', '-v', mu_path + '@base') expected_output = svntest.verify.UnorderedRegexListOutput([ - 'Properties on', + 'Properties on.*', ' yellow', ' submarine', ' orange', Modified: subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/relocate_tests.py Sat May 23 14:16:56 2020 @@ -417,8 +417,8 @@ def prefix_partial_component(sbox): wc_dir) svntest.actions.run_and_verify_info([{ 'URL' : '.*.yyyother$' }], wc_dir) - - + + ######################################################################## # Run the tests Modified: subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/revert_tests.py Sat May 23 14:16:56 2020 @@ -46,6 +46,23 @@ Item = svntest.wc.StateItem ###################################################################### # Helpers +def expected_output_revert(reverted_paths, skipped_paths=[]): + return svntest.verify.UnorderedRegexListOutput( + ["Reverted '%s'\n" % re.escape(path) for path in reverted_paths] + + ["Skipped '%s'.*\n" % re.escape(path) for path in skipped_paths]) + +def run_and_verify_revert(targets, options=[], + reverted_paths=None, skipped_paths=[]): + """Run 'svn revert OPTIONS TARGETS'. Verify that the printed output matches + REVERTED_PATHS and SKIPPED_PATHS. If REVERTED_PATHS is None, it defaults + to TARGETS. + """ + if reverted_paths is None: + reverted_paths = targets + expected_output = expected_output_revert(reverted_paths, skipped_paths) + svntest.actions.run_and_verify_svn(expected_output, [], + *(['revert'] + options + targets)) + def revert_replacement_with_props(sbox, wc_copy): """Helper implementing the core of revert_{repos,wc}_to_wc_replace_with_props(). @@ -129,9 +146,7 @@ def revert_replacement_with_props(sbox, svntest.actions.run_and_verify_status(wc_dir, expected_status) expected_status.tweak('A/D/G/rho', status=' ', copied=None, wc_rev='2') - expected_output = ["Reverted '" + rho_path + "'\n"] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '-R', wc_dir) + run_and_verify_revert([wc_dir], ['-R'], [rho_path]) svntest.actions.run_and_verify_status(wc_dir, expected_status) # Check disk status @@ -356,8 +371,7 @@ def revert_replaced_file_without_props(s svntest.actions.run_and_verify_status(wc_dir, expected_status) # revert file1 - svntest.actions.run_and_verify_svn(["Reverted '" + file1_path + "'\n"], - [], 'revert', file1_path) + run_and_verify_revert([file1_path]) # test that file1 really was reverted expected_status.tweak('file1', status=' ', wc_rev=2) @@ -402,10 +416,7 @@ def revert_moved_file(sbox): actions.run_and_verify_unquiet_status(wc_dir, expected_status) # svn revert iota - expected_stdout = ["Reverted '" + iota + "'\n"] - - actions.run_and_verify_svn2(expected_stdout, [], 0, 'revert', - iota) + run_and_verify_revert([iota]) # svn st expected_status.tweak('iota', status=' ', moved_to=None) @@ -644,9 +655,7 @@ def revert_propset__dir(sbox): wc_dir = sbox.wc_dir a_path = os.path.join(wc_dir, 'A') svntest.main.run_svn(None, 'propset', 'foo', 'x', a_path) - expected_output = re.escape("Reverted '" + a_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - a_path) + run_and_verify_revert([a_path]) def revert_propset__file(sbox): "revert a simple propset on a file" @@ -655,9 +664,7 @@ def revert_propset__file(sbox): wc_dir = sbox.wc_dir iota_path = os.path.join(wc_dir, 'iota') svntest.main.run_svn(None, 'propset', 'foo', 'x', iota_path) - expected_output = re.escape("Reverted '" + iota_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - iota_path) + run_and_verify_revert([iota_path]) def revert_propdel__dir(sbox): "revert a simple propdel on a dir" @@ -669,9 +676,7 @@ def revert_propdel__dir(sbox): svntest.main.run_svn(None, 'commit', '-m', 'ps', a_path) svntest.main.run_svn(None, 'propdel', 'foo', a_path) - expected_output = re.escape("Reverted '" + a_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - a_path) + run_and_verify_revert([a_path]) def revert_propdel__file(sbox): "revert a simple propdel on a file" @@ -683,9 +688,7 @@ def revert_propdel__file(sbox): svntest.main.run_svn(None, 'commit', '-m', 'ps', iota_path) svntest.main.run_svn(None, 'propdel', 'foo', iota_path) - expected_output = re.escape("Reverted '" + iota_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - iota_path) + run_and_verify_revert([iota_path]) def revert_replaced_with_history_file_1(sbox): "revert a committed replace-with-history == no-op" @@ -776,9 +779,7 @@ def status_of_missing_dir_after_revert(s A_D_G_path = os.path.join(wc_dir, "A", "D", "G") svntest.actions.run_and_verify_svn(None, [], "rm", A_D_G_path) - expected_output = re.escape("Reverted '" + A_D_G_path + "'") - svntest.actions.run_and_verify_svn(expected_output, [], "revert", - A_D_G_path) + run_and_verify_revert([A_D_G_path]) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) expected_status.tweak('A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau', @@ -877,11 +878,7 @@ def status_of_missing_dir_after_revert_r revert_paths = [G_path] + [os.path.join(G_path, child) for child in ['alpha', 'beta', 'pi', 'rho', 'tau']] - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % path for path in revert_paths]) - - svntest.actions.run_and_verify_svn(expected_output, [], "revert", "-R", - G_path) + run_and_verify_revert([G_path], ["-R"], revert_paths) svntest.actions.run_and_verify_svn([], [], "status", wc_dir) @@ -947,12 +944,6 @@ def revert_tree_conflicts_in_updated_fil G2_tau = os.path.join(G2, 'tau') # Expectations - expected_output = svntest.verify.UnorderedOutput( - ["Reverted '%s'\n" % G_pi, - "Reverted '%s'\n" % G_rho, - "Reverted '%s'\n" % G_tau, - ]) - expected_status = svntest.actions.get_virginal_state(wc_dir, 2) expected_status.tweak('A/D/G/pi', status=' ') expected_status.remove('A/D/G/rho') @@ -965,23 +956,15 @@ def revert_tree_conflicts_in_updated_fil expected_disk.remove('A/D/G/tau') # Revert individually in wc - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', G_pi, G_rho, G_tau) + run_and_verify_revert([G_pi, G_rho, G_tau]) svntest.actions.run_and_verify_status(wc_dir, expected_status) svntest.actions.verify_disk(wc_dir, expected_disk) # Expectations - expected_output = svntest.verify.UnorderedOutput( - ["Reverted '%s'\n" % G2_pi, - "Reverted '%s'\n" % G2_rho, - "Reverted '%s'\n" % G2_tau, - ]) - expected_status.wc_dir = wc_dir_2 # Revert recursively in wc 2 - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '-R', G2) + run_and_verify_revert([G2], ['-R'], [G2_pi, G2_rho, G2_tau]) svntest.actions.run_and_verify_status(wc_dir_2, expected_status) svntest.actions.verify_disk(wc_dir_2, expected_disk) @@ -1049,9 +1032,7 @@ def revert_child_of_copy(sbox): svntest.actions.run_and_verify_status(wc_dir, expected_status) # First revert removes text change, child is still copied - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E2/beta')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E2/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E2/beta'])) expected_status.tweak('A/B/E2/beta', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1074,9 +1055,7 @@ def revert_non_recusive_after_delete(sbo svntest.actions.run_and_verify_status(wc_dir, expected_status) # This appears to work but gets the op-depth wrong - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B')) + run_and_verify_revert(sbox.ospaths(['A/B'])) expected_status.tweak('A/B', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1086,9 +1065,7 @@ def revert_non_recusive_after_delete(sbo svntest.actions.run_and_verify_status(wc_dir, expected_status) # Since the op-depth was wrong A/B/E erroneously remains deleted - expected_output = ["Reverted '%s'\n" % sbox.ospath('A/B/E')] - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', sbox.ospath('A/B/E')) + run_and_verify_revert(sbox.ospaths(['A/B/E'])) expected_status.tweak('A/B/E', status=' ') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1134,17 +1111,13 @@ def revert_permissions_only(sbox): 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, [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) is_writable(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): 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, [], - 'revert', sbox.ospath('A/B/E/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E/beta'])) is_non_executable(sbox.ospath('A/B/E/beta')) svntest.actions.run_and_verify_svn(None, [], @@ -1167,17 +1140,13 @@ def revert_permissions_only(sbox): 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, [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) is_readonly(sbox.ospath('A/B/E/alpha')) if svntest.main.is_posix_os(): 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, [], - 'revert', sbox.ospath('A/B/E/beta')) + run_and_verify_revert(sbox.ospaths(['A/B/E/beta'])) is_executable(sbox.ospath('A/B/E/beta')) # copied file is always writeable @@ -1212,14 +1181,8 @@ def revert_copy_depth_files(sbox): }) svntest.actions.run_and_verify_status(wc_dir, expected_status) - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath(path) for path in ['A/B/E2', - 'A/B/E2/alpha', - 'A/B/E2/beta']]) - - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '--depth', 'files', - sbox.ospath('A/B/E2')) + run_and_verify_revert(sbox.ospaths(['A/B/E2']), ['--depth', 'files'], + sbox.ospaths(['A/B/E2', 'A/B/E2/alpha', 'A/B/E2/beta'])) expected_status.remove('A/B/E2', 'A/B/E2/alpha', 'A/B/E2/beta') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1242,12 +1205,8 @@ def revert_nested_add_depth_immediates(s }) svntest.actions.run_and_verify_status(wc_dir, expected_status) - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath(path) for path in ['A/X', 'A/X/Y']]) - - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', '--depth', 'immediates', - sbox.ospath('A/X')) + run_and_verify_revert(sbox.ospaths(['A/X']), ['--depth', 'immediates'], + sbox.ospaths(['A/X', 'A/X/Y'])) expected_status.remove('A/X', 'A/X/Y') svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1299,9 +1258,7 @@ def revert_empty_actual(sbox): wc_dir = sbox.wc_dir # Non-recursive code path works - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" % sbox.ospath('alpha')], - [], - 'revert', sbox.ospath('alpha')) + run_and_verify_revert(sbox.ospaths(['alpha'])) expected_status = svntest.actions.get_virginal_state(wc_dir, 2) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1316,9 +1273,7 @@ def revert_empty_actual_recursive(sbox): # Recursive code path fails, the superfluous actual node suppresses the # notification - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" % sbox.ospath('alpha')], - [], - 'revert', '-R', sbox.ospath('alpha')) + run_and_verify_revert(sbox.ospaths(['alpha']), ['-R']) expected_status = svntest.actions.get_virginal_state(wc_dir, 2) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1433,7 +1388,7 @@ def revert_tree_conflicts_with_replaceme cd_and_status_u('A/D/H') # Revert everything (i.e., accept "theirs-full"). - svntest.actions.run_and_verify_revert([ + reverted_paths = [ wc('A/B/E'), wc('A/B/E/alpha'), # incoming & local wc('A/B/E/beta'), @@ -1450,7 +1405,8 @@ def revert_tree_conflicts_with_replaceme wc('A/D/H/loc_psi'), wc('A/D/gamma'), wc('A/mu'), - ], '-R', wc_dir) + ] + run_and_verify_revert([wc_dir], ['-R'], reverted_paths) # Remove a few unversioned files that revert left behind. os.remove(wc('A/B/E/loc_beta')) @@ -1511,10 +1467,7 @@ def revert_no_text_change_conflict(sbox) create_no_text_change_conflict(sbox) wc_dir = sbox.wc_dir - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" - % sbox.ospath('A/B/E/alpha')], - [], - 'revert', sbox.ospath('A/B/E/alpha')) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha'])) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1526,10 +1479,7 @@ def revert_no_text_change_conflict_recur create_no_text_change_conflict(sbox) wc_dir = sbox.wc_dir - svntest.actions.run_and_verify_svn(["Reverted '%s'\n" - % sbox.ospath('A/B/E/alpha')], - [], - 'revert', '-R', wc_dir) + run_and_verify_revert(sbox.ospaths(['A/B/E/alpha']), ['-R']) expected_status = svntest.actions.get_virginal_state(wc_dir, 1) svntest.actions.run_and_verify_status(wc_dir, expected_status) @@ -1550,20 +1500,18 @@ def revert_with_unversioned_targets(sbox psi_contents = "modified psi\n" # touch delta - open(delta_path, 'w').write(delta_contents) + with open(delta_path, 'w') as f: + f.write(delta_contents) # modify chi psi - open(chi_path, 'w').write(chi_contents) - open(psi_path, 'w').write(psi_contents) + with open(chi_path, 'w') as f: + f.write(chi_contents) + with open(psi_path, 'w') as f: + f.write(psi_contents) # revert - expected_output = svntest.verify.UnorderedOutput([ - "Reverted '%s'\n" % sbox.ospath('A/D/H/chi'), - "Skipped '%s'\n" % sbox.ospath('A/D/H/delta'), - "Reverted '%s'\n" % sbox.ospath('A/D/H/psi'), - ]) - svntest.actions.run_and_verify_svn(expected_output, [], - 'revert', chi_path, delta_path, psi_path) + run_and_verify_revert([chi_path, delta_path, psi_path], [], + [chi_path, psi_path], [delta_path]) # verify status expected_status = svntest.actions.get_virginal_state(wc_dir, 1) @@ -1582,8 +1530,8 @@ def revert_with_unversioned_targets(sbox def revert_nonexistent(sbox): 'svn revert -R nonexistent' sbox.build(read_only=True) - svntest.actions.run_and_verify_svn('Skipped.*nonexistent', [], - 'revert', '-R', sbox.ospath('nonexistent')) + run_and_verify_revert(sbox.ospaths(['nonexistent']), ['-R'], + [], sbox.ospaths(['nonexistent'])) @Issue(4168) def revert_obstructing_wc(sbox): @@ -1638,6 +1586,33 @@ def revert_moved_dir_partial(sbox): sbox.simple_move('A', 'A_') svntest.actions.run_and_verify_svn(None, [], 'revert', sbox.ospath('A')) +@XFail() +@Issue(4798) +def revert_remove_added(sbox): + "revert_remove_added" + + sbox.build(empty=True, read_only=True) + + # We'll test the items named with a '1' as direct targets to 'revert', + # and items named with a '2' as items found by recursion. + sbox.simple_mkdir('D1', 'D2') + sbox.simple_add_text('This is a new file.', + 'D1/file', 'file1', + 'D2/file', 'file2') + + run_and_verify_revert(sbox.ospaths(['D1']), ['--remove-added', '-R'], + sbox.ospaths(['D1/file', 'D1'])) + assert(not os.path.exists(sbox.ospath('D1'))) + + run_and_verify_revert(sbox.ospaths(['file1']), ['--remove-added'], + sbox.ospaths(['file1'])) + assert(not os.path.exists(sbox.ospath('file1'))) + + run_and_verify_revert(sbox.ospaths(['.']), ['--remove-added', '-R'], + sbox.ospaths(['D2/file', 'D2', 'file2'])) + assert(not os.path.exists(sbox.ospath('file2'))) + assert(not os.path.exists(sbox.ospath('D2'))) + ######################################################################## # Run the tests @@ -1680,6 +1655,7 @@ test_list = [ None, revert_nonexistent, revert_obstructing_wc, revert_moved_dir_partial, + revert_remove_added, ] if __name__ == '__main__': Modified: subversion/branches/addremove/subversion/tests/cmdline/special_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/special_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/special_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/special_tests.py Sat May 23 14:16:56 2020 @@ -535,7 +535,7 @@ def diff_symlink_to_dir(sbox): "+++ link\t(working copy)\n", "@@ -0,0 +1 @@\n", "+link A/D\n", - "\ No newline at end of file\n", + "\\ No newline at end of file\n", "\n", "Property changes on: link\n", "___________________________________________________________________\n", @@ -730,7 +730,8 @@ def unrelated_changed_special_status(sbo os.chdir(os.path.join(sbox.wc_dir, 'A/D/H')) - open('chi', 'a').write('random local mod') + with open('chi', 'a') as f: + f.write('random local mod') os.unlink('psi') os.symlink('omega', 'psi') # omega is versioned! svntest.main.run_svn(None, 'changelist', 'chi cl', 'chi') Modified: subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/stat_tests.py Sat May 23 14:16:56 2020 @@ -1606,7 +1606,7 @@ def status_dash_u_deleted_directories(sb os.path.join("B", "E", "alpha"), "D 1 1 jrandom %s\n" % \ os.path.join("B", "E", "beta"), - "D 1 1 jrandom %s\n" % + "D 1 1 jrandom %s\n" % os.path.join("B", "F"), "Status against revision: 1\n" ]) svntest.actions.run_and_verify_svn(expected, @@ -1949,7 +1949,8 @@ def modified_modulo_translation(sbox): sbox.simple_commit() # CRLF it. - open(sbox.ospath('iota'), 'wb').write("This is the file 'iota'.\r\n") + with open(sbox.ospath('iota'), 'wb') as f: + f.write("This is the file 'iota'.\r\n") # Run status. Expect some output. # TODO: decide how such files should show in the output; whether they Modified: subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py?rev=1878061&r1=1878060&r2=1878061&view=diff ============================================================================== --- subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py (original) +++ subversion/branches/addremove/subversion/tests/cmdline/svnadmin_tests.py Sat May 23 14:16:56 2020 @@ -53,6 +53,24 @@ Wimp = svntest.testcase.Wimp_deco SkipDumpLoadCrossCheck = svntest.testcase.SkipDumpLoadCrossCheck_deco Item = svntest.wc.StateItem +def read_rep_cache(repo_dir): + """Return the rep-cache contents as a dict {hash: (rev, index, ...)}. + """ + db_path = os.path.join(repo_dir, 'db', 'rep-cache.db') + db1 = svntest.sqlite3.connect(db_path) + schema1 = db1.execute("pragma user_version").fetchone()[0] + # Can't test newer rep-cache schemas with an old built-in SQLite; see the + # documentation of STMT_CREATE_SCHEMA_V2 in ../../libsvn_fs_fs/rep-cache-db.sql + if schema1 >= 2 and svntest.sqlite3.sqlite_version_info < (3, 8, 2): + raise svntest.Failure("Can't read rep-cache schema %d using old " + "Python-SQLite version %s < (3,8,2)" % + (schema1, + svntest.sqlite3.sqlite_version_info)) + + content = { row[0]: row[1:] for row in + db1.execute("select * from rep_cache") } + return content + def check_hotcopy_bdb(src, dst): "Verify that the SRC BDB repository has been correctly copied to DST." ### TODO: This function should be extended to verify all hotcopied files, @@ -129,6 +147,15 @@ def check_hotcopy_fsfs_fsx(src, dst): if src_file == 'rep-cache.db': db1 = svntest.sqlite3.connect(src_path) db2 = svntest.sqlite3.connect(dst_path) + schema1 = db1.execute("pragma user_version").fetchone()[0] + schema2 = db2.execute("pragma user_version").fetchone()[0] + if schema1 != schema2: + raise svntest.Failure("rep-cache schema differs: '%s' vs. '%s'" + % (schema1, schema2)) + # Can't test newer rep-cache schemas with an old built-in SQLite. + if schema1 >= 2 and svntest.sqlite3.sqlite_version_info < (3, 8, 2): + continue + rows1 = [] rows2 = [] for row in db1.execute("select * from rep_cache order by hash"): @@ -247,7 +274,8 @@ def patch_format(repo_dir, shard_size): new_contents = b"\n".join(processed_lines) os.chmod(format_path, svntest.main.S_ALL_RW) - open(format_path, 'wb').write(new_contents) + with open(format_path, 'wb') as f: + f.write(new_contents) def is_sharded(repo_dir): """Return whether the FSFS repository REPO_DIR is sharded.""" @@ -746,7 +774,7 @@ def verify_windows_paths_in_repos(sbox): "* Verified revision 0.\n", "* Verified revision 1.\n", "* Verified revision 2.\n"], output) - elif svntest.main.fs_has_rep_sharing(): + elif svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb(): svntest.verify.compare_and_display_lines( "Error while running 'svnadmin verify'.", 'STDOUT', ["* Verifying repository metadata ...\n", @@ -768,9 +796,13 @@ def verify_windows_paths_in_repos(sbox): def fsfs_file(repo_dir, kind, rev): if svntest.main.options.server_minor_version >= 5: if svntest.main.options.fsfs_sharding is None: + if svntest.main.is_fs_type_fsx(): + rev = 'r' + rev return os.path.join(repo_dir, 'db', kind, '0', rev) else: shard = int(rev) // svntest.main.options.fsfs_sharding + if svntest.main.is_fs_type_fsx(): + rev = 'r' + rev path = os.path.join(repo_dir, 'db', kind, str(shard), rev) if svntest.main.options.fsfs_packing is None or kind == 'revprops': @@ -790,6 +822,10 @@ def fsfs_file(repo_dir, kind, rev): def verify_incremental_fsfs(sbox): """svnadmin verify detects corruption dump can't""" + if svntest.main.options.fsfs_version is not None and \ + svntest.main.options.fsfs_version not in [4, 6]: + raise svntest.Skip("Unsupported prepackaged repository version") + # setup a repo with a directory 'c:hi' # use physical addressing as this is hard to provoke with logical addressing sbox.build(create_wc = False, @@ -807,7 +843,7 @@ def verify_incremental_fsfs(sbox): # the listing itself is valid. r2 = fsfs_file(sbox.repo_dir, 'revs', '2') if r2.endswith('pack'): - raise svntest.Skip('Test doesn\'t handle packed revisions') + raise svntest.Skip("Test doesn't handle packed revisions") fp = open(r2, 'wb') fp.write(b"""id: 0-2.0.r2/0 @@ -1030,7 +1066,7 @@ def fsfs_recover_old_db_current(sbox): def load_with_parent_dir(sbox): "'svnadmin load --parent-dir' reparents mergeinfo" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2983. ## + ## See https://issues.apache.org/jira/browse/SVN-2983. ## sbox.build(empty=True) dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]), @@ -1121,7 +1157,7 @@ def set_uuid(sbox): def reflect_dropped_renumbered_revs(sbox): "reflect dropped renumbered revs in svn:mergeinfo" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3020. ## + ## See https://issues.apache.org/jira/browse/SVN-3020. ## sbox.build(empty=True) @@ -1313,7 +1349,7 @@ def verify_with_invalid_revprops(sbox): # 2) Dump 'SOURCE-REPOS' in a series of incremental dumps and load # each of them to 'TARGET-REPOS'. # -# See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc13 +# See https://issues.apache.org/jira/browse/SVN-3020#desc13 @Issue(3020) def dont_drop_valid_mergeinfo_during_incremental_loads(sbox): "don't filter mergeinfo revs from incremental dump" @@ -1499,7 +1535,7 @@ def dont_drop_valid_mergeinfo_during_inc # Check the resulting mergeinfo. We expect the exact same results # as Part 3. - # See http://subversion.tigris.org/issues/show_bug.cgi?id=3020#desc16. + # See https://issues.apache.org/jira/browse/SVN-3020#desc16. svntest.actions.run_and_verify_svn(expected_output, [], 'propget', 'svn:mergeinfo', '-R', sbox.repo_url) @@ -1510,7 +1546,7 @@ def dont_drop_valid_mergeinfo_during_inc def hotcopy_symlink(sbox): "'svnadmin hotcopy' replicates symlink" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=2591. ## + ## See https://issues.apache.org/jira/browse/SVN-2591. ## # Create a repository. sbox.build(create_wc=False, empty=True) @@ -1616,9 +1652,9 @@ text sbox.build(empty=True) # Try to load the dumpstream, expecting a failure (because of mixed EOLs). - exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005', - 'svnadmin: E125005', - 'svnadmin: E125017'], + exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005:.*', + 'svnadmin: E125005:.*', + 'svnadmin: E125017:.*'], match_all=False) load_and_verify_dumpstream(sbox, [], exp_err, dumpfile_revisions, False, dump_str, '--ignore-uuid') @@ -1654,6 +1690,10 @@ text def verify_non_utf8_paths(sbox): "svnadmin verify with non-UTF-8 paths" + if svntest.main.options.fsfs_version is not None and \ + svntest.main.options.fsfs_version not in [4, 6]: + raise svntest.Skip("Unsupported prepackaged repository version") + dumpfile = clean_dumpfile() # Corruption only possible in physically addressed revisions created @@ -1682,14 +1722,11 @@ def verify_non_utf8_paths(sbox): elif line == b"text: 1 340 44 32 a6be7b4cf075fd39e6a99eb69a31232b\n": # phys, deltified directories: fix up the representation checksum fp_new.write(b"text: 1 340 44 32 f2e93e73272cac0f18fccf16f224eb93\n") - elif line == b"text: 1 6 31 31 90f306aa9bfd72f456072076a2bd94f7\n": - # log addressing: fix up the representation checksum - fp_new.write(b"text: 1 6 31 31 db2d4a0bad5dff0aea9a288dec02f1fb\n") elif line == b"cpath: /A\n": # also fix up the 'created path' field fp_new.write(b"cpath: /\xE6\n") elif line == b"_0.0.t0-0 add-file true true /A\n": - # and another occurrance + # and another occurrence fp_new.write(b"_0.0.t0-0 add-file true true /\xE6\n") else: fp_new.write(line) @@ -1746,10 +1783,10 @@ def test_lslocks_and_rmlocks(sbox): def expected_output_list(path): return [ "Path: " + path, - "UUID Token: opaquelocktoken", + "UUID Token: opaquelocktoken:.*", "Owner: jrandom", - "Created:", - "Expires:", + "Created:.*", + "Expires:.*", "Comment \(1 line\):", "Locking files", "\n", # empty line @@ -1800,7 +1837,7 @@ def test_lslocks_and_rmlocks(sbox): def load_ranges(sbox): "'svnadmin load --revision X:Y'" - ## See http://subversion.tigris.org/issues/show_bug.cgi?id=3734. ## + ## See https://issues.apache.org/jira/browse/SVN-3734. ## sbox.build(empty=True) dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]), @@ -2151,7 +2188,7 @@ def verify_keep_going(sbox): sbox.repo_dir) if (svntest.main.is_fs_log_addressing()): - exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at revision 0"]) + exp_out = svntest.verify.RegexListOutput([".*Verifying metadata at revision 0.*"]) else: exp_out = svntest.verify.RegexListOutput([".*Verified revision 0.", ".*Verified revision 1."]) @@ -2520,7 +2557,7 @@ def verify_denormalized_names(sbox): ".*Verified revision 7."] # The BDB backend doesn't do global metadata verification. - if (svntest.main.fs_has_rep_sharing()): + if (svntest.main.fs_has_rep_sharing() and not svntest.main.is_fs_type_bdb()): expected_output_regex_list.insert(0, ".*Verifying repository metadata.*") if svntest.main.options.fsfs_sharding is not None: @@ -2842,10 +2879,7 @@ def verify_quickly(sbox): "verify quickly using metadata" sbox.build(create_wc = False) - if svntest.main.is_fs_type_fsfs(): - rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b') - else: - rev_file = open(fsfs_file(sbox.repo_dir, 'revs', 'r1'), 'r+b') + rev_file = open(fsfs_file(sbox.repo_dir, 'revs', '1'), 'r+b') # set new contents rev_file.seek(8) @@ -3143,7 +3177,7 @@ def load_txdelta(sbox): sbox.build(empty=True) - # This dumpfile produced a BDB repository that generated cheksum + # This dumpfile produced a BDB repository that generated checksum # mismatches on read caused by the improper handling of # svn_txdelta_target ops. The bug was fixed by r1640832. @@ -3186,7 +3220,7 @@ def load_no_svndate_r0(sbox): b"Content-length: 10\n", b"\n", b"PROPS-END\n", b"\n"] svntest.actions.run_and_verify_load(sbox.repo_dir, dump_old) - + # svn:date should have been removed svntest.actions.run_and_verify_svnlook([], [], 'proplist', '--revprop', '-r0', @@ -3351,6 +3385,7 @@ def dump_no_op_change(sbox): sbox2.repo_url + '/bar') @XFail(svntest.main.is_fs_type_bdb) +@XFail(svntest.main.is_fs_type_fsx) @Issue(4623) def dump_no_op_prop_change(sbox): "svnadmin dump with no-op property change" @@ -3443,7 +3478,8 @@ def load_from_file(sbox): sbox.build(empty=True) file = sbox.get_tempname() - open(file, 'wb').writelines(clean_dumpfile()) + with open(file, 'wb') as f: + f.writelines(clean_dumpfile()) svntest.actions.run_and_verify_svnadmin2(None, [], 0, 'load', '--file', file, '--ignore-uuid', sbox.repo_dir) @@ -3747,7 +3783,7 @@ def dump_exclude_all_rev_changes(sbox): # Check log. Revision properties ('svn:log' etc.) should be empty for r2. expected_output = svntest.verify.RegexListOutput([ '-+\\n', - 'r3\ |\ jrandom\ |\ .*\ |\ 1\ line\\n', + 'r3 | jrandom | .* | 1 line\\n', re.escape('Changed paths:'), re.escape(' A /r3a'), re.escape(' A /r3b'), @@ -3759,7 +3795,7 @@ def dump_exclude_all_rev_changes(sbox): '', '', '-+\\n', - 'r1\ |\ jrandom\ |\ .*\ |\ 1\ line\\n', + 'r1 | jrandom | .* | 1 line\\n', re.escape('Changed paths:'), re.escape(' A /r1a'), re.escape(' A /r1b'), @@ -3786,6 +3822,243 @@ def dump_invalid_filtering_option(sbox): '--include', '/A/B/E', sbox.repo_dir) +@Issue(4725) +def load_issue4725(sbox): + """load that triggers issue 4725""" + + sbox.build(empty=True) + + sbox.simple_mkdir('subversion') + sbox.simple_commit() + sbox.simple_mkdir('subversion/trunk') + sbox.simple_mkdir('subversion/branches') + sbox.simple_commit() + sbox.simple_mkdir('subversion/trunk/src') + sbox.simple_commit() + + _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [], + 'dump', '-q', + sbox.repo_dir) + + sbox2 = sbox.clone_dependent() + sbox2.build(create_wc=False, empty=True) + load_and_verify_dumpstream(sbox2, None, [], None, False, dump, '-M100') + +@Issue(4767) +def dump_no_canonicalize_svndate(sbox): + "svnadmin dump shouldn't canonicalize svn:date" + + sbox.build(create_wc=False, empty=True) + svntest.actions.enable_revprop_changes(sbox.repo_dir) + + # set svn:date in a non-canonical format (not six decimal places) + propval = "2015-01-01T00:00:00.0Z" + svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], + "propset", "--revprop", "-r0", "svn:date", + propval, + sbox.repo_url) + + dump_lines = svntest.actions.run_and_verify_dump(sbox.repo_dir) + assert propval.encode() + b'\n' in dump_lines + +def check_recover_prunes_rep_cache(sbox, enable_rep_sharing): + """Check 'recover' prunes the rep-cache while enable-rep-sharing is + true/false. + """ + # Remember the initial rep cache content. + rep_cache_r1 = read_rep_cache(sbox.repo_dir) + #print '\n'.join([h + ": " + repr(ref) for h, ref in rep_cache_r1.items()]) + + # Commit one new rep and check the rep-cache is extended. + sbox.simple_append('iota', 'New line.\n') + sbox.simple_commit() + rep_cache_r2 = read_rep_cache(sbox.repo_dir) + if not (len(rep_cache_r2) == len(rep_cache_r1) + 1): + raise svntest.Failure + + fsfs_conf = svntest.main.get_fsfs_conf_file_path(sbox.repo_dir) + svntest.main.file_append(fsfs_conf, + # Add a newline in case the existing file doesn't + # end with one. + "\n" + "[rep-sharing]\n" + "enable-rep-sharing = %s\n" + % (('true' if enable_rep_sharing else 'false'),)) + + # Break r2 in such a way that 'recover' will discard it + head_rev_path = fsfs_file(sbox.repo_dir, 'revs', '2') + os.remove(head_rev_path) + current_path = os.path.join(sbox.repo_dir, 'db', 'current') + svntest.main.file_write(current_path, '1\n') + + # Recover back to r1. + svntest.actions.run_and_verify_svnadmin(None, [], + "recover", sbox.repo_dir) + svntest.actions.run_and_verify_svnlook(['1\n'], [], 'youngest', + sbox.repo_dir) + + # Check the rep-cache is pruned. + rep_cache_recovered = read_rep_cache(sbox.repo_dir) + if not (rep_cache_recovered == rep_cache_r1): + raise svntest.Failure + +@Issue(4077) +@SkipUnless(svntest.main.is_fs_type_fsfs) +@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid) +def recover_prunes_rep_cache_when_enabled(sbox): + "recover prunes rep cache when enabled" + sbox.build() + + check_recover_prunes_rep_cache(sbox, enable_rep_sharing=True) + +@Issue(4077) +@SkipUnless(svntest.main.is_fs_type_fsfs) +@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid) +def recover_prunes_rep_cache_when_disabled(sbox): + "recover prunes rep cache when disabled" + sbox.build() + + check_recover_prunes_rep_cache(sbox, enable_rep_sharing=False) + +@Issue(4760) +def dump_include_copied_directory(sbox): + "include copied directory with nested nodes" + + sbox.build(create_wc=False) + + svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "copy", + sbox.repo_url + '/A/D', + sbox.repo_url + '/COPY', + "-m", "Create branch.") + + # Dump repository with only /COPY path included. + _, dump, _ = svntest.actions.run_and_verify_svnadmin(None, [], + 'dump', '-q', + '--include', '/COPY', + sbox.repo_dir) + + # Load repository from dump. + sbox2 = sbox.clone_dependent() + sbox2.build(create_wc=False, empty=True) + load_and_verify_dumpstream(sbox2, None, [], None, False, dump) + + # Check log. + expected_output = svntest.verify.RegexListOutput([ + '-+\\n', + 'r2\ .*\n', + # Only '/COPY' is added + re.escape('Changed paths:\n'), + re.escape(' A /COPY'), + re.escape(' A /COPY/G'), + re.escape(' A /COPY/G/pi'), + re.escape(' A /COPY/G/rho'), + re.escape(' A /COPY/G/tau'), + re.escape(' A /COPY/H'), + re.escape(' A /COPY/H/chi'), + re.escape(' A /COPY/H/omega'), + re.escape(' A /COPY/H/psi'), + re.escape(' A /COPY/gamma'), + '-+\\n', + 'r1\ .*\n', + '-+\\n' + ]) + svntest.actions.run_and_verify_svn(expected_output, [], + 'log', '-v', '-q', sbox2.repo_url) + +def load_normalize_node_props(sbox): + "svnadmin load --normalize node props" + + dump_str = b"""SVN-fs-dump-format-version: 2 + +UUID: dc40867b-38f6-0310-9f5f-f81aa277e06f + +Revision-number: 0 +Prop-content-length: 56 +Content-length: 56 + +K 8 +svn:date +V 27 +2005-05-03T19:09:41.129900Z +PROPS-END + +Revision-number: 1 +Prop-content-length: 99 +Content-length: 99 + +K 7 +svn:log +V 0 + +K 10 +svn:author +V 2 +pl +K 8 +svn:date +V 27 +2005-05-03T19:10:19.975578Z +PROPS-END + +Node-path:\x20 +Node-kind: dir +Node-action: change +Prop-content-length: 32 +Content-length: 32 + +K 10 +svn:ignore +V 3 +\n\r\n +PROPS-END + + +""" + sbox.build(empty=True) + + # Try to load the dumpstream, expecting a failure (because of mixed + # EOLs in the svn:ignore property value). + exp_err = svntest.verify.RegexListOutput(['svnadmin: E125005:.*', + 'svnadmin: E125017:.*'], + match_all=False) + load_and_verify_dumpstream(sbox, [], exp_err, dumpfile_revisions, + False, dump_str, '--ignore-uuid') + + # Now try it again with prop normalization. + svntest.actions.load_repo(sbox, dump_str=dump_str, + bypass_prop_validation=False, + normalize_props=True) + # We should get the normalized property value. + exit_code, output, _ = svntest.main.run_svn(None, 'pg', 'svn:ignore', + '--no-newline', + sbox.repo_url) + svntest.verify.verify_exit_code(None, exit_code, 0) + if output != ['\n', '\n']: + raise svntest.Failure("Unexpected property value %s" % output) + +@SkipUnless(svntest.main.is_fs_type_fsfs) +@SkipUnless(svntest.main.fs_has_rep_sharing) +@SkipUnless(svntest.main.python_sqlite_can_read_without_rowid) +def build_repcache(sbox): + "svnadmin build-repcache" + + sbox.build(create_wc = False) + + # Remember and remove the existing rep-cache. + rep_cache = read_rep_cache(sbox.repo_dir) + rep_cache_path = os.path.join(sbox.repo_dir, 'db', 'rep-cache.db') + os.remove(rep_cache_path) + + # Build a new rep-cache and compare with the original one. + expected_output = ["* Processed revision 1.\n"] + svntest.actions.run_and_verify_svnadmin(expected_output, [], + "build-repcache", sbox.repo_dir) + + new_rep_cache = read_rep_cache(sbox.repo_dir) + if new_rep_cache != rep_cache: + raise svntest.Failure + + ######################################################################## # Run the tests @@ -3858,7 +4131,14 @@ test_list = [ None, dump_exclude_by_pattern, dump_include_by_pattern, dump_exclude_all_rev_changes, - dump_invalid_filtering_option + dump_invalid_filtering_option, + load_issue4725, + dump_no_canonicalize_svndate, + recover_prunes_rep_cache_when_enabled, + recover_prunes_rep_cache_when_disabled, + dump_include_copied_directory, + load_normalize_node_props, + build_repcache, ] if __name__ == '__main__':