| #!/usr/bin/env python |
| # |
| # copy_tests.py: testing the many uses of 'svn cp' and 'svn mv' |
| # |
| # Subversion is a tool for revision control. |
| # See https://subversion.apache.org for more information. |
| # |
| # ==================================================================== |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| ###################################################################### |
| |
| # General modules |
| import stat, os, re, shutil, logging |
| |
| logger = logging.getLogger() |
| |
| # Our testing module |
| import svntest |
| from svntest import main |
| from svntest.main import ( |
| SVN_PROP_MERGEINFO, |
| file_append, |
| file_write, |
| make_log_msg, |
| run_svn, |
| ) |
| |
| # (abbreviation) |
| Skip = svntest.testcase.Skip_deco |
| SkipUnless = svntest.testcase.SkipUnless_deco |
| XFail = svntest.testcase.XFail_deco |
| Issues = svntest.testcase.Issues_deco |
| Issue = svntest.testcase.Issue_deco |
| Wimp = svntest.testcase.Wimp_deco |
| Item = svntest.wc.StateItem |
| exp_noop_up_out = svntest.actions.expected_noop_update_output |
| |
| # |
| #---------------------------------------------------------------------- |
| # Helper for wc_copy_replacement and repos_to_wc_copy_replacement |
| def copy_replace(sbox, wc_copy): |
| """Tests for 'R'eplace functionanity for files. |
| |
| Depending on the value of wc_copy either a working copy (when true) |
| or a url (when false) copy source is used.""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # File scheduled for deletion |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', rho_path) |
| |
| # Status before attempting copies |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/rho', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # The copy shouldn't fail |
| if wc_copy: |
| pi_src = sbox.ospath('A/D/G/pi') |
| else: |
| pi_src = sbox.repo_url + '/A/D/G/pi' |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', pi_src, rho_path) |
| |
| # Now commit |
| expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-') |
| 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 = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho': Item(verb='Replacing'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Helper for wc_copy_replace_with_props and |
| # repos_to_wc_copy_replace_with_props |
| def copy_replace_with_props(sbox, wc_copy): |
| """Tests for 'R'eplace functionanity for files with props. |
| |
| Depending on the value of wc_copy either a working copy (when true) or |
| a url (when false) copy source is used.""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Use a temp file to set properties with wildcards in their values |
| # otherwise Win32/VS2005 will expand them |
| prop_path = sbox.ospath('proptmp') |
| svntest.main.file_append(prop_path, '*') |
| |
| # Set props on file which is copy-source later on |
| pi_path = sbox.ospath('A/D/G/pi') |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ps', 'phony-prop', '-F', |
| prop_path, pi_path) |
| os.remove(prop_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ps', 'svn:eol-style', 'LF', rho_path) |
| |
| # Verify props having been set |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/D/G/pi', |
| props={ 'phony-prop': '*' }) |
| expected_disk.tweak('A/D/G/rho', |
| props={ 'svn:eol-style': 'LF' }) |
| |
| svntest.actions.verify_disk(wc_dir, expected_disk, True) |
| |
| # Commit props |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/pi': Item(verb='Sending'), |
| 'A/D/G/rho': Item(verb='Sending'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/pi', wc_rev='2') |
| expected_status.tweak('A/D/G/rho', wc_rev='2') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Bring wc into sync |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| |
| # File scheduled for deletion |
| svntest.actions.run_and_verify_svn(None, [], 'rm', rho_path) |
| |
| # Status before attempting copies |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.tweak('A/D/G/rho', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # The copy shouldn't fail |
| if wc_copy: |
| pi_src = sbox.ospath('A/D/G/pi') |
| else: |
| pi_src = sbox.repo_url + '/A/D/G/pi' |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', pi_src, rho_path) |
| |
| # Verify both content and props have been copied |
| if wc_copy: |
| props = { 'phony-prop' : '*'} |
| else: |
| props = { 'phony-prop' : '*'} |
| |
| expected_disk.tweak('A/D/G/rho', |
| contents="This is the file 'pi'.\n", |
| props=props) |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| # Now commit and verify |
| expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_status.tweak('A/D/G/rho', status=' ', copied=None, |
| wc_rev='3') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho': Item(verb='Replacing'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| ###################################################################### |
| # Tests |
| # |
| # Each test must return on success or raise on failure. |
| |
| # (Taken from notes/copy-planz.txt:) |
| # |
| # We have four use cases for 'svn cp' now. |
| # |
| # A. svn cp wc_path1 wc_path2 |
| # |
| # This duplicates a path in the working copy, and schedules it |
| # for addition with history. |
| # |
| # B. svn cp URL [-r rev] wc_path |
| # |
| # This "checks out" URL (in REV) into the working copy at |
| # wc_path, integrates it, and schedules it for addition with |
| # history. |
| # |
| # C. svn cp wc_path URL |
| # |
| # This immediately commits wc_path to URL on the server; the |
| # commit will be an addition with history. The commit will not |
| # change the working copy at all. |
| # |
| # D. svn cp URL1 [-r rev] URL2 |
| # |
| # This causes a server-side copy to happen immediately; no |
| # working copy is required. |
| |
| |
| |
| # TESTS THAT NEED TO BE WRITTEN |
| # |
| # Use Cases A & C |
| # |
| # -- single files, with/without local mods, as both 'cp' and 'mv'. |
| # (need to verify commit worked by updating a 2nd working copy |
| # to see the local mods) |
| # |
| # -- dir copy, has mixed revisions |
| # |
| # -- dir copy, has local mods (an edit, an add, a delete, and a replace) |
| # |
| # -- dir copy, has mixed revisions AND local mods |
| # |
| # -- dir copy, has mixed revisions AND another previously-made copy! |
| # (perhaps done as two nested 'mv' commands!) |
| # |
| # Use Case D |
| # |
| |
| # By the time the copy setup algorithm is complete, the copy |
| # operation will have four parts: SRC-DIR, SRC-BASENAME, DST-DIR, |
| # DST-BASENAME. In all cases, SRC-DIR/SRC-BASENAME and DST_DIR must |
| # already exist before the operation, but DST_DIR/DST_BASENAME must |
| # NOT exist. |
| # |
| # Besides testing things that don't meet the above criteria, we want to |
| # also test valid cases: |
| # |
| # - where SRC-DIR/SRC-BASENAME is a file or a dir. |
| # - where SRC-DIR (or SRC-DIR/SRC-BASENAME) is a parent/grandparent |
| # directory of DST-DIR |
| # - where SRC-DIR (or SRC-DIR/SRC-BASENAME) is a child/grandchild |
| # directory of DST-DIR |
| # - where SRC-DIR (or SRC-DIR/SRC-BASENAME) is not in the lineage |
| # of DST-DIR at all |
| |
| |
| |
| #---------------------------------------------------------------------- |
| @Issue(1091) |
| def basic_copy_and_move_files(sbox): |
| "basic copy and move commands -- on files only" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| mu_path = sbox.ospath('A/mu') |
| iota_path = sbox.ospath('iota') |
| rho_path = sbox.ospath('A/D/G/rho') |
| D_path = sbox.ospath('A/D') |
| alpha_path = sbox.ospath('A/B/E/alpha') |
| H_path = sbox.ospath('A/D/H') |
| F_path = sbox.ospath('A/B/F') |
| alpha2_path = sbox.ospath('A/C/alpha2') |
| |
| # Make local mods to mu and rho |
| svntest.main.file_append(mu_path, 'appended mu text') |
| svntest.main.file_append(rho_path, 'new appended text for rho') |
| |
| # Copy rho to D -- local mods |
| svntest.actions.run_and_verify_svn(None, [], 'cp', rho_path, D_path) |
| |
| # Copy alpha to C -- no local mods, and rename it to 'alpha2' also |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| alpha_path, alpha2_path) |
| |
| # Move mu to H -- local mods |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| mu_path, H_path) |
| |
| # Move iota to F -- no local mods |
| svntest.actions.run_and_verify_svn(None, [], 'mv', iota_path, F_path) |
| |
| # Created expected output tree for 'svn ci': |
| # We should see four adds, two deletes, and one change in total. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho' : Item(verb='Sending'), |
| 'A/D/rho' : Item(verb='Adding'), |
| 'A/C/alpha2' : Item(verb='Adding'), |
| 'A/D/H/mu' : Item(verb='Adding'), |
| 'A/B/F/iota' : Item(verb='Adding'), |
| 'A/mu' : Item(verb='Deleting'), |
| 'iota' : Item(verb='Deleting'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but several files should be at revision 2. Also, two files should |
| # be missing. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/rho', 'A/mu', wc_rev=2) |
| |
| expected_status.add({ |
| 'A/D/rho' : Item(status=' ', wc_rev=2), |
| 'A/C/alpha2' : Item(status=' ', wc_rev=2), |
| 'A/D/H/mu' : Item(status=' ', wc_rev=2), |
| 'A/B/F/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/mu', 'iota') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Issue 1091, alpha2 would now have the wrong checksum and so a |
| # subsequent commit would fail |
| svntest.main.file_append(alpha2_path, 'appended alpha2 text') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/alpha2' : Item(verb='Sending'), |
| }) |
| expected_status.tweak('A/C/alpha2', wc_rev=3) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Assure that attempts at local copy and move fail when a log |
| # message is provided. |
| expected_stderr = \ |
| ".*Local, non-commit operations do not take a log message" |
| svntest.actions.run_and_verify_svn(None, expected_stderr, |
| 'cp', '-m', 'op fails', rho_path, D_path) |
| svntest.actions.run_and_verify_svn(None, expected_stderr, |
| 'mv', '-m', 'op fails', rho_path, D_path) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # This test passes over ra_local certainly; we're adding it because at |
| # one time it failed over ra_neon. Specifically, it failed when |
| # mod_dav_svn first started sending vsn-rsc-urls as "CR/path", and was |
| # sending bogus CR/paths for items within copied subtrees. |
| |
| def receive_copy_in_update(sbox): |
| "receive a copied directory during update" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Make a backup copy of the working copy. |
| wc_backup = sbox.add_wc_path('backup') |
| svntest.actions.duplicate_dir(wc_dir, wc_backup) |
| |
| # Define a zillion paths in both working copies. |
| G_path = sbox.ospath('A/D/G') |
| newG_path = sbox.ospath('A/B/newG') |
| |
| # Copy directory A/D to A/B/newG |
| svntest.actions.run_and_verify_svn(None, [], 'cp', G_path, newG_path) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/newG' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/newG' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/tau' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Now update the other working copy; it should receive a full add of |
| # the newG directory and its contents. |
| |
| # Expected output of update |
| expected_output = svntest.wc.State(wc_backup, { |
| 'A/B/newG' : Item(status='A '), |
| 'A/B/newG/pi' : Item(status='A '), |
| 'A/B/newG/rho' : Item(status='A '), |
| 'A/B/newG/tau' : Item(status='A '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/B/newG' : Item(), |
| 'A/B/newG/pi' : Item("This is the file 'pi'.\n"), |
| 'A/B/newG/rho' : Item("This is the file 'rho'.\n"), |
| 'A/B/newG/tau' : Item("This is the file 'tau'.\n"), |
| }) |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(wc_backup, 2) |
| expected_status.add({ |
| 'A/B/newG' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/newG/tau' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Do the update and check the results in three ways. |
| svntest.actions.run_and_verify_update(wc_backup, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Regression test for issue #683. In particular, this bug prevented |
| # us from running 'svn cp -r N src_URL dst_URL' as a means of |
| # resurrecting a deleted directory. Also, the final 'update' at the |
| # end of this test was uncovering a ghudson 'deleted' edge-case bug. |
| # (In particular, re-adding G to D, when D already had a 'deleted' |
| # entry for G. The entry-merge wasn't overwriting the 'deleted' |
| # attribute, and thus the newly-added G was ending up disconnected |
| # from D.) |
| @Issue(683) |
| def resurrect_deleted_dir(sbox): |
| "resurrect a deleted directory" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| G_path = sbox.ospath('A/D/G') |
| |
| # Delete directory A/D/G, commit that as r2. |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--force', |
| G_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G' : Item(verb='Deleting'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/D/G') |
| expected_status.remove('A/D/G/pi') |
| expected_status.remove('A/D/G/rho') |
| expected_status.remove('A/D/G/tau') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Use 'svn cp URL@1 URL' to resurrect the deleted directory, where |
| # the two URLs are identical. This used to trigger a failure. |
| url = sbox.repo_url + '/A/D/G' |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| url + '@1', url, |
| '-m', 'logmsg') |
| |
| # For completeness' sake, update to HEAD, and verify we have a full |
| # greek tree again, all at revision 3. |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G' : Item(status='A '), |
| 'A/D/G/pi' : Item(status='A '), |
| 'A/D/G/rho' : Item(status='A '), |
| 'A/D/G/tau' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| def copy_deleted_dir_into_prefix(sbox): |
| "copy a deleted dir to a prefix of its old path" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| D_path = sbox.ospath('A/D') |
| |
| # Delete directory A/D, commit that as r2. |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--force', |
| D_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D' : Item(verb='Deleting'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| None) |
| |
| # Ok, copy from a deleted URL into a prefix of that URL, this used to |
| # result in an assert failing. |
| url1 = sbox.repo_url + '/A/D/G' |
| url2 = sbox.repo_url + '/A/D' |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| url1 + '@1', url2, |
| '-m', 'logmsg') |
| |
| #---------------------------------------------------------------------- |
| |
| # Test that we're enforcing proper 'svn cp' overwrite behavior. Note |
| # that svn_fs_copy() will always overwrite its destination if an entry |
| # by the same name already exists. However, libsvn_client should be |
| # doing existence checks to prevent directories from being |
| # overwritten, and files can't be overwritten because the RA layers |
| # are doing out-of-dateness checks during the commit. |
| |
| |
| def no_copy_overwrites(sbox): |
| "svn cp URL URL cannot overwrite destination" |
| |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| |
| fileURL1 = sbox.repo_url + "/A/B/E/alpha" |
| fileURL2 = sbox.repo_url + "/A/B/E/beta" |
| dirURL1 = sbox.repo_url + "/A/D/G" |
| dirURL2 = sbox.repo_url + "/A/D/H" |
| |
| # Expect out-of-date failure if 'svn cp URL URL' tries to overwrite a file |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'cp', fileURL1, fileURL2, |
| '-m', 'fooogle') |
| |
| # Create A/D/H/G by running 'svn cp ...A/D/G .../A/D/H' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', dirURL1, dirURL2, |
| '-m', 'fooogle') |
| |
| # Repeat the last command. It should *fail* because A/D/H/G already exists. |
| svntest.actions.run_and_verify_svn( |
| None, ".*E160020: Path.*/A/D/H/G' already exists.*", |
| 'cp', dirURL1, dirURL2, |
| '-m', 'fooogle') |
| |
| #---------------------------------------------------------------------- |
| |
| # Issue 845. WC -> WC copy should not overwrite base text-base |
| @Issue(845) |
| def no_wc_copy_overwrites(sbox): |
| "svn cp PATH PATH cannot overwrite destination" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # File simply missing |
| tau_path = sbox.ospath('A/D/G/tau') |
| os.remove(tau_path) |
| |
| # Status before attempting copies |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/tau', status='! ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # These copies should fail |
| pi_path = sbox.ospath('A/D/G/pi') |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'cp', pi_path, rho_path) |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'cp', pi_path, tau_path) |
| |
| # Status after failed copies should not have changed |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Takes out working-copy locks for A/B2 and child A/B2/E. At one stage |
| # during issue 749 the second lock cause an already-locked error. |
| @Issue(749) |
| def copy_modify_commit(sbox): |
| "copy a tree and modify before commit" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| B_path = sbox.ospath('A/B') |
| B2_path = sbox.ospath('A/B2') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| B_path, B2_path) |
| |
| alpha_path = sbox.ospath('A/B2/E/alpha') |
| svntest.main.file_append(alpha_path, "modified alpha") |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B2' : Item(verb='Adding'), |
| 'A/B2/E/alpha' : Item(verb='Sending'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| None) |
| |
| #---------------------------------------------------------------------- |
| |
| # Issue 591, at one point copying a file from URL to WC didn't copy |
| # properties. |
| @Issue(591) |
| def copy_files_with_properties(sbox): |
| "copy files with properties" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Set a property on a file |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'propset', 'pname', 'pval', rho_path) |
| |
| # and commit it |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/rho', status=' ', wc_rev=2) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status) |
| |
| # Set another property, but don't commit it yet |
| svntest.actions.run_and_verify_svn(None, [], |
| 'propset', 'pname2', 'pval2', rho_path) |
| |
| # WC to WC copy of file with committed and uncommitted properties |
| rho_wc_path = sbox.ospath('A/D/G/rho_wc') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', rho_path, rho_wc_path) |
| |
| # REPOS to WC copy of file with properties |
| rho_url_path = sbox.ospath('A/D/G/rho_url') |
| rho_url = sbox.repo_url + '/A/D/G/rho' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', rho_url, rho_url_path) |
| |
| # Properties are not visible in WC status 'A' |
| expected_status.add({ |
| 'A/D/G/rho' : Item(status=' M', wc_rev='2'), |
| 'A/D/G/rho_wc' : Item(status='A ', wc_rev='-', copied='+'), |
| 'A/D/G/rho_url' : Item(status='A ', wc_rev='-', copied='+'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Check properties explicitly |
| svntest.actions.run_and_verify_svn(['pval\n'], [], |
| 'propget', 'pname', rho_wc_path) |
| svntest.actions.run_and_verify_svn(['pval2\n'], [], |
| 'propget', 'pname2', rho_wc_path) |
| svntest.actions.run_and_verify_svn(['pval\n'], [], |
| 'propget', 'pname', rho_url_path) |
| |
| # Commit and properties are visible in status |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho' : Item(verb='Sending'), |
| 'A/D/G/rho_wc' : Item(verb='Adding'), |
| 'A/D/G/rho_url' : Item(verb='Adding'), |
| }) |
| expected_status.tweak('A/D/G/rho', status=' ', wc_rev=3) |
| expected_status.remove('A/D/G/rho_wc', 'A/D/G/rho_url') |
| expected_status.add({ |
| 'A/D/G/rho_wc' : Item(status=' ', wc_rev=3), |
| 'A/D/G/rho_url' : Item(status=' ', wc_rev=3), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Issue 918 |
| @Issue(918) |
| def copy_delete_commit(sbox): |
| "copy a tree and delete part of it before commit" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| B_path = sbox.ospath('A/B') |
| B2_path = sbox.ospath('A/B2') |
| |
| # copy a tree |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| B_path, B2_path) |
| |
| # delete two files |
| lambda_path = sbox.ospath('A/B2/lambda') |
| alpha_path = sbox.ospath('A/B2/E/alpha') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', alpha_path, lambda_path) |
| |
| # commit copied tree containing a deleted file |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B2' : Item(verb='Adding'), |
| 'A/B2/lambda' : Item(verb='Deleting'), |
| 'A/B2/E/alpha' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| None) |
| |
| # copy a tree |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('A/B'), |
| sbox.ospath('A/B3')) |
| |
| # delete a directory |
| E_path = sbox.ospath('A/B3/E') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', E_path) |
| |
| # commit copied tree containing a deleted directory |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B3' : Item(verb='Adding'), |
| 'A/B3/E' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| None) |
| |
| |
| #---------------------------------------------------------------------- |
| @Issues(931,932) |
| def mv_and_revert_directory(sbox): |
| "move and revert a directory" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| E_path = sbox.ospath('A/B/E') |
| F_path = sbox.ospath('A/B/F') |
| new_E_path = os.path.join(F_path, 'E') |
| |
| # Issue 931: move failed to lock the directory being deleted |
| svntest.actions.run_and_verify_svn(None, [], 'move', |
| E_path, F_path) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status='D ') |
| expected_status.tweak('A/B/E', status='D ', moved_to='A/B/F/E') |
| expected_status.add({ |
| 'A/B/F/E' : Item(status='A ', wc_rev='-', copied='+', |
| moved_from='A/B/E'), |
| 'A/B/F/E/alpha' : Item(status=' ', wc_rev='-', copied='+'), |
| 'A/B/F/E/beta' : Item(status=' ', wc_rev='-', copied='+'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Issue 932: revert failed to lock the parent directory |
| svntest.actions.run_and_verify_svn(None, [], 'revert', '--recursive', |
| new_E_path) |
| expected_status.remove('A/B/F/E', 'A/B/F/E/alpha', 'A/B/F/E/beta') |
| expected_status.tweak('A/B/E', moved_to=None) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue 982. When copying a file with the executable bit set, the copied |
| # file should also have its executable bit set. |
| @Issue(982) |
| @SkipUnless(svntest.main.is_posix_os) |
| def copy_preserve_executable_bit(sbox): |
| "executable bit should be preserved when copying" |
| |
| # Bootstrap |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create two paths |
| newpath1 = sbox.ospath('newfile1') |
| newpath2 = sbox.ospath('newfile2') |
| |
| # Create the first file. |
| svntest.main.file_append(newpath1, "a new file") |
| svntest.actions.run_and_verify_svn(None, [], 'add', newpath1) |
| |
| mode1 = os.stat(newpath1)[stat.ST_MODE] |
| |
| # Doing this to get the executable bit set on systems that support |
| # that -- the property itself is not the point. |
| svntest.actions.run_and_verify_svn(None, [], 'propset', |
| 'svn:executable', 'on', newpath1) |
| |
| mode2 = os.stat(newpath1)[stat.ST_MODE] |
| |
| if mode1 == mode2: |
| logger.warn("setting svn:executable did not change file's permissions") |
| raise svntest.Failure |
| |
| # Commit the file |
| svntest.actions.run_and_verify_svn(None, [], 'ci', |
| '-m', 'create file and set svn:executable', |
| wc_dir) |
| |
| # Copy the file |
| svntest.actions.run_and_verify_svn(None, [], 'cp', newpath1, newpath2) |
| |
| mode3 = os.stat(newpath2)[stat.ST_MODE] |
| |
| # The mode on the original and copied file should be identical |
| if mode2 != mode3: |
| logger.warn("permissions on the copied file are not identical to original file") |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| # Issue 1029, copy failed with a "working copy not locked" error |
| @Issue(1029) |
| def wc_to_repos(sbox): |
| "working-copy to repository copy" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| beta_path = sbox.ospath('A/B/E/beta') |
| beta2_url = sbox.repo_url + "/A/B/E/beta2" |
| H_path = sbox.ospath('A/D/H') |
| H2_url = sbox.repo_url + "/A/D/H2" |
| |
| # modify some items to be copied |
| svntest.main.file_append(sbox.ospath('A/D/H/omega'), |
| "new otext\n") |
| svntest.actions.run_and_verify_svn(None, [], 'propset', 'foo', 'bar', |
| beta_path) |
| |
| # copy a file |
| svntest.actions.run_and_verify_svn(None, [], '-m', 'fumble file', |
| 'copy', beta_path, beta2_url) |
| # and a directory |
| svntest.actions.run_and_verify_svn(None, [], '-m', 'fumble dir', |
| 'copy', H_path, H2_url) |
| # copy a file to a directory |
| svntest.actions.run_and_verify_svn(None, [], '-m', 'fumble file', |
| 'copy', beta_path, H2_url) |
| |
| # update the working copy. post-update mereinfo elision will remove |
| # A/D/H2/beta's mergeinfo, leaving a local mod. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E/beta2' : Item(status='A '), |
| 'A/D/H2' : Item(status='A '), |
| 'A/D/H2/chi' : Item(status='A '), |
| 'A/D/H2/omega' : Item(status='A '), |
| 'A/D/H2/psi' : Item(status='A '), |
| 'A/D/H2/beta' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/D/H/omega', |
| contents="This is the file 'omega'.\nnew otext\n") |
| expected_disk.add({ |
| 'A/B/E/beta2' : Item("This is the file 'beta'.\n"), |
| 'A/D/H2/chi' : Item("This is the file 'chi'.\n"), |
| 'A/D/H2/omega' : Item("This is the file 'omega'.\nnew otext\n"), |
| 'A/D/H2/psi' : Item("This is the file 'psi'.\n"), |
| 'A/D/H2/beta' : Item("This is the file 'beta'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 4) |
| expected_status.add({ |
| 'A/B/E/beta' : Item(status=' M', wc_rev=4), |
| 'A/D/H/omega' : Item(status='M ', wc_rev=4), |
| 'A/B/E/beta2' : Item(status=' ', wc_rev=4), |
| 'A/D/H2' : Item(status=' ', wc_rev=4), |
| 'A/D/H2/chi' : Item(status=' ', wc_rev=4), |
| 'A/D/H2/omega' : Item(status=' ', wc_rev=4), |
| 'A/D/H2/psi' : Item(status=' ', wc_rev=4), |
| 'A/D/H2/beta' : Item(status=' ', wc_rev=4), |
| }) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # check local property was copied |
| svntest.actions.run_and_verify_svn(['bar\n'], [], |
| 'propget', 'foo', |
| beta_path + "2") |
| |
| #---------------------------------------------------------------------- |
| # Issue 1090: various use-cases of 'svn cp URL wc' where the |
| # repositories might be different, or be the same repository. |
| @Issues(1090, 1444, 3590) |
| def repos_to_wc(sbox): |
| "repository to working-copy copy" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # We have a standard repository and working copy. Now we create a |
| # second repository with the same greek tree, but different UUID. |
| repo_dir = sbox.repo_dir |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 1) |
| |
| # URL->wc copy: |
| # copy a file and a directory from the same repository. |
| # we should get some scheduled additions *with history*. |
| E_url = sbox.repo_url + "/A/B/E" |
| pi_url = sbox.repo_url + "/A/D/G/pi" |
| pi_path = sbox.ospath('pi') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'copy', E_url, wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], 'copy', pi_url, wc_dir) |
| |
| # Extra test: modify file ASAP to check there was a timestamp sleep |
| svntest.main.file_append(pi_path, 'zig\n') |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.add({ |
| 'pi' : Item(status='A ', copied='+', wc_rev='-'), |
| 'E' : Item(status='A ', copied='+', wc_rev='-'), |
| 'E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Modification will only show up if timestamps differ |
| exit_code, out, err = svntest.main.run_svn(None, 'diff', pi_path) |
| if err or not out: |
| logger.warn("diff failed") |
| raise svntest.Failure |
| for line in out: |
| if line == '+zig\n': # Crude check for diff-like output |
| break |
| else: |
| logger.warn("diff output incorrect %s" % out) |
| raise svntest.Failure |
| |
| # Revert everything and verify. |
| svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir) |
| |
| svntest.main.safe_rmtree(sbox.ospath('E')) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # URL->wc copy: |
| # Copy an empty directory from the same repository, see issue #1444. |
| C_url = sbox.repo_url + "/A/C" |
| |
| svntest.actions.run_and_verify_svn(None, [], 'copy', C_url, wc_dir) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.add({ |
| 'C' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Revert everything and verify. |
| svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir) |
| |
| svntest.main.safe_rmtree(sbox.ospath('C')) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # URL->wc copy: |
| # copy a file and a directory from a foreign repository. |
| # we should get some scheduled additions *without history*. |
| E_url = other_repo_url + "/A/B/E" |
| pi_url = other_repo_url + "/A/D/G/pi" |
| |
| # Finally, for 1.8 we allow this copy to succeed. |
| expected_output = svntest.verify.UnorderedOutput([ |
| '--- Copying from foreign repository URL \'%s\':\n' % E_url, |
| 'A %s\n' % sbox.ospath('E'), |
| 'A %s\n' % sbox.ospath('E/beta'), |
| 'A %s\n' % sbox.ospath('E/alpha'), |
| ]) |
| svntest.actions.run_and_verify_svn(expected_output, [], |
| 'copy', E_url, wc_dir) |
| |
| expected_output = [ |
| '--- Copying from foreign repository URL \'%s\':\n' % pi_url, |
| 'A %s\n' % sbox.ospath('pi'), |
| ] |
| svntest.actions.run_and_verify_svn(expected_output, [], |
| 'copy', pi_url, wc_dir) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.add({ |
| 'pi' : Item(status='A ', wc_rev='0'), |
| 'E' : Item(status='A ', wc_rev='0'), |
| 'E/beta' : Item(status='A ', wc_rev='0'), |
| 'E/alpha' : Item(status='A ', wc_rev='0'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Revert everything and verify. |
| svntest.actions.run_and_verify_svn(None, [], 'revert', '-R', wc_dir) |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # URL->wc copy: |
| # Copy a directory to a pre-existing WC directory. |
| # The source directory should be copied *under* the target directory. |
| B_url = sbox.repo_url + "/A/B" |
| D_dir = sbox.ospath('A/D') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', B_url, D_dir) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.add({ |
| 'A/D/B' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/D/B/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/B/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/B/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/B/F' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Validate the mergeinfo of the copy destination (we expect none) |
| svntest.actions.run_and_verify_svn([], '.*W200017: Property.*not found', |
| 'propget', SVN_PROP_MERGEINFO, |
| os.path.join(D_dir, 'B')) |
| |
| #---------------------------------------------------------------------- |
| def foreign_repos_to_wc(sbox): |
| "foreign repository to WC copy" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| def move_url(repo_url, source, dest): |
| svntest.main.run_svn(False, 'move', '-m', svntest.main.make_log_msg(), |
| repo_url + '/' + source, |
| repo_url + '/' + dest) |
| |
| # Scenarios: |
| # (parent-path-under-'A/', base-name, child-paths, mergeinfo-inheritance) |
| scenarios = [ |
| ('B', 'E', ['alpha','beta'], 'explicit'), |
| ('B', 'F', [], 'inherited'), |
| ('D/G', 'pi', [], 'explicit'), |
| ('D/G', 'rho', [], 'inherited'), |
| ] |
| |
| # Add some mergeinfo, which should be discarded by a foreign repo copy. |
| # On each path of interest, add either explicit or inherited mergeinfo: |
| # the implementation handles these cases differently. |
| # (We commit these initially in the original repo just for convenience: as |
| # we already have a WC. Really they only need to be in the 'other' repo.) |
| for parent, name, children, mi_inheritance in scenarios: |
| if mi_inheritance == 'explicit': |
| sbox.simple_propset(SVN_PROP_MERGEINFO, |
| '/branch/' + name + ':1', 'A/' + parent + '/' + name) |
| else: |
| sbox.simple_propset(SVN_PROP_MERGEINFO, |
| '/branch/' + name + ':1', 'A/' + parent) |
| sbox.simple_commit() |
| |
| # We have a standard repository and working copy. Now we create a |
| # second repository with the same greek tree, but different UUID. |
| repo_dir = sbox.repo_dir |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 1) |
| move_url(other_repo_url, 'A', 'A2') |
| move_url(other_repo_url, 'A2', 'A3') |
| |
| # URL->wc copy: |
| # copy a file and a directory from a foreign repository. |
| # we should get some scheduled additions *without history*. |
| peg_rev = '3' |
| op_rev = '2' |
| |
| for parent, name, children, mi_inheritance in scenarios: |
| src_url = other_repo_url + '/A2/' + parent + '/' + name |
| src_url_resolved = src_url.replace('/A2/', '/A/') |
| |
| expected_output = svntest.verify.UnorderedOutput([ |
| '--- Copying from foreign repository URL \'%s\':\n' % src_url_resolved, |
| 'A %s\n' % sbox.ospath(name), |
| ] + [ |
| 'A %s\n' % sbox.ospath(name + '/' + child) |
| for child in children |
| ]) |
| svntest.actions.run_and_verify_svn(expected_output, [], |
| 'copy', '-r' + op_rev, |
| src_url + '@' + peg_rev, |
| wc_dir) |
| |
| # Validate the mergeinfo of the copy destination (we expect none) |
| svntest.actions.run_and_verify_svn([], '.*W200017: Property.*not found', |
| 'propget', SVN_PROP_MERGEINFO, |
| sbox.ospath(name)) |
| |
| #---------------------------------------------------------------------- |
| # Issue 1084: ra_svn move/copy bug |
| @Issue(1084) |
| def copy_to_root(sbox): |
| 'copy item to root of repository' |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| root = sbox.repo_url |
| mu = root + '/A/mu' |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| '-m', '', |
| mu, root) |
| |
| # Update to HEAD, and check to see if the files really were copied in the |
| # repo |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'mu': Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'mu': Item(contents="This is the file 'mu'.\n") |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'mu': Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| @Issue(1367) |
| def url_copy_parent_into_child(sbox): |
| "copy URL URL/subdir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| B_url = sbox.repo_url + "/A/B" |
| F_url = sbox.repo_url + "/A/B/F" |
| |
| # Issue 1367 parent/child URL-to-URL was rejected. |
| svntest.actions.run_and_verify_svn(['Committing transaction...\n', |
| 'Committed revision 2.\n'], [], |
| 'cp', |
| '-m', 'a can of worms', |
| B_url, F_url) |
| |
| # Do an update to verify the copy worked |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F/B' : Item(status='A '), |
| 'A/B/F/B/E' : Item(status='A '), |
| 'A/B/F/B/E/alpha' : Item(status='A '), |
| 'A/B/F/B/E/beta' : Item(status='A '), |
| 'A/B/F/B/F' : Item(status='A '), |
| 'A/B/F/B/lambda' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/B/F/B' : Item(), |
| 'A/B/F/B/E' : Item(), |
| 'A/B/F/B/E/alpha' : Item("This is the file 'alpha'.\n"), |
| 'A/B/F/B/E/beta' : Item("This is the file 'beta'.\n"), |
| 'A/B/F/B/F' : Item(), |
| 'A/B/F/B/lambda' : Item("This is the file 'lambda'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/B/F/B' : Item(status=' ', wc_rev=2), |
| 'A/B/F/B/E' : Item(status=' ', wc_rev=2), |
| 'A/B/F/B/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/B/F/B/E/beta' : Item(status=' ', wc_rev=2), |
| 'A/B/F/B/F' : Item(status=' ', wc_rev=2), |
| 'A/B/F/B/lambda' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| @Issue(1367) |
| def wc_copy_parent_into_child(sbox): |
| "copy WC URL/subdir" |
| |
| sbox.build(create_wc = False) |
| wc_dir = sbox.wc_dir |
| |
| B_url = sbox.repo_url + "/A/B" |
| F_B_url = sbox.repo_url + "/A/B/F/B" |
| |
| # Want a smaller WC |
| svntest.main.safe_rmtree(wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'checkout', |
| B_url, wc_dir) |
| |
| # Issue 1367: A) copying '.' to URL failed with a parent/child |
| # error, and also B) copying root of a working copy attempted to |
| # lock the non-working copy parent directory. |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| |
| svntest.actions.run_and_verify_svn(['Adding copy of .\n', |
| 'Committing transaction...\n', |
| 'Committed revision 2.\n'], [], |
| 'cp', |
| '-m', 'a larger can', |
| '.', F_B_url) |
| |
| os.chdir(was_cwd) |
| |
| # Do an update to verify the copy worked |
| expected_output = svntest.wc.State(wc_dir, { |
| 'F/B' : Item(status='A '), |
| 'F/B/E' : Item(status='A '), |
| 'F/B/E/alpha' : Item(status='A '), |
| 'F/B/E/beta' : Item(status='A '), |
| 'F/B/F' : Item(status='A '), |
| 'F/B/lambda' : Item(status='A '), |
| }) |
| expected_disk = svntest.wc.State('', { |
| 'E' : Item(), |
| 'E/alpha' : Item("This is the file 'alpha'.\n"), |
| 'E/beta' : Item("This is the file 'beta'.\n"), |
| 'F' : Item(), |
| 'lambda' : Item("This is the file 'lambda'.\n"), |
| 'F/B' : Item(), |
| 'F/B/E' : Item(), |
| 'F/B/E/alpha' : Item("This is the file 'alpha'.\n"), |
| 'F/B/E/beta' : Item("This is the file 'beta'.\n"), |
| 'F/B/F' : Item(), |
| 'F/B/lambda' : Item("This is the file 'lambda'.\n"), |
| }) |
| expected_status = svntest.wc.State(wc_dir, { |
| '' : Item(status=' ', wc_rev=2), |
| 'E' : Item(status=' ', wc_rev=2), |
| 'E/alpha' : Item(status=' ', wc_rev=2), |
| 'E/beta' : Item(status=' ', wc_rev=2), |
| 'F' : Item(status=' ', wc_rev=2), |
| 'lambda' : Item(status=' ', wc_rev=2), |
| 'F/B' : Item(status=' ', wc_rev=2), |
| 'F/B/E' : Item(status=' ', wc_rev=2), |
| 'F/B/E/alpha' : Item(status=' ', wc_rev=2), |
| 'F/B/E/beta' : Item(status=' ', wc_rev=2), |
| 'F/B/F' : Item(status=' ', wc_rev=2), |
| 'F/B/lambda' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| @Issue(4913) |
| def url_move_parent_into_child(sbox): |
| "move URL URL/subdir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| B_url = sbox.repo_url + "/A/B" |
| F_url = sbox.repo_url + "/A/B/F" |
| print(B_url) |
| print(F_url) |
| |
| expected_error = "svn: E200007: Cannot move path '.*%s' into its own " \ |
| "child '.*%s'" % (re.escape(B_url), |
| re.escape(F_url)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'mv', |
| '-m', 'a can of worms', |
| B_url, F_url) |
| |
| #---------------------------------------------------------------------- |
| @Issue(4913) |
| def wc_move_parent_into_child(sbox): |
| "move WC WC/subdir" |
| |
| sbox.build(create_wc = False) |
| wc_dir = sbox.wc_dir |
| |
| B_url = sbox.repo_url + "/A/B" |
| F_B_url = sbox.repo_url + "/A/B/F/B" |
| |
| # Want a smaller WC |
| svntest.main.safe_rmtree(wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'checkout', |
| B_url, wc_dir) |
| |
| was_cwd = os.getcwd() |
| from_path = os.path.abspath(sbox.ospath('')) |
| to_path = os.path.abspath(sbox.ospath('F/B')) |
| os.chdir(wc_dir) |
| |
| expected_error = "svn: E200007: Cannot move path '%s' into its own " \ |
| "child '%s'" % (from_path, to_path) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'mv', |
| '.', 'F/B') |
| |
| os.chdir(was_cwd) |
| |
| #---------------------------------------------------------------------- |
| # Issue 1419: at one point ra_neon->get_uuid() was failing on a |
| # non-existent public URL, which prevented us from resurrecting files |
| # (svn cp -rOLD URL wc). |
| @Issue(1419) |
| def resurrect_deleted_file(sbox): |
| "resurrect a deleted file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Delete a file in the repository via immediate commit |
| rho_url = sbox.repo_url + '/A/D/G/rho' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', rho_url, '-m', 'rev 2') |
| |
| # Update the wc to HEAD (r2) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/rho' : Item(status='D '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/D/G/rho') |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.remove('A/D/G/rho') |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # repos->wc copy, to resurrect deleted file. |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', rho_url + '@1', wc_dir) |
| |
| # status should now show the file scheduled for addition-with-history |
| expected_status.add({ |
| 'rho' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| #------------------------------------------------------------- |
| # Regression tests for Issue #1297: |
| # svn diff failed after a repository to WC copy of a single file |
| # This test checks just that. |
| @Issue(1297) |
| def diff_repos_to_wc_copy(sbox): |
| "copy file from repos to working copy and run diff" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| iota_repos_path = sbox.repo_url + '/iota' |
| target_wc_path = sbox.ospath('new_file') |
| |
| # Copy a file from the repository to the working copy. |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| iota_repos_path, target_wc_path) |
| |
| # Run diff. |
| svntest.actions.run_and_verify_svn(None, [], 'diff', wc_dir) |
| |
| |
| #------------------------------------------------------------- |
| @Issue(1473) |
| def repos_to_wc_copy_eol_keywords(sbox): |
| "repos->WC copy with keyword or eol property set" |
| |
| # See issue #1473: repos->wc copy would seg fault if svn:keywords or |
| # svn:eol were set on the copied file, because we'd be querying an |
| # entry for keyword values when the entry was still null (because |
| # not yet been fully installed in the wc). |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_repos_path = sbox.repo_url + '/iota' |
| iota_wc_path = sbox.ospath('iota') |
| target_wc_path = sbox.ospath('new_file') |
| |
| # Modify iota to make it checkworthy. |
| svntest.main.file_write(iota_wc_path, |
| "Hello\nSubversion\n$LastChangedRevision$\n", |
| "ab") |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'propset', 'svn:eol-style', |
| 'CRLF', iota_wc_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'propset', 'svn:keywords', |
| 'Rev', iota_wc_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'commit', '-m', 'log msg', |
| wc_dir) |
| |
| # Copy a file from the repository to the working copy. |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| iota_repos_path, target_wc_path) |
| |
| # The original bug was that the copy would seg fault. So we test |
| # that the copy target exists now; if it doesn't, it's probably |
| # because of the segfault. Note that the crash would be independent |
| # of whether there are actually any line breaks or keywords in the |
| # file's contents -- the mere existence of the property would |
| # trigger the bug. |
| if not os.path.exists(target_wc_path): |
| raise svntest.Failure |
| |
| # Okay, if we got this far, we might as well make sure that the |
| # translations/substitutions were done correctly: |
| f = open(target_wc_path, "rb") |
| raw_contents = f.read() |
| f.seek(0, 0) |
| line_contents = f.readlines() |
| f.close() |
| |
| if re.match(b'[^\\r]\\n', raw_contents): |
| raise svntest.Failure |
| |
| if not re.match(b'.*\$LastChangedRevision:\s*\d+\s*\$', line_contents[3]): |
| raise svntest.Failure |
| |
| #------------------------------------------------------------- |
| # Regression test for revision 7331, with commented-out parts for a further |
| # similar bug. |
| |
| def revision_kinds_local_source(sbox): |
| "revision-kind keywords with non-URL source" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| mu_path = sbox.ospath('A/mu') |
| |
| # Make a file with different content in each revision and WC; BASE != HEAD. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), }) |
| svntest.main.file_append(mu_path, "New r2 text.\n") |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| svntest.main.file_append(mu_path, "New r3 text.\n") |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| svntest.actions.run_and_verify_svn(None, [], 'up', '-r2', mu_path) |
| svntest.main.file_append(mu_path, "Working copy.\n") |
| |
| r1 = "This is the file 'mu'.\n" |
| r2 = r1 + "New r2 text.\n" |
| r3 = r2 + "New r3 text.\n" |
| rWC = r2 + "Working copy.\n" |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/mu', contents=rWC) |
| |
| # Test the various revision-kind keywords, and none. |
| sub_tests = [ ('file0', 2, rWC, None), |
| ('file1', 3, r3, 'HEAD'), |
| ('file2', 2, r2, 'BASE'), |
| # ('file3', 2, r2, 'COMMITTED'), |
| # ('file4', 1, r1, 'PREV'), |
| ] |
| |
| for dst, from_rev, text, peg_rev in sub_tests: |
| dst_path = os.path.join(wc_dir, dst) |
| if peg_rev is None: |
| svntest.actions.run_and_verify_svn(None, [], "copy", |
| mu_path, dst_path) |
| else: |
| svntest.actions.run_and_verify_svn(None, [], "copy", |
| mu_path + "@" + peg_rev, dst_path) |
| expected_disk.add({ dst: Item(contents=text) }) |
| |
| # Check that the copied-from revision == from_rev. |
| exit_code, output, errput = svntest.main.run_svn(None, "info", dst_path) |
| for line in output: |
| if line.rstrip() == "Copied From Rev: " + str(from_rev): |
| break |
| else: |
| logger.warn("%s should have been copied from revision %s" % (dst, from_rev)) |
| raise svntest.Failure |
| |
| # Check that the new files have the right contents |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| |
| #------------------------------------------------------------- |
| # Regression test for issue 1581. |
| @Issue(1581) |
| def copy_over_missing_file(sbox): |
| "copy over a missing file" |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| mu_path = sbox.ospath('A/mu') |
| iota_path = sbox.ospath('iota') |
| iota_url = sbox.repo_url + "/iota" |
| |
| # Make the target missing. |
| os.remove(mu_path) |
| |
| # Try both wc->wc copy and repos->wc copy, expect failures: |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'cp', iota_path, mu_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'cp', iota_url, mu_path) |
| |
| # Make sure that the working copy is not corrupted: |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output = svntest.wc.State(wc_dir, {'A/mu' : Item(verb='Restored')}) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issue 1634 |
| @Issue(1634) |
| def repos_to_wc_1634(sbox): |
| "copy a deleted directory back from the repos" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # First delete a subdirectory and commit. |
| E_path = sbox.ospath('A/B/E') |
| svntest.actions.run_and_verify_svn(None, [], 'delete', E_path) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E' : Item(verb='Deleting'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Now copy the directory back. |
| E_url = sbox.repo_url + "/A/B/E@1" |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', E_url, E_path) |
| expected_status.add({ |
| 'A/B/E' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/B/E' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issue 1814 |
| @Issue(1814) |
| def double_uri_escaping_1814(sbox): |
| "check for double URI escaping in svn ls -R" |
| |
| sbox.build(create_wc = False) |
| |
| base_url = sbox.repo_url + '/base' |
| |
| # rev. 2 |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', '-m', 'mybase', |
| base_url) |
| |
| orig_url = base_url + '/foo%20bar' |
| |
| # rev. 3 |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', '-m', 'r1', |
| orig_url) |
| orig_rev = 3 |
| |
| # rev. 4 |
| new_url = base_url + '/foo_bar' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', '-m', 'r2', |
| orig_url, new_url) |
| |
| # This had failed with ra_neon because "foo bar" would be double-encoded |
| # "foo bar" ==> "foo%20bar" ==> "foo%2520bar" |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ls', ('-r'+str(orig_rev)), |
| '-R', base_url) |
| |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issues 2404 |
| @Issue(2404) |
| def wc_to_wc_copy_between_different_repos(sbox): |
| "wc to wc copy attempts between different repos" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| sbox2 = sbox.clone_dependent() |
| sbox2.build() |
| wc2_dir = sbox2.wc_dir |
| |
| # Attempt a copy between different repositories. |
| exit_code, out, err = svntest.main.run_svn(1, 'cp', |
| os.path.join(wc2_dir, 'A'), |
| sbox.ospath('A/B')) |
| for line in err: |
| if line.find("it is not from repository") != -1: |
| break |
| else: |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issues 2101, 2020 and 3776 |
| @Issues(2101,2020,3776) |
| def wc_to_wc_copy_deleted(sbox): |
| "wc to wc copy with presence=not-present items" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| B_path = sbox.ospath('A/B') |
| B2_path = sbox.ospath('A/B2') |
| |
| # Schedule for delete |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| os.path.join(B_path, 'E', 'alpha'), |
| os.path.join(B_path, 'lambda'), |
| os.path.join(B_path, 'F')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B/E/alpha', 'A/B/lambda', 'A/B/F', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Commit to get state not-present |
| expected_status.remove('A/B/E/alpha', 'A/B/lambda', 'A/B/F') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E/alpha' : Item(verb='Deleting'), |
| 'A/B/lambda' : Item(verb='Deleting'), |
| 'A/B/F' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Copy including stuff in state not-present |
| svntest.actions.run_and_verify_svn(None, [], 'copy', B_path, B2_path) |
| expected_status.add({ |
| 'A/B2' : Item(status='A ', wc_rev='-', copied='+'), |
| 'A/B2/E' : Item(status=' ', wc_rev='-', copied='+'), |
| 'A/B2/E/beta' : Item(status=' ', wc_rev='-', copied='+'), |
| 'A/B2/E/alpha' : Item(status='D ', wc_rev='-', copied='+'), |
| 'A/B2/lambda' : Item(status='D ', wc_rev='-', copied='+'), |
| 'A/B2/F' : Item(status='D ', wc_rev='-', copied='+'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Reverting the copied not-present is a no-op. |
| svntest.main.run_svn(1, 'revert', os.path.join(B2_path, 'F')) |
| svntest.main.run_svn(1, 'revert', os.path.join(B2_path, 'lambda')) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Revert the entire copy including the schedule not-present bits |
| svntest.actions.run_and_verify_svn(None, [], 'revert', '--recursive', |
| B2_path) |
| expected_status.remove('A/B2', |
| 'A/B2/E', |
| 'A/B2/E/beta', |
| 'A/B2/E/alpha', |
| 'A/B2/lambda', |
| 'A/B2/F') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| svntest.main.safe_rmtree(B2_path) |
| |
| # Copy again and commit |
| svntest.actions.run_and_verify_svn(None, [], 'copy', B_path, B2_path) |
| |
| expected_status.add({ |
| 'A/B2' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/B2/lambda' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A/B2/F' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A/B2/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B2/E/alpha' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A/B2/E/beta' : Item(status=' ', copied='+', wc_rev='-') |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_status.remove('A/B2/lambda', 'A/B2/F', 'A/B2/E/alpha') |
| expected_status.tweak('A/B2', 'A/B2/E', 'A/B2/E/beta', status=' ', |
| copied=None, wc_rev=3) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B2' : Item(verb='Adding'), |
| 'A/B2/E/alpha' : Item(verb='Deleting'), |
| 'A/B2/lambda' : Item(verb='Deleting'), |
| 'A/B2/F' : Item(verb='Deleting'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| # Test for copy into a non-existent URL path |
| def url_to_non_existent_url_path(sbox): |
| "svn cp src-URL non-existent-URL-path" |
| |
| sbox.build(create_wc = False) |
| |
| dirURL1 = sbox.repo_url + "/A/B/E" |
| dirURL2 = sbox.repo_url + "/G/C/E/I" |
| |
| # Look for both possible versions of the error message, as the DAV |
| # error is worded differently from that of other RA layers. |
| msg = ".*: (" + \ |
| "|".join(["Path 'G(/C/E)?' not present", |
| ".*G(/C/E)?' path not found", |
| "File not found.*'/G/C/E/I'", |
| ]) + ")" |
| |
| # Expect failure on 'svn cp SRC DST' where one or more ancestor |
| # directories of DST do not exist |
| exit_code, out, err = svntest.main.run_svn(1, 'cp', dirURL1, dirURL2, |
| '-m', 'fooogle') |
| for err_line in err: |
| if re.match (msg, err_line): |
| break |
| else: |
| logger.warn("message \"%s\" not found in error output: %s" % (msg, err)) |
| raise svntest.Failure |
| |
| |
| #---------------------------------------------------------------------- |
| # Test for a copying (URL to URL) an old rev of a deleted file in a |
| # deleted directory. |
| def non_existent_url_to_url(sbox): |
| "svn cp oldrev-of-deleted-URL URL" |
| |
| sbox.build(create_wc = False) |
| |
| adg_url = sbox.repo_url + '/A/D/G' |
| pi_url = sbox.repo_url + '/A/D/G/pi' |
| new_url = sbox.repo_url + '/newfile' |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'delete', |
| adg_url, '-m', '') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', |
| pi_url + '@1', new_url, |
| '-m', '') |
| |
| #---------------------------------------------------------------------- |
| def old_dir_url_to_url(sbox): |
| "test URL to URL copying edge case" |
| |
| sbox.build(create_wc = False) |
| |
| adg_url = sbox.repo_url + '/A/D/G' |
| pi_url = sbox.repo_url + '/A/D/G/pi' |
| iota_url = sbox.repo_url + '/iota' |
| new_url = sbox.repo_url + '/newfile' |
| |
| # Delete a directory |
| svntest.actions.run_and_verify_svn(None, [], |
| 'delete', |
| adg_url, '-m', '') |
| |
| # Copy a file to where the directory used to be |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', |
| iota_url, adg_url, |
| '-m', '') |
| |
| # Try copying a file that was in the deleted directory that is now a |
| # file |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', |
| pi_url + '@1', new_url, |
| '-m', '') |
| |
| |
| |
| #---------------------------------------------------------------------- |
| # Test fix for issue 2224 - copying wc dir to itself causes endless |
| # recursion |
| @Issue(2224) |
| def wc_copy_dir_to_itself(sbox): |
| "copy wc dir to itself" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| dnames = ['A','A/B'] |
| |
| for dirname in dnames: |
| dir_path = os.path.join(wc_dir, dirname) |
| |
| # try to copy dir to itself |
| svntest.actions.run_and_verify_svn([], |
| '.*Cannot copy .* into its own child.*', |
| 'copy', dir_path, dir_path) |
| |
| |
| #---------------------------------------------------------------------- |
| @Issue(2153) |
| def mixed_wc_to_url(sbox): |
| "copy a complex mixed-rev wc" |
| |
| # For issue 2153. |
| # |
| # Copy a mixed-revision wc (that also has some uncommitted local |
| # mods, and an entry marked as 'deleted') to a URL. Make sure the |
| # copy gets the uncommitted mods, and does not contain the deleted |
| # file. |
| |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| Z_url = sbox.repo_url + '/A/D/Z' |
| Z2_url = sbox.repo_url + '/A/D/Z2' |
| G_path = sbox.ospath('A/D/G') |
| B_path = sbox.ospath('A/B') |
| X_path = sbox.ospath('A/D/G/X') |
| Y_path = sbox.ospath('A/D/G/Y') |
| E_path = sbox.ospath('A/D/G/X/E') |
| alpha_path = sbox.ospath('A/D/G/X/E/alpha') |
| pi_path = sbox.ospath('A/D/G/pi') |
| rho_path = sbox.ospath('A/D/G/rho') |
| |
| # Remove A/D/G/pi, then commit that removal. |
| svntest.actions.run_and_verify_svn(None, [], 'rm', pi_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', '-m', "Delete pi.", wc_dir) |
| |
| # Make a modification to A/D/G/rho, then commit that modification. |
| svntest.main.file_append(rho_path, "\nFirst modification to rho.\n") |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', '-m', "Modify rho.", wc_dir) |
| |
| # Make another modification to A/D/G/rho, but don't commit it. |
| svntest.main.file_append(rho_path, "Second modification to rho.\n") |
| |
| # Copy into the source, delete part of the copy, add a non-copied directory |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', B_path, X_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', alpha_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', Y_path) |
| |
| # Now copy local A/D/G to create new directory A/D/Z the repository. |
| |
| expected_status = svntest.wc.State(G_path, { |
| '' : Item(status=' ', wc_rev='1'), |
| 'X' : Item(status='A ', copied='+', wc_rev='-'), |
| 'X/F' : Item(status=' ', copied='+', wc_rev='-'), |
| 'X/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'X/E/alpha' : Item(status='D ', copied='+', wc_rev='-'), |
| 'X/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'X/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| 'Y' : Item(status='A ', wc_rev='-'), |
| 'rho' : Item(status='M ', wc_rev='3'), |
| 'tau' : Item(status=' ', wc_rev='1'), |
| }) |
| |
| svntest.actions.run_and_verify_status(G_path, expected_status) |
| |
| expected_output = svntest.verify.UnorderedOutput([ |
| 'Adding copy of %s\n' % sbox.ospath('A/D/G'), |
| 'Adding copy of %s\n' % sbox.ospath('A/D/G/X'), |
| 'Deleting copy of %s\n' % sbox.ospath('A/D/G/X/E/alpha'), |
| 'Adding copy of %s\n' % sbox.ospath('A/D/G/Y'), |
| 'Deleting copy of %s\n' % sbox.ospath('A/D/G/pi'), |
| 'Replacing copy of %s\n' % sbox.ospath('A/D/G/rho'), |
| 'Transmitting file data .done\n', |
| 'Committing transaction...\n', |
| 'Committed revision 4.\n', |
| ]) |
| svntest.actions.run_and_verify_svn(expected_output, [], |
| 'cp', '-m', "Make a copy.", |
| G_path, Z_url) |
| expected_output = svntest.verify.UnorderedOutput([ |
| 'A + A/D/Z/\n', |
| ' (from A/D/G/:r1)\n', |
| 'A + A/D/Z/X/\n', |
| ' (from A/B/:r1)\n', |
| 'D A/D/Z/X/E/alpha\n', |
| 'A A/D/Z/Y/\n', |
| 'D A/D/Z/pi\n', |
| 'D A/D/Z/rho\n', |
| 'A + A/D/Z/rho\n', |
| ' (from A/D/G/rho:r3)\n', |
| ]) |
| svntest.actions.run_and_verify_svnlook(expected_output, [], |
| 'changed', sbox.repo_dir, |
| '--copy-info') |
| |
| # Copy from copied source |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '-m', "Make a copy.", |
| E_path, Z2_url) |
| expected_output = svntest.verify.UnorderedOutput([ |
| 'A + A/D/Z2/\n', |
| ' (from A/B/E/:r1)\n', |
| 'D A/D/Z2/alpha\n', |
| ]) |
| svntest.actions.run_and_verify_svnlook(expected_output, [], |
| 'changed', sbox.repo_dir, |
| '--copy-info') |
| |
| # Check out A/D/Z. If it has pi, that's a bug; or if its rho does |
| # not have the second local mod, that's also a bug. |
| svntest.main.safe_rmtree(wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'co', Z_url, wc_dir) |
| |
| if os.path.exists(sbox.ospath('pi')): |
| raise svntest.Failure("Path 'pi' exists but should be gone.") |
| |
| fp = open(sbox.ospath('rho'), 'r') |
| found_it = 0 |
| for line in fp.readlines(): |
| if re.match("^Second modification to rho.", line): |
| found_it = 1 |
| if not found_it: |
| raise svntest.Failure("The second modification to rho didn't make it.") |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Issue 845 and 1516: WC replacement of files requires |
| # a second text-base and prop-base |
| @Issues(845,1516) |
| def wc_copy_replacement(sbox): |
| "svn cp PATH PATH replace file" |
| |
| copy_replace(sbox, 1) |
| |
| def wc_copy_replace_with_props(sbox): |
| "svn cp PATH PATH replace file with props" |
| |
| copy_replace_with_props(sbox, 1) |
| |
| |
| def repos_to_wc_copy_replacement(sbox): |
| "svn cp URL PATH replace file" |
| |
| copy_replace(sbox, 0) |
| |
| def repos_to_wc_copy_replace_with_props(sbox): |
| "svn cp URL PATH replace file with props" |
| |
| copy_replace_with_props(sbox, 0) |
| |
| # See also delete_replace_delete() which does the same for a directory. |
| def delete_replaced_file(sbox): |
| "delete a file scheduled for replacement" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # File scheduled for deletion. |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', rho_path) |
| |
| # Status before attempting copies |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/rho', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Copy 'pi' over 'rho' with history. |
| pi_src = sbox.ospath('A/D/G/pi') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', pi_src, rho_path) |
| |
| # Check that file copied. |
| expected_status.tweak('A/D/G/rho', status='R ', copied='+', wc_rev='-') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Now delete replaced file. |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| '--force', rho_path) |
| |
| # Verify status after deletion. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/G/rho', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| @Issue(2436) |
| def mv_unversioned_file(sbox): |
| "move an unversioned file" |
| # Issue #2436: Attempting to move an unversioned file would seg fault. |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| unver_path_1 = sbox.ospath('unversioned1') |
| dest_path_1 = sbox.ospath('dest') |
| svntest.main.file_append(unver_path_1, "an unversioned file") |
| |
| unver_path_2 = sbox.ospath('A/unversioned2') |
| dest_path_2 = sbox.ospath('A/dest_forced') |
| svntest.main.file_append(unver_path_2, "another unversioned file") |
| |
| # Try to move an unversioned file. |
| svntest.actions.run_and_verify_svn(None, |
| ".*unversioned1' " + |
| "(does not exist|is not under version control)", |
| 'mv', unver_path_1, dest_path_1) |
| |
| # Try to forcibly move an unversioned file. |
| svntest.actions.run_and_verify_svn(None, |
| ".*unversioned2.* " + |
| "(does not exist|is not under version control)", |
| 'mv', |
| unver_path_2, dest_path_2) |
| |
| @Issue(2435) |
| def force_move(sbox): |
| "'move' should not lose local mods" |
| # Issue #2435: 'svn move' / 'svn mv' can lose local modifications. |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| file_name = "iota" |
| file_path = os.path.join(wc_dir, file_name) |
| |
| # modify the content |
| file_handle = open(file_path, "a") |
| file_handle.write("Added contents\n") |
| file_handle.close() |
| expected_file_content = [ "This is the file 'iota'.\n", |
| "Added contents\n", |
| ] |
| |
| # check for the new content |
| file_handle = open(file_path, "r") |
| modified_file_content = file_handle.readlines() |
| file_handle.close() |
| if modified_file_content != expected_file_content: |
| raise svntest.Failure("Test setup failed. Incorrect file contents.") |
| |
| # force move the file |
| move_output = [ "A dest\n", |
| "D iota\n", |
| ] |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| |
| svntest.actions.run_and_verify_svn(move_output, |
| [], |
| 'move', |
| file_name, "dest") |
| os.chdir(was_cwd) |
| |
| # check for the new content |
| file_handle = open(sbox.ospath('dest'), "r") |
| modified_file_content = file_handle.readlines() |
| file_handle.close() |
| # Error if we dont find the modified contents... |
| if modified_file_content != expected_file_content: |
| raise svntest.Failure("File modifications were lost on 'move'") |
| |
| # Commit the move and make sure the new content actually reaches |
| # the repository. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota': Item(verb='Deleting'), |
| 'dest': Item(verb='Adding'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove("iota") |
| expected_status.add({ |
| 'dest': Item(status=' ', wc_rev='2'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| svntest.actions.run_and_verify_svn(expected_file_content, [], |
| 'cat', |
| sbox.repo_url + '/dest') |
| |
| |
| def copy_copied_file_and_dir(sbox): |
| "copy a copied file and dir" |
| # Improve support for copy and move |
| # Allow copy of copied items without a commit between |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| rho_path = sbox.ospath('A/D/G/rho') |
| rho_copy_path_1 = sbox.ospath('A/D/rho_copy_1') |
| rho_copy_path_2 = sbox.ospath('A/B/F/rho_copy_2') |
| |
| # Copy A/D/G/rho to A/D/rho_copy_1 |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| rho_path, rho_copy_path_1) |
| |
| # Copy the copied file: A/D/rho_copy_1 to A/B/F/rho_copy_2 |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| rho_copy_path_1, rho_copy_path_2) |
| |
| E_path = sbox.ospath('A/B/E') |
| E_path_copy_1 = sbox.ospath('A/B/F/E_copy_1') |
| E_path_copy_2 = sbox.ospath('A/D/G/E_copy_2') |
| |
| # Copy A/B/E to A/B/F/E_copy_1 |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| E_path, E_path_copy_1) |
| |
| # Copy the copied dir: A/B/F/E_copy_1 to A/D/G/E_copy_2 |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| E_path_copy_1, E_path_copy_2) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/rho_copy_1' : Item(verb='Adding'), |
| 'A/B/F/rho_copy_2' : Item(verb='Adding'), |
| 'A/B/F/E_copy_1/' : Item(verb='Adding'), |
| 'A/D/G/E_copy_2/' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/rho_copy_1' : Item(status=' ', wc_rev=2), |
| 'A/B/F/rho_copy_2' : Item(status=' ', wc_rev=2), |
| 'A/B/F/E_copy_1' : Item(status=' ', wc_rev=2), |
| 'A/B/F/E_copy_1/alpha' : Item(status=' ', wc_rev=2), |
| 'A/B/F/E_copy_1/beta' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_2' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_2/alpha' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_2/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_copied_file_and_dir(sbox): |
| "move a copied file and dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| rho_path = sbox.ospath('A/D/G/rho') |
| rho_copy_path = sbox.ospath('A/D/rho_copy') |
| rho_copy_move_path = sbox.ospath('A/B/F/rho_copy_moved') |
| |
| # Copy A/D/G/rho to A/D/rho_copy |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| rho_path, rho_copy_path) |
| |
| # Move the copied file: A/D/rho_copy to A/B/F/rho_copy_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| rho_copy_path, rho_copy_move_path) |
| |
| E_path = sbox.ospath('A/B/E') |
| E_path_copy = sbox.ospath('A/B/F/E_copy') |
| E_path_copy_move = sbox.ospath('A/D/G/E_copy_moved') |
| |
| # Copy A/B/E to A/B/F/E_copy |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| E_path, E_path_copy) |
| |
| # Move the copied file: A/B/F/E_copy to A/D/G/E_copy_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| E_path_copy, E_path_copy_move) |
| |
| # Created expected output tree for 'svn ci': |
| # Since we are moving items that were only *scheduled* for addition |
| # we expect only to additions when checking in, rather than a |
| # deletion/addition pair. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F/rho_copy_moved' : Item(verb='Adding'), |
| 'A/D/G/E_copy_moved/' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/rho_copy_moved' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_moved' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_moved/alpha' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_copy_moved/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_moved_file_and_dir(sbox): |
| "move a moved file and dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| rho_path = sbox.ospath('A/D/G/rho') |
| rho_move_path = sbox.ospath('A/D/rho_moved') |
| rho_move_moved_path = sbox.ospath('A/B/F/rho_move_moved') |
| |
| # Move A/D/G/rho to A/D/rho_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| rho_path, rho_move_path) |
| |
| # Move the moved file: A/D/rho_moved to A/B/F/rho_move_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| rho_move_path, rho_move_moved_path) |
| |
| E_path = sbox.ospath('A/B/E') |
| E_path_moved = sbox.ospath('A/B/F/E_moved') |
| E_path_move_moved = sbox.ospath('A/D/G/E_move_moved') |
| |
| # Copy A/B/E to A/B/F/E_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| E_path, E_path_moved) |
| |
| # Move the moved file: A/B/F/E_moved to A/D/G/E_move_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| E_path_moved, E_path_move_moved) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E' : Item(verb='Deleting'), |
| 'A/D/G/E_move_moved/' : Item(verb='Adding'), |
| 'A/D/G/rho' : Item(verb='Deleting'), |
| 'A/B/F/rho_move_moved' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/G/E_move_moved' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_move_moved/alpha' : Item(status=' ', wc_rev=2), |
| 'A/D/G/E_move_moved/beta' : Item(status=' ', wc_rev=2), |
| 'A/B/F/rho_move_moved' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/B/E', |
| 'A/B/E/alpha', |
| 'A/B/E/beta', |
| 'A/D/G/rho') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_file_within_moved_dir(sbox): |
| "move a file twice within a moved dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| D_path = sbox.ospath('A/D') |
| D_path_moved = sbox.ospath('A/B/F/D_moved') |
| |
| # Move A/B/D to A/B/F/D_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| D_path, D_path_moved) |
| |
| chi_path = sbox.ospath('A/B/F/D_moved/H/chi') |
| chi_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', |
| 'H', 'chi_moved') |
| chi_moved_again_path = os.path.join(wc_dir, 'A', 'B', 'F', |
| 'D_moved', 'H', 'chi_moved_again') |
| |
| # Move A/B/F/D_moved/H/chi to A/B/F/D_moved/H/chi_moved |
| # then move that to A/B/F/D_moved/H/chi_moved_again |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| chi_path, chi_moved_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| chi_moved_path, |
| chi_moved_again_path) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F/D_moved/' : Item(verb='Adding'), |
| 'A/B/F/D_moved/H/chi' : Item(verb='Deleting'), |
| 'A/B/F/D_moved/H/chi_moved_again' : Item(verb='Adding'), |
| 'A/D' : Item(verb='Deleting'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/D_moved' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/gamma' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/tau' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H/omega' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H/psi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H/chi_moved_again' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/D', |
| 'A/D/gamma', |
| 'A/D/G', |
| 'A/D/G/pi', |
| 'A/D/G/rho', |
| 'A/D/G/tau', |
| 'A/D/H', |
| 'A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi', |
| ) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_file_out_of_moved_dir(sbox): |
| "move a file out of a moved dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| D_path = sbox.ospath('A/D') |
| D_path_moved = sbox.ospath('A/B/F/D_moved') |
| |
| # Move A/B/D to A/B/F/D_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| D_path, D_path_moved) |
| |
| chi_path = sbox.ospath('A/B/F/D_moved/H/chi') |
| chi_moved_path = os.path.join(wc_dir, 'A', 'B', 'F', 'D_moved', |
| 'H', 'chi_moved') |
| chi_moved_again_path = sbox.ospath('A/C/chi_moved_again') |
| |
| # Move A/B/F/D_moved/H/chi to A/B/F/D_moved/H/chi_moved |
| # then move that to A/C/chi_moved_again |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| chi_path, chi_moved_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| chi_moved_path, |
| chi_moved_again_path) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F/D_moved/' : Item(verb='Adding'), |
| 'A/B/F/D_moved/H/chi' : Item(verb='Deleting'), |
| 'A/C/chi_moved_again' : Item(verb='Adding'), |
| 'A/D' : Item(verb='Deleting'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/D_moved' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/gamma' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/tau' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H/omega' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/chi_moved_again' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/D', |
| 'A/D/gamma', |
| 'A/D/G', |
| 'A/D/G/pi', |
| 'A/D/G/rho', |
| 'A/D/G/tau', |
| 'A/D/H', |
| 'A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi', |
| ) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_dir_within_moved_dir(sbox): |
| "move a dir twice within a moved dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| D_path = sbox.ospath('A/D') |
| D_path_moved = sbox.ospath('A/B/F/D_moved') |
| |
| # Move A/D to A/B/F/D_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| D_path, D_path_moved) |
| |
| H_path = sbox.ospath('A/B/F/D_moved/H') |
| H_moved_path = sbox.ospath('A/B/F/D_moved/H_moved') |
| H_moved_again_path = os.path.join(wc_dir, 'A', 'B', 'F', |
| 'D_moved', 'H_moved_again') |
| |
| # Move A/B/F/D_moved/H to A/B/F/D_moved/H_moved |
| # then move that to A/B/F/D_moved/H_moved_again |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| H_path, H_moved_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| H_moved_path, |
| H_moved_again_path) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D' : Item(verb='Deleting'), |
| 'A/B/F/D_moved' : Item(verb='Adding'), |
| 'A/B/F/D_moved/H' : Item(verb='Deleting'), |
| 'A/B/F/D_moved/H_moved_again' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/D_moved' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/gamma' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/tau' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H_moved_again' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H_moved_again/omega' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H_moved_again/psi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/H_moved_again/chi' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/D', |
| 'A/D/gamma', |
| 'A/D/G', |
| 'A/D/G/pi', |
| 'A/D/G/rho', |
| 'A/D/G/tau', |
| 'A/D/H', |
| 'A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi', |
| ) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def move_dir_out_of_moved_dir(sbox): |
| "move a dir out of a moved dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| D_path = sbox.ospath('A/D') |
| D_path_moved = sbox.ospath('A/B/F/D_moved') |
| |
| # Move A/D to A/B/F/D_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| D_path, D_path_moved) |
| |
| H_path = sbox.ospath('A/B/F/D_moved/H') |
| H_moved_path = sbox.ospath('A/B/F/D_moved/H_moved') |
| H_moved_again_path = sbox.ospath('A/C/H_moved_again') |
| |
| # Move A/B/F/D_moved/H to A/B/F/D_moved/H_moved |
| # then move that to A/C/H_moved_again |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| H_path, H_moved_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| H_moved_path, |
| H_moved_again_path) |
| |
| # Created expected output tree for 'svn ci': |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D' : Item(verb='Deleting'), |
| 'A/B/F/D_moved' : Item(verb='Adding'), |
| 'A/B/F/D_moved/H' : Item(verb='Deleting'), |
| 'A/C/H_moved_again' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/D_moved' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/gamma' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/pi' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/rho' : Item(status=' ', wc_rev=2), |
| 'A/B/F/D_moved/G/tau' : Item(status=' ', wc_rev=2), |
| 'A/C/H_moved_again' : Item(status=' ', wc_rev=2), |
| 'A/C/H_moved_again/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/H_moved_again/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/H_moved_again/chi' : Item(status=' ', wc_rev=2), |
| }) |
| |
| expected_status.remove('A/D', |
| 'A/D/gamma', |
| 'A/D/G', |
| 'A/D/G/pi', |
| 'A/D/G/rho', |
| 'A/D/G/tau', |
| 'A/D/H', |
| 'A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi', |
| ) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Includes regression testing for issue #3429 ("svn mv A B; svn mv B A" |
| # generates replace without history). |
| @Issue(3429) |
| def move_file_back_and_forth(sbox): |
| "move a moved file back to original location" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| rho_path = sbox.ospath('A/D/G/rho') |
| rho_move_path = sbox.ospath('A/D/rho_moved') |
| |
| # Move A/D/G/rho away from and then back to its original path |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| rho_path, rho_move_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| rho_move_path, rho_path) |
| |
| # Check expected status before commit |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Try to commit and find out that there is nothing to commit. |
| expected_output = [] |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| # Includes regression testing for issue #3429 ("svn mv A B; svn mv B A" |
| # generates replace without history). |
| @Issue(3429) |
| def move_dir_back_and_forth(sbox): |
| "move a moved dir back to original location" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| D_path = sbox.ospath('A/D') |
| D_move_path = sbox.ospath('D_moved') |
| |
| # Move A/D to D_moved |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| D_path, D_move_path) |
| |
| # Move the moved dir: D_moved back to its starting |
| # location at A/D. |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', D_move_path, D_path) |
| |
| # Verify that the status indicates a replace with history |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| def copy_move_added_paths(sbox): |
| "copy and move added paths without commits" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a new file and schedule it for addition |
| upsilon_path = sbox.ospath('A/D/upsilon') |
| svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") |
| svntest.actions.run_and_verify_svn(None, [], 'add', upsilon_path) |
| |
| # Create a dir with children and schedule it for addition |
| I_path = sbox.ospath('A/D/I') |
| J_path = os.path.join(I_path, 'J') |
| eta_path = os.path.join(I_path, 'eta') |
| theta_path = os.path.join(I_path, 'theta') |
| kappa_path = os.path.join(J_path, 'kappa') |
| os.mkdir(I_path) |
| os.mkdir(J_path) |
| svntest.main.file_write(eta_path, "This is the file 'eta'\n") |
| svntest.main.file_write(theta_path, "This is the file 'theta'\n") |
| svntest.main.file_write(kappa_path, "This is the file 'kappa'\n") |
| svntest.actions.run_and_verify_svn(None, [], 'add', I_path) |
| |
| # Create another dir and schedule it for addition |
| K_path = sbox.ospath('K') |
| os.mkdir(K_path) |
| svntest.actions.run_and_verify_svn(None, [], 'add', K_path) |
| |
| # Verify all the adds took place correctly. |
| expected_status_after_adds = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status_after_adds.add({ |
| 'A/D/I' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/eta' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/J' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/J/kappa' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/theta' : Item(status='A ', wc_rev='0'), |
| 'A/D/upsilon' : Item(status='A ', wc_rev='0'), |
| 'K' : Item(status='A ', wc_rev='0'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status_after_adds) |
| |
| # Scatter some unversioned paths within the added dir I. |
| unversioned_path_1 = os.path.join(I_path, 'unversioned1') |
| unversioned_path_2 = os.path.join(J_path, 'unversioned2') |
| L_path = os.path.join(I_path, "L_UNVERSIONED") |
| unversioned_path_3 = os.path.join(L_path, 'unversioned3') |
| svntest.main.file_write(unversioned_path_1, "An unversioned file\n") |
| svntest.main.file_write(unversioned_path_2, "An unversioned file\n") |
| os.mkdir(L_path) |
| svntest.main.file_write(unversioned_path_3, "An unversioned file\n") |
| |
| # Copy added dir A/D/I to added dir K/I |
| I_copy_path = os.path.join(K_path, 'I') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| I_path, I_copy_path) |
| |
| # Copy added file A/D/upsilon into added dir K |
| upsilon_copy_path = os.path.join(K_path, 'upsilon') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| upsilon_path, upsilon_copy_path) |
| |
| # Move added file A/D/upsilon to upsilon, |
| # then move it again to A/upsilon |
| upsilon_move_path = sbox.ospath('upsilon') |
| upsilon_move_path_2 = sbox.ospath('A/upsilon') |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| upsilon_path, upsilon_move_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| upsilon_move_path, upsilon_move_path_2) |
| |
| # Move added dir A/D/I to A/B/I, |
| # then move it again to A/D/H/I |
| I_move_path = sbox.ospath('A/B/I') |
| I_move_path_2 = sbox.ospath('A/D/H/I') |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| I_path, I_move_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| I_move_path, I_move_path_2) |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/H/I' : Item(verb='Adding'), |
| 'A/D/H/I/J' : Item(verb='Adding'), |
| 'A/D/H/I/J/kappa' : Item(verb='Adding'), |
| 'A/D/H/I/eta' : Item(verb='Adding'), |
| 'A/D/H/I/theta' : Item(verb='Adding'), |
| 'A/upsilon' : Item(verb='Adding'), |
| 'K' : Item(verb='Adding'), |
| 'K/I' : Item(verb='Adding'), |
| 'K/I/J' : Item(verb='Adding'), |
| 'K/I/J/kappa' : Item(verb='Adding'), |
| 'K/I/eta' : Item(verb='Adding'), |
| 'K/I/theta' : Item(verb='Adding'), |
| 'K/upsilon' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/H/I' : Item(status=' ', wc_rev=2), |
| 'A/D/H/I/J' : Item(status=' ', wc_rev=2), |
| 'A/D/H/I/J/kappa' : Item(status=' ', wc_rev=2), |
| 'A/D/H/I/eta' : Item(status=' ', wc_rev=2), |
| 'A/D/H/I/theta' : Item(status=' ', wc_rev=2), |
| 'A/upsilon' : Item(status=' ', wc_rev=2), |
| 'K' : Item(status=' ', wc_rev=2), |
| 'K/I' : Item(status=' ', wc_rev=2), |
| 'K/I/J' : Item(status=' ', wc_rev=2), |
| 'K/I/J/kappa' : Item(status=' ', wc_rev=2), |
| 'K/I/eta' : Item(status=' ', wc_rev=2), |
| 'K/I/theta' : Item(status=' ', wc_rev=2), |
| 'K/upsilon' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Run_and_verify_commit() doesn't handle status of unversioned paths |
| # so manually confirm unversioned paths got copied and moved too. |
| unversioned_paths = [ |
| sbox.ospath('A/D/H/I/unversioned1'), |
| sbox.ospath('A/D/H/I/L_UNVERSIONED'), |
| os.path.join(wc_dir, 'A', 'D', 'H', 'I', 'L_UNVERSIONED', |
| 'unversioned3'), |
| sbox.ospath('A/D/H/I/J/unversioned2'), |
| sbox.ospath('K/I/unversioned1'), |
| sbox.ospath('K/I/L_UNVERSIONED'), |
| sbox.ospath('K/I/L_UNVERSIONED/unversioned3'), |
| sbox.ospath('K/I/J/unversioned2')] |
| for path in unversioned_paths: |
| if not os.path.exists(path): |
| raise svntest.Failure("Unversioned path '%s' not found." % path) |
| |
| def copy_added_paths_with_props(sbox): |
| "copy added uncommitted paths with props" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a new file, schedule it for addition and set properties |
| upsilon_path = sbox.ospath('A/D/upsilon') |
| svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") |
| svntest.actions.run_and_verify_svn(None, [], 'add', upsilon_path) |
| svntest.actions.run_and_verify_svn(None, [], 'propset', |
| 'foo', 'bar', upsilon_path) |
| |
| # Create a dir and schedule it for addition and set properties |
| I_path = sbox.ospath('A/D/I') |
| os.mkdir(I_path) |
| svntest.actions.run_and_verify_svn(None, [], 'add', I_path) |
| svntest.actions.run_and_verify_svn(None, [], 'propset', |
| 'foo', 'bar', I_path) |
| |
| # Verify all the adds took place correctly. |
| expected_status_after_adds = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status_after_adds.add({ |
| 'A/D/upsilon' : Item(status='A ', wc_rev='0'), |
| 'A/D/I' : Item(status='A ', wc_rev='0'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status_after_adds) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/D/upsilon' : Item(props={'foo' : 'bar'}, |
| contents="This is the file 'upsilon'\n"), |
| 'A/D/I' : Item(props={'foo' : 'bar'}), |
| }) |
| |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| # Copy added dir I to dir A/C |
| I_copy_path = sbox.ospath('A/C/I') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| I_path, I_copy_path) |
| |
| # Copy added file A/upsilon into dir A/C |
| upsilon_copy_path = sbox.ospath('A/C/upsilon') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| upsilon_path, upsilon_copy_path) |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/upsilon' : Item(verb='Adding'), |
| 'A/D/I' : Item(verb='Adding'), |
| 'A/C/upsilon' : Item(verb='Adding'), |
| 'A/C/I' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/upsilon' : Item(status=' ', wc_rev=2), |
| 'A/D/I' : Item(status=' ', wc_rev=2), |
| 'A/C/upsilon' : Item(status=' ', wc_rev=2), |
| 'A/C/I' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Tweak expected disk tree |
| expected_disk.add({ |
| 'A/C/upsilon' : Item(props={ 'foo' : 'bar'}, |
| contents="This is the file 'upsilon'\n"), |
| 'A/C/I' : Item(props={ 'foo' : 'bar'}), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| def copy_added_paths_to_URL(sbox): |
| "copy added path to URL" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a new file and schedule it for addition |
| upsilon_path = sbox.ospath('A/D/upsilon') |
| svntest.main.file_write(upsilon_path, "This is the file 'upsilon'\n") |
| svntest.actions.run_and_verify_svn(None, [], 'add', upsilon_path) |
| |
| # Create a dir with children and schedule it for addition |
| I_path = sbox.ospath('A/D/I') |
| J_path = os.path.join(I_path, 'J') |
| eta_path = os.path.join(I_path, 'eta') |
| theta_path = os.path.join(I_path, 'theta') |
| kappa_path = os.path.join(J_path, 'kappa') |
| os.mkdir(I_path) |
| os.mkdir(J_path) |
| svntest.main.file_write(eta_path, "This is the file 'eta'\n") |
| svntest.main.file_write(theta_path, "This is the file 'theta'\n") |
| svntest.main.file_write(kappa_path, "This is the file 'kappa'\n") |
| svntest.actions.run_and_verify_svn(None, [], 'add', I_path) |
| |
| # Verify all the adds took place correctly. |
| expected_status_after_adds = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status_after_adds.add({ |
| 'A/D/I' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/eta' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/J' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/J/kappa' : Item(status='A ', wc_rev='0'), |
| 'A/D/I/theta' : Item(status='A ', wc_rev='0'), |
| 'A/D/upsilon' : Item(status='A ', wc_rev='0'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status_after_adds) |
| |
| # Scatter some unversioned paths within the added dir I. |
| # These don't get copied in a WC->URL copy obviously. |
| unversioned_path_1 = os.path.join(I_path, 'unversioned1') |
| unversioned_path_2 = os.path.join(J_path, 'unversioned2') |
| L_path = os.path.join(I_path, "L_UNVERSIONED") |
| unversioned_path_3 = os.path.join(L_path, 'unversioned3') |
| svntest.main.file_write(unversioned_path_1, "An unversioned file\n") |
| svntest.main.file_write(unversioned_path_2, "An unversioned file\n") |
| os.mkdir(L_path) |
| svntest.main.file_write(unversioned_path_3, "An unversioned file\n") |
| |
| # Copy added file A/D/upsilon to URL://A/C/upsilon |
| upsilon_copy_URL = sbox.repo_url + '/A/C/upsilon' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '-m', '', |
| upsilon_path, upsilon_copy_URL) |
| |
| # Validate the mergeinfo of the copy destination (we expect none). |
| svntest.actions.run_and_verify_svn([], '.*W200017: Property.*not found', |
| 'propget', |
| SVN_PROP_MERGEINFO, upsilon_copy_URL) |
| |
| # Copy added dir A/D/I to URL://A/D/G/I |
| I_copy_URL = sbox.repo_url + '/A/D/G/I' |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '-m', '', |
| I_path, I_copy_URL) |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/I' : Item(verb='Adding'), |
| 'A/D/I/J' : Item(verb='Adding'), |
| 'A/D/I/J/kappa' : Item(verb='Adding'), |
| 'A/D/I/eta' : Item(verb='Adding'), |
| 'A/D/I/theta' : Item(verb='Adding'), |
| 'A/D/upsilon' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/I' : Item(status=' ', wc_rev=4), |
| 'A/D/I/J' : Item(status=' ', wc_rev=4), |
| 'A/D/I/J/kappa' : Item(status=' ', wc_rev=4), |
| 'A/D/I/eta' : Item(status=' ', wc_rev=4), |
| 'A/D/I/theta' : Item(status=' ', wc_rev=4), |
| 'A/D/upsilon' : Item(status=' ', wc_rev=4), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Created expected output for update |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/I' : Item(status='A '), |
| 'A/D/G/I/theta' : Item(status='A '), |
| 'A/D/G/I/J' : Item(status='A '), |
| 'A/D/G/I/J/kappa' : Item(status='A '), |
| 'A/D/G/I/eta' : Item(status='A '), |
| 'A/C/upsilon' : Item(status='A '), |
| }) |
| |
| # Created expected disk for update |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/D/G/I' : Item(), |
| 'A/D/G/I/theta' : Item("This is the file 'theta'\n"), |
| 'A/D/G/I/J' : Item(), |
| 'A/D/G/I/J/kappa' : Item("This is the file 'kappa'\n"), |
| 'A/D/G/I/eta' : Item("This is the file 'eta'\n"), |
| 'A/C/upsilon' : Item("This is the file 'upsilon'\n"), |
| 'A/D/I' : Item(), |
| 'A/D/I/J' : Item(), |
| 'A/D/I/J/kappa' : Item("This is the file 'kappa'\n"), |
| 'A/D/I/eta' : Item("This is the file 'eta'\n"), |
| 'A/D/I/theta' : Item("This is the file 'theta'\n"), |
| 'A/D/upsilon' : Item("This is the file 'upsilon'\n"), |
| 'A/D/I/L_UNVERSIONED/unversioned3' : Item("An unversioned file\n"), |
| 'A/D/I/L_UNVERSIONED' : Item(), |
| 'A/D/I/unversioned1' : Item("An unversioned file\n"), |
| 'A/D/I/J/unversioned2' : Item("An unversioned file\n"), |
| }) |
| |
| # Some more changes to the expected_status to reflect post update WC |
| expected_status.tweak(wc_rev=4) |
| expected_status.add({ |
| 'A/C' : Item(status=' ', wc_rev=4), |
| 'A/C/upsilon' : Item(status=' ', wc_rev=4), |
| 'A/D/G' : Item(status=' ', wc_rev=4), |
| 'A/D/G/I' : Item(status=' ', wc_rev=4), |
| 'A/D/G/I/theta' : Item(status=' ', wc_rev=4), |
| 'A/D/G/I/J' : Item(status=' ', wc_rev=4), |
| 'A/D/G/I/J/kappa' : Item(status=' ', wc_rev=4), |
| 'A/D/G/I/eta' : Item(status=' ', wc_rev=4), |
| }) |
| |
| # Update WC, the WC->URL copies above should be added |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| # Issue #1869. |
| @Issue(1869) |
| def move_to_relative_paths(sbox): |
| "move file using relative dst path names" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| E_path = sbox.ospath('A/B/E') |
| rel_path = os.path.join('..', '..', '..') |
| |
| current_dir = os.getcwd() |
| os.chdir(E_path) |
| svntest.main.run_svn(None, 'mv', 'beta', rel_path) |
| os.chdir(current_dir) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'beta' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B/E/beta'), |
| 'A/B/E/beta' : Item(status='D ', wc_rev='1', moved_to='beta') |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def move_from_relative_paths(sbox): |
| "move file using relative src path names" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| F_path = sbox.ospath('A/B/F') |
| beta_rel_path = os.path.join('..', 'E', 'beta') |
| |
| current_dir = os.getcwd() |
| os.chdir(F_path) |
| svntest.main.run_svn(None, 'mv', beta_rel_path, '.') |
| os.chdir(current_dir) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/beta' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B/E/beta'), |
| 'A/B/E/beta' : Item(status='D ', wc_rev='1', moved_to='A/B/F/beta') |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def copy_to_relative_paths(sbox): |
| "copy file using relative dst path names" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| E_path = sbox.ospath('A/B/E') |
| rel_path = os.path.join('..', '..', '..') |
| |
| current_dir = os.getcwd() |
| os.chdir(E_path) |
| svntest.main.run_svn(None, 'cp', 'beta', rel_path) |
| os.chdir(current_dir) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'beta' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def copy_from_relative_paths(sbox): |
| "copy file using relative src path names" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| F_path = sbox.ospath('A/B/F') |
| beta_rel_path = os.path.join('..', 'E', 'beta') |
| |
| current_dir = os.getcwd() |
| os.chdir(F_path) |
| svntest.main.run_svn(None, 'cp', beta_rel_path, '.') |
| os.chdir(current_dir) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/F/beta' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Test moving multiple files within a wc. |
| |
| def move_multiple_wc(sbox): |
| "svn mv multiple files to a common directory" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_path = sbox.ospath('A/D/H/chi') |
| psi_path = sbox.ospath('A/D/H/psi') |
| omega_path = sbox.ospath('A/D/H/omega') |
| E_path = sbox.ospath('A/B/E') |
| C_path = sbox.ospath('A/C') |
| |
| # Move chi, psi, omega and E to A/C |
| svntest.actions.run_and_verify_svn(None, [], 'mv', chi_path, psi_path, |
| omega_path, E_path, C_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(verb='Adding'), |
| 'A/C/psi' : Item(verb='Adding'), |
| 'A/C/omega' : Item(verb='Adding'), |
| 'A/C/E' : Item(verb='Adding'), |
| 'A/D/H/chi' : Item(verb='Deleting'), |
| 'A/D/H/psi' : Item(verb='Deleting'), |
| 'A/D/H/omega' : Item(verb='Deleting'), |
| 'A/B/E' : Item(verb='Deleting'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=2), |
| 'A/C/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/E' : Item(status=' ', wc_rev=2), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Removed the moved files |
| expected_status.remove('A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega', 'A/B/E/alpha', |
| 'A/B/E/beta', 'A/B/E') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test copying multiple files within a wc. |
| |
| def copy_multiple_wc(sbox): |
| "svn cp multiple files to a common directory" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_path = sbox.ospath('A/D/H/chi') |
| psi_path = sbox.ospath('A/D/H/psi') |
| omega_path = sbox.ospath('A/D/H/omega') |
| E_path = sbox.ospath('A/B/E') |
| C_path = sbox.ospath('A/C') |
| |
| # Copy chi, psi, omega and E to A/C |
| svntest.actions.run_and_verify_svn(None, [], 'cp', chi_path, psi_path, |
| omega_path, E_path, C_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(verb='Adding'), |
| 'A/C/psi' : Item(verb='Adding'), |
| 'A/C/omega' : Item(verb='Adding'), |
| 'A/C/E' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=2), |
| 'A/C/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/E' : Item(status=' ', wc_rev=2), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test moving multiple files within a repo. |
| |
| def move_multiple_repo(sbox): |
| "move multiple files within a repo" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_url = sbox.repo_url + '/A/D/H/chi' |
| psi_url = sbox.repo_url + '/A/D/H/psi' |
| omega_url = sbox.repo_url + '/A/D/H/omega' |
| E_url = sbox.repo_url + '/A/B/E' |
| C_url = sbox.repo_url + '/A/C' |
| |
| # Move three files and a directory in the repo to a different location |
| # in the repo |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| chi_url, psi_url, omega_url, E_url, C_url, |
| '-m', 'logmsg') |
| |
| # Update to HEAD, and check to see if the files really moved in the repo |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(status='A '), |
| 'A/C/psi' : Item(status='A '), |
| 'A/C/omega' : Item(status='A '), |
| 'A/C/E' : Item(status='A '), |
| 'A/C/E/alpha' : Item(status='A '), |
| 'A/C/E/beta' : Item(status='A '), |
| 'A/D/H/chi' : Item(status='D '), |
| 'A/D/H/psi' : Item(status='D '), |
| 'A/D/H/omega' : Item(status='D '), |
| 'A/B/E' : Item(status='D '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega', 'A/B/E/alpha', |
| 'A/B/E/beta', 'A/B/E') |
| expected_disk.add({ |
| 'A/C/chi' : Item(contents="This is the file 'chi'.\n"), |
| 'A/C/psi' : Item(contents="This is the file 'psi'.\n"), |
| 'A/C/omega' : Item(contents="This is the file 'omega'.\n"), |
| 'A/C/E' : Item(), |
| 'A/C/E/alpha' : Item(contents="This is the file 'alpha'.\n"), |
| 'A/C/E/beta' : Item(contents="This is the file 'beta'.\n"), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.remove('A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega', 'A/B/E/alpha', |
| 'A/B/E/beta', 'A/B/E') |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=2), |
| 'A/C/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/E' : Item(status=' ', wc_rev=2), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test copying multiple files within a repo. |
| |
| def copy_multiple_repo(sbox): |
| "copy multiple files within a repo" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_url = sbox.repo_url + '/A/D/H/chi' |
| psi_url = sbox.repo_url + '/A/D/H/psi' |
| omega_url = sbox.repo_url + '/A/D/H/omega' |
| E_url = sbox.repo_url + '/A/B/E' |
| C_url = sbox.repo_url + '/A/C' |
| |
| # Copy three files and a directory in the repo to a different location |
| # in the repo |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| chi_url, psi_url, omega_url, E_url, C_url, |
| '-m', 'logmsg') |
| |
| # Update to HEAD, and check to see if the files really moved in the repo |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(status='A '), |
| 'A/C/psi' : Item(status='A '), |
| 'A/C/omega' : Item(status='A '), |
| 'A/C/E' : Item(status='A '), |
| 'A/C/E/alpha' : Item(status='A '), |
| 'A/C/E/beta' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/C/chi' : Item(contents="This is the file 'chi'.\n"), |
| 'A/C/psi' : Item(contents="This is the file 'psi'.\n"), |
| 'A/C/omega' : Item(contents="This is the file 'omega'.\n"), |
| 'A/C/E' : Item(), |
| 'A/C/E/alpha' : Item(contents="This is the file 'alpha'.\n"), |
| 'A/C/E/beta' : Item(contents="This is the file 'beta'.\n"), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=2), |
| 'A/C/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/E' : Item(status=' ', wc_rev=2), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test moving copying multiple files from a repo to a wc |
| @Issue(2955) |
| def copy_multiple_repo_wc(sbox): |
| "copy multiple files from a repo to a wc" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_url = sbox.repo_url + '/A/D/H/chi' |
| psi_url = sbox.repo_url + '/A/D/H/psi' |
| omega_with_space_url = sbox.repo_url + '/A/D/H/omega 2' |
| E_url = sbox.repo_url + '/A/B/E' |
| C_path = sbox.ospath('A/C') |
| |
| # We need this in order to check that we don't end up with URI-encoded |
| # paths in the WC (issue #2955) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', '-m', 'log_msg', |
| sbox.repo_url + '/A/D/H/omega', |
| omega_with_space_url) |
| |
| # Perform the copy and check the output |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| chi_url, psi_url, omega_with_space_url, |
| E_url, C_path) |
| |
| # Commit the changes, and verify the content actually got copied |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(verb='Adding'), |
| 'A/C/psi' : Item(verb='Adding'), |
| 'A/C/omega 2' : Item(verb='Adding'), |
| 'A/C/E' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=3), |
| 'A/C/psi' : Item(status=' ', wc_rev=3), |
| 'A/C/omega 2' : Item(status=' ', wc_rev=3), |
| 'A/C/E' : Item(status=' ', wc_rev=3), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=3), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=3), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test moving copying multiple files from a wc to a repo |
| |
| def copy_multiple_wc_repo(sbox): |
| "copy multiple files from a wc to a repo" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| chi_path = sbox.ospath('A/D/H/chi') |
| psi_path = sbox.ospath('A/D/H/psi') |
| omega_path = sbox.ospath('A/D/H/omega') |
| E_path = sbox.ospath('A/B/E') |
| C_url = sbox.repo_url + '/A/C' |
| |
| # Perform the copy and check the output |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| chi_path, psi_path, omega_path, E_path, |
| C_url, '-m', 'logmsg') |
| |
| # Update to HEAD, and check to see if the files really got copied in the repo |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/chi' : Item(status='A '), |
| 'A/C/psi' : Item(status='A '), |
| 'A/C/omega' : Item(status='A '), |
| 'A/C/E' : Item(status='A '), |
| 'A/C/E/alpha' : Item(status='A '), |
| 'A/C/E/beta' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/C/chi': Item(contents="This is the file 'chi'.\n"), |
| 'A/C/psi': Item(contents="This is the file 'psi'.\n"), |
| 'A/C/omega': Item(contents="This is the file 'omega'.\n"), |
| 'A/C/E' : Item(), |
| 'A/C/E/alpha' : Item(contents="This is the file 'alpha'.\n"), |
| 'A/C/E/beta' : Item(contents="This is the file 'beta'.\n"), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/C/chi' : Item(status=' ', wc_rev=2), |
| 'A/C/psi' : Item(status=' ', wc_rev=2), |
| 'A/C/omega' : Item(status=' ', wc_rev=2), |
| 'A/C/E' : Item(status=' ', wc_rev=2), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=2), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| # Test copying local files using peg revision syntax |
| # (Issue 2546) |
| @Issue(2546) |
| def copy_peg_rev_local_files(sbox): |
| "copy local files using peg rev syntax" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| psi_path = sbox.ospath('A/D/H/psi') |
| new_iota_path = sbox.ospath('new_iota') |
| iota_path = sbox.ospath('iota') |
| sigma_path = sbox.ospath('sigma') |
| |
| psi_text = "This is the file 'psi'.\n" |
| iota_text = "This is the file 'iota'.\n" |
| |
| # Play a shell game with some WC files, then commit the changes back |
| # to the repository (making r2). |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| psi_path, new_iota_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| iota_path, psi_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| new_iota_path, iota_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 2', |
| wc_dir) |
| |
| # Copy using a peg rev (remember, the object at iota_path at HEAD |
| # was at psi_path back at r1). |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', |
| iota_path + '@HEAD', '-r', '1', |
| sigma_path) |
| |
| # Commit and verify disk contents |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', wc_dir, |
| '-m', 'rev 3') |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/D/H/psi', contents=iota_text) |
| expected_disk.add({ |
| 'iota' : Item(contents=psi_text), |
| 'A/D/H/psi' : Item(contents=iota_text), |
| 'sigma' : Item(contents=psi_text, props={}), |
| }) |
| |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Test copying local directories using peg revision syntax |
| # (Issue 2546) |
| @Issue(2546) |
| def copy_peg_rev_local_dirs(sbox): |
| "copy local dirs using peg rev syntax" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| E_path = sbox.ospath('A/B/E') |
| G_path = sbox.ospath('A/D/G') |
| I_path = sbox.ospath('A/D/I') |
| J_path = sbox.ospath('A/J') |
| alpha_path = os.path.join(E_path, 'alpha') |
| |
| # Make some changes to the repository |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| alpha_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 2', |
| wc_dir) |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', |
| E_path, I_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 3', |
| wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', |
| G_path, E_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 4', |
| wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', |
| I_path, G_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 5', |
| wc_dir) |
| |
| # Copy using a peg rev |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', |
| G_path + '@HEAD', '-r', '1', |
| J_path) |
| |
| # Commit and verify disk contents |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', wc_dir, |
| '-m', 'rev 6') |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/E/beta') |
| expected_disk.remove('A/B/E/alpha') |
| expected_disk.remove('A/D/G/pi') |
| expected_disk.remove('A/D/G/rho') |
| expected_disk.remove('A/D/G/tau') |
| expected_disk.add({ |
| 'A/B/E' : Item(), |
| 'A/B/E/pi' : Item(contents="This is the file 'pi'.\n"), |
| 'A/B/E/rho' : Item(contents="This is the file 'rho'.\n"), |
| 'A/B/E/tau' : Item(contents="This is the file 'tau'.\n"), |
| 'A/D/G' : Item(), |
| 'A/D/G/beta' : Item(contents="This is the file 'beta'.\n"), |
| 'A/J' : Item(), |
| 'A/J/alpha' : Item(contents="This is the file 'alpha'.\n"), |
| 'A/J/beta' : Item(contents="This is the file 'beta'.\n"), |
| }) |
| |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| # Test copying urls using peg revision syntax |
| # (Issue 2546) |
| @Issues(2546,3651) |
| def copy_peg_rev_url(sbox): |
| "copy urls using peg rev syntax" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| psi_path = sbox.ospath('A/D/H/psi') |
| new_iota_path = sbox.ospath('new_iota') |
| iota_path = sbox.ospath('iota') |
| iota_url = sbox.repo_url + '/iota' |
| sigma_url = sbox.repo_url + '/sigma' |
| |
| psi_text = "This is the file 'psi'.\n" |
| iota_text = "This is the file 'iota'.\n" |
| |
| # Make some changes to the repository |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| psi_path, new_iota_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| iota_path, psi_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| new_iota_path, iota_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', |
| '-m', 'rev 2', |
| wc_dir) |
| |
| # Copy using a peg rev |
| # Add an empty peg specifier ('@') to sigma_url when copying, to test for |
| # issue #3651 "svn copy does not eat peg revision within copy target path". |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', |
| iota_url + '@HEAD', '-r', '1', |
| sigma_url + '@', '-m', 'rev 3') |
| |
| # Validate the copy destination's mergeinfo (we expect none). |
| svntest.actions.run_and_verify_svn([], '.*W200017: Property.*not found', |
| 'propget', SVN_PROP_MERGEINFO, sigma_url) |
| |
| # Update to HEAD and verify disk contents |
| expected_output = svntest.wc.State(wc_dir, { |
| 'sigma' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('iota', contents=psi_text) |
| expected_disk.tweak('A/D/H/psi', contents=iota_text) |
| expected_disk.add({ |
| 'sigma' : Item(contents=psi_text), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.add({ |
| 'sigma' : Item(status=' ', wc_rev=3) |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Test copying an older revision of a wc directory in the wc. |
| def old_dir_wc_to_wc(sbox): |
| "copy old revision of wc dir to new dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| E = sbox.ospath('A/B/E') |
| E2 = sbox.ospath('E2') |
| E_url = sbox.repo_url + '/A/B/E' |
| alpha_url = E_url + '/alpha' |
| |
| # delete E/alpha in r2 |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', '', alpha_url) |
| |
| # delete E in r3 |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', '', E_url) |
| |
| # Copy an old revision of E into a new path in the WC |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '-r1', E, E2) |
| |
| # Create expected output tree. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'E2' : Item(verb='Adding'), |
| }) |
| |
| # Created expected status tree. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'E2' : Item(status=' ', wc_rev=4), |
| 'E2/alpha' : Item(status=' ', wc_rev=4), |
| 'E2/beta' : Item(status=' ', wc_rev=4), |
| }) |
| # Commit the one file. |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents in the wc |
| |
| def copy_make_parents_wc_wc(sbox): |
| "svn cp --parents WC_PATH WC_PATH" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| new_iota_path = sbox.ospath('X/Y/Z/iota') |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], 'cp', '--parents', |
| iota_path, new_iota_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(verb='Adding'), |
| 'X/Y' : Item(verb='Adding'), |
| 'X/Y/Z' : Item(verb='Adding'), |
| 'X/Y/Z/iota' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents in the wc with dst directory being |
| # precreated and unversioned |
| |
| def copy_make_parents_wc_wc_existing_unversioned_dst(sbox): |
| "svn cp --parents WC_PATH WC_PATH (ex. unver. dst)" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| new_iota_path = sbox.ospath('X/Y/Z/iota') |
| os.makedirs(os.path.dirname(new_iota_path)) |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '--parents', |
| iota_path, new_iota_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(verb='Adding'), |
| 'X/Y' : Item(verb='Adding'), |
| 'X/Y/Z' : Item(verb='Adding'), |
| 'X/Y/Z/iota' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents from the repo to the wc |
| |
| def copy_make_parents_repo_wc(sbox): |
| "svn cp --parents URL WC_PATH" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_url = sbox.repo_url + '/iota' |
| new_iota_path = sbox.ospath('X/Y/Z/iota') |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '--parents', |
| iota_url, new_iota_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(verb='Adding'), |
| 'X/Y' : Item(verb='Adding'), |
| 'X/Y/Z' : Item(verb='Adding'), |
| 'X/Y/Z/iota' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents from the repo to the wc with dst |
| # directory being precreated and unversioned |
| |
| def copy_make_parents_repo_wc_existing_unversioned_dst(sbox): |
| "svn cp --parents URL WC_PATH with (ex. unver. dst)" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_url = sbox.repo_url + '/iota' |
| new_iota_path = sbox.ospath('X/Y/Z/iota') |
| os.makedirs(os.path.dirname(new_iota_path)) |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '--parents', |
| iota_url, new_iota_path) |
| |
| # Create expected output |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(verb='Adding'), |
| 'X/Y' : Item(verb='Adding'), |
| 'X/Y/Z' : Item(verb='Adding'), |
| 'X/Y/Z/iota' : Item(verb='Adding'), |
| }) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Add the moved files |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents from the wc to the repo |
| |
| def copy_make_parents_wc_repo(sbox): |
| "svn cp --parents WC_PATH URL" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| new_iota_url = sbox.repo_url + '/X/Y/Z/iota' |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '--parents', |
| '-m', 'log msg', |
| iota_path, new_iota_url) |
| |
| # Update to HEAD and verify disk contents |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(status='A '), |
| 'X/Y' : Item(status='A '), |
| 'X/Y/Z' : Item(status='A '), |
| 'X/Y/Z/iota' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X' : Item(), |
| 'X/Y' : Item(), |
| 'X/Y/Z' : Item(), |
| 'X/Y/Z/iota' : Item(contents="This is the file 'iota'.\n"), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Test copying and creating parents from repo to repo |
| |
| def copy_make_parents_repo_repo(sbox): |
| "svn cp --parents URL URL" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_url = sbox.repo_url + '/iota' |
| new_iota_url = sbox.repo_url + '/X/Y/Z/iota' |
| |
| # Copy iota |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', '--parents', |
| '-m', 'log msg', |
| iota_url, new_iota_url) |
| |
| # Update to HEAD and verify disk contents |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X' : Item(status='A '), |
| 'X/Y' : Item(status='A '), |
| 'X/Y/Z' : Item(status='A '), |
| 'X/Y/Z/iota' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X' : Item(), |
| 'X/Y' : Item(), |
| 'X/Y/Z' : Item(), |
| 'X/Y/Z/iota' : Item(contents="This is the file 'iota'.\n"), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2), |
| 'X/Y' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z' : Item(status=' ', wc_rev=2), |
| 'X/Y/Z/iota' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Test for issue #2894 |
| # Can't perform URL to WC copy if URL needs URI encoding. |
| @Issue(2894) |
| def URI_encoded_repos_to_wc(sbox): |
| "copy a URL that needs URI encoding to WC" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_disk = svntest.main.greek_state.copy() |
| |
| 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", |
| ] |
| |
| def copy_URL_to_WC(URL_rel_path, dest_name, rev): |
| expected = svntest.verify.UnorderedOutput( |
| [ "A " + sbox.ospath(path_join(dest_name, p)) + "\n" |
| for p in A_paths ]) |
| expected_status.add( |
| { path_join(dest_name, p) : Item(status=' ', wc_rev=rev) |
| for p in A_paths }) |
| expected_disk.add( |
| { path_join(dest_name, p) : greek_file_item(p) |
| for p in A_paths }) |
| |
| # Make a copy |
| svntest.actions.run_and_verify_svn(expected, [], |
| 'copy', |
| sbox.repo_url + '/' + URL_rel_path, |
| os.path.join(wc_dir, |
| dest_name)) |
| |
| expected_output = svntest.wc.State(wc_dir, |
| {dest_name : Item(verb='Adding')}) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| copy_URL_to_WC('A', 'A COPY', 2) |
| copy_URL_to_WC('A COPY', 'A_COPY_2', 3) |
| |
| #---------------------------------------------------------------------- |
| # Issue #3068: copy source parent may be unversioned |
| @Issue(3068) |
| def allow_unversioned_parent_for_copy_src(sbox): |
| "copy wc in unversioned parent to other wc" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Make the "other" working copy |
| wc2_dir = sbox.add_wc_path('other') |
| svntest.actions.duplicate_dir(wc_dir, wc2_dir) |
| copy_to_path = sbox.ospath('A/copy_of_wc2') |
| |
| # Copy the wc-in-unversioned-parent working copy to our original wc. |
| svntest.actions.run_and_verify_svn(None, |
| [], |
| 'cp', |
| wc2_dir, |
| copy_to_path) |
| |
| def unneeded_parents(sbox): |
| "svn cp --parents FILE_URL DIR_URL" |
| |
| # In this message... |
| # |
| # http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=138738 |
| # From: Alexander Kitaev <Alexander.Kitaev@svnkit.com> |
| # To: dev@subversion.tigris.org |
| # Subject: 1.5.x segmentation fault on Repos to Repos copy |
| # Message-ID: <4830332A.6060301@svnkit.com> |
| # Date: Sun, 18 May 2008 15:46:18 +0200 |
| # |
| # ...Alexander Kitaev describes the bug: |
| # |
| # svn cp --parents SRC_FILE_URL DST_DIR_URL -m "message" |
| # |
| # SRC_FILE_URL - existing file |
| # DST_DIR_URL - existing directory |
| # |
| # Omitting "--parents" option makes above copy operation work as |
| # expected. |
| # |
| # Bug is in libsvn_client/copy.c:801, where "dir" should be |
| # checked for null before using it in svn_ra_check_path call. |
| # |
| # At first we couldn't reproduce it, but later he added this: |
| # |
| # Looks like there is one more condition to reproduce the problem - |
| # dst URL should has no more segments count than source one. |
| # |
| # In other words, if we had "/A/B" below instead of "/A" (adjusting |
| # expected_* accordingly, of course), the bug wouldn't reproduce. |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_url = sbox.repo_url + '/iota' |
| A_url = sbox.repo_url + '/A' |
| |
| # The --parents is unnecessary, but should still work (not segfault). |
| svntest.actions.run_and_verify_svn(None, [], 'cp', '--parents', |
| '-m', 'log msg', iota_url, A_url) |
| |
| # Verify that it worked. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/iota' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/iota' : Item(contents="This is the file 'iota'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/iota' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_update( |
| wc_dir, expected_output, expected_disk, expected_status) |
| |
| |
| def double_parents_with_url(sbox): |
| "svn cp --parents URL/src_dir URL/dst_dir" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| E_url = sbox.repo_url + '/A/B/E' |
| Z_url = sbox.repo_url + '/A/B/Z' |
| |
| # --parents shouldn't result in a double commit of the same directory. |
| svntest.actions.run_and_verify_svn(None, [], 'cp', '--parents', |
| '-m', 'log msg', E_url, Z_url) |
| |
| # Verify that it worked. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/Z/alpha' : Item(status='A '), |
| 'A/B/Z/beta' : Item(status='A '), |
| 'A/B/Z' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/B/Z/alpha' : Item(contents="This is the file 'alpha'.\n"), |
| 'A/B/Z/beta' : Item(contents="This is the file 'beta'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'A/B/Z/alpha' : Item(status=' ', wc_rev=2), |
| 'A/B/Z/beta' : Item(status=' ', wc_rev=2), |
| 'A/B/Z' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_update( |
| wc_dir, expected_output, expected_disk, expected_status) |
| |
| |
| # Used to cause corruption not fixable by 'svn cleanup'. |
| def copy_into_missing_dir(sbox): |
| "copy file into missing dir" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| A_path = sbox.ospath('A') |
| iota_path = sbox.ospath('iota') |
| |
| # Remove 'A' |
| svntest.main.safe_rmtree(A_path) |
| |
| # Copy into the now-missing dir. This used to give this error: |
| # svn: In directory '.' |
| # svn: Error processing command 'modify-entry' in '.' |
| # svn: Error modifying entry for 'A' |
| # svn: Entry 'A' is already under version control |
| svntest.actions.run_and_verify_svn(None, ".*: Path '.*' is not a directory", |
| 'cp', iota_path, A_path) |
| |
| # 'cleanup' should not error. |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cleanup', wc_dir) |
| |
| |
| def find_copyfrom_information_upstairs(sbox): |
| "renaming inside a copied subtree shouldn't hang" |
| |
| # The final command in this series would cause the client to hang... |
| # |
| # ${SVN} cp A A2 |
| # cd A2/B |
| # ${SVN} mkdir blah |
| # ${SVN} mv lambda blah |
| # |
| # ...because it wouldn't walk up past "" to find copyfrom information |
| # (which would be in A2/.svn/entries, not on A2/B/.svn/entries). |
| # Instead, it would keep thinking the parent of "" is "", and so |
| # loop forever, gobbling a little bit more memory with each iteration. |
| # |
| # Two things fixed this: |
| # |
| # 1) The client walks upward beyond CWD now, so it finds the |
| # copyfrom information. |
| # |
| # 2) Even if we do top out at "" without finding copyfrom information |
| # (say, because someone has corrupted their working copy), we'll |
| # still detect it and error, thus breaking the loop. |
| # |
| # This only tests case (1). We could test that (2) gets the expected |
| # error ("no parent with copyfrom information found above 'lambda'"), |
| # but we'd need to chroot to the top of the working copy or manually |
| # corrupt the wc by removing the copyfrom lines from A2/.svn/entries. |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| A_path = sbox.ospath('A') |
| A2_path = sbox.ospath('A2') |
| B2_path = os.path.join(A2_path, 'B') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', A_path, A2_path) |
| saved_cwd = os.getcwd() |
| try: |
| os.chdir(B2_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', 'blah') |
| svntest.actions.run_and_verify_svn(None, [], 'mv', 'lambda', 'blah') |
| finally: |
| os.chdir(saved_cwd) |
| |
| #---------------------------------------------------------------------- |
| |
| def change_case_of_hostname(input): |
| "Change the case of the hostname, try uppercase first" |
| |
| m = re.match(r"^(.*://)([^/]*)(.*)", input) |
| if m: |
| scheme = m.group(1) |
| host = m.group(2).upper() |
| if host == m.group(2): |
| host = m.group(2).lower() |
| |
| path = m.group(3) |
| |
| return scheme + host + path |
| |
| # regression test for issue #2475 - move file and folder |
| @Issue(2475) |
| def path_move_and_copy_between_wcs_2475(sbox): |
| "issue #2475 - move and copy between working copies" |
| sbox.build() |
| |
| # checkout a second working copy, use repository url with different case |
| wc2_dir = sbox.add_wc_path('2') |
| repo_url2 = change_case_of_hostname(sbox.repo_url) |
| |
| expected_output = svntest.main.greek_state.copy() |
| expected_output.wc_dir = wc2_dir |
| expected_output.tweak(status='A ', contents=None) |
| |
| expected_wc = svntest.main.greek_state |
| |
| # Do a checkout, and verify the resulting output and disk contents. |
| svntest.actions.run_and_verify_checkout(repo_url2, |
| wc2_dir, |
| expected_output, |
| expected_wc) |
| |
| # Copy a file from wc to wc2 |
| mu_path = sbox.ospath('A/mu') |
| E_path = os.path.join(wc2_dir, 'A', 'B', 'E') |
| |
| svntest.main.run_svn(None, 'cp', mu_path, E_path) |
| |
| # Copy a folder from wc to wc2 |
| C_path = sbox.ospath('A/C') |
| B_path = os.path.join(wc2_dir, 'A', 'B') |
| |
| svntest.main.run_svn(None, 'cp', C_path, B_path) |
| |
| # Move a file from wc to wc2 |
| mu_path = sbox.ospath('A/mu') |
| B_path = os.path.join(wc2_dir, 'A', 'B') |
| |
| svntest.main.run_svn(None, 'mv', mu_path, B_path) |
| |
| # Move a folder from wc to wc2 |
| C_path = sbox.ospath('A/C') |
| D_path = os.path.join(wc2_dir, 'A', 'D') |
| |
| svntest.main.run_svn(None, 'mv', C_path, D_path) |
| |
| # Verify modified status |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/C', status='D ') |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| expected_status2 = svntest.actions.get_virginal_state(wc2_dir, 1) |
| expected_status2.add({ 'A/B/mu' : |
| Item(status='A ', copied='+', wc_rev='-') }) |
| expected_status2.add({ 'A/B/C' : |
| Item(status='A ', copied='+', wc_rev='-') }) |
| expected_status2.add({ 'A/B/E/mu' : |
| Item(status='A ', copied='+', wc_rev='-') }) |
| expected_status2.add({ 'A/D/C' : |
| Item(status='A ', copied='+', wc_rev='-') }) |
| svntest.actions.run_and_verify_status(wc2_dir, expected_status2) |
| |
| |
| # regression test for issue #2475 - direct copy in the repository |
| # this test handles the 'direct move' case too, that uses the same code. |
| @Issue(2475) |
| def path_copy_in_repo_2475(sbox): |
| "issue #2475 - direct copy in the repository" |
| sbox.build() |
| |
| repo_url2 = change_case_of_hostname(sbox.repo_url) |
| |
| # Copy a file from repo to repo2 |
| mu_url = sbox.repo_url + '/A/mu' |
| E_url = repo_url2 + '/A/B/E' |
| |
| svntest.main.run_svn(None, 'cp', mu_url, E_url, '-m', 'copy mu to /A/B/E') |
| |
| # For completeness' sake, update to HEAD, and verify we have a full |
| # greek tree again, all at revision 2. |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'A/B/E/mu' : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({'A/B/E/mu' : Item("This is the file 'mu'.\n") }) |
| |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2) |
| expected_status.add({'A/B/E/mu' : Item(status=' ', wc_rev=2) }) |
| svntest.actions.run_and_verify_update(sbox.wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| def commit_copy_depth_empty(sbox): |
| "copy a wcdir, then commit it with --depth empty" |
| sbox.build() |
| |
| a = sbox.ospath('A') |
| new_a = sbox.ospath('new_A') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', a, new_a) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'ci', |
| new_a, '--depth', 'empty', |
| '-m', 'Copied directory') |
| |
| def copy_below_copy(sbox): |
| "copy a dir below a copied dir" |
| sbox.build() |
| |
| A = sbox.ospath('A') |
| new_A = sbox.ospath('new_A') |
| new_A_D = os.path.join(new_A, 'D') |
| new_A_new_D = os.path.join(new_A, 'new_D') |
| new_A_mu = os.path.join(new_A, 'mu') |
| new_A_new_mu = os.path.join(new_A, 'new_mu') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', A, new_A) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', new_A_D, new_A_new_D) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', new_A_mu, new_A_new_mu) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'new_A' : Item(verb='Adding'), |
| 'new_A/new_D' : Item(verb='Adding'), |
| 'new_A/new_mu' : Item(verb='Adding'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| expected_status.add({ |
| 'new_A' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/gamma' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/pi' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/rho' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/tau' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/chi' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/omega': Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/psi' : Item(status=' ', wc_rev='2'), |
| 'new_A/D' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/H' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/H/chi' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/H/omega' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/H/psi' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/G' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/G/rho' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/G/pi' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/G/tau' : Item(status=' ', wc_rev='2'), |
| 'new_A/D/gamma' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_mu' : Item(status=' ', wc_rev='2'), |
| 'new_A/B' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E/alpha' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E/beta' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/F' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/lambda' : Item(status=' ', wc_rev='2'), |
| 'new_A/C' : Item(status=' ', wc_rev='2'), |
| 'new_A/mu' : Item(status=' ', wc_rev='2'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(sbox.wc_dir, |
| expected_output, |
| expected_status) |
| |
| def move_below_move(sbox): |
| "move a dir below a moved dir" |
| sbox.build() |
| |
| A = sbox.ospath('A') |
| new_A = sbox.ospath('new_A') |
| new_A_D = os.path.join(new_A, 'D') |
| new_A_new_D = os.path.join(new_A, 'new_D') |
| new_A_mu = os.path.join(new_A, 'mu') |
| new_A_new_mu = os.path.join(new_A, 'new_mu') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', A, new_A) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', new_A_D, new_A_new_D) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mv', new_A_mu, new_A_new_mu) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'A' : Item(verb='Deleting'), |
| 'new_A/D' : Item(verb='Deleting'), |
| 'new_A/mu' : Item(verb='Deleting'), |
| 'new_A' : Item(verb='Adding'), |
| 'new_A/new_D' : Item(verb='Adding'), |
| 'new_A/new_mu' : Item(verb='Adding'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| expected_status.add({ |
| 'new_A' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/gamma' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/pi' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/rho' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/G/tau' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/chi' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/omega': Item(status=' ', wc_rev='2'), |
| 'new_A/new_D/H/psi' : Item(status=' ', wc_rev='2'), |
| 'new_A/new_mu' : Item(status=' ', wc_rev='2'), |
| 'new_A/B' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E/alpha' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/E/beta' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/F' : Item(status=' ', wc_rev='2'), |
| 'new_A/B/lambda' : Item(status=' ', wc_rev='2'), |
| 'new_A/C' : Item(status=' ', wc_rev='2'), |
| }) |
| |
| expected_status.remove('A', 'A/D', 'A/D/gamma', 'A/D/G', 'A/D/G/pi', |
| 'A/D/G/rho', 'A/D/G/tau', 'A/D/H', 'A/D/H/chi', |
| 'A/D/H/omega', 'A/D/H/psi', 'A/B', 'A/B/E', |
| 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda', |
| 'A/C', 'A/mu') |
| |
| svntest.actions.run_and_verify_commit(sbox.wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| def reverse_merge_move(sbox): |
| """reverse merge move""" |
| |
| # Alias for svntest.actions.run_and_verify_svn |
| rav_svn = svntest.actions.run_and_verify_svn |
| |
| wc_dir = sbox.wc_dir |
| a_dir = sbox.ospath('A') |
| a_repo_url = sbox.repo_url + '/A' |
| sbox.build() |
| |
| # Create another working copy path and checkout. |
| wc2_dir = sbox.add_wc_path('2') |
| rav_svn(None, [], 'co', sbox.repo_url, wc2_dir) |
| |
| # Update working directory and ensure that we are at revision 1. |
| rav_svn(exp_noop_up_out(1), [], 'up', wc_dir) |
| |
| # Add new folder and file, later commit |
| new_path = os.path.join(a_dir, 'New') |
| os.mkdir(new_path) |
| first_path = os.path.join(new_path, 'first') |
| svntest.main.file_append(first_path, 'appended first text') |
| svntest.main.run_svn(None, "add", new_path) |
| rav_svn(None, [], 'ci', wc_dir, '-m', 'Add new folder %s' % new_path) |
| rav_svn(exp_noop_up_out(2), [], 'up', wc_dir) |
| |
| # Reverse merge to revert previous changes and commit |
| rav_svn(None, [], 'merge', '-c', '-2', a_repo_url, a_dir) |
| rav_svn(None, [], 'ci', '-m', 'Reverting svn merge -c -2.', a_dir) |
| rav_svn(exp_noop_up_out(3), [], 'up', wc_dir) |
| |
| # Reverse merge again to undo last revert. |
| rav_svn(None, [], 'merge', '-c', '-3', a_repo_url, a_dir) |
| |
| # Move new added file to another one and commit. |
| second_path = os.path.join(new_path, 'second') |
| rav_svn(None, [], 'move', first_path, second_path) |
| rav_svn("Adding.*New|Adding.*first||Committed revision 4.", [], |
| 'ci', '-m', |
| 'Revert svn merge. svn mv %s %s.' % (first_path, second_path), a_dir) |
| |
| # Update second working copy. There was a bug (at least on the 1.6.x |
| # branch) in which this update received both "first" and "second". |
| expected_output = svntest.wc.State(wc2_dir, { |
| 'A/New' : Item(status='A '), |
| 'A/New/second' : Item(status='A '), |
| }) |
| svntest.actions.run_and_verify_update(wc2_dir, |
| expected_output, |
| None, |
| None) |
| |
| @Issue(3699) |
| def nonrecursive_commit_of_copy(sbox): |
| """commit only top of copy; check child behavior""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| main.run_svn(None, 'cp', sbox.ospath('A'), |
| sbox.ospath('A_new')) |
| main.run_svn(None, 'cp', sbox.ospath('A/D/G'), |
| sbox.ospath('A_new/G_new')) |
| main.run_svn(None, 'rm', sbox.ospath('A_new/C')) |
| main.run_svn(None, 'rm', sbox.ospath('A_new/B/E')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A_new' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A_new/D' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/G' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/H' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/H/psi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/H/chi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/H/omega' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/D/gamma' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/B' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/B/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/B/E' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A_new/B/E/alpha' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A_new/B/E/beta' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A_new/B/F' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/mu' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/C' : Item(status='D ', copied='+', wc_rev='-'), |
| 'A_new/G_new' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A_new/G_new/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/G_new/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_new/G_new/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A_new': Item(verb='Adding'), |
| }) |
| |
| # These nodes are added by the commit |
| expected_status.tweak('A_new', 'A_new/D', 'A_new/D/G', 'A_new/D/G/pi', |
| 'A_new/D/G/rho', 'A_new/D/G/tau', 'A_new/D/H', |
| 'A_new/D/H/psi', 'A_new/D/H/chi', 'A_new/D/H/omega', |
| 'A_new/D/gamma', 'A_new/B', 'A_new/B/lambda', |
| 'A_new/B/F', 'A_new/mu', |
| status=' ', copied=None, wc_rev='2') |
| |
| # And these are now normal deletes, because their parent was committed. |
| expected_status.tweak('A_new/C', 'A_new/B/E', 'A_new/B/E/alpha', |
| 'A_new/B/E/beta', copied=None, wc_rev='2') |
| |
| # 'A_new/G_new' and everything below should still be added |
| # as their operation root was not committed |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| [], |
| wc_dir, '--depth', 'immediates') |
| |
| # Regression test for issue #3474 - making a new subdir, moving files into it |
| # and then renaming the subdir, breaks history of the moved files. |
| @Issue(3474) |
| def copy_added_dir_with_copy(sbox): |
| """copy/mv of new dir with copied file keeps history""" |
| |
| sbox.build(read_only=True) |
| wc_dir = sbox.wc_dir |
| |
| new_dir = sbox.ospath('NewDir') |
| new_dir2 = sbox.ospath('NewDir2') |
| new_dir3 = sbox.ospath('NewDir3') |
| |
| # Alias for svntest.actions.run_and_verify_svn |
| rav_svn = svntest.actions.run_and_verify_svn |
| |
| rav_svn(None, [], 'mkdir', new_dir) |
| rav_svn(None, [], 'cp', sbox.ospath('A/mu'), new_dir) |
| rav_svn(None, [], 'cp', new_dir, new_dir2) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| expected_status.add( |
| { |
| 'NewDir' : Item(status='A ', wc_rev='0'), |
| 'NewDir/mu' : Item(status='A ', copied='+', wc_rev='-'), |
| 'NewDir2' : Item(status='A ', wc_rev='0'), |
| 'NewDir2/mu' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # move of added dir also retains copy history of children |
| rav_svn(None, [], 'mv', new_dir, new_dir3) |
| expected_status.remove('NewDir', 'NewDir/mu') |
| expected_status.add( |
| { |
| 'NewDir3' : Item(status='A ', wc_rev='0'), |
| 'NewDir3/mu' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| @Issue(3303) |
| def copy_broken_symlink(sbox): |
| """copy broken symlink""" |
| |
| ## See https://issues.apache.org/jira/browse/SVN-3303. ## |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| new_symlink = sbox.ospath('new_symlink') |
| copied_symlink = sbox.ospath('copied_symlink') |
| |
| # Alias for svntest.actions.run_and_verify_svn |
| rav_svn = svntest.actions.run_and_verify_svn |
| |
| sbox.simple_add_symlink('linktarget', 'new_symlink') |
| |
| rav_svn(None, [], 'cp', new_symlink, copied_symlink) |
| |
| # Check whether both new_symlink and copied_symlink are added to the |
| # working copy |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| expected_status.add( |
| { |
| 'new_symlink' : Item(status='A ', wc_rev='0'), |
| 'copied_symlink' : Item(status='A ', wc_rev='0'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| def move_dir_containing_move(sbox): |
| """move a directory containing moved node""" |
| |
| sbox.build() |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B/E/alpha'), |
| sbox.ospath('A/B/E/alpha_moved')) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B/F'), |
| sbox.ospath('A/B/F_moved')) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B'), |
| sbox.ospath('A/B_tmp')) |
| |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.tweak('A/B', status='D ', moved_to='A/B_tmp') |
| expected_status.tweak('A/B/E', |
| 'A/B/E/alpha', |
| 'A/B/E/beta', |
| 'A/B/F', |
| 'A/B/lambda', |
| status='D ') |
| expected_status.add({ |
| 'A/B_tmp' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B'), |
| # alpha has a revision that isn't reported by status. |
| 'A/B_tmp/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B_tmp/E/alpha' : Item(status='D ', copied='+', wc_rev='-', |
| moved_to='A/B_tmp/E/alpha_moved'), |
| 'A/B_tmp/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B_tmp/E/alpha'), |
| 'A/B_tmp/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B_tmp/F' : Item(status='D ', copied='+', wc_rev='-', |
| moved_to='A/B_tmp/F_moved'), |
| 'A/B_tmp/F_moved' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B_tmp/F'), |
| 'A/B_tmp/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B_tmp'), |
| sbox.ospath('A/B_moved')) |
| expected_status.tweak('A/B', moved_to='A/B_moved') |
| expected_status.remove('A/B_tmp', |
| 'A/B_tmp/E', |
| 'A/B_tmp/E/alpha', |
| 'A/B_tmp/E/alpha_moved', |
| 'A/B_tmp/E/beta', |
| 'A/B_tmp/F', |
| 'A/B_tmp/F_moved', |
| 'A/B_tmp/lambda') |
| expected_status.add({ |
| 'A/B_moved' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B'), |
| 'A/B_moved/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B_moved/E/alpha' : Item(status='D ', copied='+', wc_rev='-', |
| moved_to='A/B_moved/E/alpha_moved'), |
| 'A/B_moved/E/alpha_moved' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B_moved/E/alpha'), |
| 'A/B_moved/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B_moved/F' : Item(status='D ', copied='+', wc_rev='-', |
| moved_to='A/B_moved/F_moved'), |
| 'A/B_moved/F_moved' : Item(status='A ', copied='+', wc_rev='-', |
| moved_from='A/B_moved/F'), |
| 'A/B_moved/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'A/B' : Item(verb='Deleting'), |
| 'A/B_moved' : Item(verb='Adding'), |
| 'A/B_moved/E/alpha' : Item(verb='Deleting'), |
| 'A/B_moved/E/alpha_moved': Item(verb='Adding'), |
| 'A/B_moved/F' : Item(verb='Deleting'), |
| 'A/B_moved/F_moved' : Item(verb='Adding'), |
| }) |
| |
| expected_status.tweak('A/B_moved', |
| 'A/B_moved/E', |
| 'A/B_moved/E/alpha_moved', |
| 'A/B_moved/E/beta', |
| 'A/B_moved/F_moved', |
| 'A/B_moved/lambda', |
| status=' ', copied=None, wc_rev='2') |
| expected_status.remove('A/B', |
| 'A/B/E', |
| 'A/B/E/alpha', |
| 'A/B/E/beta', |
| 'A/B/F', |
| 'A/B/lambda', |
| 'A/B_moved/E/alpha', |
| 'A/B_moved/F') |
| expected_status.tweak('A/B_moved', 'A/B_moved/E/alpha_moved', |
| 'A/B_moved/F_moved', moved_from=None) |
| svntest.actions.run_and_verify_commit(sbox.wc_dir, |
| expected_output, |
| expected_status) |
| |
| def copy_dir_with_space(sbox): |
| """copy a directory with whitespace to one without""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('A/B/E'), |
| sbox.ospath('E with spaces')) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('A/B/E/alpha'), |
| sbox.ospath('E with spaces/al pha')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'E with spaces' : Item(verb='Adding'), |
| 'E with spaces/al pha' : Item(verb='Adding'), |
| }) |
| expected_status.add({ |
| 'E with spaces' : Item(status=' ', wc_rev='2'), |
| 'E with spaces/alpha' : Item(status=' ', wc_rev='2'), |
| 'E with spaces/beta' : Item(status=' ', wc_rev='2'), |
| 'E with spaces/al pha' : Item(status=' ', wc_rev='2'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('E with spaces'), |
| sbox.ospath('E also spaces') |
| ) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('E with spaces/al pha'), |
| sbox.ospath('E also spaces/al b') |
| ) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'E also spaces' : Item(verb='Adding'), |
| 'E also spaces/al b': Item(verb='Adding'), |
| }) |
| expected_status.add({ |
| 'E also spaces' : Item(status=' ', wc_rev='3'), |
| 'E also spaces/beta': Item(status=' ', wc_rev='3'), |
| 'E also spaces/al b': Item(status=' ', wc_rev='3'), |
| 'E also spaces/alpha': Item(status=' ', wc_rev='3'), |
| 'E also spaces/al pha': Item(status=' ', wc_rev='3'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('E with spaces'), |
| sbox.ospath('E new spaces') |
| ) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('E new spaces/al pha'), |
| sbox.ospath('E also spaces/al c') |
| ) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'E with spaces' : Item(verb='Deleting'), |
| 'E also spaces/al c': Item(verb='Adding'), |
| 'E new spaces' : Item(verb='Adding'), |
| 'E new spaces/al pha': Item(verb='Deleting'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'E also spaces' : Item(status=' ', wc_rev='3'), |
| 'E also spaces/beta': Item(status=' ', wc_rev='3'), |
| 'E also spaces/al b': Item(status=' ', wc_rev='3'), |
| 'E also spaces/al c': Item(status=' ', wc_rev='4'), |
| 'E also spaces/alpha': Item(status=' ', wc_rev='3'), |
| 'E also spaces/al pha': Item(status=' ', wc_rev='3'), |
| 'E new spaces' : Item(status=' ', wc_rev='4'), |
| 'E new spaces/alpha': Item(status=' ', wc_rev='4'), |
| 'E new spaces/beta' : Item(status=' ', wc_rev='4'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Regression test for issue #3676 |
| @Issue(3676) |
| def changed_data_should_match_checkout(sbox): |
| """changed data after commit should match checkout""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| A_B_E = sbox.ospath('A/B/E') |
| E_new = sbox.ospath('E_new') |
| |
| verify_dir = sbox.add_wc_path('verify') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'copy', A_B_E, E_new) |
| |
| sbox.simple_commit() |
| |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'co', sbox.repo_url, verify_dir) |
| |
| was_cwd = os.getcwd() |
| os.chdir(verify_dir) |
| |
| rv, verify_out, err = main.run_svn(None, 'status', '-v') |
| |
| os.chdir(was_cwd) |
| os.chdir(wc_dir) |
| verify_out = svntest.verify.UnorderedOutput(verify_out) |
| svntest.actions.run_and_verify_svn(verify_out, [], 'status', '-v') |
| os.chdir(was_cwd) |
| |
| # Regression test for issue #3676 for copies including directories |
| @Issue(3676) |
| def changed_dir_data_should_match_checkout(sbox): |
| """changed dir after commit should match checkout""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| A_B = sbox.ospath('A/B') |
| B_new = sbox.ospath('B_new') |
| |
| verify_dir = sbox.add_wc_path('verify') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'copy', A_B, B_new) |
| |
| sbox.simple_commit() |
| |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'co', sbox.repo_url, verify_dir) |
| |
| was_cwd = os.getcwd() |
| os.chdir(verify_dir) |
| |
| rv, verify_out, err = main.run_svn(None, 'status', '-v') |
| |
| os.chdir(was_cwd) |
| os.chdir(wc_dir) |
| rv, verify_out2, err = main.run_svn (None, 'status', '-v') |
| os.chdir(was_cwd) |
| |
| # The order of the status output is not absolutely defined, but |
| # otherwise should match |
| svntest.verify.verify_outputs(None, |
| sorted(verify_out2), None, |
| sorted(verify_out), None) |
| |
| def move_added_nodes(sbox): |
| """move added nodes""" |
| |
| sbox.build(read_only=True) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', |
| sbox.ospath('X'), |
| sbox.ospath('X/Y')) |
| |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.add({ |
| 'X' : Item(status='A ', wc_rev='0'), |
| 'X/Y' : Item(status='A ', wc_rev='0'), |
| }) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('X/Y'), |
| sbox.ospath('X/Z')) |
| expected_status.remove('X/Y') |
| expected_status.add({'X/Z' : Item(status='A ', wc_rev='0')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('X/Z'), |
| sbox.ospath('Z')) |
| expected_status.remove('X/Z') |
| expected_status.add({'Z' : Item(status='A ', wc_rev='0')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('Z'), |
| sbox.ospath('X/Z')) |
| expected_status.remove('Z') |
| expected_status.add({'X/Z' : Item(status='A ', wc_rev='0')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| def copy_over_deleted_dir(sbox): |
| "copy a directory over a deleted directory" |
| sbox.build(read_only = True) |
| |
| main.run_svn(None, 'rm', sbox.ospath('A/B')) |
| main.run_svn(None, 'cp', sbox.ospath('A/D'), |
| sbox.ospath('A/B')) |
| |
| @Issue(3314) |
| def mixed_rev_copy_del(sbox): |
| """copy mixed-rev and delete children""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Delete and commit A/B/E/alpha |
| svntest.main.run_svn(None, 'rm', sbox.ospath('A/B/E/alpha')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B/E/alpha', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E/alpha': Item(verb='Deleting'), |
| }) |
| expected_status.remove('A/B/E/alpha') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Update to r2, then update A/B/E/alpha and A/B/E/beta to r1 |
| svntest.main.run_svn(None, 'up', wc_dir) |
| expected_status.tweak(wc_rev=2) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E/alpha' : Item(status='A '), |
| }) |
| |
| expected_status.add({ |
| 'A/B/E/alpha' : Item(status=' ', wc_rev=1), |
| }) |
| expected_status.tweak('A/B/E/beta', wc_rev=1) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, None, |
| expected_status, [], False, |
| '-r1', |
| sbox.ospath('A/B/E/alpha'), |
| sbox.ospath('A/B/E/beta')) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Copy A/B/E to A/B/E_copy |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('A/B/E'), |
| sbox.ospath('A/B/E_copy')) |
| expected_status.add({ |
| 'A/B/E_copy' : Item(status='A ', copied='+', wc_rev='-'), |
| # In the entries world mixed revision copies have only a single op_root |
| 'A/B/E_copy/alpha' : Item(status='A ', copied='+', wc_rev='-', |
| entry_status=' '), |
| 'A/B/E_copy/beta' : Item(status='A ', copied='+', wc_rev='-', |
| entry_status=' '), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Delete A/B/E_copy/alpha and A/B/E_copy/beta |
| svntest.main.run_svn(None, 'rm', '--force', |
| sbox.ospath('A/B/E_copy/alpha'), |
| sbox.ospath('A/B/E_copy/beta')) |
| expected_status.tweak('A/B/E_copy/alpha', 'A/B/E_copy/beta', status='D ', |
| entry_status=None) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E_copy' : Item(verb='Adding'), |
| 'A/B/E_copy/beta' : Item(verb='Deleting'), |
| }) |
| expected_status.tweak('A/B/E_copy', wc_rev=3, copied=None, status=' ') |
| expected_status.remove('A/B/E_copy/alpha', 'A/B/E_copy/beta') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| def copy_delete_undo(sbox, use_revert): |
| "copy, delete child, undo" |
| |
| sbox.build(read_only=True) |
| wc_dir = sbox.wc_dir |
| |
| # Copy directory with children |
| svntest.main.run_svn(wc_dir, 'copy', |
| sbox.ospath('A/B/E'), sbox.ospath('A/B/E-copied')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B/E-copied' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/B/E-copied/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B/E-copied/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Delete a child |
| svntest.main.run_svn(wc_dir, 'rm', sbox.ospath('A/B/E-copied/alpha')) |
| expected_status.tweak('A/B/E-copied/alpha', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Undo the whole copy |
| if (use_revert): |
| svntest.main.run_svn(wc_dir, 'revert', '--recursive', |
| sbox.ospath('A/B/E-copied')) |
| svntest.main.safe_rmtree(sbox.ospath('A/B/E-copied')) |
| else: |
| svntest.main.run_svn(wc_dir, 'rm', '--force', sbox.ospath('A/B/E-copied')) |
| expected_status.remove('A/B/E-copied', |
| 'A/B/E-copied/alpha', |
| 'A/B/E-copied/beta') |
| |
| # Undo via revert FAILs here because a wq item remains |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Copy a directory without children. |
| svntest.main.run_svn(wc_dir, 'copy', |
| sbox.ospath('A/B/F'), sbox.ospath('A/B/E-copied')) |
| expected_status.add({ |
| 'A/B/E-copied' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| def copy_delete_delete(sbox): |
| "copy, delete child, delete copy" |
| copy_delete_undo(sbox, False) |
| |
| @Issue(3784) |
| def copy_delete_revert(sbox): |
| "copy, delete child, revert copy" |
| copy_delete_undo(sbox, True) |
| |
| # See also delete_replaced_file() which does the same for a file. |
| def delete_replace_delete(sbox): |
| "delete a directory scheduled for replacement" |
| |
| sbox.build(read_only=True) |
| wc_dir = sbox.wc_dir |
| |
| # Delete directory with children |
| svntest.main.run_svn(wc_dir, 'rm', sbox.ospath('A/B/E')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Replace with directory with different children |
| svntest.main.run_svn(wc_dir, 'copy', |
| sbox.ospath('A/D/G'), sbox.ospath('A/B/E')) |
| expected_status.tweak('A/B/E', status='R ', copied='+', wc_rev='-') |
| expected_status.add({ |
| 'A/B/E/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B/E/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/B/E/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| # A/B/E/alpha and A/B/E/beta show up as deleted, is that right? |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Delete replacement |
| svntest.main.run_svn(wc_dir, 'rm', '--force', sbox.ospath('A/B/E')) |
| expected_status.tweak('A/B/E', status='D ', copied=None, wc_rev='1') |
| expected_status.remove('A/B/E/pi', 'A/B/E/rho', 'A/B/E/tau') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| A_B_children = ['A/B/lambda', 'A/B/F', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/E'] |
| A_D_children = ['A/D/gamma', 'A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau', |
| 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega'] |
| |
| def copy_repos_over_deleted_same_kind(sbox): |
| "copy repos node over deleted node, same kind" |
| sbox.build(read_only = True) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| # Set up some deleted paths |
| sbox.simple_rm('iota', 'A/B') |
| for path in ['iota', 'A/B'] + A_B_children: |
| expected_status.tweak(path, status='D ') |
| |
| # Test copying |
| main.run_svn(None, 'cp', sbox.repo_url + '/A/mu', sbox.ospath('iota')) |
| expected_status.tweak('iota', status='R ', wc_rev='-', copied='+') |
| main.run_svn(None, 'cp', sbox.repo_url + '/A/D', sbox.ospath('A/B')) |
| expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+') |
| for child in A_D_children: |
| expected_status.add({ child.replace('A/D', 'A/B'): |
| Item(status=' ', wc_rev='-', copied='+')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| def copy_repos_over_deleted_other_kind(sbox): |
| "copy repos node over deleted node, other kind" |
| sbox.build(read_only = True) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| # Set up some deleted paths |
| sbox.simple_rm('iota', 'A/B') |
| for path in ['iota', 'A/B'] + A_B_children: |
| expected_status.tweak(path, status='D ') |
| |
| # Test copying |
| main.run_svn(None, 'cp', sbox.repo_url + '/iota', sbox.ospath('A/B')) |
| expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+') |
| expected_status.remove(*A_B_children) |
| main.run_svn(None, 'cp', sbox.repo_url + '/A/B', sbox.ospath('iota')) |
| expected_status.tweak('iota', status='R ', wc_rev='-', copied='+') |
| for child in A_B_children: |
| expected_status.add({ child.replace('A/B', 'iota'): |
| Item(status=' ', wc_rev='-', copied='+')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| def copy_wc_over_deleted_same_kind(sbox): |
| "copy WC node over a deleted node, same kind" |
| sbox.build(read_only = True) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| # Set up some deleted paths |
| sbox.simple_rm('iota', 'A/B') |
| for path in ['iota', 'A/B'] + A_B_children: |
| expected_status.tweak(path, status='D ') |
| |
| # Test copying |
| main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('iota')) |
| expected_status.tweak('iota', status='R ', wc_rev='-', copied='+') |
| main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('A/B')) |
| expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+') |
| for child in A_D_children: |
| expected_status.add({ child.replace('A/D', 'A/B'): |
| Item(status=' ', wc_rev='-', copied='+')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| def copy_wc_over_deleted_other_kind(sbox): |
| "copy WC node over deleted node, other kind" |
| sbox.build(read_only = True) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| |
| # Set up some deleted paths |
| sbox.simple_rm('iota', 'A/B') |
| for path in ['iota', 'A/B'] + A_B_children: |
| expected_status.tweak(path, status='D ') |
| |
| # Test copying |
| main.run_svn(None, 'cp', sbox.ospath('A/mu'), sbox.ospath('A/B')) |
| expected_status.tweak('A/B', status='R ', wc_rev='-', copied='+') |
| expected_status.remove(*A_B_children) |
| main.run_svn(None, 'cp', sbox.ospath('A/D'), sbox.ospath('iota')) |
| expected_status.tweak('iota', status='R ', wc_rev='-', copied='+') |
| for child in A_D_children: |
| expected_status.add({ child.replace('A/D', 'iota'): |
| Item(status=' ', wc_rev='-', copied='+')}) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| def move_wc_and_repo_dir_to_itself(sbox): |
| "move wc and repo dir to itself" |
| sbox.build(read_only = True) |
| wc_dir = sbox.ospath('A') |
| repo_url = sbox.repo_url + '/A' |
| |
| # try to move wc dir to itself |
| svntest.actions.run_and_verify_svn([], |
| '.*Cannot move path.* into itself.*', |
| 'move', wc_dir, wc_dir) |
| |
| # try to move repo dir to itself |
| svntest.actions.run_and_verify_svn([], |
| '.*Cannot move URL.* into itself.*', |
| 'move', repo_url, repo_url) |
| |
| @Issues(2763,3314) |
| def copy_wc_url_with_absent(sbox): |
| "copy wc to url with several absent children" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # A/B a normal delete |
| sbox.simple_rm('A/B') |
| |
| # A/no not-present but in HEAD |
| sbox.simple_copy('A/mu', 'A/no') |
| sbox.simple_commit('A/no') |
| svntest.main.run_svn(None, 'up', '-r', '1', sbox.ospath('A/no')) |
| |
| # A/mu not-present and not in HEAD |
| sbox.simple_rm('A/mu') |
| sbox.simple_commit('A/mu') |
| |
| # A/D excluded |
| svntest.main.run_svn(None, 'up', '--set-depth', 'exclude', |
| sbox.ospath('A/D')) |
| |
| # Test issue #3314 after copy |
| sbox.simple_copy('A', 'A_copied') |
| svntest.main.run_svn(None, 'ci', sbox.ospath('A_copied'), |
| '-m', 'Commit A_copied') |
| |
| # This tests issue #2763 |
| svntest.main.run_svn(None, 'cp', sbox.ospath('A'), |
| '^/A_tagged', '-m', 'Tag A') |
| |
| # And perform a normal commit |
| svntest.main.run_svn(None, 'ci', sbox.ospath('A'), |
| '-m', 'Commit A') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A_tagged' : Item(status='A '), |
| 'A_tagged/D' : Item(status='A '), |
| 'A_tagged/D/gamma' : Item(status='A '), |
| 'A_tagged/D/H' : Item(status='A '), |
| 'A_tagged/D/H/psi' : Item(status='A '), |
| 'A_tagged/D/H/chi' : Item(status='A '), |
| 'A_tagged/D/H/omega': Item(status='A '), |
| 'A_tagged/D/G' : Item(status='A '), |
| 'A_tagged/D/G/pi' : Item(status='A '), |
| 'A_tagged/D/G/rho' : Item(status='A '), |
| 'A_tagged/D/G/tau' : Item(status='A '), |
| 'A_tagged/C' : Item(status='A '), |
| |
| 'A/no' : Item(status='A '), |
| }) |
| |
| # This should bring in A_tagged and A/no |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| None) |
| |
| # And now bring in the excluded nodes from A and A_copied |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D' : Item(status='A '), |
| 'A/D/G' : Item(status='A '), |
| 'A/D/G/pi' : Item(status='A '), |
| 'A/D/G/tau' : Item(status='A '), |
| 'A/D/G/rho' : Item(status='A '), |
| 'A/D/H' : Item(status='A '), |
| 'A/D/H/psi' : Item(status='A '), |
| 'A/D/H/chi' : Item(status='A '), |
| 'A/D/H/omega' : Item(status='A '), |
| 'A/D/gamma' : Item(status='A '), |
| |
| 'A_copied/D' : Item(status='A '), |
| 'A_copied/D/H' : Item(status='A '), |
| 'A_copied/D/H/omega': Item(status='A '), |
| 'A_copied/D/H/psi' : Item(status='A '), |
| 'A_copied/D/H/chi' : Item(status='A '), |
| 'A_copied/D/G' : Item(status='A '), |
| 'A_copied/D/G/tau' : Item(status='A '), |
| 'A_copied/D/G/rho' : Item(status='A '), |
| 'A_copied/D/G/pi' : Item(status='A '), |
| 'A_copied/D/gamma' : Item(status='A '), |
| }) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| None, |
| [], False, |
| wc_dir, '--set-depth', 'infinity') |
| |
| # Except for A/no, the 3 directories should now have the same children |
| |
| items = { |
| '' : Item(status=' ', wc_rev='6'), |
| 'C' : Item(status=' ', wc_rev='6'), |
| 'D' : Item(status=' ', wc_rev='6'), |
| 'D/gamma' : Item(status=' ', wc_rev='6'), |
| 'D/H' : Item(status=' ', wc_rev='6'), |
| 'D/H/psi' : Item(status=' ', wc_rev='6'), |
| 'D/H/chi' : Item(status=' ', wc_rev='6'), |
| 'D/H/omega' : Item(status=' ', wc_rev='6'), |
| 'D/G' : Item(status=' ', wc_rev='6'), |
| 'D/G/pi' : Item(status=' ', wc_rev='6'), |
| 'D/G/tau' : Item(status=' ', wc_rev='6'), |
| 'D/G/rho' : Item(status=' ', wc_rev='6'), |
| } |
| |
| expected_status = svntest.wc.State(sbox.ospath('A_copied'), items) |
| svntest.actions.run_and_verify_status(sbox.ospath('A_copied'), |
| expected_status) |
| |
| expected_status = svntest.wc.State(sbox.ospath('A_tagged'), items) |
| svntest.actions.run_and_verify_status(sbox.ospath('A_tagged'), |
| expected_status) |
| |
| expected_status.add({ |
| 'no' : Item(status=' ', wc_rev='6') |
| }) |
| |
| expected_status = svntest.wc.State(sbox.ospath('A'), items) |
| svntest.actions.run_and_verify_status(sbox.ospath('A'), |
| expected_status) |
| |
| |
| def copy_url_shortcut(sbox): |
| "copy using URL shortcut source" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Can't use ^/A/D/G shortcut here because wc/X is unversioned. |
| svntest.actions.run_and_verify_svn(None, [], 'copy', |
| sbox.ospath('A/D/G'), sbox.ospath('X')) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| sbox.ospath('X/pi')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'X' : Item(status='A ', copied='+', wc_rev='-'), |
| 'X/pi' : Item(status='D ', copied='+', wc_rev='-'), |
| 'X/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'X/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Can use ^/A/D/G even though X/pi is a delete within a copy. |
| svntest.actions.run_and_verify_svn(None, [], 'copy', |
| '^/A/D/G/pi', sbox.ospath('X/pi')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'X' : Item(status='A ', copied='+', wc_rev='-'), |
| 'X/pi' : Item(status='R ', copied='+', wc_rev='-', entry_status=' '), |
| 'X/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'X/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| # Regression test for issue #3865: 'svn' on Windows cannot address |
| # scheduled-for-delete file, if another file differing only in case is |
| # present on disk |
| @Issue(3865) |
| def deleted_file_with_case_clash(sbox): |
| """address a deleted file hidden by case clash""" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| iota2_path = sbox.ospath('iota2') |
| IOTA_path = sbox.ospath('IOTA') |
| iota_url = sbox.repo_url + '/iota' |
| |
| # Perform a case-only rename in two steps. |
| svntest.main.run_svn(None, 'move', iota_path, iota2_path) |
| svntest.main.run_svn(None, 'move', iota2_path, IOTA_path) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'iota' : Item(status='D ', wc_rev=1, moved_to='IOTA'), |
| 'IOTA' : Item(status='A ', copied='+', wc_rev='-', moved_from='iota'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Perform 'info' calls on both the deleted and added paths, to see if |
| # we get the correct information. The deleted path is not on disk and |
| # hidden by the on-disk case-clashing file, but we should be able to |
| # target it explicitly because it's in the wc-db. |
| expected_info_iota = {'Path' : re.escape(iota_path), |
| 'Schedule' : 'delete', |
| 'Copied From URL': None, |
| } |
| svntest.actions.run_and_verify_info([expected_info_iota], iota_path) |
| |
| expected_info_IOTA = {'Path' : re.escape(IOTA_path), |
| 'Schedule' : 'add', |
| 'Copied From URL': iota_url, |
| } |
| svntest.actions.run_and_verify_info([expected_info_IOTA], IOTA_path) |
| |
| def copy_base_of_deleted(sbox): |
| """copy -rBASE deleted""" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', sbox.ospath('A/mu')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', '-rBASE', |
| sbox.ospath('A/mu'), sbox.ospath('A/mu2')) |
| expected_status.add({ |
| 'A/mu2' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| |
| |
| # Regression test for issue #3702: Unable to perform case-only rename |
| # on windows. |
| @Issue(3702) |
| # APR's apr_filepath_merge() with APR_FILEPATH_TRUENAME is broken on OS X. |
| @XFail(svntest.main.is_os_darwin) |
| def case_only_rename(sbox): |
| """case-only rename""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| IoTa_path = sbox.ospath('IoTa') |
| B_path = sbox.ospath('A/B') |
| b_path = sbox.ospath('A/b') |
| |
| # Perform a couple of case-only renames. |
| svntest.main.run_svn(None, 'move', iota_path, IoTa_path) |
| svntest.main.run_svn(None, 'move', B_path, b_path) |
| |
| # Create expected status. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| |
| 'iota' : Item(status='D ', wc_rev=1, moved_to='IoTa'), |
| 'IoTa' : Item(status='A ', copied='+', wc_rev='-', moved_from='iota'), |
| 'A/B' : Item(status='D ', wc_rev='1', moved_to='A/b'), |
| 'A/B/lambda' : Item(status='D ', wc_rev='1'), |
| 'A/B/E' : Item(status='D ', wc_rev='1'), |
| 'A/B/E/alpha' : Item(status='D ', wc_rev='1'), |
| 'A/B/E/beta' : Item(status='D ', wc_rev='1'), |
| 'A/B/F' : Item(status='D ', wc_rev='1'), |
| 'A/b' : Item(status='A ', copied='+', wc_rev='-', moved_from='A/B'), |
| 'A/b/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/b/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/b/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/b/F' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/b/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| }) |
| |
| # Test that the necessary deletes and adds are present in status. |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| @XFail() |
| @Issue(3899) |
| def copy_and_move_conflicts(sbox): |
| """copy and move conflicts""" |
| |
| # The destination of a copy or move operation should *not* be |
| # conflicted, and should contain the "mine-full" contents. |
| |
| sbox.build() |
| wc = sbox.ospath |
| def url(relpath): |
| return '/'.join([sbox.repo_url, relpath]) |
| |
| # Create an assortment of conflicts. |
| # text A/B/E/alpha |
| # text (resolved by deleting markers) A/B/E/alpha |
| # property (dir) A/D/H |
| # property (file) A/D/H/chi |
| # tree: local delete, incoming edit A/D/gamma |
| # tree: local edit, incoming delete A/D/G |
| # tree: local add, incoming add A/Q |
| # tree: local missing, incoming edit A/B/E/sigma |
| |
| ### As we improve tree-conflict handling, this test may need some |
| ### maintenance. |
| |
| # Create a branch for merging. |
| run_svn(None, 'cp', url('A'), url('A2'), '-m', make_log_msg()) # r2 |
| sbox.simple_update() |
| |
| # This revision won't be included in the merge, producing a "local |
| # missing" tree conflict. |
| file_write(wc('A2/B/E/sigma'), "New for merge.\n") |
| sbox.simple_add('A2/B/E/sigma') |
| |
| sbox.simple_commit('A2') # r3 |
| |
| # Make "incoming" changes in A2 for the merge |
| # incoming edits |
| file_append(wc('A2/B/E/alpha'), "Edit for merge\n") |
| file_append(wc('A2/B/E/beta'), "Edit for merge\n") |
| file_append(wc('A2/B/E/sigma'), "Edit for merge\n") |
| sbox.simple_propset('foo', '99', 'A2/D/H') |
| sbox.simple_propset('foo', '99', 'A2/D/H/chi') |
| # incoming add |
| sbox.simple_mkdir('A2/Q') |
| file_write(wc('A2/Q/zeta'), "New for merge\n") |
| sbox.simple_add('A2/Q/zeta') |
| |
| sbox.simple_commit('A2') # r4 |
| |
| # Make some "local" changes in A before the merge. |
| # local edit |
| file_append(wc('A/B/E/alpha'), "Local edit\n") |
| file_append(wc('A/B/E/beta'), "Local edit\n") |
| sbox.simple_propset('foo', '100', 'A/D/H') |
| sbox.simple_propset('foo', '100', 'A/D/H/chi') |
| # local add |
| sbox.simple_mkdir('A/Q') |
| file_write(wc('A/Q/sigma'), "New local file\n") |
| sbox.simple_add('A/Q/sigma') |
| |
| # Make some "incoming" changes in A before the update. |
| # incoming edit |
| file_append(wc('A/D/gamma'), "Edit for merge\n") |
| # incoming delete |
| sbox.simple_rm('A/D/G') |
| |
| sbox.simple_commit('A') # r5 |
| |
| # Roll back, make local, uncommitted changes. |
| run_svn(None, 'up', '-r', 4, sbox.wc_dir) |
| # local delete |
| sbox.simple_rm('A/D/gamma') |
| # local edit |
| file_append(wc('A/D/G/rho'), "Local edit\n") |
| |
| # Update to reveal the "local {delete,edit'}" tree conflicts, |
| # which we can't yet catch when merging. |
| sbox.simple_update() |
| |
| # Merge just one revision to reveal more conflicts. |
| run_svn(None, 'merge', '-c', 4, url('A2'), wc('A')) |
| |
| # Resolve one text conflict via marker file deletion. |
| os.remove(wc('A/B/E/beta.merge-left.r3')) |
| os.remove(wc('A/B/E/beta.working')) |
| os.remove(wc('A/B/E/beta')) |
| os.rename(wc('A/B/E/beta.merge-right.r4'), wc('A/B/E/beta')) |
| |
| # Prepare for local copies and moves. |
| sbox.simple_mkdir('copy-dest') |
| sbox.simple_mkdir('move-dest') |
| |
| # Copy conflict victims. |
| sbox.simple_copy('A/B/E/alpha', 'copy-dest') |
| sbox.simple_copy('A/D/H', 'copy-dest') |
| sbox.simple_copy('A/D/G', 'copy-dest') |
| sbox.simple_copy('A/Q', 'copy-dest') |
| |
| # Copy directories with conflicted children. |
| sbox.simple_copy('A/B', 'copy-dest') |
| sbox.simple_copy('A/D', 'copy-dest') |
| |
| # Everything copied without conflicts. The entry_status for D/G is |
| # for 1.6 compatibility (see notes/api-errata/1.7/wc003.xt). |
| expected_status = svntest.wc.State(wc('copy-dest'), { |
| '' : Item(status='A ', wc_rev=0), |
| 'B' : Item(status='A ', copied='+', wc_rev='-'), |
| 'B/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'), |
| 'B/E/beta' : Item(status='M ', copied='+', wc_rev='-'), |
| 'B/F' : Item(status=' ', copied='+', wc_rev='-'), |
| 'B/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D' : Item(status='A ', copied='+', wc_rev='-'), |
| 'D/G' : Item(status='A ', copied='+', wc_rev='-', |
| entry_status=' '), |
| 'D/G/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/G/rho' : Item(status='M ', copied='+', wc_rev='-'), |
| 'D/G/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/H' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/H/chi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/H/omega' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/H/psi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'D/gamma' : Item(status='D ', copied='+', wc_rev='-'), |
| 'G' : Item(status='A ', copied='+', wc_rev='-'), |
| 'G/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'G/rho' : Item(status='M ', copied='+', wc_rev='-'), |
| 'G/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| 'H' : Item(status='A ', copied='+', wc_rev='-'), |
| 'H/chi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'H/omega' : Item(status=' ', copied='+', wc_rev='-'), |
| 'H/psi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'Q' : Item(status='A ', copied='+', wc_rev='-'), |
| 'Q/sigma' : Item(status=' ', copied='+', wc_rev='-'), |
| 'alpha' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_status(wc('copy-dest'), expected_status) |
| |
| # Only the local changes appear at the copy destinations. Note that |
| # B/E/beta had been resolved via marker-file deletion before the copy. |
| expected_disk = svntest.wc.State('', { |
| 'B/E/alpha' : Item(contents="This is the file 'alpha'.\n" |
| "Local edit\n"), |
| 'B/E/beta' : Item(contents="This is the file 'beta'.\n" |
| "Edit for merge\n"), |
| 'B/F' : Item(), |
| 'B/lambda' : Item(contents="This is the file 'lambda'.\n"), |
| 'D/G/pi' : Item(contents="This is the file 'pi'.\n"), |
| 'D/G/rho' : Item(contents="This is the file 'rho'.\n" |
| "Local edit\n"), |
| 'D/G/tau' : Item(contents="This is the file 'tau'.\n"), |
| 'D/H' : Item(props={'foo':'100'}), |
| 'D/H/chi' : Item(contents="This is the file 'chi'.\n", |
| props={'foo':'100'}), |
| 'D/H/omega' : Item(contents="This is the file 'omega'.\n"), |
| 'D/H/psi' : Item(contents="This is the file 'psi'.\n"), |
| 'G/pi' : Item(contents="This is the file 'pi'.\n"), |
| 'G/rho' : Item(contents="This is the file 'rho'.\n" |
| "Local edit\n"), |
| 'G/tau' : Item(contents="This is the file 'tau'.\n"), |
| 'H' : Item(props={'foo':'100'}), |
| 'H/chi' : Item(contents="This is the file 'chi'.\n", |
| props={'foo':'100'}), |
| 'H/omega' : Item(contents="This is the file 'omega'.\n"), |
| 'H/psi' : Item(contents="This is the file 'psi'.\n"), |
| 'Q/sigma' : Item(contents="New local file\n"), |
| 'alpha' : Item(contents="This is the file 'alpha'.\n" |
| "Local edit\n"), |
| }) |
| svntest.actions.verify_disk(wc('copy-dest'), expected_disk, True) |
| |
| # Move conflict victims. |
| sbox.simple_move('A/B/E/alpha', 'move-dest') |
| sbox.simple_move('A/D/H', 'move-dest') |
| sbox.simple_move('A/D/G', 'move-dest') |
| sbox.simple_move('A/Q', 'move-dest') |
| |
| # Move directories with conflicted children. |
| sbox.simple_move('A/B', 'move-dest') |
| sbox.simple_move('A/D', 'move-dest') |
| |
| # Expect same status and disk content as at the copy destination, except |
| # that A/B/E/alpha, A/D/G, and A/D/H were moved away first. |
| expected_status.wc_dir = wc('move-dest') |
| expected_status.tweak('B/E/alpha', |
| 'D/H', |
| 'D/H/chi', |
| 'D/H/omega', |
| 'D/H/psi', |
| status='D ') |
| # A/D/G had been re-added from r4 due to a "local edit, incoming delete" |
| # tree conflict, so moving it away has a different effect. |
| expected_status.remove('D/G', |
| 'D/G/pi', |
| 'D/G/rho', |
| 'D/G/tau') |
| expected_status.tweak('B', moved_from='../A/B') |
| expected_status.tweak('D', moved_from='../A/D') |
| expected_status.tweak('H', moved_from='D/H') |
| expected_status.tweak('Q', moved_from='../A/Q') |
| expected_status.tweak('D/H', moved_to='H') |
| expected_status.tweak('alpha', moved_from='B/E/alpha') |
| expected_status.tweak('B/E/alpha', moved_to='alpha') |
| svntest.actions.run_and_verify_status(wc('move-dest'), expected_status) |
| |
| expected_disk = svntest.wc.State('', { |
| 'B/E/beta' : Item(contents="This is the file 'beta'.\n" |
| "Edit for merge\n"), |
| 'B/lambda' : Item(contents="This is the file 'lambda'.\n"), |
| 'B/F' : Item(), |
| 'H' : Item(props={'foo':'100'}), |
| 'H/chi' : Item(contents="This is the file 'chi'.\n", |
| props={'foo':'100'}), |
| 'H/psi' : Item(contents="This is the file 'psi'.\n"), |
| 'H/omega' : Item(contents="This is the file 'omega'.\n"), |
| 'D' : Item(), |
| 'G/tau' : Item(contents="This is the file 'tau'.\n"), |
| 'G/rho' : Item(contents="This is the file 'rho'.\n" |
| "Local edit\n"), |
| 'G/pi' : Item(contents="This is the file 'pi'.\n"), |
| 'Q/sigma' : Item(contents="New local file\n"), |
| 'alpha' : Item(contents="This is the file 'alpha'.\n" |
| "Local edit\n"), |
| }) |
| svntest.actions.verify_disk(wc('move-dest'), expected_disk, True) |
| |
| def copy_deleted_dir(sbox): |
| "try to copy a deleted directory that exists" |
| sbox.build(read_only = True) |
| |
| sbox.simple_rm('iota') |
| sbox.simple_rm('A') |
| |
| # E145000 - SVN_ERR_NODE_UNKNOWN_KIND |
| # E155035 - SVN_ERR_WC_PATH_UNEXPECTED_STATUS |
| # E155010 - SVN_ERR_WC_PATH_NOT_FOUND |
| |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: (E145000|E155035|E155010): ' + |
| '(Path \'.*iota\' does not exist)|' + |
| '(Deleted node .*iota\' copied)', |
| 'cp', sbox.ospath('iota'), |
| sbox.ospath('new_iota')) |
| |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: (E145000|E155035|E155010): ' + |
| '(Path \'.*D\' does not exist)|' + |
| '(Deleted node .*D\' copied)', |
| 'cp', sbox.ospath('A/D'), |
| sbox.ospath('new_D')) |
| |
| svntest.main.file_write(sbox.ospath('iota'), 'Not iota!') |
| os.mkdir(sbox.ospath('A')) |
| os.mkdir(sbox.ospath('A/D')) |
| |
| # At one time these two invocations raised an assertion. |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: (E155035|E155010): ' + |
| '(Path \'.*iota\' does not exist)|' + |
| '(Deleted node.* .*iota\' can\'t be.*)', |
| 'cp', sbox.ospath('iota'), |
| sbox.ospath('new_iota')) |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: (E155035|E155010): ' + |
| '(Path \'.*D\' does not exist)|' + |
| '(Deleted node.* .*D\' can\'t be.*)', |
| 'cp', sbox.ospath('A/D'), |
| sbox.ospath('new_D')) |
| |
| @Issue(3631) |
| def commit_copied_half_of_move(sbox): |
| "attempt to commit the copied part of move" |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| D_path = sbox.ospath('A/D') |
| |
| # iota -> A/D/iota; verify we cannot commit just A/D/iota |
| svntest.actions.run_and_verify_svn(None, [], 'mv', iota_path, D_path) |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ |
| "moved from '.*%s'" % (re.escape(sbox.ospath('A/D/iota')), |
| re.escape(iota_path)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', |
| os.path.join(D_path, 'iota')) |
| |
| # verify we cannot commit just A/D |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ |
| "moved from '.*%s'" % (re.escape(sbox.ospath('A/D/iota')), |
| re.escape(iota_path)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', D_path) |
| |
| # A/D -> A/C/D; verify we cannot commit just A/C |
| C_path = sbox.ospath('A/C') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', D_path, C_path) |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ |
| "from '.*%s'" % (re.escape(os.path.join(C_path, "D")), |
| re.escape(D_path)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', C_path) |
| |
| # A/C/D/iota -> A/iota; verify that iota's moved-from hasn't changed |
| D_iota_path = sbox.ospath('A/C/D/iota') |
| A_iota_path = sbox.ospath('A/iota') |
| svntest.actions.run_and_verify_svn(None, [], 'mv', D_iota_path, |
| A_iota_path) |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was " \ |
| "moved from '.*%s'" % (re.escape(A_iota_path), |
| re.escape(iota_path)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', A_iota_path) |
| |
| |
| @Issue(3631) |
| def commit_deleted_half_of_move(sbox): |
| "attempt to commit the deleted part of move" |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| A_path = sbox.ospath('A') |
| D_path = sbox.ospath('A/D') |
| |
| # iota -> A/D/iota; verify we cannot commit just iota |
| svntest.actions.run_and_verify_svn(None, [], 'mv', iota_path, D_path) |
| |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ |
| "to '.*%s'" % (re.escape(iota_path), |
| re.escape(os.path.join(D_path, "iota"))) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', iota_path) |
| |
| # A/D -> C; verify we cannot commit just A |
| C_path = sbox.ospath('C') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', D_path, C_path) |
| expected_error = "svn: E200009: Cannot commit '.*%s' because it was moved " \ |
| "to '.*%s'" % (re.escape(D_path), re.escape(C_path)) |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'commit', '-m', 'foo', A_path) |
| |
| @Issue(4026) |
| def wc_wc_copy_incomplete(sbox): |
| "wc-to-wc copy of an incomplete directory" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # We don't know what order the copy will do children of A/B so |
| # remove files so that only subdirs remain then all children can be |
| # marked incomplete. |
| sbox.simple_rm('A/B/lambda') |
| sbox.simple_commit() |
| sbox.simple_update() |
| |
| # We don't know whether copy will do E or F first, so make both |
| # incomplete |
| svntest.actions.set_incomplete(sbox.ospath('A/B/E'), 2) |
| svntest.actions.set_incomplete(sbox.ospath('A/B/F'), 2) |
| |
| # Copy fails with no changes to wc |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: E155035: Cannot handle status', |
| 'copy', |
| sbox.ospath('A/B/E'), |
| sbox.ospath('A/B/E2')) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.remove('A/B/lambda') |
| expected_status.tweak('A/B/E', 'A/B/F', status='! ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Copy fails part way through |
| svntest.actions.run_and_verify_svn(None, |
| 'svn: E155035: Cannot handle status', |
| 'copy', |
| sbox.ospath('A/B'), |
| sbox.ospath('A/B2')) |
| |
| expected_status.add({ |
| 'A/B2' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/B2/E' : Item(status='! ', wc_rev='-'), |
| 'A/B2/F' : Item(status='! ', wc_rev='-'), |
| }) |
| ### Can't get this to work as copied status of E and F in 1.6 |
| ### entries tree doesn't match 1.7 status tree |
| #svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Commit preserves incomplete status |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B2': Item(verb='Adding'), |
| }) |
| expected_status.tweak('A/B2', |
| status=' ', copied=None, wc_rev=3) |
| expected_status.tweak('A/B2/E', 'A/B2/F', |
| status='! ', copied=None, wc_rev=3) |
| ### E and F are status '!' but the test code ignores them? |
| expected_status.remove('A/B2/E', 'A/B2/F') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| expected_status.add({ |
| 'A/B2/E' : Item(status='! ', wc_rev=3), |
| 'A/B2/F' : Item(status='! ', wc_rev=3), |
| }) |
| |
| # Update makes things complete |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B2/E' : Item(status='A '), |
| 'A/B2/E/alpha' : Item(status='A '), |
| 'A/B2/E/beta' : Item(status='A '), |
| 'A/B2/F' : Item(status='A '), |
| }) |
| expected_status.tweak(wc_rev=3, status=' ') |
| expected_status.add({ |
| 'A/B2/E/alpha' : Item(status=' ', wc_rev=3), |
| 'A/B2/E/beta' : Item(status=' ', wc_rev=3), |
| }) |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| expected_status) |
| |
| def three_nested_moves(sbox): |
| "three nested moves" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B'), |
| sbox.ospath('A/B2')) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B2/E'), |
| sbox.ospath('A/B2/E2')) |
| svntest.actions.run_and_verify_svn(None, [], 'mv', |
| sbox.ospath('A/B2/E2/alpha'), |
| sbox.ospath('A/B2/E2/alpha2')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/B2' : Item(status=' ', wc_rev=2), |
| 'A/B2/E2' : Item(status=' ', wc_rev=2), |
| 'A/B2/E2/alpha2' : Item(status=' ', wc_rev=2), |
| 'A/B2/E2/beta' : Item(status=' ', wc_rev=2), |
| 'A/B2/F' : Item(status=' ', wc_rev=2), |
| 'A/B2/lambda' : Item(status=' ', wc_rev=2), |
| }) |
| expected_status.remove('A/B', 'A/B/E', 'A/B/E/alpha', 'A/B/E/beta', |
| 'A/B/F', 'A/B/lambda') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B' : Item(verb='Deleting'), |
| 'A/B2' : Item(verb='Adding'), |
| 'A/B2/E' : Item(verb='Deleting'), |
| 'A/B2/E2' : Item(verb='Adding'), |
| 'A/B2/E2/alpha' : Item(verb='Deleting'), |
| 'A/B2/E2/alpha2' : Item(verb='Adding'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| def copy_to_unversioned_parent(sbox): |
| "copy to unversioned parent" |
| |
| sbox.build() |
| |
| # This succeeds |
| #svntest.actions.run_and_verify_svn(None, [], 'cp', '--parents', |
| # sbox.ospath('A/B'), |
| # sbox.ospath('New/B2')) |
| |
| # And this currently fails with The node '.*Unversioned' was not found, |
| # while it should succeed or returns some error that a GUI client can use. |
| os.mkdir(sbox.ospath('Unversioned')) |
| svntest.actions.run_and_verify_svn(None, [], 'cp', '--parents', |
| sbox.ospath('A/B'), |
| sbox.ospath('Unversioned/B2')) |
| |
| def copy_text_conflict(sbox): |
| "copy with a text conflict should not copy markers" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| mu_path = sbox.ospath('A/mu') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| |
| sbox.simple_commit() |
| svntest.main.file_append(mu_path, 'appended mu text') |
| |
| sbox.simple_update(revision='1') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.ospath('A'), |
| sbox.ospath('A_copied')) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', status='C ') |
| expected_status.add({ |
| # The markers in A |
| 'A/mu.mine' : Item(status='? '), |
| 'A/mu.r1' : Item(status='? '), |
| 'A/mu.r2' : Item(status='? '), |
| # And what is copied (without markers) |
| 'A_copied' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A_copied/C' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B/lambda' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B/E' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B/E/alpha': Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B/E/beta' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/B/F' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/G' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/G/tau' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/G/rho' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/G/pi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/H' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/H/omega': Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/H/psi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/H/chi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/D/gamma' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A_copied/mu' : Item(status='M ', copied='+', wc_rev='-'), |
| }) |
| svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status) |
| |
| @Issue(2843) |
| def copy_over_excluded(sbox): |
| "copy on top of excluded should give error" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'update', '--set-depth', 'exclude', |
| sbox.ospath('A/D')) |
| |
| expected_error = "svn: E155000: Path '.*D' exists.*excluded.*" |
| |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'cp', |
| sbox.repo_url + '/A/C', |
| sbox.ospath('A/D')) |
| |
| expected_error = "svn: E155000: Path '.*D' exists.*excluded.*" |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'cp', |
| sbox.ospath('A/C'), |
| sbox.ospath('A/D')) |
| |
| def copy_relocate(sbox): |
| "copy from a relocated location" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| tmp_dir, url = sbox.add_repo_path('relocated') |
| |
| shutil.copytree(sbox.repo_dir, tmp_dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'relocate', url, wc_dir) |
| |
| copiedpath = sbox.ospath('AA') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', url + '/A', copiedpath) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'info', copiedpath) |
| |
| def ext_wc_copy_deleted(sbox): |
| "copy deleted tree from separate wc" |
| |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| wc2_dir = sbox.add_wc_path('2') |
| |
| sbox.simple_rm('A/B') |
| sbox.simple_commit() |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'up', '--set-depth', 'exclude', |
| sbox.ospath('A/D')) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'co', sbox.repo_url, wc2_dir, '-r', 1) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', sbox.path('A'), os.path.join(wc2_dir,'AA')) |
| |
| expected_output = expected_output = svntest.wc.State(wc2_dir, { |
| 'AA' : Item(verb='Adding'), |
| 'AA/B' : Item(verb='Deleting'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc2_dir, |
| expected_output, None) |
| |
| def copy_subtree_deleted(sbox): |
| "copy to-be-deleted subtree" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| wc2_dir = sbox.add_wc_path('2') |
| svntest.actions.duplicate_dir(wc_dir, wc2_dir) |
| |
| sbox.simple_rm('A/B') |
| |
| # Commit copy within a working copy |
| sbox.simple_copy('A', 'AA') |
| expected_output = expected_output = svntest.wc.State(wc_dir, { |
| 'AA' : Item(verb='Adding'), |
| 'AA/B' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, None, [], |
| sbox.ospath('AA')) |
| |
| # Commit copy between working copies |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cp', sbox.path('A'), |
| os.path.join(wc2_dir,'AA2')) |
| expected_output = expected_output = svntest.wc.State(wc2_dir, { |
| 'AA2' : Item(verb='Adding'), |
| 'AA2/B' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc2_dir, |
| expected_output, None) |
| |
| def resurrect_at_root(sbox): |
| "resurrect directory at root" |
| |
| sbox.build(create_wc=False) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', sbox.repo_url + '/A', |
| '-m', '') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'cp', |
| sbox.repo_url + '/A/D/H@1', |
| sbox.repo_url + '/A', '-m', '') |
| |
| ######################################################################## |
| # Run the tests |
| |
| |
| # list all tests here, starting with None: |
| test_list = [ None, |
| basic_copy_and_move_files, |
| receive_copy_in_update, |
| resurrect_deleted_dir, |
| no_copy_overwrites, |
| no_wc_copy_overwrites, |
| copy_modify_commit, |
| copy_files_with_properties, |
| copy_delete_commit, |
| mv_and_revert_directory, |
| copy_preserve_executable_bit, |
| wc_to_repos, |
| repos_to_wc, |
| copy_to_root, |
| url_copy_parent_into_child, |
| wc_copy_parent_into_child, |
| url_move_parent_into_child, |
| wc_move_parent_into_child, |
| resurrect_deleted_file, |
| diff_repos_to_wc_copy, |
| repos_to_wc_copy_eol_keywords, |
| revision_kinds_local_source, |
| copy_over_missing_file, |
| repos_to_wc_1634, |
| double_uri_escaping_1814, |
| wc_to_wc_copy_between_different_repos, |
| wc_to_wc_copy_deleted, |
| url_to_non_existent_url_path, |
| non_existent_url_to_url, |
| old_dir_url_to_url, |
| wc_copy_dir_to_itself, |
| mixed_wc_to_url, |
| wc_copy_replacement, |
| wc_copy_replace_with_props, |
| repos_to_wc_copy_replacement, |
| repos_to_wc_copy_replace_with_props, |
| delete_replaced_file, |
| mv_unversioned_file, |
| force_move, |
| copy_deleted_dir_into_prefix, |
| copy_copied_file_and_dir, |
| move_copied_file_and_dir, |
| move_moved_file_and_dir, |
| move_file_within_moved_dir, |
| move_file_out_of_moved_dir, |
| move_dir_within_moved_dir, |
| move_dir_out_of_moved_dir, |
| move_file_back_and_forth, |
| move_dir_back_and_forth, |
| copy_move_added_paths, |
| copy_added_paths_with_props, |
| copy_added_paths_to_URL, |
| move_to_relative_paths, |
| move_from_relative_paths, |
| copy_to_relative_paths, |
| copy_from_relative_paths, |
| move_multiple_wc, |
| copy_multiple_wc, |
| move_multiple_repo, |
| copy_multiple_repo, |
| copy_multiple_repo_wc, |
| copy_multiple_wc_repo, |
| copy_peg_rev_local_files, |
| copy_peg_rev_local_dirs, |
| copy_peg_rev_url, |
| old_dir_wc_to_wc, |
| copy_make_parents_wc_wc, |
| copy_make_parents_wc_wc_existing_unversioned_dst, |
| copy_make_parents_repo_wc, |
| copy_make_parents_repo_wc_existing_unversioned_dst, |
| copy_make_parents_wc_repo, |
| copy_make_parents_repo_repo, |
| URI_encoded_repos_to_wc, |
| allow_unversioned_parent_for_copy_src, |
| unneeded_parents, |
| double_parents_with_url, |
| copy_into_missing_dir, |
| find_copyfrom_information_upstairs, |
| path_move_and_copy_between_wcs_2475, |
| path_copy_in_repo_2475, |
| commit_copy_depth_empty, |
| copy_below_copy, |
| move_below_move, |
| reverse_merge_move, |
| nonrecursive_commit_of_copy, |
| copy_added_dir_with_copy, |
| copy_broken_symlink, |
| move_dir_containing_move, |
| copy_dir_with_space, |
| changed_data_should_match_checkout, |
| changed_dir_data_should_match_checkout, |
| move_added_nodes, |
| copy_over_deleted_dir, |
| mixed_rev_copy_del, |
| copy_delete_delete, |
| copy_delete_revert, |
| delete_replace_delete, |
| copy_repos_over_deleted_same_kind, |
| copy_repos_over_deleted_other_kind, |
| copy_wc_over_deleted_same_kind, |
| copy_wc_over_deleted_other_kind, |
| move_wc_and_repo_dir_to_itself, |
| copy_wc_url_with_absent, |
| copy_url_shortcut, |
| deleted_file_with_case_clash, |
| copy_base_of_deleted, |
| case_only_rename, |
| copy_and_move_conflicts, |
| copy_deleted_dir, |
| commit_copied_half_of_move, |
| commit_deleted_half_of_move, |
| wc_wc_copy_incomplete, |
| three_nested_moves, |
| copy_to_unversioned_parent, |
| copy_text_conflict, |
| copy_over_excluded, |
| copy_relocate, |
| ext_wc_copy_deleted, |
| copy_subtree_deleted, |
| resurrect_at_root, |
| foreign_repos_to_wc, |
| ] |
| |
| if __name__ == '__main__': |
| svntest.main.run_tests(test_list) |
| # NOTREACHED |
| |
| |
| ### End of file. |