| #!/usr/bin/env python |
| # |
| # switch_tests.py: testing `svn switch'. |
| # |
| # Subversion is a tool for revision control. |
| # See http://subversion.tigris.org for more information. |
| # |
| # ==================================================================== |
| # Copyright (c) 2000-2004 CollabNet. All rights reserved. |
| # |
| # This software is licensed as described in the file COPYING, which |
| # you should have received as part of this distribution. The terms |
| # are also available at http://subversion.tigris.org/license-1.html. |
| # If newer versions of this license are posted there, you may use a |
| # newer version instead, at your option. |
| # |
| ###################################################################### |
| |
| # General modules |
| import shutil, re, os |
| |
| # Our testing module |
| import svntest |
| |
| # (abbreviation) |
| Skip = svntest.testcase.Skip |
| XFail = svntest.testcase.XFail |
| Item = svntest.wc.StateItem |
| |
| from svntest.main import SVN_PROP_MERGE_INFO |
| |
| ### Bummer. It would be really nice to have easy access to the URL |
| ### member of our entries files so that switches could be testing by |
| ### examining the modified ancestry. But status doesn't show this |
| ### information. Hopefully in the future the cmdline binary will have |
| ### a subcommand for dumping multi-line detailed information about |
| ### versioned things. Until then, we'll stick with the traditional |
| ### verification methods. |
| ### |
| ### gjs says: we have 'svn info' now |
| |
| def get_routine_status_state(wc_dir): |
| """get the routine status list for WC_DIR at the completion of an |
| initial call to do_routine_switching()""" |
| |
| # Construct some paths for convenience |
| ADH_path = os.path.join(wc_dir, 'A', 'D', 'H') |
| chi_path = os.path.join(ADH_path, 'chi') |
| omega_path = os.path.join(ADH_path, 'omega') |
| psi_path = os.path.join(ADH_path, 'psi') |
| pi_path = os.path.join(ADH_path, 'pi') |
| tau_path = os.path.join(ADH_path, 'tau') |
| rho_path = os.path.join(ADH_path, 'rho') |
| |
| # Now generate a state |
| state = svntest.actions.get_virginal_state(wc_dir, 1) |
| state.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda') |
| state.add({ |
| 'A/B/pi' : Item(status=' ', wc_rev=1), |
| 'A/B/tau' : Item(status=' ', wc_rev=1), |
| 'A/B/rho' : Item(status=' ', wc_rev=1), |
| }) |
| |
| return state |
| |
| #---------------------------------------------------------------------- |
| |
| def get_routine_disk_state(wc_dir): |
| """get the routine disk list for WC_DIR at the completion of an |
| initial call to do_routine_switching()""" |
| |
| disk = svntest.main.greek_state.copy() |
| |
| # iota has the same contents as gamma |
| disk.tweak('iota', contents=disk.desc['A/D/gamma'].contents) |
| |
| # A/B/* no longer exist, but have been replaced by copies of A/D/G/* |
| disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', 'A/B/F', 'A/B/lambda') |
| disk.add({ |
| 'A/B/pi' : Item("This is the file 'pi'.\n"), |
| 'A/B/rho' : Item("This is the file 'rho'.\n"), |
| 'A/B/tau' : Item("This is the file 'tau'.\n"), |
| }) |
| |
| return disk |
| |
| #---------------------------------------------------------------------- |
| |
| def do_routine_switching(wc_dir, repo_url, verify): |
| """perform some routine switching of the working copy WC_DIR for |
| other tests to use. If VERIFY, then do a full verification of the |
| switching, else don't bother.""" |
| |
| ### Switch the file `iota' to `A/D/gamma'. |
| |
| # Construct some paths for convenience |
| iota_path = os.path.join(wc_dir, 'iota') |
| gamma_url = repo_url + '/A/D/gamma' |
| |
| if verify: |
| # Create expected output tree |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(status='U '), |
| }) |
| |
| # Create expected disk tree (iota will have gamma's contents) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('iota', |
| contents=expected_disk.desc['A/D/gamma'].contents) |
| |
| # Create expected status tree |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('iota', switched='S') |
| |
| # Do the switch and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| else: |
| svntest.main.run_svn(None, 'switch', |
| gamma_url, iota_path) |
| |
| ### Switch the directory `A/B' to `A/D/G'. |
| |
| # Construct some paths for convenience |
| AB_path = os.path.join(wc_dir, 'A', 'B') |
| ADG_url = repo_url + '/A/D/G' |
| |
| if verify: |
| # Create expected output tree |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E' : Item(status='D '), |
| 'A/B/F' : Item(status='D '), |
| 'A/B/lambda' : Item(status='D '), |
| 'A/B/pi' : Item(status='A '), |
| 'A/B/tau' : Item(status='A '), |
| 'A/B/rho' : Item(status='A '), |
| }) |
| |
| # Create expected disk tree (iota will have gamma's contents, |
| # A/B/* will look like A/D/G/*) |
| expected_disk = get_routine_disk_state(wc_dir) |
| |
| # Create expected status |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| |
| # Do the switch and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, ADG_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| else: |
| svntest.main.run_svn(None, |
| 'switch', ADG_url, AB_path) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def commit_routine_switching(wc_dir, verify): |
| "Commit some stuff in a routinely-switched working copy." |
| |
| # Make some local mods |
| iota_path = os.path.join(wc_dir, 'iota') |
| Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi') |
| Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') |
| Z_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z') |
| zeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta') |
| |
| svntest.main.file_append(iota_path, "apple") |
| svntest.main.file_append(Bpi_path, "melon") |
| svntest.main.file_append(Gpi_path, "banana") |
| os.mkdir(Z_path) |
| svntest.main.file_append(zeta_path, "This is the file 'zeta'.\n") |
| svntest.main.run_svn(None, 'add', Z_path) |
| |
| # Try to commit. We expect this to fail because, if all the |
| # switching went as expected, A/B/pi and A/D/G/pi point to the |
| # same URL. We don't allow this. |
| svntest.actions.run_and_verify_commit( |
| wc_dir, None, None, |
| "svn: Cannot commit both .* as they refer to the same URL$", |
| None, None, None, None, |
| wc_dir) |
| |
| # Okay, that all taken care of, let's revert the A/D/G/pi path and |
| # move along. Afterward, we should be okay to commit. (Sorry, |
| # holsta, that banana has to go...) |
| svntest.main.run_svn(None, 'revert', Gpi_path) |
| |
| # Create expected output tree. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/Z' : Item(verb='Adding'), |
| 'A/D/G/Z/zeta' : Item(verb='Adding'), |
| 'iota' : Item(verb='Sending'), |
| 'A/B/pi' : Item(verb='Sending'), |
| }) |
| |
| # Created expected status tree. |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| expected_status.tweak('iota', 'A/B/pi', wc_rev=2, status=' ') |
| expected_status.add({ |
| 'A/D/G/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Commit should succeed |
| if verify: |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| None, None, None, None, None, |
| wc_dir) |
| else: |
| svntest.main.run_svn(None, |
| 'ci', '-m', 'log msg', wc_dir) |
| |
| |
| ###################################################################### |
| # Tests |
| # |
| |
| #---------------------------------------------------------------------- |
| |
| def routine_switching(sbox): |
| "test some basic switching operations" |
| |
| sbox.build() |
| |
| # Setup (and verify) some switched things |
| do_routine_switching(sbox.wc_dir, sbox.repo_url, 1) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def commit_switched_things(sbox): |
| "commits after some basic switching operations" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # Commit some stuff (and verify) |
| commit_routine_switching(wc_dir, 1) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def full_update(sbox): |
| "update wc that contains switched things" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # Copy wc_dir to a backup location |
| wc_backup = sbox.add_wc_path('backup') |
| svntest.actions.duplicate_dir(wc_dir, wc_backup) |
| |
| # Commit some stuff (don't bother verifying) |
| commit_routine_switching(wc_backup, 0) |
| |
| # Some convenient path variables |
| iota_path = os.path.join(wc_dir, 'iota') |
| gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') |
| Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi') |
| BZ_path = os.path.join(wc_dir, 'A', 'B', 'Z') |
| Bzeta_path = os.path.join(wc_dir, 'A', 'B', 'Z', 'zeta') |
| Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') |
| GZ_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z') |
| Gzeta_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z', 'zeta') |
| |
| # Create expected output tree for an update of wc_backup. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(status='U '), |
| 'A/D/gamma' : Item(status='U '), |
| 'A/B/pi' : Item(status='U '), |
| 'A/B/Z' : Item(status='A '), |
| 'A/B/Z/zeta' : Item(status='A '), |
| 'A/D/G/pi' : Item(status='U '), |
| 'A/D/G/Z' : Item(status='A '), |
| 'A/D/G/Z/zeta' : Item(status='A '), |
| }) |
| |
| # Create expected disk tree for the update |
| expected_disk = get_routine_disk_state(wc_dir) |
| expected_disk.tweak('iota', contents="This is the file 'gamma'.\napple") |
| expected_disk.tweak('A/D/gamma', contents="This is the file 'gamma'.\napple") |
| expected_disk.tweak('A/B/pi', contents="This is the file 'pi'.\nmelon") |
| expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nmelon") |
| expected_disk.add({ |
| 'A/B/Z' : Item(), |
| 'A/B/Z/zeta' : Item(contents="This is the file 'zeta'.\n"), |
| 'A/D/G/Z' : Item(), |
| 'A/D/G/Z/zeta' : Item(contents="This is the file 'zeta'.\n"), |
| }) |
| |
| # Create expected status tree for the update. |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak(wc_rev=2) |
| expected_status.add({ |
| 'A/D/G/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2), |
| 'A/B/Z' : Item(status=' ', wc_rev=2), |
| 'A/B/Z/zeta' : Item(status=' ', wc_rev=2), |
| }) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| def full_rev_update(sbox): |
| "reverse update wc that contains switched things" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # Commit some stuff (don't bother verifying) |
| commit_routine_switching(wc_dir, 0) |
| |
| # Update to HEAD (tested elsewhere) |
| svntest.main.run_svn(None, 'up', wc_dir) |
| |
| # Some convenient path variables |
| iota_path = os.path.join(wc_dir, 'iota') |
| gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') |
| Bpi_path = os.path.join(wc_dir, 'A', 'B', 'pi') |
| BZ_path = os.path.join(wc_dir, 'A', 'B', 'Z') |
| Gpi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi') |
| GZ_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Z') |
| |
| # Now, reverse update, back to the pre-commit state. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(status='U '), |
| 'A/D/gamma' : Item(status='U '), |
| 'A/B/pi' : Item(status='U '), |
| 'A/B/Z' : Item(status='D '), |
| 'A/D/G/pi' : Item(status='U '), |
| 'A/D/G/Z' : Item(status='D '), |
| }) |
| |
| # Create expected disk tree |
| expected_disk = get_routine_disk_state(wc_dir) |
| |
| # Create expected status |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, |
| None, None, 1, |
| '-r', '1', wc_dir) |
| |
| #---------------------------------------------------------------------- |
| |
| def update_switched_things(sbox): |
| "update switched wc things to HEAD" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # Copy wc_dir to a backup location |
| wc_backup = sbox.add_wc_path('backup') |
| svntest.actions.duplicate_dir(wc_dir, wc_backup) |
| |
| # Commit some stuff (don't bother verifying) |
| commit_routine_switching(wc_backup, 0) |
| |
| # Some convenient path variables |
| iota_path = os.path.join(wc_dir, 'iota') |
| B_path = os.path.join(wc_dir, 'A', 'B') |
| |
| # Create expected output tree for an update of wc_backup. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(status='U '), |
| 'A/B/pi' : Item(status='U '), |
| 'A/B/Z' : Item(status='A '), |
| 'A/B/Z/zeta' : Item(status='A '), |
| }) |
| |
| # Create expected disk tree for the update |
| expected_disk = get_routine_disk_state(wc_dir) |
| expected_disk.tweak('iota', contents="This is the file 'gamma'.\napple") |
| |
| expected_disk.tweak('A/B/pi', contents="This is the file 'pi'.\nmelon") |
| expected_disk.add({ |
| 'A/B/Z' : Item(), |
| 'A/B/Z/zeta' : Item("This is the file 'zeta'.\n"), |
| }) |
| |
| # Create expected status tree for the update. |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| expected_status.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota', |
| wc_rev=2) |
| expected_status.add({ |
| 'A/B/Z' : Item(status=' ', wc_rev=2), |
| 'A/B/Z/zeta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, |
| None, None, 0, |
| B_path, |
| iota_path) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def rev_update_switched_things(sbox): |
| "reverse update switched wc things to an older rev" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # Commit some stuff (don't bother verifying) |
| commit_routine_switching(wc_dir, 0) |
| |
| # Some convenient path variables |
| iota_path = os.path.join(wc_dir, 'iota') |
| B_path = os.path.join(wc_dir, 'A', 'B') |
| |
| # Update to HEAD (tested elsewhere) |
| svntest.main.run_svn(None, 'up', wc_dir) |
| |
| # Now, reverse update, back to the pre-commit state. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(status='U '), |
| 'A/B/pi' : Item(status='U '), |
| 'A/B/Z' : Item(status='D '), |
| }) |
| |
| # Create expected disk tree |
| expected_disk = get_routine_disk_state(wc_dir) |
| expected_disk.tweak('A/D/gamma', contents="This is the file 'gamma'.\napple") |
| expected_disk.tweak('A/D/G/pi', contents="This is the file 'pi'.\nmelon") |
| expected_disk.add({ |
| 'A/D/G/Z' : Item(), |
| 'A/D/G/Z/zeta' : Item("This is the file 'zeta'.\n"), |
| }) |
| |
| # Create expected status tree for the update. |
| expected_status = get_routine_status_state(wc_dir) |
| expected_status.tweak(wc_rev=2) |
| expected_status.tweak('iota', 'A/B', switched='S') |
| expected_status.tweak('A/B', 'A/B/pi', 'A/B/rho', 'A/B/tau', 'iota', |
| wc_rev=1) |
| expected_status.add({ |
| 'A/D/G/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/G/Z/zeta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, |
| None, None, 1, |
| '-r', '1', |
| B_path, |
| iota_path) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def log_switched_file(sbox): |
| "show logs for a switched file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Setup some switched things (don't bother verifying) |
| do_routine_switching(wc_dir, sbox.repo_url, 0) |
| |
| # edit and commit switched file 'iota' |
| iota_path = os.path.join(wc_dir, 'iota') |
| svntest.main.run_svn(None, 'ps', 'x', 'x', iota_path) |
| svntest.main.run_svn(None, |
| 'ci', '-m', |
| 'set prop on switched iota', |
| iota_path) |
| |
| # log switched file 'iota' |
| output, error = svntest.main.run_svn(None, 'log', iota_path) |
| for line in output: |
| if line.find("set prop on switched iota") != -1: |
| break |
| else: |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| |
| def relocate_deleted_missing_copied(sbox): |
| "relocate with deleted, missing and copied entries" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Delete A/mu to create a deleted entry for mu in A/.svn/entries |
| mu_path = os.path.join(wc_dir, 'A', 'mu') |
| svntest.actions.run_and_verify_svn(None, None, [], 'rm', mu_path) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/mu') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| None, None, None, None, None, |
| wc_dir) |
| |
| # Remove A/B/F to create a missing entry |
| svntest.main.safe_rmtree(os.path.join(wc_dir, 'A', 'B', 'F')) |
| |
| # Copy A/D/H to A/D/H2 |
| H_path = os.path.join(wc_dir, 'A', 'D', 'H') |
| H2_path = os.path.join(wc_dir, 'A', 'D', 'H2') |
| svntest.actions.run_and_verify_svn(None, None, [], 'copy', |
| H_path, H2_path) |
| expected_status.add({ |
| 'A/D/H2' : Item(status='A ', wc_rev='-', copied='+'), |
| 'A/D/H2/chi' : Item(status=' ', wc_rev='-', copied='+'), |
| 'A/D/H2/omega' : Item(status=' ', wc_rev='-', copied='+'), |
| 'A/D/H2/psi' : Item(status=' ', wc_rev='-', copied='+'), |
| }) |
| expected_status.tweak('A/B/F', status='! ', wc_rev='?') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Relocate |
| repo_dir = sbox.repo_dir |
| repo_url = sbox.repo_url |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 2, 0) |
| svntest.main.safe_rmtree(repo_dir, 1) |
| svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate', |
| repo_url, other_repo_url, wc_dir) |
| |
| # Deleted and missing entries should be preserved, so update should |
| # show only A/B/F being reinstated |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/mu') |
| expected_disk.add({ |
| 'A/D/H2' : Item(), |
| 'A/D/H2/chi' : Item("This is the file 'chi'.\n"), |
| 'A/D/H2/omega' : Item("This is the file 'omega'.\n"), |
| 'A/D/H2/psi' : Item("This is the file 'psi'.\n"), |
| }) |
| expected_status.add({ |
| 'A/B/F' : Item(status=' ', wc_rev='2'), |
| }) |
| expected_status.tweak(wc_rev=2) |
| expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi', |
| wc_rev='-') |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Commit to verify that copyfrom URLs have been relocated |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/H2' : Item(verb='Adding'), |
| }) |
| expected_status.tweak('A/D/H2', 'A/D/H2/chi', 'A/D/H2/omega', 'A/D/H2/psi', |
| status=' ', wc_rev='3', copied=None) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status, |
| None, None, None, None, None, |
| wc_dir) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def delete_subdir(sbox): |
| "switch that deletes a sub-directory" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| A_path = os.path.join(wc_dir, 'A') |
| A_url = sbox.repo_url + '/A' |
| A2_url = sbox.repo_url + '/A2' |
| A2_B_F_url = sbox.repo_url + '/A2/B/F' |
| |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 2.\n'], [], |
| 'cp', '-m', 'make copy', A_url, A2_url) |
| |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 3.\n'], [], |
| 'rm', '-m', 'delete subdir', A2_B_F_url) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A' : Item(status=' U'), |
| 'A/B/F' : Item(status='D '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/F') |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.tweak('A', switched='S') |
| expected_status.remove('A/B/F') |
| expected_status.tweak('', 'iota', wc_rev=1) |
| |
| # Used to fail with a 'directory not locked' error for A/B/F |
| svntest.actions.run_and_verify_switch(wc_dir, A_path, A2_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| # Issue 1532: Switch a file to a dir: can't switch it back to the file |
| |
| def file_dir_file(sbox): |
| "switch a file to a dir and back to the file" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| file_path = os.path.join(wc_dir, 'iota') |
| file_url = sbox.repo_url + '/iota' |
| dir_url = sbox.repo_url + '/A/C' |
| |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'switch', dir_url, file_path) |
| |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'switch', file_url, file_path) |
| |
| #---------------------------------------------------------------------- |
| # Issue 1751: "svn switch --non-recursive" does not switch existing files, |
| # and generates the wrong URL for new files. |
| |
| def nonrecursive_switching(sbox): |
| "non-recursive switch" |
| sbox.build() |
| wc1_dir = sbox.wc_dir |
| wc2_dir = os.path.join(wc1_dir, 'wc2') |
| |
| # "Trunk" will be the existing dir "A/", with existing file "mu". |
| # "Branch" will be the new dir "branch/version1/", with added file "newfile". |
| # "wc1" will hold the whole repository (including trunk and branch). |
| # "wc2" will hold the "trunk" and then be switched to the "branch". |
| # It is irrelevant that wc2 is located on disk as a sub-directory of wc1. |
| trunk_url = sbox.repo_url + '/A' |
| branch_url = sbox.repo_url + '/branch' |
| version1_url = branch_url + '/version1' |
| wc1_new_file = os.path.join(wc1_dir, 'branch', 'version1', 'newfile') |
| wc2_new_file = os.path.join(wc2_dir, 'newfile') |
| wc2_mu_file = os.path.join(wc2_dir, 'mu') |
| wc2_B_dir = os.path.join(wc2_dir, 'B') |
| wc2_C_dir = os.path.join(wc2_dir, 'C') |
| wc2_D_dir = os.path.join(wc2_dir, 'D') |
| |
| # Check out the trunk as "wc2" |
| svntest.main.run_svn(None, 'co', trunk_url, wc2_dir) |
| |
| # Make a branch, and add a new file, in "wc_dir" and repository |
| svntest.main.run_svn(None, |
| 'mkdir', '-m', '', branch_url) |
| svntest.main.run_svn(None, |
| 'cp', '-m', '', trunk_url, version1_url) |
| svntest.main.run_svn(None, |
| 'up', wc1_dir) |
| svntest.main.file_append(wc1_new_file, "This is the file 'newfile'.\n") |
| svntest.main.run_svn(None, 'add', wc1_new_file) |
| svntest.main.run_svn(None, 'ci', '-m', '', wc1_dir) |
| |
| # Try to switch "wc2" to the branch (non-recursively) |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'switch', '-N', version1_url, wc2_dir) |
| |
| # Check the URLs of the (not switched) directories. |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', wc2_B_dir) |
| if out[1].find('/A/B') == -1: |
| print out[1] |
| raise svntest.Failure |
| |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', wc2_C_dir) |
| if out[1].find('/A/C') == -1: |
| print out[1] |
| raise svntest.Failure |
| |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', wc2_D_dir) |
| if out[1].find('/A/D') == -1: |
| print out[1] |
| raise svntest.Failure |
| |
| # Check the URLs of the switched files. |
| # ("svn status -u" might be a better check: it fails when newfile's URL |
| # is bad, and shows "S" when mu's URL is wrong.) |
| # mu: not switched |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', wc2_mu_file) |
| if out[2].find('/branch/version1/mu') == -1: |
| print out[2] |
| raise svntest.Failure |
| # newfile: wrong URL |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', wc2_new_file) |
| if out[2].find('/branch/version1/newfile') == -1: |
| print out[2] |
| raise svntest.Failure |
| |
| |
| #---------------------------------------------------------------------- |
| def failed_anchor_is_target(sbox): |
| "anchor=target that fails due to local mods" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| G_url = sbox.repo_url + '/A/D/G' |
| G_psi_url = G_url + '/psi' |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 2.\n'], [], |
| 'mkdir', '-m', 'log msg', G_psi_url) |
| |
| H_path = os.path.join(wc_dir, 'A', 'D', 'H') |
| psi_path = os.path.join(H_path, 'psi') |
| svntest.main.file_append(psi_path, "more text") |
| |
| # This switch leaves psi unversioned, because of the local mods, |
| # then fails because it tries to add a directory of the same name. |
| out, err = svntest.main.run_svn(1, 'switch', |
| G_url, H_path) |
| if not err: |
| raise svntest.Failure |
| |
| # Some items under H show up as switched because, while H itself was |
| # switched, the switch command failed before it reached all items |
| # |
| # NOTE: I suspect this whole test is dependent on the order in |
| # which changes are received, but since the new psi is a dir, it |
| # appears we can count on it being received last. But if this test |
| # ever starts failing, you read it here first :-). |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/H', status='! ', switched='S', wc_rev=2) |
| expected_status.remove('A/D/H/psi', 'A/D/H/chi', 'A/D/H/omega') |
| expected_status.add({ |
| 'A/D/H/pi' : Item(status=' ', wc_rev=2), |
| 'A/D/H/tau' : Item(status=' ', wc_rev=2), |
| 'A/D/H/rho' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # There was a bug whereby the failed switch left the wrong URL in |
| # the target directory H. Check for that. |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], 'info', H_path) |
| for line in out: |
| if line.find('URL: ' + G_url) != -1: |
| break |
| else: |
| raise svntest.Failure |
| |
| # Remove the now-unversioned psi, and repeat the switch. This |
| # should complete the switch. |
| os.remove(psi_path) |
| svntest.actions.run_and_verify_svn(None, None, [], 'switch', |
| G_url, H_path) |
| |
| expected_status.tweak('A/D/H', status=' ') # remains switched |
| expected_status.add({ 'A/D/H/psi' : Item(status=' ', |
| switched=None, |
| wc_rev=2) }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| #---------------------------------------------------------------------- |
| # Issue #1826 - svn switch temporarily drops invalid URLs into the entries |
| # files (which become not-temporary if the switch fails). |
| def bad_intermediate_urls(sbox): |
| "bad intermediate urls in use" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # We'll be switching our working copy to (a modified) A/C in the Greek tree. |
| |
| # First, make an extra subdirectory in C to match one in the root, plus |
| # another one inside of that. |
| C_url = sbox.repo_url + '/A/C' |
| C_A_url = sbox.repo_url + '/A/C/A' |
| C_A_Z_url = sbox.repo_url + '/A/C/A/Z' |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 2.\n'], [], |
| 'mkdir', '-m', 'log msg', |
| C_A_url, C_A_Z_url) |
| |
| # Now, we'll drop a conflicting path under the root. |
| A_path = os.path.join(wc_dir, 'A') |
| A_Z_path = os.path.join(A_path, 'Z') |
| svntest.main.file_append(A_Z_path, 'Look, Mom, no ... switch success.') |
| |
| # This switch should fail for reasons of obstruction. |
| out, err = svntest.main.run_svn(1, 'switch', |
| C_url, wc_dir) |
| if not err: |
| raise svntest.Failure |
| |
| # However, the URL for A should now reflect A/C/A, not something else. |
| out, err = svntest.actions.run_and_verify_svn(None, None, [], |
| 'info', A_path) |
| if out[1].find('/A/C/A') == -1: |
| raise svntest.Failure |
| |
| |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issue #1825: failed switch may corrupt |
| # working copy |
| |
| def obstructed_switch(sbox): |
| "obstructed switch" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| E_url = sbox.repo_url + '/A/B/E' |
| E_url2 = sbox.repo_url + '/A/B/Esave' |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 2.\n'], [], |
| 'cp', '-m', 'msgcopy', E_url, E_url2) |
| |
| E_path = os.path.join(wc_dir, 'A', 'B', 'E') |
| alpha_path = os.path.join(E_path, 'alpha') |
| svntest.actions.run_and_verify_svn(None, None, [], 'rm', alpha_path) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/E/alpha') |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E/alpha' : Item(verb='Deleting'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status, |
| None, None, None, None, None, |
| wc_dir) |
| |
| svntest.main.file_append(alpha_path, "hello") |
| out, err = svntest.main.run_svn(1, |
| 'sw', E_url2, E_path) |
| for line in err: |
| if line.find("object of the same name already exists") != -1: |
| break |
| else: |
| raise svntest.Failure |
| |
| os.remove(alpha_path) |
| svntest.actions.run_and_verify_svn(None, None, [], 'sw', E_url2, E_path) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B/E', 'A/B/E/alpha', 'A/B/E/beta', wc_rev=3) |
| expected_status.tweak('A/B/E', switched='S') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue 2353. |
| def commit_mods_below_switch(sbox): |
| "commit with mods below switch" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| C_path = os.path.join(wc_dir, 'A', 'C') |
| B_url = sbox.repo_url + '/A/B' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C/E' : Item(status='A '), |
| 'A/C/E/alpha' : Item(status='A '), |
| 'A/C/E/beta' : Item(status='A '), |
| 'A/C/F' : Item(status='A '), |
| 'A/C/lambda' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| '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"), |
| 'A/C/F' : Item(), |
| 'A/C/lambda' : Item(contents="This is the file 'lambda'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/C', switched='S') |
| expected_status.add({ |
| 'A/C/E' : Item(status=' ', wc_rev=1), |
| 'A/C/E/alpha' : Item(status=' ', wc_rev=1), |
| 'A/C/E/beta' : Item(status=' ', wc_rev=1), |
| 'A/C/F' : Item(status=' ', wc_rev=1), |
| 'A/C/lambda' : Item(status=' ', wc_rev=1), |
| }) |
| svntest.actions.run_and_verify_switch(wc_dir, C_path, B_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| D_path = os.path.join(wc_dir, 'A', 'D') |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'propset', 'x', 'x', C_path, D_path) |
| |
| expected_status.tweak('A/C', 'A/D', status=' M') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/C' : Item(verb='Sending'), |
| 'A/D' : Item(verb='Sending'), |
| }) |
| expected_status.tweak('A/C', 'A/D', status=' ', wc_rev=2) |
| |
| # A/C erroneously classified as a wc root caused the commit to fail |
| # with "'A/C/E' is missing or not locked" |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status, |
| None, None, None, None, None, |
| C_path, D_path) |
| |
| def relocate_beyond_repos_root(sbox): |
| "relocate with prefixes longer than repo root" |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| repo_url = sbox.repo_url |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0) |
| svntest.main.safe_rmtree(repo_dir, 1) |
| |
| A_url = repo_url + "/A" |
| other_A_url = other_repo_url + "/A" |
| other_B_url = other_repo_url + "/B" |
| A_wc_dir = os.path.join(wc_dir, "A") |
| |
| # A relocate that changes the repo path part of the URL shouldn't work. |
| # This tests for issue #2380. |
| svntest.actions.run_and_verify_svn(None, None, |
| ".*can only change the repository part.*", |
| 'switch', '--relocate', |
| A_url, other_B_url, A_wc_dir) |
| |
| # Another way of trying to change the fs path, leading to an invalid |
| # repository root. |
| svntest.actions.run_and_verify_svn(None, None, |
| ".*is not the root.*", |
| 'switch', '--relocate', |
| repo_url, other_B_url, A_wc_dir) |
| |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'switch', '--relocate', |
| A_url, other_A_url, A_wc_dir) |
| |
| # Check that we can contact the repository, meaning that the |
| # relocate actually changed the URI. Escape the expected URI to |
| # avoid problems from any regex meta-characters it may contain |
| # (e.g. '+'). |
| escaped_exp = '^URL: ' + re.escape(other_A_url) + '$' \ |
| '|Path.+|Repository.+|Revision.+|Node.+|Last.+|\n' |
| svntest.actions.run_and_verify_svn(None, escaped_exp, [], |
| 'info', '-rHEAD', A_wc_dir) |
| |
| #---------------------------------------------------------------------- |
| # Issue 2306. |
| def refresh_read_only_attribute(sbox): |
| "refresh the WC file system read-only attribute " |
| |
| # This test will fail when run as root. Since that's normal behavior, just skip |
| # the test. |
| if os.name == 'posix': |
| if os.geteuid() == 0: |
| raise svntest.Skip |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a branch. |
| url = sbox.repo_url + '/A' |
| branch_url = sbox.repo_url + '/A-branch' |
| svntest.actions.run_and_verify_svn(None, |
| ['\n', 'Committed revision 2.\n'], [], |
| 'cp', '-m', 'svn:needs-lock not set', |
| url, branch_url) |
| |
| # Set the svn:needs-lock property on a file from the "trunk". |
| A_path = os.path.join(wc_dir, 'A') |
| mu_path = os.path.join(A_path, 'mu') |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'ps', 'svn:needs-lock', '1', mu_path) |
| |
| # Commit the propset of svn:needs-lock. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', wc_rev=3) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status, |
| None, None, None, None, None, |
| mu_path) |
| |
| # The file on which svn:needs-lock was set is now expected to be read-only. |
| if os.access(mu_path, os.W_OK): |
| raise svntest.Failure("'%s' expected to be read-only after having had " |
| "its svn:needs-lock property set" % mu_path) |
| |
| # Switch to the branch with the WC state from before the propset of |
| # svn:needs-lock. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A' : Item(status=' U'), |
| 'A/mu' : Item(status=' U'), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.tweak('', wc_rev=1) |
| expected_status.tweak('iota', wc_rev=1) |
| expected_status.tweak('A', switched='S') |
| svntest.actions.run_and_verify_switch(wc_dir, A_path, branch_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # The file with we set svn:needs-lock on should now be writable, but |
| # is still read-only! |
| if not os.access(mu_path, os.W_OK): |
| raise svntest.Failure("'%s' expected to be writable after being switched " |
| "to a branch on which its svn:needs-lock property " |
| "is not set" % mu_path) |
| |
| # Check that switch can't change the repository root. |
| def switch_change_repos_root(sbox): |
| "switch shouldn't allow changing repos root" |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| other_repo_url = repo_url |
| |
| # Strip trailing slashes and add something bogus to that other URL. |
| while other_repo_url[-1] == '/': |
| other_repos_url = other_repo_url[:-1] |
| other_repo_url = other_repo_url + "_bogus" |
| |
| other_A_url = other_repo_url + "/A" |
| A_wc_dir = os.path.join(wc_dir, "A") |
| |
| # Test 1: A switch that changes to a non-existing repo shouldn't work. |
| expected_err = ".*Unable to open repository.*|.*Could not open.*|"\ |
| ".*No repository found.*" |
| svntest.actions.run_and_verify_svn(None, None, |
| expected_err, |
| 'switch', |
| other_A_url, A_wc_dir) |
| |
| # Test 2: A switch that changes the repo root part of the URL shouldn't work. |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| other_A_url = other_repo_url + "/A" |
| |
| svntest.main.create_repos(other_repo_dir) |
| svntest.actions.run_and_verify_svn(None, None, |
| ".*not the same repository.*", |
| 'switch', |
| other_A_url, A_wc_dir) |
| |
| # Make sure we didn't break the WC. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Issue 2578. |
| def relocate_and_propset(sbox): |
| "out of date propset should fail after a relocate" |
| |
| # Create virgin repos and working copy |
| svntest.main.safe_rmtree(sbox.repo_dir, 1) |
| svntest.main.create_repos(sbox.repo_dir) |
| |
| wc_dir = sbox.wc_dir |
| repo_dir = sbox.repo_dir |
| repo_url = sbox.repo_url |
| |
| # import the greek tree |
| svntest.main.greek_state.write_to_disk(svntest.main.greek_dump_dir) |
| output, errput = svntest.main.run_svn(None, 'import', |
| '-m', 'Log message for revision 1.', |
| svntest.main.greek_dump_dir, sbox.repo_url) |
| |
| # checkout |
| svntest.main.safe_rmtree(wc_dir, 1) |
| svntest.actions.run_and_verify_svn(None, |
| None, [], |
| 'checkout', |
| repo_url, wc_dir) |
| |
| # Relocate |
| other_repo_dir, other_repo_url = sbox.add_repo_path('other') |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0) |
| svntest.main.safe_rmtree(repo_dir, 1) |
| svntest.actions.run_and_verify_svn(None, None, [], 'switch', '--relocate', |
| repo_url, other_repo_url, wc_dir) |
| |
| # Remove gamma from the working copy. |
| D_path = os.path.join(wc_dir, 'A', 'D') |
| gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') |
| svntest.main.run_svn(None, 'rm', gamma_path) |
| |
| # Create expected commit output. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/gamma' : Item(verb='Deleting'), |
| }) |
| |
| # After committing, status should show no sign of gamma. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/D/gamma') |
| |
| # Commit the deletion of gamma and verify. |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| None, None, None, None, None, |
| wc_dir) |
| |
| # Now gamma should be marked as `deleted' under the hood, at |
| # revision 2. Meanwhile, A/D is still lagging at revision 1. |
| |
| # Make a propchange on A/D |
| svntest.main.run_svn(None, 'ps', 'foo', 'bar', D_path) |
| |
| # Commit and *expect* a repository Merge failure: |
| svntest.actions.run_and_verify_commit(wc_dir, |
| None, |
| None, |
| "[Oo]ut.of.date", |
| None, None, |
| None, None, |
| wc_dir) |
| |
| #---------------------------------------------------------------------- |
| |
| def forced_switch(sbox): |
| "forced switch tolerates obstructions to adds" |
| sbox.build() |
| |
| # Dir obstruction |
| G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G') |
| os.mkdir(G_path) |
| |
| # Faux file obstructions |
| shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'gamma'), |
| os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'gamma')) |
| shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'tau'), |
| os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'tau')) |
| |
| # Real file obstruction |
| pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'pi') |
| svntest.main.file_write(pi_path, |
| "This is the OBSTRUCTING file 'pi'.\n") |
| |
| # Non-obstructing dir and file |
| I_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'I') |
| os.mkdir(I_path) |
| upsilon_path = os.path.join(G_path, 'upsilon') |
| svntest.main.file_write(upsilon_path, |
| "This is the unversioned file 'upsilon'.\n") |
| |
| # Setup expected results of switch. |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| "A/B/F/gamma" : Item(status='E '), |
| "A/B/F/G" : Item(status='E '), |
| "A/B/F/G/pi" : Item(status='E '), |
| "A/B/F/G/rho" : Item(status='A '), |
| "A/B/F/G/tau" : Item(status='E '), |
| "A/B/F/H" : Item(status='A '), |
| "A/B/F/H/chi" : Item(status='A '), |
| "A/B/F/H/omega" : Item(status='A '), |
| "A/B/F/H/psi" : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| "A/B/F/gamma" : Item("This is the file 'gamma'.\n"), |
| "A/B/F/G" : Item(), |
| "A/B/F/G/pi" : Item("This is the OBSTRUCTING file 'pi'.\n"), |
| "A/B/F/G/rho" : Item("This is the file 'rho'.\n"), |
| "A/B/F/G/tau" : Item("This is the file 'tau'.\n"), |
| "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"), |
| "A/B/F/H" : Item(), |
| "A/B/F/H/chi" : Item("This is the file 'chi'.\n"), |
| "A/B/F/H/omega" : Item("This is the file 'omega'.\n"), |
| "A/B/F/H/psi" : Item("This is the file 'psi'.\n"), |
| "A/B/F/I" : Item(), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.tweak('A/B/F', switched='S') |
| expected_status.add({ |
| "A/B/F/gamma" : Item(status=' ', wc_rev=1), |
| "A/B/F/G" : Item(status=' ', wc_rev=1), |
| "A/B/F/G/pi" : Item(status='M ', wc_rev=1), |
| "A/B/F/G/rho" : Item(status=' ', wc_rev=1), |
| "A/B/F/G/tau" : Item(status=' ', wc_rev=1), |
| "A/B/F/H" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/chi" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/omega" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/psi" : Item(status=' ', wc_rev=1), |
| }) |
| |
| # Do the switch and check the results in three ways. |
| F_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F') |
| AD_url = sbox.repo_url + '/A/D' |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, F_path, AD_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--force') |
| |
| #---------------------------------------------------------------------- |
| |
| def forced_switch_failures(sbox): |
| "forced switch fails with some types of obstuctions" |
| sbox.build() |
| |
| # Add a directory to obstruct a file. |
| pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'pi') |
| os.mkdir(pi_path) |
| |
| # Add a file to obstruct a directory. |
| H_path = os.path.join(sbox.wc_dir, 'A', 'C', 'H') |
| svntest.main.file_write(H_path, "The file 'H'\n") |
| |
| # Test three cases where forced switch should fail: |
| |
| # 1) A forced switch that tries to add a file when an unversioned |
| # directory of the same name already exists should fail. |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| os.path.join(sbox.wc_dir, 'A', 'C'), |
| sbox.repo_url + "/A/D", |
| None, None, None, |
| ".*Failed to add directory .*" + \ |
| ": a non-directory object of the" + \ |
| " same name already exists\n", |
| None, None, None, None, 0, '--force') |
| |
| # 2) A forced switch that tries to add a dir when a file of the same |
| # name already exists should fail. |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| os.path.join(sbox.wc_dir, |
| 'A', 'B', 'F'), |
| sbox.repo_url + "/A/D/G", |
| None, None, None, |
| ".*Failed to add file .*" + \ |
| ": a non-file object of the " + \ |
| "same name already exists\n", |
| None, None, None, None, 0, '--force') |
| |
| # 3) A forced update that tries to add a directory when a versioned |
| # directory of the same name already exists should fail. |
| |
| # Make dir A/D/H/I in repos. |
| I_url = sbox.repo_url + "/A/D/H/I" |
| so, se = svntest.actions.run_and_verify_svn("Unexpected error during mkdir", |
| ['\n', 'Committed revision 2.\n'], |
| [], |
| "mkdir", I_url, |
| "-m", "Log Message") |
| |
| # Make A/D/G/I and co A/D/H/I into it. |
| I_path = os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'I') |
| os.mkdir(I_path) |
| so, se = svntest.actions.run_and_verify_svn("Unexpected error during co", |
| ['Checked out revision 2.\n'], |
| [], |
| "co", I_url, I_path) |
| |
| # Try the forced switch. A/D/G/I obstructs the dir A/D/G/I coming |
| # from the repos. Normally this isn't a problem, but A/D/G/I is already |
| # versioned so this should fail. |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| os.path.join(sbox.wc_dir, |
| 'A', 'D', 'G'), |
| sbox.repo_url + "/A/D/H", |
| None, None, None, |
| ".*Failed to add " + \ |
| "directory .*: a versioned " + \ |
| "directory of the same name " + \ |
| "already exists\n", |
| None, None, None, None, 0, '--force') |
| |
| def switch_with_obstructing_local_adds(sbox): |
| "switch tolerates WC adds" |
| sbox.build() |
| |
| # Dir obstruction scheduled for addition without history. |
| G_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G') |
| os.mkdir(G_path) |
| |
| # File obstructions scheduled for addition without history. |
| # Contents identical to additions from switch. |
| gamma_copy_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'gamma') |
| shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'gamma'), |
| gamma_copy_path) |
| shutil.copyfile(os.path.join(sbox.wc_dir, 'A', 'D', 'G', 'tau'), |
| os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'tau')) |
| |
| # File obstruction scheduled for addition without history. |
| # Contents conflict with addition from switch. |
| pi_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'G', 'pi') |
| svntest.main.file_write(pi_path, |
| "This is the OBSTRUCTING file 'pi'.\n") |
| |
| # Non-obstructing dir and file scheduled for addition without history. |
| I_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F', 'I') |
| os.mkdir(I_path) |
| upsilon_path = os.path.join(G_path, 'upsilon') |
| svntest.main.file_write(upsilon_path, |
| "This is the unversioned file 'upsilon'.\n") |
| |
| # Add the above obstructions. |
| svntest.actions.run_and_verify_svn("Add error:", None, [], |
| 'add', G_path, I_path, |
| gamma_copy_path) |
| |
| # Setup expected results of switch. |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| "A/B/F/gamma" : Item(status='E '), |
| "A/B/F/G" : Item(status='E '), |
| "A/B/F/G/pi" : Item(status='C '), |
| "A/B/F/G/rho" : Item(status='A '), |
| "A/B/F/G/tau" : Item(status='E '), |
| "A/B/F/H" : Item(status='A '), |
| "A/B/F/H/chi" : Item(status='A '), |
| "A/B/F/H/omega" : Item(status='A '), |
| "A/B/F/H/psi" : Item(status='A '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| "A/B/F/gamma" : Item("This is the file 'gamma'.\n"), |
| "A/B/F/G" : Item(), |
| "A/B/F/G/pi" : Item("\n".join(["<<<<<<< .mine", |
| "This is the OBSTRUCTING file 'pi'.", |
| "=======", |
| "This is the file 'pi'.", |
| ">>>>>>> .r1", |
| ""])), |
| "A/B/F/G/rho" : Item("This is the file 'rho'.\n"), |
| "A/B/F/G/tau" : Item("This is the file 'tau'.\n"), |
| "A/B/F/G/upsilon" : Item("This is the unversioned file 'upsilon'.\n"), |
| "A/B/F/H" : Item(), |
| "A/B/F/H/chi" : Item("This is the file 'chi'.\n"), |
| "A/B/F/H/omega" : Item("This is the file 'omega'.\n"), |
| "A/B/F/H/psi" : Item("This is the file 'psi'.\n"), |
| "A/B/F/I" : Item(), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.tweak('A/B/F', switched='S') |
| expected_status.add({ |
| "A/B/F/gamma" : Item(status=' ', wc_rev=1), |
| "A/B/F/G" : Item(status=' ', wc_rev=1), |
| "A/B/F/G/pi" : Item(status='C ', wc_rev=1), |
| "A/B/F/G/rho" : Item(status=' ', wc_rev=1), |
| "A/B/F/G/tau" : Item(status=' ', wc_rev=1), |
| "A/B/F/G/upsilon" : Item(status='A ', wc_rev=0), |
| "A/B/F/H" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/chi" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/omega" : Item(status=' ', wc_rev=1), |
| "A/B/F/H/psi" : Item(status=' ', wc_rev=1), |
| "A/B/F/I" : Item(status='A ', wc_rev=0), |
| }) |
| |
| # "Extra" files that we expect to result from the conflicts. |
| extra_files = ['pi\.r0', 'pi\.r1', 'pi\.mine'] |
| |
| # Do the switch and check the results in three ways. |
| F_path = os.path.join(sbox.wc_dir, 'A', 'B', 'F') |
| D_url = sbox.repo_url + '/A/D' |
| |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, F_path, D_url, |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, |
| svntest.tree.detect_conflict_files, |
| extra_files, None, None, 0) |
| |
| #---------------------------------------------------------------------- |
| |
| def switch_scheduled_add(sbox): |
| "switch a scheduled-add file" |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| file_path = os.path.join(wc_dir, 'stub_file') |
| switch_url = sbox.repo_url + '/iota' |
| |
| svntest.main.file_append(file_path, "") |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'add', file_path) |
| svntest.actions.run_and_verify_svn(None, None, [], |
| 'switch', switch_url, file_path) |
| |
| #---------------------------------------------------------------------- |
| |
| def mergeinfo_switch_elision(sbox): |
| "mergeinfo elides to closest ancestor w/ same info" |
| |
| # When a switch would add mergeinfo on a node which is identical to |
| # the *local* mergeinfo on one of the node's descendents, then the |
| # mergeinfo on the descendent node is "elided" in favor of the ancestor's |
| # mergeinfo. |
| |
| # Search for the comment entitled "The Merge Kluge" in merge_tests.py |
| # to understand why we shorten, and subsequently chdir() after calling |
| # this function. |
| def shorten_path_kludge(path): |
| shorten_by = len(svntest.main.work_dir) + len(os.sep) |
| return path[shorten_by:] |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Some paths we'll care about |
| lambda_path = os.path.join(wc_dir, "A", "B_COPY_1", "lambda") |
| B_COPY_1_path = os.path.join(wc_dir, "A", "B_COPY_1") |
| B_COPY_2_path = os.path.join(wc_dir, "A", "B_COPY_2") |
| E_COPY_2_path = os.path.join(wc_dir, "A", "B_COPY_2", "E") |
| alpha_path = os.path.join(wc_dir, "A", "B", "E", "alpha") |
| beta_path = os.path.join(wc_dir, "A", "B", "E", "beta") |
| |
| # Make branches A/B_COPY_1 and A/B_COPY_2 |
| svntest.actions.run_and_verify_svn( |
| None, |
| ["A " + os.path.join(wc_dir, "A", "B_COPY_1", "lambda") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "alpha") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_1", "E", "beta") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_1", "F") + "\n", |
| "Checked out revision 1.\n", |
| "A " + B_COPY_1_path + "\n"], |
| [], |
| 'copy', |
| sbox.repo_url + "/A/B", |
| B_COPY_1_path) |
| |
| svntest.actions.run_and_verify_svn( |
| None, |
| ["A " + os.path.join(wc_dir, "A", "B_COPY_2", "lambda") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "alpha") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_2", "E", "beta") + "\n", |
| "A " + os.path.join(wc_dir, "A", "B_COPY_2", "F") + "\n", |
| "Checked out revision 1.\n", |
| "A " + B_COPY_2_path + "\n"], |
| [], |
| 'copy', |
| sbox.repo_url + "/A/B", |
| B_COPY_2_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B_COPY_1' : Item(verb='Adding'), |
| 'A/B_COPY_2' : Item(verb='Adding') |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| "A/B_COPY_1" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/lambda" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/E" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/E/alpha" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/E/beta" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/F" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2/lambda" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2/E" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2/E/alpha" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2/E/beta" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_2/F" : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| None, |
| None, None, None, None, |
| wc_dir) |
| |
| # Make some changes under A/B |
| |
| # r3 - modify and commit A/B/E/beta |
| svntest.main.file_write(beta_path, "New content") |
| expected_output = svntest.wc.State(wc_dir, |
| {'A/B/E/beta' : Item(verb='Sending')}) |
| expected_status.tweak('A/B/E/beta', wc_rev=3) |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status, None, None, None, |
| None, None, wc_dir) |
| |
| # r4 - modify and commit A/B/E/alpha |
| svntest.main.file_write(alpha_path, "New content") |
| expected_output = svntest.wc.State(wc_dir, |
| {'A/B/E/alpha' : Item(verb='Sending')}) |
| expected_status.tweak('A/B/E/alpha', wc_rev=4) |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status, None, None, None, |
| None, None, wc_dir) |
| |
| # Merge r2:4 into A/B_COPY_1 |
| # Search for the comment entitled "The Merge Kluge" in merge_tests.py, |
| # to understand why we shorten and chdir() below. |
| short_B_COPY_1_path = shorten_path_kludge(B_COPY_1_path) |
| expected_output = svntest.wc.State(short_B_COPY_1_path, { |
| 'E/alpha' : Item(status='U '), |
| 'E/beta' : Item(status='U '), |
| }) |
| expected_merge_status = svntest.wc.State(short_B_COPY_1_path, { |
| '' : Item(status=' M', wc_rev=2), |
| 'lambda' : Item(status=' ', wc_rev=2), |
| 'E' : Item(status=' ', wc_rev=2), |
| 'E/alpha' : Item(status='M ', wc_rev=2), |
| 'E/beta' : Item(status='M ', wc_rev=2), |
| 'F' : Item(status=' ', wc_rev=2), |
| }) |
| expected_merge_disk = svntest.wc.State('', { |
| '' : Item(props={SVN_PROP_MERGE_INFO : '/A/B:1,3-4'}), |
| 'lambda' : Item("This is the file 'lambda'.\n"), |
| 'E' : Item(), |
| 'E/alpha' : Item("New content"), |
| 'E/beta' : Item("New content"), |
| 'F' : Item(), |
| }) |
| expected_skip = svntest.wc.State(short_B_COPY_1_path, { }) |
| saved_cwd = os.getcwd() |
| |
| os.chdir(svntest.main.work_dir) |
| svntest.actions.run_and_verify_merge(short_B_COPY_1_path, '2', '4', |
| sbox.repo_url + \ |
| '/A/B', |
| expected_output, |
| expected_merge_disk, |
| expected_merge_status, |
| expected_skip, |
| None, None, None, None, |
| None, 1) |
| |
| os.chdir(saved_cwd) |
| |
| # r5 - Commit the merge into A/B_COPY_1/E |
| expected_output = svntest.wc.State( |
| wc_dir, |
| {'A/B_COPY_1' : Item(verb='Sending'), |
| 'A/B_COPY_1/E/alpha' : Item(verb='Sending'), |
| 'A/B_COPY_1/E/beta' : Item(verb='Sending'), |
| }) |
| expected_status.tweak('A/B_COPY_1', wc_rev=5) |
| expected_status.tweak('A/B_COPY_1/E/alpha', wc_rev=5) |
| expected_status.tweak('A/B_COPY_1/E/beta', wc_rev=5) |
| expected_status.tweak('A/B_COPY_1/lambda', wc_rev=2) |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status, None, None, None, |
| None, None, wc_dir) |
| |
| # Merge r2:4 into A/B_COPY_2/E |
| short_E_COPY_2_path = shorten_path_kludge(E_COPY_2_path) |
| expected_output = svntest.wc.State(short_E_COPY_2_path, { |
| 'alpha' : Item(status='U '), |
| 'beta' : Item(status='U '), |
| }) |
| expected_merge_status = svntest.wc.State(short_E_COPY_2_path, { |
| '' : Item(status=' M', wc_rev=2), |
| 'alpha' : Item(status='M ', wc_rev=2), |
| 'beta' : Item(status='M ', wc_rev=2), |
| }) |
| expected_merge_disk = svntest.wc.State('', { |
| '' : Item(props={SVN_PROP_MERGE_INFO : '/A/B/E:1,3-4'}), |
| 'alpha' : Item("New content"), |
| 'beta' : Item("New content"), |
| }) |
| expected_skip = svntest.wc.State(short_E_COPY_2_path, { }) |
| saved_cwd = os.getcwd() |
| |
| os.chdir(svntest.main.work_dir) |
| svntest.actions.run_and_verify_merge(short_E_COPY_2_path, '2', '4', |
| sbox.repo_url + \ |
| '/A/B/E', |
| expected_output, |
| expected_merge_disk, |
| expected_merge_status, |
| expected_skip, |
| None, None, None, None, |
| None, 1) |
| |
| os.chdir(saved_cwd) |
| |
| # Switch A/B_COPY_2 to URL of A/B_COPY_1. The local mergeinfo for r1,3-4 |
| # on A/B_COPY_2/E is identical to the mergeinfo added to A/B_COPY_2 as a |
| # result of the switch, so the former should be elided to the latter. |
| |
| # Setup expected results of switch. |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| "A/B_COPY_2" : Item(status=' U'), |
| "A/B_COPY_2/E/alpha" : Item(status='G '), |
| "A/B_COPY_2/E/beta" : Item(status='G '), |
| }) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak("A/B/E/alpha", contents="New content") |
| expected_disk.tweak("A/B/E/beta", contents="New content") |
| expected_disk.add({ |
| "A/B_COPY_1" : Item(props={SVN_PROP_MERGE_INFO : '/A/B:1,3-4'}), |
| "A/B_COPY_1/E" : Item(), |
| "A/B_COPY_1/F" : Item(), |
| "A/B_COPY_1/lambda" : Item("This is the file 'lambda'.\n"), |
| "A/B_COPY_1/E/alpha" : Item("New content"), |
| "A/B_COPY_1/E/beta" : Item("New content"), |
| "A/B_COPY_2" : Item(props={SVN_PROP_MERGE_INFO : '/A/B:1,3-4'}), |
| "A/B_COPY_2/E" : Item(), |
| "A/B_COPY_2/F" : Item(), |
| "A/B_COPY_2/lambda" : Item("This is the file 'lambda'.\n"), |
| "A/B_COPY_2/E/alpha" : Item("New content"), |
| "A/B_COPY_2/E/beta" : Item("New content"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.tweak("A/B/E/beta", wc_rev=3) |
| expected_status.tweak("A/B/E/alpha", wc_rev=4) |
| expected_status.add({ |
| "A/B_COPY_1" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_1/E" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/F" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/lambda" : Item(status=' ', wc_rev=2), |
| "A/B_COPY_1/E/alpha" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_1/E/beta" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_2" : Item(status=' ', wc_rev=5, switched='S'), |
| "A/B_COPY_2/E" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_2/F" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_2/lambda" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_2/E/alpha" : Item(status=' ', wc_rev=5), |
| "A/B_COPY_2/E/beta" : Item(status=' ', wc_rev=5), |
| }) |
| |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| B_COPY_2_path, |
| sbox.repo_url + "/A/B_COPY_1", |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, None, None, 1) |
| |
| # Now check that a switch which reverses and earlier switch and leaves |
| # a path in an unswitched state does elide its mergeinfo. |
| # |
| # Switch A/B_COPY_1/lambda to iota. Use propset to give A/B_COPY/lambda |
| # the mergeinfo '/A/B/lambda:1,3-4'. Then switch A/B_COPY_1/lambda back |
| # to A/B_COPY_1/lambda. The local mergeinfo for r1,3-4 should elide this |
| # time to A/B_COPY_1. |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| "A/B_COPY_1/lambda" : Item(status='U '), |
| }) |
| expected_disk.tweak("A/B_COPY_1/lambda", |
| contents="This is the file 'iota'.\n") |
| expected_status.tweak("A/B_COPY_1/lambda", wc_rev=5, switched='S') |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| lambda_path, |
| sbox.repo_url + "/iota", |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, None, None, 1) |
| |
| svntest.actions.run_and_verify_svn(None, |
| ["property '" + SVN_PROP_MERGE_INFO + |
| "' set on '" + lambda_path + "'" + |
| "\n"], [], 'ps', SVN_PROP_MERGE_INFO, |
| '/A/B/lambda:1,3-4', lambda_path) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| "A/B_COPY_1/lambda" : Item(status='U '), |
| }) |
| expected_disk.tweak("A/B_COPY_1/lambda", |
| contents="This is the file 'lambda'.\n") |
| expected_status.tweak("A/B_COPY_1/lambda", switched=None) |
| svntest.actions.run_and_verify_switch(sbox.wc_dir, |
| lambda_path, |
| sbox.repo_url + "/A/B_COPY_1/lambda", |
| expected_output, |
| expected_disk, |
| expected_status, |
| None, None, None, None, None, 1) |
| |
| #---------------------------------------------------------------------- |
| |
| def switch_with_depth(sbox): |
| "basic tests to verify switch along with depth" |
| |
| sbox.build() |
| |
| # Form some paths and URLs required |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| AD_url = repo_url + '/A/D' |
| AB_url = repo_url + '/A/B' |
| AB_path = os.path.join(wc_dir, 'A', 'B') |
| |
| # Set up expected results of 'switch --depth=empty' |
| expected_output = svntest.wc.State(wc_dir, {}) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/B', switched='S') |
| expected_status.tweak('A/B/lambda', switched='S') |
| expected_status.tweak('A/B/E', switched='S') |
| expected_status.tweak('A/B/F', switched='S') |
| |
| # Do 'switch --depth=empty' and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'empty') |
| |
| # Set up expected results for reverting 'switch --depth=empty' |
| expected_output = svntest.wc.State(wc_dir, {}) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'empty') |
| |
| # Set up expected results of 'switch --depth=files' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/lambda' : Item(status='D '), |
| 'A/B/gamma' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/lambda') |
| expected_disk.add({ |
| 'A/B/gamma' : Item("This is the file 'gamma'.\n") |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/lambda') |
| expected_status.add({ |
| 'A/B/gamma' : Item(status=' ', wc_rev=1) |
| }) |
| expected_status.tweak('A/B', switched='S') |
| expected_status.tweak('A/B/E', switched='S') |
| expected_status.tweak('A/B/F', switched='S') |
| |
| # Do 'switch --depth=files' and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'files') |
| |
| # Set up expected results for reverting 'switch --depth=files' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/gamma' : Item(status='D '), |
| 'A/B/lambda' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'files') |
| |
| # Putting the depth=immediates stuff in a subroutine, because we're |
| # going to run it at least twice. |
| def sw_depth_imm(): |
| # Set up expected results of 'switch --depth=immediates' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/lambda' : Item(status='D '), |
| 'A/B/E' : Item(status='D '), |
| 'A/B/F' : Item(status='D '), |
| 'A/B/gamma' : Item(status='A '), |
| 'A/B/G' : Item(status='A '), |
| 'A/B/H' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha', |
| 'A/B/E', 'A/B/F') |
| expected_disk.add({ |
| 'A/B/gamma' : Item("This is the file 'gamma'.\n"), |
| 'A/B/G' : Item(), |
| 'A/B/H' : Item(), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/lambda', 'A/B/E/beta', 'A/B/E/alpha', |
| 'A/B/E', 'A/B/F') |
| expected_status.add({ |
| 'A/B/gamma' : Item(status=' ', wc_rev=1), |
| 'A/B/G' : Item(status=' ', wc_rev=1), |
| 'A/B/H' : Item(status=' ', wc_rev=1) |
| }) |
| expected_status.tweak('A/B', switched='S') |
| |
| # Do 'switch --depth=immediates' and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AD_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'immediates') |
| |
| sw_depth_imm() |
| |
| # Set up expected results for reverting 'switch --depth=immediates'. |
| # (Reverting with default [infinite] depth, so that the result is a |
| # standard Greek Tree working copy again.) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/gamma' : Item(status='D '), |
| 'A/B/G' : Item(status='D '), |
| 'A/B/H' : Item(status='D '), |
| 'A/B/lambda' : Item(status='A '), |
| 'A/B/E' : Item(status='A '), |
| 'A/B/E/alpha' : Item(status='A '), |
| 'A/B/E/beta' : Item(status='A '), |
| 'A/B/F' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0) |
| |
| # Okay, repeat 'switch --depth=immediates'. (Afterwards we'll |
| # 'switch --depth=infinity', to test going all the way.) |
| sw_depth_imm() |
| |
| # Set up expected results of 'switch --depth=infinity' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/gamma' : Item(status='D '), |
| 'A/B/G' : Item(status='D '), |
| 'A/B/H' : Item(status='D '), |
| 'A/B/lambda' : Item(status='A '), |
| 'A/B/E' : Item(status='A '), |
| 'A/B/E/alpha' : Item(status='A '), |
| 'A/B/E/beta' : Item(status='A '), |
| 'A/B/F' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # Do the 'switch --depth=infinity' and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, AB_path, AB_url, |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '--depth', 'infinity') |
| |
| #---------------------------------------------------------------------- |
| |
| def switch_to_dir_with_peg_rev(sbox): |
| "switch to dir@peg where dir doesn't exist in HEAD" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| |
| # prepare two dirs X and Y in rev. 2 |
| X_path = os.path.join(wc_dir, 'X') |
| Y_path = os.path.join(wc_dir, 'Y') |
| svntest.main.run_svn(None, 'mkdir', X_path, Y_path) |
| svntest.main.run_svn(None, 'ci', |
| '-m', 'log message', |
| wc_dir) |
| |
| # change tau in rev. 3 |
| ADG_path = os.path.join(wc_dir, 'A', 'D', 'G') |
| tau_path = os.path.join(ADG_path, 'tau') |
| svntest.main.file_append(tau_path, "new line\n") |
| svntest.main.run_svn(None, 'ci', |
| '-m', 'log message', |
| wc_dir) |
| |
| # delete A/D/G in rev. 4 |
| svntest.main.run_svn(None, 'up', wc_dir) |
| svntest.main.run_svn(None, 'rm', ADG_path) |
| svntest.main.run_svn(None, 'ci', |
| '-m', 'log message', |
| wc_dir) |
| |
| # Test 1: switch X to A/D/G@2 |
| ADG_url = repo_url + '/A/D/G' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X/pi' : Item(status='A '), |
| 'X/rho' : Item(status='A '), |
| 'X/tau' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X' : Item(), |
| 'X/pi' : Item("This is the file 'pi'.\n"), |
| 'X/rho' : Item("This is the file 'rho'.\n"), |
| 'X/tau' : Item("This is the file 'tau'.\n"), |
| 'Y' : Item(), |
| }) |
| expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2, switched='S'), |
| 'X/pi' : Item(status=' ', wc_rev=2), |
| 'X/rho' : Item(status=' ', wc_rev=2), |
| 'X/tau' : Item(status=' ', wc_rev=2), |
| 'Y' : Item(status=' ', wc_rev=3) |
| }) |
| |
| # Do the switch to rev. 2 of /A/D/G@3. |
| svntest.actions.run_and_verify_switch(wc_dir, X_path, ADG_url + '@3', |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '-r', '2') |
| |
| def switch_urls_with_spaces(sbox): |
| "switch file and dir to url containing spaces" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| |
| # add file and directory with spaces in their names. |
| XYZ_path = os.path.join(wc_dir, 'X Y Z') |
| ABC_path = os.path.join(wc_dir, 'A B C') |
| svntest.main.run_svn(None, 'mkdir', XYZ_path, ABC_path) |
| |
| tpm_path = os.path.join(wc_dir, 'tau pau mau') |
| bbb_path = os.path.join(wc_dir, 'bar baz bal') |
| svntest.main.file_write(tpm_path, "This is the file 'tau pau mau'.\n") |
| svntest.main.file_write(bbb_path, "This is the file 'bar baz bal'.\n") |
| svntest.main.run_svn(None, 'add', tpm_path, bbb_path) |
| |
| svntest.main.run_svn(None, 'ci', '-m', 'log message', wc_dir) |
| |
| # Test 1: switch directory 'A B C' to url 'X Y Z' |
| XYZ_url = repo_url + '/X Y Z' |
| expected_output = svntest.wc.State(wc_dir, { |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X Y Z' : Item(), |
| 'A B C' : Item(), |
| 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"), |
| 'bar baz bal' : Item("This is the file 'bar baz bal'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'X Y Z' : Item(status=' ', wc_rev=2), |
| 'A B C' : Item(status=' ', wc_rev=2, switched='S'), |
| 'tau pau mau' : Item(status=' ', wc_rev=2), |
| 'bar baz bal' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_switch(wc_dir, ABC_path, XYZ_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Test 2: switch file 'bar baz bal' to 'tau pau mau' |
| tpm_url = repo_url + '/tau pau mau' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'bar baz bal' : Item(status='U '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X Y Z' : Item(), |
| 'A B C' : Item(), |
| 'tau pau mau' : Item("This is the file 'tau pau mau'.\n"), |
| 'bar baz bal' : Item("This is the file 'tau pau mau'.\n"), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'X Y Z' : Item(status=' ', wc_rev=2), |
| 'A B C' : Item(status=' ', wc_rev=2, switched='S'), |
| 'tau pau mau' : Item(status=' ', wc_rev=2), |
| 'bar baz bal' : Item(status=' ', wc_rev=2, switched='S'), |
| }) |
| |
| svntest.actions.run_and_verify_switch(wc_dir, bbb_path, tpm_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| def switch_to_dir_with_peg_rev2(sbox): |
| "switch to old rev of now renamed branch" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| |
| # prepare dir X in rev. 2 |
| X_path = os.path.join(wc_dir, 'X') |
| svntest.main.run_svn(None, 'mkdir', X_path) |
| svntest.main.run_svn(None, 'ci', |
| '-m', 'log message', |
| wc_dir) |
| |
| # make a change in ADG in rev. 3 |
| tau_path = os.path.join(wc_dir, 'A', 'D', 'G', 'tau') |
| svntest.main.file_append(tau_path, "extra line\n") |
| svntest.main.run_svn(None, 'ci', '-m', 'log message', wc_dir) |
| |
| # Rename ADG to ADY in rev 4 |
| svntest.main.run_svn(None, 'up', wc_dir) |
| ADG_path = os.path.join(wc_dir, 'A', 'D', 'G') |
| ADY_path = os.path.join(wc_dir, 'A', 'D', 'Y') |
| svntest.main.run_svn(None, 'mv', ADG_path, ADY_path) |
| svntest.main.run_svn(None, 'ci', |
| '-m', 'log message', |
| wc_dir) |
| |
| # Test switch X to rev 2 of A/D/Y@HEAD |
| ADY_url = sbox.repo_url + '/A/D/Y' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'X/pi' : Item(status='A '), |
| 'X/rho' : Item(status='A '), |
| 'X/tau' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X' : Item(), |
| 'X/pi' : Item("This is the file 'pi'.\n"), |
| 'X/rho' : Item("This is the file 'rho'.\n"), |
| 'X/tau' : Item("This is the file 'tau'.\n"), |
| 'A/D/Y' : Item(), |
| 'A/D/Y/pi' : Item("This is the file 'pi'.\n"), |
| 'A/D/Y/rho' : Item("This is the file 'rho'.\n"), |
| 'A/D/Y/tau' : Item("This is the file 'tau'.\nextra line\n"), |
| }) |
| expected_disk.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.remove('A/D/G', 'A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=2, switched='S'), |
| 'X/pi' : Item(status=' ', wc_rev=2), |
| 'X/rho' : Item(status=' ', wc_rev=2), |
| 'X/tau' : Item(status=' ', wc_rev=2), |
| 'A/D/Y' : Item(status=' ', wc_rev=4), |
| 'A/D/Y/pi' : Item(status=' ', wc_rev=4), |
| 'A/D/Y/rho' : Item(status=' ', wc_rev=4), |
| 'A/D/Y/tau' : Item(status=' ', wc_rev=4), |
| }) |
| |
| svntest.actions.run_and_verify_switch(wc_dir, X_path, ADY_url + '@HEAD', |
| expected_output, |
| expected_disk, |
| expected_status, None, |
| None, None, None, None, 0, |
| '-r', '2') |
| |
| def switch_to_root(sbox): |
| "switch a folder to the root of its repository" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| |
| ADG_path = os.path.join(wc_dir, 'A', 'D', 'G') |
| |
| # Test switch /A/D/G to / |
| AD_url = sbox.repo_url + '/A/D' |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/G/pi' : Item(status='D '), |
| 'A/D/G/rho' : Item(status='D '), |
| 'A/D/G/tau' : Item(status='D '), |
| 'A/D/G/A' : Item(status='A '), |
| 'A/D/G/A/B' : Item(status='A '), |
| 'A/D/G/A/B/lambda' : Item(status='A '), |
| 'A/D/G/A/B/E' : Item(status='A '), |
| 'A/D/G/A/B/E/alpha' : Item(status='A '), |
| 'A/D/G/A/B/E/beta' : Item(status='A '), |
| 'A/D/G/A/B/F' : Item(status='A '), |
| 'A/D/G/A/mu' : Item(status='A '), |
| 'A/D/G/A/C' : Item(status='A '), |
| 'A/D/G/A/D' : Item(status='A '), |
| 'A/D/G/A/D/gamma' : Item(status='A '), |
| 'A/D/G/A/D/G' : Item(status='A '), |
| 'A/D/G/A/D/G/pi' : Item(status='A '), |
| 'A/D/G/A/D/G/rho' : Item(status='A '), |
| 'A/D/G/A/D/G/tau' : Item(status='A '), |
| 'A/D/G/A/D/H' : Item(status='A '), |
| 'A/D/G/A/D/H/chi' : Item(status='A '), |
| 'A/D/G/A/D/H/omega' : Item(status='A '), |
| 'A/D/G/A/D/H/psi' : Item(status='A '), |
| 'A/D/G/iota' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| expected_disk.add_state('A/D/G', svntest.main.greek_state.copy()) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/D/G/pi', 'A/D/G/rho', 'A/D/G/tau') |
| expected_status.add_state('A/D/G', |
| svntest.actions.get_virginal_state(wc_dir, 1)) |
| expected_status.tweak('A/D/G', switched = 'S') |
| svntest.actions.run_and_verify_switch(wc_dir, ADG_path, sbox.repo_url, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| ######################################################################## |
| # Run the tests |
| |
| # list all tests here, starting with None: |
| test_list = [ None, |
| routine_switching, |
| commit_switched_things, |
| full_update, |
| full_rev_update, |
| update_switched_things, |
| rev_update_switched_things, |
| log_switched_file, |
| relocate_deleted_missing_copied, |
| delete_subdir, |
| XFail(file_dir_file), |
| nonrecursive_switching, |
| failed_anchor_is_target, |
| bad_intermediate_urls, |
| obstructed_switch, |
| commit_mods_below_switch, |
| relocate_beyond_repos_root, |
| refresh_read_only_attribute, |
| switch_change_repos_root, |
| XFail(relocate_and_propset, svntest.main.is_ra_type_dav), |
| forced_switch, |
| forced_switch_failures, |
| switch_scheduled_add, |
| mergeinfo_switch_elision, |
| switch_with_obstructing_local_adds, |
| switch_with_depth, |
| switch_to_dir_with_peg_rev, |
| switch_urls_with_spaces, |
| switch_to_dir_with_peg_rev2, |
| switch_to_root, |
| ] |
| |
| if __name__ == '__main__': |
| svntest.main.run_tests(test_list) |
| # NOTREACHED |
| |
| |
| ### End of file. |