| #!/usr/bin/env python |
| # |
| # basic_tests.py: testing working-copy interactions with ra_local |
| # |
| # Subversion is a tool for revision control. |
| # See http://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 shutil, stat, re, os, logging |
| |
| logger = logging.getLogger() |
| |
| # Our testing module |
| import svntest |
| from svntest import wc |
| |
| # (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 = wc.StateItem |
| |
| # Generic UUID-matching regular expression |
| uuid_regex = re.compile(r"[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}") |
| |
| ###################################################################### |
| # Tests |
| # |
| # Each test must return on success or raise on failure. |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_checkout(sbox): |
| "basic checkout of a wc" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Checkout of a different URL into a working copy fails |
| A_url = sbox.repo_url + '/A' |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| # "Obstructed update", |
| 'co', A_url, |
| wc_dir) |
| |
| # Make some changes to the working copy |
| mu_path = sbox.ospath('A/mu') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| lambda_path = sbox.ospath('A/B/lambda') |
| os.remove(lambda_path) |
| G_path = sbox.ospath('A/D/G') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', G_path) |
| |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.tweak('A/mu', status='M ') |
| expected_output.tweak('A/B/lambda', status='! ') |
| expected_output.tweak('A/D/G', |
| 'A/D/G/pi', |
| 'A/D/G/rho', |
| 'A/D/G/tau', status='D ') |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Repeat checkout of original URL into working copy with modifications |
| url = sbox.repo_url |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'co', url, |
| wc_dir) |
| |
| # lambda is restored, modifications remain, deletes remain scheduled |
| # for deletion although files are restored to the filesystem |
| expected_output.tweak('A/B/lambda', status=' ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_status(sbox): |
| "basic status command" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Created expected output tree for 'svn status' |
| output = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| svntest.actions.run_and_verify_status(wc_dir, output) |
| |
| os.chdir(sbox.ospath('A')) |
| output = svntest.actions.get_virginal_state("..", 1) |
| svntest.actions.run_and_verify_status("..", output) |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_commit(sbox): |
| "basic commit command" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Make a couple of local mods to files |
| mu_path = sbox.ospath('A/mu') |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| svntest.main.file_append(rho_path, 'new appended text for rho') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_update(sbox): |
| "basic update command" |
| |
| 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) |
| |
| # Make a couple of local mods to files |
| mu_path = sbox.ospath('A/mu') |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| svntest.main.file_append(rho_path, 'new appended text for rho') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2) |
| |
| # Commit. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Create expected output tree for an update of the wc_backup. |
| expected_output = wc.State(wc_backup, { |
| 'A/mu' : Item(status='U '), |
| 'A/D/G/rho' : Item(status='U '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/mu', |
| contents=expected_disk.desc['A/mu'].contents |
| + 'appended mu text') |
| expected_disk.tweak('A/D/G/rho', |
| contents=expected_disk.desc['A/D/G/rho'].contents |
| + 'new appended text for rho') |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(wc_backup, 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) |
| |
| # Unversioned paths, those that are not immediate children of a versioned |
| # path, are skipped and do raise an error if they are the only targets |
| xx_path = sbox.ospath('xx/xx') |
| expected_err = "svn: E155007: " |
| svntest.actions.run_and_verify_svn( |
| ["Skipped '"+xx_path+"'\n", ], |
| expected_err, |
| 'update', xx_path) |
| svntest.actions.run_and_verify_svn( |
| [], expected_err, |
| 'update', '--quiet', xx_path) |
| |
| # Unversioned paths, that are not the only targets of the command are |
| # skipped without an error |
| svntest.actions.run_and_verify_svn( |
| ["Updating '"+mu_path+"':\n", |
| "At revision 2.\n", |
| "Skipped '"+xx_path+"'\n", |
| "Summary of updates:\n", |
| " Updated '"+mu_path+"' to r2.\n" |
| ] + svntest.main.summary_of_conflicts(skipped_paths=1), |
| [], 'update', mu_path, xx_path) |
| svntest.actions.run_and_verify_svn( |
| [], [], 'update', '--quiet', mu_path, xx_path) |
| |
| #---------------------------------------------------------------------- |
| def basic_mkdir_url(sbox): |
| "basic mkdir URL" |
| |
| sbox.build() |
| |
| Y_url = sbox.repo_url + '/Y' |
| Y_Z_url = sbox.repo_url + '/Y/Z' |
| |
| svntest.actions.run_and_verify_svn(["Committing transaction...\n", |
| "Committed revision 2.\n"], [], |
| 'mkdir', '-m', 'log_msg', Y_url, Y_Z_url) |
| |
| expected_output = wc.State(sbox.wc_dir, { |
| 'Y' : Item(status='A '), |
| 'Y/Z' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'Y' : Item(), |
| 'Y/Z' : Item() |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2) |
| expected_status.add({ |
| 'Y' : Item(status=' ', wc_rev=2), |
| 'Y/Z' : Item(status=' ', wc_rev=2) |
| }) |
| |
| svntest.actions.run_and_verify_update(sbox.wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def basic_mkdir_url_with_parents(sbox): |
| "basic mkdir URL, including parent directories" |
| |
| sbox.build() |
| |
| X_url = sbox.repo_url + '/X' |
| X_Y_Z_url = sbox.repo_url + '/X/Y/Z' |
| X_Y_Z2_url = sbox.repo_url + '/X/Y/Z2' |
| X_T_C_url = sbox.repo_url + '/X/T/C' |
| U_url = sbox.repo_url + '/U' |
| U_V_url = sbox.repo_url + '/U/V' |
| U_V_W_url = sbox.repo_url + '/U/V/W' |
| svntest.actions.run_and_verify_svn(None, |
| ".*Try 'svn mkdir --parents' instead.*", |
| 'mkdir', '-m', 'log_msg', |
| X_Y_Z_url, X_Y_Z2_url, X_T_C_url, U_V_W_url) |
| |
| svntest.actions.run_and_verify_svn(["Committing transaction...\n", |
| "Committed revision 2.\n"], [], |
| 'mkdir', '-m', 'log_msg', |
| X_url, U_url) |
| |
| svntest.actions.run_and_verify_svn(["Committing transaction...\n", |
| "Committed revision 3.\n"], [], |
| 'mkdir', '-m', 'log_msg', '--parents', |
| X_Y_Z_url, X_Y_Z2_url, X_T_C_url, U_V_W_url) |
| |
| expected_output = wc.State(sbox.wc_dir, { |
| 'X' : Item(status='A '), |
| 'X/Y' : Item(status='A '), |
| 'X/Y/Z' : Item(status='A '), |
| 'X/Y/Z2' : Item(status='A '), |
| 'X/T' : Item(status='A '), |
| 'X/T/C' : Item(status='A '), |
| 'U' : Item(status='A '), |
| 'U/V' : Item(status='A '), |
| 'U/V/W' : Item(status='A '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'X' : Item(), |
| 'X/Y' : Item(), |
| 'X/Y/Z' : Item(), |
| 'X/Y/Z2' : Item(), |
| 'X/T' : Item(), |
| 'X/T/C' : Item(), |
| 'U' : Item(), |
| 'U/V' : Item(), |
| 'U/V/W' : Item(), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 3) |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=3), |
| 'X/Y' : Item(status=' ', wc_rev=3), |
| 'X/Y/Z' : Item(status=' ', wc_rev=3), |
| 'X/Y/Z2' : Item(status=' ', wc_rev=3), |
| 'X/T' : Item(status=' ', wc_rev=3), |
| 'X/T/C' : Item(status=' ', wc_rev=3), |
| 'U' : Item(status=' ', wc_rev=3), |
| 'U/V' : Item(status=' ', wc_rev=3), |
| 'U/V/W' : Item(status=' ', wc_rev=3), |
| }) |
| svntest.actions.run_and_verify_update(sbox.wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def basic_mkdir_wc_with_parents(sbox): |
| "basic mkdir, including parent directories" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| Y_Z_path = sbox.ospath('Y/Z') |
| |
| svntest.actions.run_and_verify_svn([], |
| ".*Try 'svn mkdir --parents' instead.*", |
| 'mkdir', Y_Z_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', '--parents', Y_Z_path) |
| |
| # Verify the WC status, because there was a regression in which parts of |
| # the WC were left locked. |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.add({ |
| 'Y' : Item(status='A ', wc_rev=0), |
| 'Y/Z' : Item(status='A ', wc_rev=0), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| def basic_commit_corruption(sbox): |
| "basic corruption detection on commit" |
| |
| ## I always wanted a test named "basic_corruption". :-) |
| ## Here's how it works: |
| ## |
| ## 1. Make a working copy at rev 1, duplicate it. Now we have |
| ## two working copies at rev 1. Call them first and second. |
| ## 2. Make a local mod to `first/A/mu'. |
| ## 3. Intentionally corrupt `first/A/.svn/text-base/mu.svn-base'. |
| ## 4. Try to commit, expect a failure. |
| ## 5. Repair the text-base, commit again, expect success. |
| ## |
| ## Here we go... |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Make a local mod to mu |
| mu_path = sbox.ospath('A/mu') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', wc_rev=2) |
| |
| # Modify mu's text-base, so we get a checksum failure the first time |
| # we try to commit. |
| mu_tb_path = svntest.wc.text_base_path(mu_path) |
| tb_dir_path = os.path.dirname(mu_tb_path) |
| mu_saved_tb_path = mu_tb_path + "-saved" |
| tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE] |
| mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE] |
| ### What's a more portable way to do this? |
| os.chmod(tb_dir_path, svntest.main.S_ALL_RWX) |
| os.chmod(mu_tb_path, svntest.main.S_ALL_RW) |
| shutil.copyfile(mu_tb_path, mu_saved_tb_path) |
| svntest.main.file_append(mu_tb_path, 'Aaagggkkk, corruption!') |
| os.chmod(tb_dir_path, tb_dir_saved_mode) |
| os.chmod(mu_tb_path, mu_tb_saved_mode) |
| |
| # This commit should fail due to text base corruption. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| None, # expected_status, |
| "svn: E200014: Checksum") |
| |
| # Restore the uncorrupted text base. |
| os.chmod(tb_dir_path, svntest.main.S_ALL_RWX) |
| os.chmod(mu_tb_path, svntest.main.S_ALL_RW) |
| os.remove(mu_tb_path) |
| os.rename(mu_saved_tb_path, mu_tb_path) |
| os.chmod(tb_dir_path, tb_dir_saved_mode) |
| os.chmod(mu_tb_path, mu_tb_saved_mode) |
| |
| # This commit should succeed. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| def basic_update_corruption(sbox): |
| "basic corruption detection on update" |
| |
| ## I always wanted a test named "basic_corruption". :-) |
| ## Here's how it works: |
| ## |
| ## 1. Make a working copy at rev 1, duplicate it. Now we have |
| ## two working copies at rev 1. Call them first and second. |
| ## 2. Make a local mod to `first/A/mu'. |
| ## 3. Repair the text-base, commit again, expect success. |
| ## 4. Intentionally corrupt `second/A/.svn/text-base/mu.svn-base'. |
| ## 5. Try to update `second', expect failure. |
| ## 6. Repair the text-base, update again, expect success. |
| ## |
| ## Here we go... |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Make the "other" working copy |
| other_wc = sbox.add_wc_path('other') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'co', sbox.repo_url, other_wc) |
| |
| # Make a local mod to mu |
| mu_path = sbox.ospath('A/mu') |
| svntest.main.file_append(mu_path, 'appended mu text') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', wc_rev=2) |
| |
| # This commit should succeed. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Create expected output tree for an update of the other_wc. |
| expected_output = wc.State(other_wc, { |
| 'A/mu' : Item(status='U '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(other_wc, 2) |
| |
| # Modify mu's text-base, so we get a checksum failure the first time |
| # we try to update. |
| other_mu_path = os.path.join(other_wc, 'A', 'mu') |
| mu_tb_path = svntest.wc.text_base_path(other_mu_path) |
| tb_dir_path = os.path.dirname(mu_tb_path) |
| mu_saved_tb_path = mu_tb_path + "-saved" |
| tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE] |
| mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE] |
| os.chmod(tb_dir_path, svntest.main.S_ALL_RWX) |
| os.chmod(mu_tb_path, svntest.main.S_ALL_RW) |
| shutil.copyfile(mu_tb_path, mu_saved_tb_path) |
| svntest.main.file_append(mu_tb_path, 'Aiyeeeee, corruption!\nHelp!\n') |
| os.chmod(tb_dir_path, tb_dir_saved_mode) |
| os.chmod(mu_tb_path, mu_tb_saved_mode) |
| |
| # Do the update and check the results in four ways. |
| fail_output = wc.State(other_wc, { |
| }) |
| fail_status = svntest.actions.get_virginal_state(other_wc, 1) |
| fail_status.tweak('A', '', status='! ', wc_rev=2) |
| svntest.actions.run_and_verify_update(other_wc, |
| fail_output, |
| expected_disk, |
| fail_status, |
| "svn: E155017: Checksum") |
| |
| # Restore the uncorrupted text base. |
| os.chmod(tb_dir_path, svntest.main.S_ALL_RWX) |
| os.chmod(mu_tb_path, svntest.main.S_ALL_RW) |
| os.remove(mu_tb_path) |
| os.rename(mu_saved_tb_path, mu_tb_path) |
| os.chmod(tb_dir_path, tb_dir_saved_mode) |
| os.chmod(mu_tb_path, mu_tb_saved_mode) |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(other_wc, 2) |
| |
| # This update should succeed. (Actually, I'm kind of astonished |
| # that this works without even an intervening "svn cleanup".) |
| expected_disk.tweak('A/mu', |
| contents=expected_disk.desc['A/mu'].contents |
| + 'appended mu text') |
| |
| svntest.actions.run_and_verify_update(other_wc, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| def basic_merging_update(sbox): |
| "receiving text merges as part of an update" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # First change the greek tree to make two files 10 lines long |
| mu_path = sbox.ospath('A/mu') |
| rho_path = sbox.ospath('A/D/G/rho') |
| mu_text = "" |
| rho_text = "" |
| for x in range(2,11): |
| mu_text = mu_text + '\nThis is line ' + repr(x) + ' in mu' |
| rho_text = rho_text + '\nThis is line ' + repr(x) + ' in rho' |
| svntest.main.file_append(mu_path, mu_text) |
| svntest.main.file_append(rho_path, rho_text) |
| |
| # Create expected output tree for initial commit |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2) |
| |
| # Initial commit. |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| [], |
| 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) |
| |
| # Make a couple of local mods to files |
| svntest.main.file_append(mu_path, ' Appended to line 10 of mu') |
| svntest.main.file_append(rho_path, ' Appended to line 10 of rho') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 3. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=3) |
| |
| # Commit. |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status, |
| [], |
| wc_dir) |
| |
| # Make local mods to wc_backup by recreating mu and rho |
| mu_path_backup = os.path.join(wc_backup, 'A', 'mu') |
| rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho') |
| |
| # open in 'truncate to zero then write" mode |
| backup_mu_text = 'This is the new line 1 in the backup copy of mu' |
| for x in range(2,11): |
| backup_mu_text = backup_mu_text + '\nThis is line ' + repr(x) + ' in mu' |
| svntest.main.file_write(mu_path_backup, backup_mu_text, 'w+') |
| |
| backup_rho_text = 'This is the new line 1 in the backup copy of rho' |
| for x in range(2,11): |
| backup_rho_text = backup_rho_text + '\nThis is line ' + repr(x) + ' in rho' |
| svntest.main.file_write(rho_path_backup, backup_rho_text, 'w+') |
| |
| # Create expected output tree for an update of the wc_backup. |
| expected_output = wc.State(wc_backup, { |
| 'A/mu' : Item(status='G '), |
| 'A/D/G/rho' : Item(status='G '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/mu', |
| contents=backup_mu_text + ' Appended to line 10 of mu') |
| expected_disk.tweak('A/D/G/rho', |
| contents=backup_rho_text + ' Appended to line 10 of rho') |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(wc_backup, 3) |
| expected_status.tweak('A/mu', 'A/D/G/rho', status='M ') |
| |
| # Do the update and check the results in three ways. |
| svntest.actions.run_and_verify_update(wc_backup, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| |
| def basic_conflict(sbox): |
| "basic conflict creation and resolution" |
| |
| 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) |
| |
| # Make a couple of local mods to files which will be committed |
| mu_path = sbox.ospath('A/mu') |
| rho_path = sbox.ospath('A/D/G/rho') |
| svntest.main.file_append(mu_path, 'Original appended text for mu\n') |
| svntest.main.file_append(rho_path, 'Original appended text for rho\n') |
| |
| # Make a couple of local mods to files which will be conflicted |
| mu_path_backup = os.path.join(wc_backup, 'A', 'mu') |
| rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho') |
| svntest.main.file_append(mu_path_backup, |
| 'Conflicting appended text for mu\n') |
| svntest.main.file_append(rho_path_backup, |
| 'Conflicting appended text for rho\n') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/D/G/rho', wc_rev=2) |
| |
| # Commit. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Create expected output tree for an update of the wc_backup. |
| expected_output = wc.State(wc_backup, { |
| 'A/mu' : Item(status='C '), |
| 'A/D/G/rho' : Item(status='C '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/mu', |
| contents="\n".join(["This is the file 'mu'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for mu", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for mu", |
| ">>>>>>> .r2", |
| ""])) |
| expected_disk.tweak('A/D/G/rho', |
| contents="\n".join(["This is the file 'rho'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for rho", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for rho", |
| ">>>>>>> .r2", |
| ""])) |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(wc_backup, '2') |
| expected_status.tweak('A/mu', 'A/D/G/rho', status='C ') |
| |
| # "Extra" files that we expect to result from the conflicts. |
| # These are expressed as list of regexps. What a cool system! :-) |
| extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine', |
| 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine',] |
| |
| # Do the update and check the results in three ways. |
| # All "extra" files are passed to detect_conflict_files(). |
| svntest.actions.run_and_verify_update(wc_backup, |
| expected_output, |
| expected_disk, |
| expected_status, |
| extra_files=extra_files) |
| |
| # verify that the extra_files list is now empty. |
| if len(extra_files) != 0: |
| # Because we want to be a well-behaved test, we silently raise if |
| # the test fails. However, these two print statements would |
| # probably reveal the cause for the failure, if they were |
| # uncommented: |
| # |
| # logger.warn("Not all extra reject files have been accounted for:") |
| # logger.warn(extra_files) |
| ### we should raise a less generic error here. which? |
| raise svntest.Failure |
| |
| # So now mu and rho are both in a "conflicted" state. Run 'svn |
| # resolved' on them. |
| |
| svntest.actions.run_and_verify_resolved([mu_path_backup, rho_path_backup]) |
| |
| # See if they've changed back to plain old 'M' state. |
| expected_status.tweak('A/mu', 'A/D/G/rho', status='M ') |
| |
| # There should be *no* extra backup files lying around the working |
| # copy after resolving the conflict; thus we're not passing a custom |
| # singleton handler. |
| svntest.actions.run_and_verify_status(wc_backup, expected_status) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_cleanup(sbox): |
| "basic cleanup command" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Lock some directories. |
| B_path = sbox.ospath('A/B') |
| G_path = sbox.ospath('A/D/G') |
| C_path = sbox.ospath('A/C') |
| svntest.actions.lock_admin_dir(B_path) |
| svntest.actions.lock_admin_dir(G_path) |
| svntest.actions.lock_admin_dir(C_path) |
| |
| # Verify locked status. |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.tweak('A/B', 'A/D/G', 'A/C', locked='L') |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # corrupted/non-existing temporary directory should be restored while |
| # we are not at single-db (where this tmp dir will be gone) |
| tmp_path = os.path.join(B_path, svntest.main.get_admin_name(), 'tmp') |
| if os.path.exists(tmp_path): |
| svntest.main.safe_rmtree(tmp_path) |
| |
| # Run cleanup (### todo: cleanup doesn't currently print anything) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'cleanup', wc_dir) |
| |
| # Verify unlocked status. |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_revert(sbox): |
| "basic revert command" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Modify some files and props. |
| beta_path = sbox.ospath('A/B/E/beta') |
| gamma_path = sbox.ospath('A/D/gamma') |
| iota_path = sbox.ospath('iota') |
| rho_path = sbox.ospath('A/D/G/rho') |
| zeta_path = sbox.ospath('A/D/H/zeta') |
| svntest.main.file_append(beta_path, "Added some text to 'beta'.\n") |
| svntest.main.file_append(iota_path, "Added some text to 'iota'.\n") |
| svntest.main.file_append(rho_path, "Added some text to 'rho'.\n") |
| svntest.main.file_append(zeta_path, "Added some text to 'zeta'.\n") |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'add', zeta_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ps', 'random-prop', 'propvalue', |
| gamma_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ps', 'random-prop', 'propvalue', |
| iota_path) |
| |
| # Verify modified status. |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.tweak('A/B/E/beta', 'A/D/G/rho', status='M ') |
| expected_output.tweak('iota', status='MM') |
| expected_output.tweak('A/D/gamma', status=' M') |
| expected_output.add({ |
| 'A/D/H/zeta' : Item(status='A ', wc_rev=0), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Run revert (### todo: revert doesn't currently print anything) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'revert', beta_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'revert', gamma_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'revert', iota_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'revert', rho_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'revert', zeta_path) |
| |
| # Verify unmodified status. |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # Now, really make sure the contents are back to their original state. |
| fp = open(beta_path, 'r') |
| lines = fp.readlines() |
| if not ((len (lines) == 1) and (lines[0] == "This is the file 'beta'.\n")): |
| logger.warn("Revert failed to restore original text.") |
| raise svntest.Failure |
| fp = open(iota_path, 'r') |
| lines = fp.readlines() |
| if not ((len (lines) == 1) and (lines[0] == "This is the file 'iota'.\n")): |
| logger.warn("Revert failed to restore original text.") |
| raise svntest.Failure |
| fp = open(rho_path, 'r') |
| lines = fp.readlines() |
| if not ((len (lines) == 1) and (lines[0] == "This is the file 'rho'.\n")): |
| logger.warn("Revert failed to restore original text.") |
| raise svntest.Failure |
| fp = open(zeta_path, 'r') |
| lines = fp.readlines() |
| if not ((len (lines) == 1) and (lines[0] == "Added some text to 'zeta'.\n")): |
| ### we should raise a less generic error here. which? |
| raise svntest.Failure |
| |
| # Finally, check that reverted file is not readonly |
| os.remove(beta_path) |
| svntest.actions.run_and_verify_svn(None, [], 'revert', beta_path) |
| if not (open(beta_path, 'r+')): |
| raise svntest.Failure |
| |
| # Check that a directory scheduled to be added, but physically |
| # removed, can be reverted. |
| X_path = sbox.ospath('X') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', X_path) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'X' : Item(status='A ', wc_rev=0), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| svntest.main.safe_rmtree(X_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'revert', X_path) |
| |
| expected_status.remove('X') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Check that a directory scheduled for deletion, but physically |
| # removed, can be reverted. |
| E_path = sbox.ospath('A/B/E') |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| ### Most of the rest of this test is ineffective, due to the |
| ### problems described in issue #1611. |
| svntest.actions.run_and_verify_svn(None, [], 'rm', E_path) |
| svntest.main.safe_rmtree(E_path) |
| expected_status.tweak('A/B/E', status='D ') |
| expected_status.tweak('A/B/E', wc_rev='?') |
| ### FIXME: A weakness in the test framework, described in detail |
| ### in issue #1611, prevents us from checking via status. Grr. |
| # |
| # svntest.actions.run_and_verify_status(wc_dir, expected_status, |
| # None, None, None, None) |
| # |
| # |
| ### If you were to uncomment the above, you'd get an error like so: |
| # |
| # ============================================================= |
| # Expected E and actual E are different! |
| # ============================================================= |
| # EXPECTED NODE TO BE: |
| # ============================================================= |
| # * Node name: E |
| # Path: working_copies/basic_tests-10/A/B/E |
| # Contents: None |
| # Properties: {} |
| # Attributes: {'status': 'D ', 'wc_rev': '?'} |
| # Children: 2 |
| # ============================================================= |
| # ACTUAL NODE FOUND: |
| # ============================================================= |
| # * Node name: E |
| # Path: working_copies/basic_tests-10/A/B/E |
| # Contents: None |
| # Properties: {} |
| # Attributes: {'status': 'D ', 'wc_rev': '?'} |
| # Children: is a file. |
| # Unequal Types: one Node is a file, the other is a directory |
| |
| # This will actually print |
| # |
| # "Failed to revert 'working_copies/basic_tests-10/A/B/E' -- \ |
| # try updating instead." |
| # |
| # ...but due to test suite lossage, it'll still look like success. |
| svntest.actions.run_and_verify_svn(None, [], 'revert', E_path) |
| |
| ### FIXME: Again, the problem described in issue #1611 bites us here. |
| # |
| # expected_status.tweak('A/B/E', status=' ') |
| # svntest.actions.run_and_verify_status(wc_dir, expected_status, |
| # None, None, None, None) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_switch(sbox): |
| "basic switch command" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| ### Switch the file `iota' to `A/D/gamma'. |
| |
| # Construct some paths for convenience |
| iota_path = sbox.ospath('iota') |
| gamma_url = sbox.repo_url + '/A/D/gamma' |
| |
| # Create expected output tree |
| expected_output = 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') |
| |
| # First, try the switch without the --ignore-ancestry flag, |
| # expecting failure. |
| expected_error = "svn: E195012: .*no common ancestry.*" |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'switch', gamma_url, iota_path) |
| |
| # Now ignore ancestry so we can ge through this switch. |
| svntest.actions.run_and_verify_switch(wc_dir, iota_path, gamma_url, |
| expected_output, |
| expected_disk, |
| expected_status, |
| [], |
| False, '--ignore-ancestry') |
| |
| ### Switch the directory `A/D/H' to `A/D/G'. |
| |
| # Construct some paths for convenience |
| ADH_path = sbox.ospath('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') |
| ADG_url = sbox.repo_url + '/A/D/G' |
| |
| # Create expected output tree |
| expected_output = wc.State(wc_dir, { |
| 'A/D/H/chi' : Item(status='D '), |
| 'A/D/H/omega' : Item(status='D '), |
| 'A/D/H/psi' : Item(status='D '), |
| 'A/D/H/pi' : Item(status='A '), |
| 'A/D/H/rho' : Item(status='A '), |
| 'A/D/H/tau' : Item(status='A '), |
| }) |
| |
| # Create expected disk tree (iota will have gamma's contents, |
| # A/D/H/* will look like A/D/G/*) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('iota', |
| contents=expected_disk.desc['A/D/gamma'].contents) |
| expected_disk.remove('A/D/H/chi', 'A/D/H/omega', 'A/D/H/psi') |
| expected_disk.add({ |
| 'A/D/H/pi' : Item("This is the file 'pi'.\n"), |
| 'A/D/H/rho' : Item("This is the file 'rho'.\n"), |
| 'A/D/H/tau' : Item("This is the file 'tau'.\n"), |
| }) |
| |
| # Create expected status |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi') |
| expected_status.add({ |
| 'A/D/H/pi' : Item(status=' ', wc_rev=1), |
| 'A/D/H/rho' : Item(status=' ', wc_rev=1), |
| 'A/D/H/tau' : Item(status=' ', wc_rev=1), |
| }) |
| expected_status.tweak('iota', 'A/D/H', switched='S') |
| |
| # First, try the switch without the --ignore-ancestry flag, |
| # expecting failure. |
| expected_error = "svn: E195012: .*no common ancestry.*" |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'switch', ADG_url, ADH_path) |
| |
| # Do the switch and check the results in three ways. |
| svntest.actions.run_and_verify_switch(wc_dir, ADH_path, ADG_url, |
| expected_output, |
| expected_disk, |
| expected_status, |
| [], |
| False, '--ignore-ancestry') |
| |
| #---------------------------------------------------------------------- |
| |
| def verify_file_deleted(message, path): |
| try: |
| open(path, 'r') |
| except IOError: |
| return |
| if message is not None: |
| logger.warn(message) |
| ###TODO We should raise a less generic error here. which? |
| raise svntest.Failure |
| |
| def verify_dir_deleted(path): |
| if not os.path.isdir(path): |
| return 0 |
| |
| return 1 |
| |
| @Issue(687,4074) |
| def basic_delete(sbox): |
| "basic delete command" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Copies of unmodified |
| sbox.simple_copy('iota', 'iota-copied') |
| sbox.simple_copy('A/B/F', 'F-copied') |
| |
| # modify text of chi |
| chi_parent_path = sbox.ospath('A/D/H') |
| chi_path = os.path.join(chi_parent_path, 'chi') |
| svntest.main.file_append(chi_path, 'added to chi') |
| |
| # modify props of rho (file) |
| rho_parent_path = sbox.ospath('A/D/G') |
| rho_path = os.path.join(rho_parent_path, 'rho') |
| svntest.main.run_svn(None, 'ps', 'abc', 'def', rho_path) |
| |
| # modify props of F (dir) |
| F_parent_path = sbox.ospath('A/B') |
| F_path = os.path.join(F_parent_path, 'F') |
| svntest.main.run_svn(None, 'ps', 'abc', 'def', F_path) |
| |
| # unversioned file |
| sigma_parent_path = sbox.ospath('A/C') |
| sigma_path = os.path.join(sigma_parent_path, 'sigma') |
| svntest.main.file_append(sigma_path, 'unversioned sigma') |
| |
| # unversioned directory |
| Q_parent_path = sigma_parent_path |
| Q_path = os.path.join(Q_parent_path, 'Q') |
| os.mkdir(Q_path) |
| |
| # added directory hierarchies |
| X_parent_path = sbox.ospath('A/B') |
| X_path = os.path.join(X_parent_path, 'X') |
| svntest.main.run_svn(None, 'mkdir', X_path) |
| X_child_path = os.path.join(X_path, 'xi') |
| svntest.main.file_append(X_child_path, 'added xi') |
| svntest.main.run_svn(None, 'add', X_child_path) |
| Y_parent_path = sbox.ospath('A/D') |
| Y_path = os.path.join(Y_parent_path, 'Y') |
| svntest.main.run_svn(None, 'mkdir', Y_path) |
| |
| # check status |
| expected_output = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_output.tweak('A/D/H/chi', status='M ') |
| expected_output.tweak('A/D/G/rho', 'A/B/F', status=' M') |
| # expected_output.tweak('A/C/sigma', status='? ') |
| expected_output.add({ |
| 'A/B/X' : Item(status='A ', wc_rev='-'), |
| 'A/B/X/xi' : Item(status='A ', wc_rev='-'), |
| 'A/D/Y' : Item(status='A ', wc_rev='-'), |
| 'F-copied' : Item(status='A ', copied='+', wc_rev='-'), |
| 'iota-copied' : Item(status='A ', copied='+', wc_rev='-'), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # 'svn rm' that should fail |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', chi_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', chi_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', rho_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', rho_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', F_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', F_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', sigma_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', sigma_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'rm', X_path) |
| |
| # check status has not changed |
| svntest.actions.run_and_verify_status(wc_dir, expected_output) |
| |
| # 'svn rm' that should work |
| E_path = sbox.ospath('A/B/E') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', E_path) |
| |
| # 'svn rm --force' that should work |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--force', |
| chi_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', rho_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', F_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', sigma_parent_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', X_path) |
| |
| # Deleting an unchanged copy shouldn't error. |
| sbox.simple_mkdir('Z-added') |
| svntest.main.run_svn(None, 'rm', sbox.ospath('iota-copied'), |
| sbox.ospath('F-copied'), |
| sbox.ospath('Z-added')) |
| |
| # Deleting already removed from wc versioned item with --force |
| iota_path = sbox.ospath('iota') |
| os.remove(iota_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', iota_path) |
| |
| # and without --force |
| gamma_path = sbox.ospath('A/D/gamma') |
| os.remove(gamma_path) |
| svntest.actions.run_and_verify_svn(None, [], 'rm', gamma_path) |
| |
| # Deleting already scheduled for deletion doesn't require --force |
| svntest.actions.run_and_verify_svn(None, [], 'rm', gamma_path) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', E_path) |
| |
| # check status |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/H', |
| 'A/D/H/chi', |
| 'A/D/H/omega', |
| 'A/D/H/psi', |
| 'A/D/G', |
| 'A/D/G/rho', |
| 'A/D/G/pi', |
| 'A/D/G/tau', |
| 'A/B/E', |
| 'A/B/E/alpha', |
| 'A/B/E/beta', |
| 'A/B/F', |
| 'A/C', |
| 'iota', |
| 'A/D/gamma', status='D ') |
| expected_status.add({ |
| 'A/D/Y' : Item(status='A ', wc_rev=0), |
| }) |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # issue 687 delete directory with uncommitted directory child |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', Y_parent_path) |
| |
| expected_status.tweak('A/D', status='D ') |
| expected_status.remove('A/D/Y') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # check files have been removed |
| verify_file_deleted("Failed to remove text modified file", rho_path) |
| verify_file_deleted("Failed to remove prop modified file", chi_path) |
| verify_file_deleted("Failed to remove unversioned file", sigma_path) |
| verify_file_deleted("Failed to remove unmodified file", |
| os.path.join(E_path, 'alpha')) |
| |
| # check versioned dir is not removed |
| if not verify_dir_deleted(F_path): |
| # If we are not running in single-db, this is an error |
| if os.path.isdir(os.path.join(F_path, '../' + svntest.main.get_admin_name())): |
| raise svntest.Failure("Removed administrative area") |
| |
| # check unversioned and added dirs has been removed |
| if verify_dir_deleted(Q_path): |
| logger.warn("Failed to remove unversioned dir") |
| ### we should raise a less generic error here. which? |
| raise svntest.Failure |
| if verify_dir_deleted(X_path): |
| logger.warn("Failed to remove added dir") |
| ### we should raise a less generic error here. which? |
| raise svntest.Failure |
| |
| # Deleting unversioned file explicitly |
| foo_path = sbox.ospath('foo') |
| svntest.main.file_append(foo_path, 'unversioned foo') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', foo_path) |
| verify_file_deleted("Failed to remove unversioned file foo", foo_path) |
| |
| # At one stage deleting a URL dumped core |
| iota_URL = sbox.repo_url + '/iota' |
| |
| svntest.actions.run_and_verify_svn(["Committing transaction...\n", |
| "Committed revision 2.\n"], [], |
| 'rm', '-m', 'delete iota URL', |
| iota_URL) |
| |
| # Issue 4074, deleting a root url SEGV. |
| expected_error = 'svn: E170000: .*not within a repository' |
| svntest.actions.run_and_verify_svn([], expected_error, |
| 'rm', sbox.repo_url, |
| '--message', 'delete root') |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_checkout_deleted(sbox): |
| "checkout a path no longer in HEAD" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Delete A/D and commit. |
| D_path = sbox.ospath('A/D') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--force', D_path) |
| |
| expected_output = wc.State(wc_dir, { |
| 'A/D' : Item(verb='Deleting'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/D', 'A/D/G', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau', |
| 'A/D/H', 'A/D/H/chi', 'A/D/H/psi', 'A/D/H/omega', |
| 'A/D/gamma') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status) |
| |
| # Now try to checkout revision 1 of A/D. |
| url = sbox.repo_url + '/A/D' |
| wc2 = sbox.ospath('new_D') |
| svntest.actions.run_and_verify_svn(None, [], 'co', '-r', '1', |
| url + "@1", wc2) |
| |
| #---------------------------------------------------------------------- |
| |
| # Issue 846, changing a deleted file to an added directory was not |
| # supported before WC-NG. But we can handle it. |
| @Issue(846) |
| def basic_node_kind_change(sbox): |
| "attempt to change node kind" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Schedule a file for deletion |
| gamma_path = sbox.ospath('A/D/gamma') |
| svntest.main.run_svn(None, 'rm', gamma_path) |
| |
| # Status shows deleted file |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/gamma', status='D ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Try and fail to create a directory (file scheduled for deletion) |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', gamma_path) |
| |
| # Status is replaced |
| expected_status.tweak('A/D/gamma', status='R ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Commit file deletion |
| expected_output = wc.State(wc_dir, { |
| 'A/D/gamma' : Item(verb='Replacing'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/D/gamma', status=' ', wc_rev='2') |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status) |
| |
| # Try and fail to create a directory (file deleted) |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'mkdir', gamma_path) |
| |
| # Status is unchanged |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Update to finally get rid of file |
| svntest.actions.run_and_verify_svn(None, [], 'up', wc_dir) |
| |
| # mkdir should succeed |
| svntest.actions.run_and_verify_svn(None, [], 'rm', gamma_path) |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', gamma_path) |
| |
| expected_status.tweak(wc_rev=2) |
| expected_status.add({ |
| 'A/D/gamma' : Item(status='R ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_import(sbox): |
| "basic import of single new file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # create a new directory with files of various permissions |
| new_path = sbox.ospath('new_file') |
| |
| svntest.main.file_append(new_path, "some text") |
| |
| # import new files into repository |
| url = sbox.repo_url + "/dirA/dirB/new_file" |
| exit_code, output, errput = svntest.actions.run_and_verify_svn( |
| None, [], 'import', |
| '-m', 'Log message for new import', new_path, url) |
| |
| lastline = output.pop().strip() |
| cm = re.compile("(Committed|Imported) revision [0-9]+.") |
| match = cm.search(lastline) |
| if not match: |
| ### we should raise a less generic error here. which? |
| raise svntest.Failure |
| |
| # remove (uncontrolled) local file |
| os.remove(new_path) |
| |
| # Create expected disk tree for the update (disregarding props) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'dirA/dirB/new_file' : Item('some text'), |
| }) |
| |
| # Create expected status tree for the update (disregarding props). |
| # Newly imported file should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'dirA' : Item(status=' ', wc_rev=2), |
| 'dirA/dirB' : Item(status=' ', wc_rev=2), |
| 'dirA/dirB/new_file' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Create expected output tree for the update. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'dirA' : Item(status='A '), |
| 'dirA/dirB' : Item(status='A '), |
| 'dirA/dirB/new_file' : Item(status='A '), |
| }) |
| |
| # do update and check three ways |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status, |
| [], True) |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_cat(sbox): |
| "basic cat of files" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| mu_path = sbox.ospath('A/mu') |
| |
| # Get repository text even if wc is modified |
| svntest.main.file_append(mu_path, "some text") |
| svntest.actions.run_and_verify_svn(["This is the file 'mu'.\n"], |
| [], 'cat', |
| ###TODO is user/pass really necessary? |
| mu_path) |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_ls(sbox): |
| 'basic ls' |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Even on Windows, the output will use forward slashes, so that's |
| # what we expect below. |
| |
| cwd = os.getcwd() |
| os.chdir(wc_dir) |
| svntest.actions.run_and_verify_svn(["A/\n", "iota\n"], |
| [], 'ls') |
| os.chdir(cwd) |
| |
| svntest.actions.run_and_verify_svn(['A/\n', 'iota\n'], |
| [], 'ls', |
| wc_dir) |
| |
| svntest.actions.run_and_verify_svn(['B/\n', 'C/\n', 'D/\n', 'mu\n'], |
| [], 'ls', |
| sbox.ospath('A')) |
| |
| svntest.actions.run_and_verify_svn(['B/\n', 'C/\n', 'D/\n', 'mu\n'], |
| [], 'ls', '-r', 'BASE', |
| sbox.ospath('A')) |
| |
| svntest.actions.run_and_verify_svn(['mu\n'], |
| [], 'ls', |
| sbox.ospath('A/mu')) |
| |
| svntest.actions.run_and_verify_svn(['E/\n', 'E/alpha\n', 'E/beta\n', 'F/\n', |
| 'lambda\n' ], [], 'ls', '-R', |
| sbox.ospath('A/B')) |
| |
| |
| #---------------------------------------------------------------------- |
| def nonexistent_repository(sbox): |
| "'svn log file:///nonexistent_path' should fail" |
| |
| # The bug was that |
| # |
| # $ svn log file:///nonexistent_path |
| # |
| # would go into an infinite loop, instead of failing immediately as |
| # it should. The loop was because svn_ra_local__split_URL() used |
| # svn_path_split() to lop off components and look for a repository |
| # in each shorter path in turn, depending on svn_path_is_empty() |
| # to test if it had reached the end. Somewhere along the line we |
| # changed the path functions (perhaps revision 3113?), and |
| # svn_path_split() stopped cooperating with svn_path_is_empty() in |
| # this particular context -- svn_path_split() would reach "/", |
| # svn_path_is_empty() would correctly claim that "/" is not empty, |
| # the next svn_path_split() would return "/" again, and so on, |
| # forever. |
| # |
| # This bug was fixed in revision 3150, by checking for "/" |
| # explicitly in svn_ra_local__split_URL(). By the time you read |
| # this, that may or may not be the settled fix, however, so check |
| # the logs to see if anything happened later. |
| # |
| # Anyway: this test _always_ operates on a file:/// path. Note that |
| # if someone runs this test on a system with "/nonexistent_path" in |
| # the root directory, the test could fail, and that's just too bad :-). |
| |
| exit_code, output, errput = svntest.actions.run_and_verify_svn( |
| None, svntest.verify.AnyOutput, |
| 'log', 'file:///nonexistent_path') |
| |
| for line in errput: |
| if re.match(".*Unable to connect to a repository at URL.*", line): |
| return |
| |
| # Else never matched the expected error output, so the test failed. |
| raise svntest.main.SVNUnmatchedError |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue 1064. This test is only useful if running over a non-local RA |
| # with authentication enabled, otherwise it will pass trivially. |
| @Issue(1064) |
| def basic_auth_cache(sbox): |
| "basic auth caching" |
| |
| sbox.build(create_wc = False, read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| repo_dir = sbox.repo_dir |
| repo_url = sbox.repo_url |
| |
| # Create a working copy without auth tokens |
| svntest.main.safe_rmtree(wc_dir) |
| |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'checkout', |
| repo_url, wc_dir) |
| |
| # Failed with "not locked" error on missing directory |
| svntest.main.safe_rmtree(sbox.ospath('A/B/E')) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'status', '-u', |
| sbox.ospath('A/B')) |
| |
| # Failed with "already locked" error on new dir |
| svntest.actions.run_and_verify_svn(None, [], |
| 'copy', |
| repo_url + '/A/B/E', |
| sbox.ospath('A/D/G')) |
| |
| |
| #---------------------------------------------------------------------- |
| def basic_add_ignores(sbox): |
| 'ignored files in added dirs should not be added' |
| |
| # The bug was that |
| # |
| # $ svn add dir |
| # |
| # where dir contains some items that match the ignore list and some |
| # do not would add all items, ignored or not. |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| dir_path = sbox.ospath('dir') |
| foo_c_path = os.path.join(dir_path, 'foo.c') |
| foo_o_path = os.path.join(dir_path, 'foo.o') |
| |
| os.mkdir(dir_path, svntest.main.S_ALL_RX | stat.S_IWUSR) |
| open(foo_c_path, 'w') |
| open(foo_o_path, 'w') |
| |
| exit_code, output, err = svntest.actions.run_and_verify_svn( |
| svntest.verify.AnyOutput, [], |
| 'add', dir_path) |
| |
| for line in output: |
| # If we see foo.o in the add output, fail the test. |
| if re.match(r'^A\s+.*foo.o$', line): |
| raise svntest.verify.SVNUnexpectedOutput |
| |
| # Else never matched the unwanted output, so the test passed. |
| |
| |
| #---------------------------------------------------------------------- |
| @Issue(2243) |
| def basic_add_local_ignores(sbox): |
| 'ignore files matching local ignores in added dirs' |
| |
| #Issue #2243 |
| #svn add command not keying off svn:ignore value |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| dir_path = sbox.ospath('dir') |
| file_path = os.path.join(dir_path, 'app.lock') |
| |
| svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], |
| 'mkdir', dir_path) |
| svntest.main.run_svn(None, 'propset', 'svn:ignore', '*.lock', dir_path) |
| open(file_path, 'w') |
| svntest.actions.run_and_verify_svn([], [], |
| 'add', '--force', dir_path) |
| |
| #---------------------------------------------------------------------- |
| def basic_add_no_ignores(sbox): |
| 'add ignored files in added dirs' |
| |
| # add ignored files using the '--no-ignore' option |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| dir_path = sbox.ospath('dir') |
| foo_c_path = os.path.join(dir_path, 'foo.c') |
| # add a few files that match the default ignore patterns |
| foo_o_path = os.path.join(dir_path, 'foo.o') |
| foo_lo_path = os.path.join(dir_path, 'foo.lo') |
| foo_rej_path = os.path.join(dir_path, 'foo.rej') |
| |
| os.mkdir(dir_path, svntest.main.S_ALL_RX | stat.S_IWUSR) |
| open(foo_c_path, 'w') |
| open(foo_o_path, 'w') |
| open(foo_lo_path, 'w') |
| open(foo_rej_path, 'w') |
| |
| exit_code, output, err = svntest.actions.run_and_verify_svn( |
| svntest.verify.AnyOutput, [], |
| 'add', '--no-ignore', dir_path) |
| |
| for line in output: |
| # If we don't see ignores in the add output, fail the test. |
| if not re.match(r'^A\s+.*(foo.(o|rej|lo|c)|dir)$', line): |
| raise svntest.verify.SVNUnexpectedOutput |
| |
| #---------------------------------------------------------------------- |
| def basic_add_parents(sbox): |
| 'test add --parents' |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| X_path = sbox.ospath('X') |
| Y_path = os.path.join(X_path, 'Y') |
| Z_path = os.path.join(Y_path, 'Z') |
| zeta_path = os.path.join(Z_path, 'zeta') |
| omicron_path = os.path.join(Y_path, 'omicron') |
| |
| # Create some unversioned directories |
| os.mkdir(X_path, svntest.main.S_ALL_RX | stat.S_IWUSR) |
| os.mkdir(Y_path, svntest.main.S_ALL_RX | stat.S_IWUSR) |
| os.mkdir(Z_path, svntest.main.S_ALL_RX | stat.S_IWUSR) |
| |
| # Create new files |
| z = open(zeta_path, 'w') |
| z.write("This is the file 'zeta'.\n") |
| z.close() |
| o = open(omicron_path, 'w') |
| o.write("This is the file 'omicron'.\n") |
| o.close() |
| |
| # Add the file, with it's parents |
| svntest.actions.run_and_verify_svn(None, [], 'add', '--parents', |
| zeta_path) |
| |
| # Build expected state |
| expected_output = wc.State(wc_dir, { |
| 'X' : Item(verb='Adding'), |
| 'X/Y' : Item(verb='Adding'), |
| 'X/Y/Z' : Item(verb='Adding'), |
| 'X/Y/Z/zeta' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| 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/zeta' : Item(status=' ', wc_rev=2), |
| }) |
| |
| # Commit and verify |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', X_path, '--keep-local') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'add', '--parents', zeta_path) |
| |
| #---------------------------------------------------------------------- |
| def uri_syntax(sbox): |
| 'make sure URI syntaxes are parsed correctly' |
| |
| sbox.build(create_wc = False, read_only = True) |
| local_dir = sbox.wc_dir |
| |
| # Revision 6638 made 'svn co http://host' seg fault, this tests the fix. |
| url = sbox.repo_url |
| scheme = url[:url.find(":")] |
| url = scheme + "://some_nonexistent_host_with_no_trailing_slash" |
| svntest.actions.run_and_verify_svn(None, svntest.verify.AnyOutput, |
| 'co', url, local_dir) |
| |
| # Different RA layers give different errors for failed checkouts; |
| # for us, it's only important to know that it _did_ error (as |
| # opposed to segfaulting), so we don't examine the error text. |
| |
| #---------------------------------------------------------------------- |
| def basic_checkout_file(sbox): |
| "trying to check out a file should fail" |
| |
| sbox.build(read_only = True) |
| |
| iota_url = sbox.repo_url + '/iota' |
| |
| exit_code, output, errput = svntest.main.run_svn(1, 'co', iota_url) |
| |
| for line in errput: |
| if line.find("refers to a file") != -1: |
| break |
| else: |
| raise svntest.Failure |
| |
| #---------------------------------------------------------------------- |
| def basic_info(sbox): |
| "basic info command" |
| |
| def check_paths(lines, expected_paths): |
| "check that paths found on input lines beginning 'Path: ' are as expected" |
| paths = [] |
| for line in lines: |
| if line.startswith('Path: '): |
| paths.append(line[6:].rstrip()) |
| if paths != expected_paths: |
| logger.warn("Reported paths: %s" % paths) |
| logger.warn("Expected paths: %s" % expected_paths) |
| raise svntest.Failure |
| |
| sbox.build(read_only = True) |
| |
| os.chdir(sbox.wc_dir) |
| |
| # Check that "info" works with 0, 1 and more than 1 explicit targets. |
| exit_code, output, errput = svntest.main.run_svn(None, 'info') |
| check_paths(output, ['.']) |
| exit_code, output, errput = svntest.main.run_svn(None, 'info', 'iota') |
| check_paths(output, ['iota']) |
| exit_code, output, errput = svntest.main.run_svn(None, 'info', 'iota', '.') |
| check_paths(output, ['iota', '.']) |
| |
| def repos_root(sbox): |
| "check that repos root gets set on checkout" |
| |
| def check_repos_root(lines): |
| for line in lines: |
| if line == "Repository Root: " + sbox.repo_url + "\n": |
| break |
| else: |
| logger.warn("Bad or missing repository root") |
| raise svntest.Failure |
| |
| sbox.build(read_only = True) |
| |
| exit_code, output, errput = svntest.main.run_svn(None, "info", |
| sbox.wc_dir) |
| check_repos_root(output) |
| |
| exit_code, output, errput = svntest.main.run_svn(None, "info", |
| os.path.join(sbox.wc_dir, |
| "A")) |
| check_repos_root(output) |
| |
| exit_code, output, errput = svntest.main.run_svn(None, "info", |
| os.path.join(sbox.wc_dir, |
| "A", "B", |
| "lambda")) |
| check_repos_root(output) |
| |
| def basic_peg_revision(sbox): |
| "checks peg revision on filename with @ sign" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| repos_dir = sbox.repo_url |
| filename = 'abc@abc' |
| wc_file = os.path.join(wc_dir, filename) |
| url = repos_dir + '/' + filename |
| |
| svntest.main.file_append(wc_file, 'xyz\n') |
| # We need to escape the @ in the middle of abc@abc by appending another @ |
| svntest.main.run_svn(None, 'add', wc_file + '@') |
| svntest.main.run_svn(None, |
| 'ci', '-m', 'secret log msg', wc_file + '@') |
| |
| # Without the trailing "@", expect failure. |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| None, ".*Syntax error parsing peg revision 'abc'", 'cat', wc_file) |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| None, ".*Syntax error parsing peg revision 'abc'", 'cat', url) |
| |
| # With the trailing "@", expect success. |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| ["xyz\n"], [], 'cat', wc_file + '@') |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| ["xyz\n"], [], 'cat', url + '@') |
| |
| # Test with leading @ character in filename. |
| filename = '@abc' |
| wc_file = os.path.join(wc_dir, filename) |
| url = repos_dir + '/' + filename |
| |
| svntest.main.file_append(wc_file, 'xyz\n') |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| None, [], 'add', wc_file + '@') |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| None, [], 'ci', '-m', 'secret log msg', wc_file + '@') |
| |
| # With a leading "@" which isn't escaped, expect failure. |
| # Note that we just test with filename starting with '@', because |
| # wc_file + '@' + filename is a different situation where svn |
| # will try to parse filename as a peg revision. |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| None, ".*'%s' is just a peg revision.*" % filename, |
| 'cat', filename) |
| |
| # With a leading "@" which is escaped, expect success. |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| ["xyz\n"], [], 'cat', wc_file + '@') |
| exit_code, output, errlines = svntest.actions.run_and_verify_svn( |
| ["xyz\n"], [], 'cat', repos_dir + '/' + filename + '@') |
| |
| def info_nonhead(sbox): |
| "info on file not existing in HEAD" |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| repo_url = sbox.repo_url |
| fname = sbox.ospath('iota') |
| furl = repo_url + "/iota" |
| |
| # Remove iota and commit. |
| svntest.actions.run_and_verify_svn(None, [], |
| "delete", fname) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota' : Item(verb='Deleting'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove("iota") |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| # Get info for old iota at r1. |
| expected_infos = [ |
| { 'URL' : '.*' }, |
| ] |
| svntest.actions.run_and_verify_info(expected_infos, furl + '@1', '-r1') |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue #2442. |
| @Issue(2442) |
| def ls_nonhead(sbox): |
| "ls a path no longer in HEAD" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Delete A/D/rho and commit. |
| G_path = sbox.ospath('A/D/G') |
| svntest.actions.run_and_verify_svn(None, [], 'rm', G_path) |
| |
| expected_output = 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', 'A/D/G/rho', 'A/D/G/pi', 'A/D/G/tau',) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, expected_status) |
| |
| # Check that we can list a file in A/D/G at revision 1. |
| rho_url = sbox.repo_url + "/A/D/G/rho" |
| svntest.actions.run_and_verify_svn('.* rho\n', [], |
| 'ls', '--verbose', rho_url + '@1') |
| |
| |
| #---------------------------------------------------------------------- |
| # Issue #2315. |
| @Issue(2315) |
| def cat_added_PREV(sbox): |
| "cat added file using -rPREV" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| f_path = sbox.ospath('f') |
| |
| # Create and add a file. |
| svntest.main.file_append(f_path, 'new text') |
| svntest.actions.run_and_verify_svn(None, [], 'add', f_path) |
| |
| # Cat'ing the previous version should fail. |
| svntest.actions.run_and_verify_svn(None, ".*has no committed revision.*", |
| 'cat', '-rPREV', f_path) |
| |
| # Issue #2612. |
| @Issue(2612) |
| def ls_space_in_repo_name(sbox): |
| 'basic ls of repos with space in name' |
| |
| sbox.build(name = "repo with spaces") |
| wc_dir = sbox.wc_dir |
| |
| svntest.actions.run_and_verify_svn(['A/\n', 'iota\n'], |
| [], 'ls', |
| sbox.repo_url) |
| |
| |
| def delete_keep_local(sbox): |
| 'delete file and directory with --keep-local' |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| iota_path = sbox.ospath('iota') |
| C_path = sbox.ospath('A/C') |
| |
| # Remove file iota |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--keep-local', |
| iota_path) |
| |
| # Remove directory 'A/C' |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--keep-local', |
| C_path) |
| |
| # Commit changes |
| expected_output = wc.State(wc_dir, { |
| 'iota' : Item(verb='Deleting'), |
| 'A/C' : Item(verb='Deleting'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('iota') |
| expected_status.remove('A/C') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| # Update working copy to check disk state still greek tree |
| expected_disk = svntest.main.greek_state.copy() |
| expected_output = svntest.wc.State(wc_dir, {}) |
| expected_status.tweak(wc_rev = 2) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| def delete_keep_local_twice(sbox): |
| 'delete file and directory with --keep-local twice' |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| dir = sbox.ospath('dir') |
| |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', dir) |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--keep-local', dir) |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '--keep-local', dir) |
| |
| if not os.path.isdir(dir): |
| logger.warn('Directory was really deleted') |
| raise svntest.Failure |
| |
| @XFail(svntest.main.is_mod_dav_url_quoting_broken) |
| def special_paths_in_repos(sbox): |
| "use folders with names like 'c:hi'" |
| |
| sbox.build(create_wc = False) |
| test_file_source = os.path.join(sbox.repo_dir, 'format') |
| repo_url = sbox.repo_url |
| |
| test_urls = [ sbox.repo_url + '/c:hi', |
| sbox.repo_url + '/C:', |
| sbox.repo_url + '/C&', |
| sbox.repo_url + '/C<', |
| sbox.repo_url + '/C# hi', |
| sbox.repo_url + '/C?', |
| sbox.repo_url + '/C+', |
| sbox.repo_url + '/C%'] |
| |
| # On Windows Apache HTTPD breaks '\' for us :( |
| if not (svntest.main.is_os_windows() and |
| svntest.main.is_ra_type_dav()): |
| test_urls += [ sbox.repo_url + '/C\\ri' ] |
| |
| for test_url in test_urls: |
| test_file_url = test_url + '/' + test_url[test_url.rindex('/')+1:] |
| |
| # do some manipulations on a folder which problematic names |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', '-m', 'log_msg', |
| test_url) |
| |
| svntest.actions.run_and_verify_svnmucc(None, [], |
| '-m', 'log_msg', |
| 'put', test_file_source, |
| test_file_url) |
| |
| svntest.actions.run_and_verify_svnmucc(None, [], |
| 'propset', '-m', 'log_msg', |
| 'propname', 'propvalue', test_url) |
| |
| svntest.actions.run_and_verify_svn('propvalue', [], |
| 'propget', 'propname', test_url) |
| |
| svntest.actions.run_and_verify_svnmucc(None, [], |
| 'propset', '-m', 'log_msg', |
| 'propname', 'propvalue', test_file_url) |
| |
| svntest.actions.run_and_verify_svn('propvalue', [], |
| 'propget', 'propname', test_file_url) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', 'log_msg', |
| test_file_url) |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', 'log_msg', |
| test_url) |
| |
| |
| def basic_rm_urls_one_repo(sbox): |
| "remotely remove directories from one repository" |
| |
| sbox.build() |
| repo_url = sbox.repo_url |
| wc_dir = sbox.wc_dir |
| |
| # Test 1: remotely delete one directory |
| E_url = repo_url + '/A/B/E' |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', 'log_msg', |
| E_url) |
| |
| # Create expected trees and update |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/E' : Item(status='D '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta') |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.remove('A/B/E', 'A/B/E/alpha', 'A/B/E/beta') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Test 2: remotely delete two directories in the same repository |
| F_url = repo_url + '/A/B/F' |
| C_url = repo_url + '/A/C' |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '-m', 'log_msg', |
| F_url, C_url) |
| |
| # Create expected output tree for an update of wc_backup. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F' : Item(status='D '), |
| 'A/C' : Item(status='D '), |
| }) |
| |
| # Create expected disk tree for the update |
| expected_disk.remove('A/B/F', 'A/C') |
| |
| # Create expected status tree for the update. |
| expected_status.tweak(wc_rev = 3) |
| expected_status.remove('A/B/F', 'A/C') |
| |
| # Do the update and check the results in three ways. |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Test for issue #1199 |
| @Issue(1199) |
| def basic_rm_urls_multi_repos(sbox): |
| "remotely remove directories from two repositories" |
| |
| sbox.build() |
| repo_url = sbox.repo_url |
| repo_dir = sbox.repo_dir |
| wc_dir = sbox.wc_dir |
| |
| # create a second repository and working copy |
| other_repo_dir, other_repo_url = sbox.add_repo_path("other") |
| svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 1) |
| other_wc_dir = sbox.add_wc_path("other") |
| svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "co", |
| other_repo_url, |
| other_wc_dir) |
| |
| # Remotely delete two x two directories in the two repositories |
| F_url = repo_url + '/A/B/F' |
| C_url = repo_url + '/A/C' |
| F2_url = other_repo_url + '/A/B/F' |
| C2_url = other_repo_url + '/A/C' |
| |
| svntest.actions.run_and_verify_svn(None, [], 'rm', '-m', 'log_msg', |
| F_url, C_url, F2_url, C2_url) |
| |
| # Check that the two rm's to each of the repositories were handled in one |
| # revision (per repo) |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/B/F' : Item(status='D '), |
| 'A/C' : Item(status='D '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/F', 'A/C') |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.remove('A/B/F', 'A/C') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| expected_status = svntest.actions.get_virginal_state(other_wc_dir, 2) |
| expected_status.remove('A/B/F', 'A/C') |
| expected_output = svntest.wc.State(other_wc_dir, { |
| 'A/B/F' : Item(status='D '), |
| 'A/C' : Item(status='D '), |
| }) |
| |
| svntest.actions.run_and_verify_update(other_wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| #----------------------------------------------------------------------- |
| def automatic_conflict_resolution(sbox): |
| "automatic conflict resolution" |
| |
| 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) |
| |
| # Make a couple of local mods to files which will be committed |
| mu_path = sbox.ospath('A/mu') |
| lambda_path = sbox.ospath('A/B/lambda') |
| rho_path = sbox.ospath('A/D/G/rho') |
| tau_path = sbox.ospath('A/D/G/tau') |
| omega_path = sbox.ospath('A/D/H/omega') |
| svntest.main.file_append(mu_path, 'Original appended text for mu\n') |
| svntest.main.file_append(lambda_path, 'Original appended text for lambda\n') |
| svntest.main.file_append(rho_path, 'Original appended text for rho\n') |
| svntest.main.file_append(tau_path, 'Original appended text for tau\n') |
| svntest.main.file_append(omega_path, 'Original appended text for omega\n') |
| |
| # Make a couple of local mods to files which will be conflicted |
| mu_path_backup = os.path.join(wc_backup, 'A', 'mu') |
| lambda_path_backup = os.path.join(wc_backup, 'A', 'B', 'lambda') |
| rho_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'rho') |
| tau_path_backup = os.path.join(wc_backup, 'A', 'D', 'G', 'tau') |
| omega_path_backup = os.path.join(wc_backup, 'A', 'D', 'H', 'omega') |
| svntest.main.file_append(mu_path_backup, |
| 'Conflicting appended text for mu\n') |
| svntest.main.file_append(lambda_path_backup, |
| 'Conflicting appended text for lambda\n') |
| svntest.main.file_append(rho_path_backup, |
| 'Conflicting appended text for rho\n') |
| svntest.main.file_append(tau_path_backup, |
| 'Conflicting appended text for tau\n') |
| svntest.main.file_append(omega_path_backup, |
| 'Conflicting appended text for omega\n') |
| |
| # Created expected output tree for 'svn ci' |
| expected_output = wc.State(wc_dir, { |
| 'A/mu' : Item(verb='Sending'), |
| 'A/B/lambda' : Item(verb='Sending'), |
| 'A/D/G/rho' : Item(verb='Sending'), |
| 'A/D/G/tau' : Item(verb='Sending'), |
| 'A/D/H/omega' : Item(verb='Sending'), |
| }) |
| |
| # Create expected status tree; all local revisions should be at 1, |
| # but lambda, mu and rho should be at revision 2. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau', |
| 'A/D/H/omega', wc_rev=2) |
| |
| # Commit. |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Create expected output tree for an update of the wc_backup. |
| expected_output = wc.State(wc_backup, { |
| 'A/mu' : Item(status='C '), |
| 'A/B/lambda' : Item(status='C '), |
| 'A/D/G/rho' : Item(status='C '), |
| 'A/D/G/tau' : Item(status='C '), |
| 'A/D/H/omega' : Item(status='C '), |
| }) |
| |
| # Create expected disk tree for the update. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/B/lambda', |
| contents="\n".join(["This is the file 'lambda'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for lambda", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for lambda", |
| ">>>>>>> .r2", |
| ""])) |
| expected_disk.tweak('A/mu', |
| contents="\n".join(["This is the file 'mu'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for mu", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for mu", |
| ">>>>>>> .r2", |
| ""])) |
| expected_disk.tweak('A/D/G/rho', |
| contents="\n".join(["This is the file 'rho'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for rho", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for rho", |
| ">>>>>>> .r2", |
| ""])) |
| expected_disk.tweak('A/D/G/tau', |
| contents="\n".join(["This is the file 'tau'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for tau", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for tau", |
| ">>>>>>> .r2", |
| ""])) |
| expected_disk.tweak('A/D/H/omega', |
| contents="\n".join(["This is the file 'omega'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for omega", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for omega", |
| ">>>>>>> .r2", |
| ""])) |
| |
| # Create expected status tree for the update. |
| expected_status = svntest.actions.get_virginal_state(wc_backup, '2') |
| expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau', |
| 'A/D/H/omega', status='C ') |
| |
| # "Extra" files that we expect to result from the conflicts. |
| # These are expressed as list of regexps. What a cool system! :-) |
| extra_files = ['mu.*\.r1', 'mu.*\.r2', 'mu.*\.mine', |
| 'lambda.*\.r1', 'lambda.*\.r2', 'lambda.*\.mine', |
| 'omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine', |
| 'rho.*\.r1', 'rho.*\.r2', 'rho.*\.mine', |
| 'tau.*\.r1', 'tau.*\.r2', 'tau.*\.mine', |
| ] |
| |
| # Do the update and check the results in three ways. |
| # All "extra" files are passed to detect_conflict_files(). |
| svntest.actions.run_and_verify_update(wc_backup, |
| expected_output, |
| expected_disk, |
| expected_status, |
| extra_files=extra_files) |
| |
| # So now lambda, mu and rho are all in a "conflicted" state. Run 'svn |
| # resolve' with the respective "--accept[mine|orig|repo]" flag. |
| |
| # But first, check --accept actions resolved does not accept. |
| svntest.actions.run_and_verify_svn(# stdout, stderr |
| None, |
| ".*invalid 'accept' ARG", |
| 'resolve', '--accept=postpone') |
| svntest.actions.run_and_verify_svn(# stdout, stderr |
| None, |
| ".*invalid 'accept' ARG", |
| 'resolve', '--accept=edit', |
| '--force-interactive') |
| svntest.actions.run_and_verify_svn(# stdout, stderr |
| None, |
| ".*invalid 'accept' ARG", |
| 'resolve', '--accept=launch', |
| '--force-interactive') |
| # Run 'svn resolved --accept=NOPE. Using omega for the test. |
| svntest.actions.run_and_verify_svn(None, |
| ".*NOPE' is not a valid --accept value", |
| 'resolve', |
| '--accept=NOPE', |
| omega_path_backup) |
| |
| # Resolve lambda, mu, and rho with different --accept options. |
| svntest.actions.run_and_verify_svn(None, [], |
| 'resolve', '--accept=base', |
| lambda_path_backup) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'resolve', |
| '--accept=mine-full', |
| mu_path_backup) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'resolve', |
| '--accept=theirs-full', |
| rho_path_backup) |
| fp = open(tau_path_backup, 'w') |
| fp.write("Resolution text for 'tau'.\n") |
| fp.close() |
| svntest.actions.run_and_verify_svn(None, [], |
| 'resolve', |
| '--accept=working', |
| tau_path_backup) |
| |
| # Set the expected disk contents for the test |
| expected_disk = svntest.main.greek_state.copy() |
| |
| expected_disk.tweak('A/B/lambda', contents="This is the file 'lambda'.\n") |
| expected_disk.tweak('A/mu', contents="This is the file 'mu'.\n" |
| "Conflicting appended text for mu\n") |
| expected_disk.tweak('A/D/G/rho', contents="This is the file 'rho'.\n" |
| "Original appended text for rho\n") |
| expected_disk.tweak('A/D/G/tau', contents="Resolution text for 'tau'.\n") |
| expected_disk.tweak('A/D/H/omega', |
| contents="\n".join(["This is the file 'omega'.", |
| "<<<<<<< .mine", |
| "Conflicting appended text for omega", |
| "||||||| .r1", |
| "=======", |
| "Original appended text for omega", |
| ">>>>>>> .r2", |
| ""])) |
| |
| # Set the expected extra files for the test |
| extra_files = ['omega.*\.r1', 'omega.*\.r2', 'omega.*\.mine',] |
| |
| # Set the expected status for the test |
| expected_status = svntest.actions.get_virginal_state(wc_backup, 2) |
| expected_status.tweak('A/mu', 'A/B/lambda', 'A/D/G/rho', 'A/D/G/tau', |
| 'A/D/H/omega', wc_rev=2) |
| |
| expected_status.tweak('A/mu', status='M ') |
| expected_status.tweak('A/B/lambda', status='M ') |
| expected_status.tweak('A/D/G/rho', status=' ') |
| expected_status.tweak('A/D/G/tau', status='M ') |
| expected_status.tweak('A/D/H/omega', status='C ') |
| |
| # Set the expected output for the test |
| expected_output = wc.State(wc_backup, {}) |
| |
| # Do the update and check the results in three ways. |
| svntest.actions.run_and_verify_update(wc_backup, |
| expected_output, |
| expected_disk, |
| expected_status, |
| extra_files=extra_files) |
| |
| def info_nonexisting_file(sbox): |
| "get info on a file not in the repo" |
| |
| sbox.build(create_wc = False, read_only = True) |
| idonotexist_url = sbox.repo_url + '/IdoNotExist' |
| exit_code, output, errput = svntest.main.run_svn(1, 'info', idonotexist_url) |
| |
| # Check for the correct error message |
| for line in errput: |
| if re.match(".*" + idonotexist_url + ".*non-existent in revision 1.*", |
| line): |
| return |
| |
| # Else never matched the expected error output, so the test failed. |
| raise svntest.main.SVNUnmatchedError |
| |
| |
| #---------------------------------------------------------------------- |
| # Relative urls |
| # |
| # Use blame to test three specific cases for relative url support. |
| def basic_relative_url_using_current_dir(sbox): |
| "basic relative url target using current dir" |
| |
| # We'll use blame to test relative url parsing |
| sbox.build() |
| |
| # First, make a new revision of iota. |
| iota = sbox.ospath('iota') |
| svntest.main.file_append(iota, "New contents for iota\n") |
| svntest.main.run_svn(None, 'ci', |
| '-m', '', iota) |
| |
| expected_output = [ |
| " 1 jrandom This is the file 'iota'.\n", |
| " 2 jrandom New contents for iota\n", |
| ] |
| |
| orig_dir = os.getcwd() |
| os.chdir(sbox.wc_dir) |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], |
| 'blame', '^/iota') |
| |
| os.chdir(orig_dir) |
| |
| def basic_relative_url_using_other_targets(sbox): |
| "basic relative url target using other targets" |
| |
| sbox.build() |
| |
| # First, make a new revision of iota. |
| iota = sbox.ospath('iota') |
| svntest.main.file_append(iota, "New contents for iota\n") |
| svntest.main.run_svn(None, 'ci', |
| '-m', '', iota) |
| |
| # Now, make a new revision of A/mu . |
| mu = sbox.ospath('A/mu') |
| mu_url = sbox.repo_url + '/A/mu' |
| |
| svntest.main.file_append(mu, "New contents for mu\n") |
| svntest.main.run_svn(None, 'ci', |
| '-m', '', mu) |
| |
| |
| expected_output = [ |
| " 1 jrandom This is the file 'iota'.\n", |
| " 2 jrandom New contents for iota\n", |
| " 1 jrandom This is the file 'mu'.\n", |
| " 3 jrandom New contents for mu\n", |
| ] |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], 'blame', |
| '^/iota', mu_url) |
| |
| def basic_relative_url_multi_repo(sbox): |
| "basic relative url target with multiple repos" |
| |
| sbox.build() |
| repo_url1 = sbox.repo_url |
| repo_dir1 = sbox.repo_dir |
| wc_dir1 = sbox.wc_dir |
| |
| repo_dir2, repo_url2 = sbox.add_repo_path("other") |
| svntest.main.copy_repos(repo_dir1, repo_dir2, 1, 1) |
| wc_dir2 = sbox.add_wc_path("other") |
| svntest.actions.run_and_verify_svn(svntest.verify.AnyOutput, [], "co", |
| repo_url2, |
| wc_dir2) |
| |
| # Don't bother with making new revisions, the command should not work. |
| iota_url_repo1 = repo_url1 + '/iota' |
| iota_url_repo2 = repo_url2 + '/iota' |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn([], |
| svntest.verify.AnyOutput, 'blame', |
| '^/A/mu', iota_url_repo1, iota_url_repo2) |
| |
| def basic_relative_url_non_canonical(sbox): |
| "basic relative url non-canonical targets" |
| |
| sbox.build() |
| |
| iota_url = sbox.repo_url + '/iota' |
| |
| expected_output = [ |
| "B/\n", |
| "C/\n", |
| "D/\n", |
| "mu\n", |
| "iota\n" |
| ] |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], 'ls', |
| '^/A/', iota_url) |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], 'ls', |
| '^//A/', iota_url) |
| |
| def basic_relative_url_with_peg_revisions(sbox): |
| "basic relative url targets with peg revisions" |
| |
| sbox.build() |
| |
| # First, make a new revision of iota. |
| iota = sbox.ospath('iota') |
| svntest.main.file_append(iota, "New contents for iota\n") |
| svntest.main.run_svn(None, 'ci', |
| '-m', '', iota) |
| |
| iota_url = sbox.repo_url + '/iota' |
| |
| # Now, make a new revision of A/mu . |
| mu = sbox.ospath('A/mu') |
| mu_url = sbox.repo_url + '/A/mu' |
| |
| svntest.main.file_append(mu, "New contents for mu\n") |
| svntest.main.run_svn(None, 'ci', '-m', '', mu) |
| |
| # Delete the file from the current revision |
| svntest.main.run_svn(None, 'rm', '-m', '', mu_url) |
| |
| expected_output = [ |
| "B/\n", |
| "C/\n", |
| "D/\n", |
| "mu\n", |
| "iota\n" |
| ] |
| |
| # Canonical version with peg revision |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], 'ls', '-r3', |
| '^/A/@3', iota_url) |
| |
| # Non-canonical version with peg revision |
| exit_code, output, error = svntest.actions.run_and_verify_svn(expected_output, [], 'ls', '-r3', |
| '^//A/@3', iota_url) |
| |
| |
| def basic_auth_test_xfail_predicate(): |
| """Predicate for XFail for basic_auth_test: |
| The test will fail if plaintext password storage is disabled, |
| and the RA method requires authentication.""" |
| return (not svntest.main.is_os_windows() |
| and svntest.main.is_ra_type_dav() |
| and svntest.main.is_plaintext_password_storage_disabled()) |
| |
| # Issue 2242, auth cache picking up password from wrong username entry |
| @Issue(2242) |
| @XFail(basic_auth_test_xfail_predicate) |
| def basic_auth_test(sbox): |
| "basic auth test" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Set up a custom config directory |
| config_dir = sbox.create_config_dir() |
| |
| # Checkout with jrandom |
| exit_code, output, errput = svntest.main.run_command( |
| svntest.main.svn_binary, None, True, 'co', sbox.repo_url, wc_dir, |
| '--username', 'jrandom', '--password', 'rayjandom', |
| '--config-dir', config_dir) |
| |
| exit_code, output, errput = svntest.main.run_command( |
| svntest.main.svn_binary, None, True, 'co', sbox.repo_url, wc_dir, |
| '--username', 'jrandom', '--non-interactive', '--config-dir', config_dir) |
| |
| # Checkout with jconstant |
| exit_code, output, errput = svntest.main.run_command( |
| svntest.main.svn_binary, None, True, 'co', sbox.repo_url, wc_dir, |
| '--username', 'jconstant', '--password', 'rayjandom', |
| '--config-dir', config_dir) |
| |
| exit_code, output, errput = svntest.main.run_command( |
| svntest.main.svn_binary, None, True, 'co', sbox.repo_url, wc_dir, |
| '--username', 'jconstant', '--non-interactive', |
| '--config-dir', config_dir) |
| |
| # Checkout with jrandom which should fail since we do not provide |
| # a password and the above cached password belongs to jconstant |
| expected_err = ["authorization failed: Could not authenticate to server:"] |
| exit_code, output, errput = svntest.main.run_command( |
| svntest.main.svn_binary, expected_err, True, 'co', sbox.repo_url, wc_dir, |
| '--username', 'jrandom', '--non-interactive', '--config-dir', config_dir) |
| |
| def basic_add_svn_format_file(sbox): |
| 'test add --parents .svn/format' |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| entries_path = os.path.join(wc_dir, svntest.main.get_admin_name(), 'format') |
| |
| output = svntest.actions.get_virginal_state(wc_dir, 1) |
| |
| # The .svn directory and the format file should not be added as this |
| # breaks the administrative area handling, so we expect some error here |
| svntest.actions.run_and_verify_svn(None, |
| ".*reserved name.*", |
| 'add', '--parents', entries_path) |
| |
| svntest.actions.run_and_verify_status(wc_dir, output) |
| |
| # Issue 2586, Unhelpful error message: Unrecognized URL scheme for '' |
| # See also input_validation_tests.py:invalid_mkdir_targets(), which tests |
| # the same thing the other way around. |
| @Issue(2586) |
| def basic_mkdir_mix_targets(sbox): |
| "mkdir mix url and local path should error" |
| |
| sbox.build() |
| Y_url = sbox.repo_url + '/Y' |
| expected_error = "svn: E200009: Cannot mix repository and working copy targets" |
| |
| svntest.actions.run_and_verify_svn(None, expected_error, |
| 'mkdir', '-m', 'log_msg', Y_url, 'subdir') |
| |
| def delete_from_url_with_spaces(sbox): |
| "delete a directory with ' ' using its url" |
| |
| sbox.build() |
| sbox.simple_mkdir('Dir With Spaces') |
| sbox.simple_mkdir('Dir With') |
| sbox.simple_mkdir('Dir With/Spaces') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'ci', sbox.wc_dir, '-m', 'Added dir') |
| |
| # This fails on 1.6.11 with an escaping error. |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', sbox.repo_url + '/Dir%20With%20Spaces', |
| '-m', 'Deleted') |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', sbox.repo_url + '/Dir%20With/Spaces', |
| '-m', 'Deleted') |
| |
| @SkipUnless(svntest.main.is_ra_type_dav) |
| def meta_correct_library_being_used(sbox): |
| "verify that neon/serf are compiled if tested" |
| expected_re = (r'^\* ra_%s :' % svntest.main.options.http_library) |
| expected_output = svntest.verify.RegexOutput(expected_re, match_all=False) |
| svntest.actions.run_and_verify_svn(expected_output, [], '--version') |
| |
| def delete_and_add_same_file(sbox): |
| "commit deletes a file and adds one with same text" |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| |
| iota = sbox.ospath('iota') |
| iota2 = sbox.ospath('iota2') |
| |
| shutil.copyfile(iota, iota2) |
| |
| svntest.main.run_svn(None, 'rm', iota) |
| svntest.main.run_svn(None, 'add', iota2) |
| |
| expected_output = wc.State(wc_dir, { |
| 'iota' : Item(verb='Deleting'), |
| 'iota2' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('iota') |
| expected_status.add({ 'iota2': Item(status=' ', wc_rev='2')}) |
| |
| # At one time the commit post-processing used to fail with "Pristine text |
| # not found". |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| def delete_child_parent_update(sbox): |
| "rm child, commit, rm parent" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| svntest.main.run_svn(wc_dir, 'rm', sbox.ospath('A/B/E/alpha')) |
| |
| expected_output = wc.State(wc_dir, { |
| 'A/B/E/alpha' : Item(verb='Deleting'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.remove('A/B/E/alpha') |
| |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, |
| expected_status) |
| |
| svntest.main.run_svn(wc_dir, 'rm', sbox.ospath('A/B/E')) |
| expected_status.tweak('A/B/E', 'A/B/E/beta', status='D ') |
| |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.remove('A/B/E/alpha', 'A/B/E/beta', 'A/B/E') |
| |
| # This produced a tree-conflict until we fixed issue #3533 |
| expected_status.tweak(wc_rev=2) |
| svntest.actions.run_and_verify_update(wc_dir, |
| [], |
| expected_disk, |
| expected_status) |
| |
| |
| |
| #---------------------------------------------------------------------- |
| |
| def basic_relocate(sbox): |
| "basic relocate of a wc" |
| sbox.build(read_only = True) |
| |
| 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) |
| |
| def _verify_url(wc_path, url): |
| name = os.path.basename(wc_path) |
| expected = {'Path' : re.escape(wc_path), |
| 'URL' : url, |
| 'Repository Root' : '.*', |
| 'Revision' : '.*', |
| 'Node Kind' : 'directory', |
| 'Repository UUID' : uuid_regex, |
| } |
| svntest.actions.run_and_verify_info([expected], wc_path) |
| |
| # No-op relocation of just the scheme. |
| scheme = repo_url[:repo_url.index('://')+3] |
| svntest.actions.run_and_verify_svn(None, [], 'switch', '--relocate', |
| scheme, scheme, wc_dir) |
| _verify_url(wc_dir, repo_url) |
| |
| # No-op relocation of a bit more of the URL. |
| substring = repo_url[:repo_url.index('://')+7] |
| svntest.actions.run_and_verify_svn(None, [], 'switch', '--relocate', |
| substring, substring, wc_dir) |
| _verify_url(wc_dir, repo_url) |
| |
| # Real relocation to OTHER_REPO_URL. |
| svntest.actions.run_and_verify_svn(None, [], 'switch', '--relocate', |
| repo_url, other_repo_url, wc_dir) |
| _verify_url(wc_dir, other_repo_url) |
| |
| # ... and back again, using the newer 'svn relocate' subcommand. |
| svntest.actions.run_and_verify_svn(None, [], 'relocate', |
| other_repo_url, repo_url, wc_dir) |
| _verify_url(wc_dir, repo_url) |
| |
| # To OTHER_REPO_URL again, this time with the single-URL form of |
| # 'svn relocate'. |
| svntest.actions.run_and_verify_svn(None, [], 'relocate', |
| other_repo_url, wc_dir) |
| _verify_url(wc_dir, other_repo_url) |
| |
| ### TODO: When testing ra_dav or ra_svn, do relocations between |
| ### those and ra_local URLs. |
| |
| #---------------------------------------------------------------------- |
| |
| def delete_urls_with_spaces(sbox): |
| "delete multiple targets with spaces" |
| sbox.build(create_wc = False) |
| |
| # Create three directories with a space in their name |
| svntest.actions.run_and_verify_svn(None, [], 'mkdir', |
| sbox.repo_url + '/A spaced', |
| sbox.repo_url + '/B spaced', |
| sbox.repo_url + '/C spaced', |
| '-m', 'Created dirs') |
| |
| # Try to delete the first |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| sbox.repo_url + '/A spaced', |
| '-m', 'Deleted A') |
| |
| # And then two at once |
| svntest.actions.run_and_verify_svn(None, [], 'rm', |
| sbox.repo_url + '/B spaced', |
| sbox.repo_url + '/C spaced', |
| '-m', 'Deleted B and C') |
| |
| def ls_url_special_characters(sbox): |
| """special characters in svn ls URL""" |
| sbox.build(create_wc = False) |
| |
| special_urls = [sbox.repo_url + '/A' + '/%2E', |
| sbox.repo_url + '%2F' + 'A'] |
| |
| for url in special_urls: |
| svntest.actions.run_and_verify_svn(['B/\n', 'C/\n', 'D/\n', 'mu\n'], |
| [], 'ls', |
| url) |
| |
| def ls_multiple_and_non_existent_targets(sbox): |
| "ls multiple and non-existent targets" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| def non_existent_wc_target(): |
| "non-existent wc target" |
| non_existent_path = sbox.ospath('non-existent') |
| |
| expected_err = ".*W155010.*" |
| svntest.actions.run_and_verify_svn2(None, expected_err, |
| 1, 'ls', non_existent_path) |
| |
| def non_existent_url_target(): |
| "non-existent url target" |
| non_existent_url = sbox.repo_url + '/non-existent' |
| expected_err = ".*W160013.*" |
| |
| svntest.actions.run_and_verify_svn2(None, expected_err, |
| 1, 'ls', non_existent_url) |
| def multiple_wc_targets(): |
| "multiple wc targets" |
| |
| alpha = sbox.ospath('A/B/E/alpha') |
| beta = sbox.ospath('A/B/E/beta') |
| non_existent_path = sbox.ospath('non-existent') |
| |
| # All targets are existing |
| svntest.actions.run_and_verify_svn2(None, [], |
| 0, 'ls', alpha, beta) |
| |
| # One non-existing target |
| expected_err = ".*W155010.*\n.*E200009.*" |
| expected_err_re = re.compile(expected_err, re.DOTALL) |
| |
| exit_code, output, error = svntest.main.run_svn(1, 'ls', alpha, |
| non_existent_path, beta) |
| |
| # Verify error |
| if not expected_err_re.match("".join(error)): |
| raise svntest.Failure('ls failed: expected error "%s", but received ' |
| '"%s"' % (expected_err, "".join(error))) |
| |
| def multiple_url_targets(): |
| "multiple url targets" |
| |
| alpha = sbox.repo_url + '/A/B/E/alpha' |
| beta = sbox.repo_url + '/A/B/E/beta' |
| non_existent_url = sbox.repo_url + '/non-existent' |
| |
| # All targets are existing |
| svntest.actions.run_and_verify_svn2(None, [], |
| 0, 'ls', alpha, beta) |
| |
| # One non-existing target |
| expected_err = ".*W160013.*\n.*E200009.*" |
| expected_err_re = re.compile(expected_err, re.DOTALL) |
| |
| exit_code, output, error = svntest.main.run_svn(1, 'ls', alpha, |
| non_existent_url, beta) |
| |
| # Verify error |
| if not expected_err_re.match("".join(error)): |
| raise svntest.Failure('ls failed: expected error "%s", but received ' |
| '"%s"' % (expected_err, "".join(error))) |
| # Test one by one |
| non_existent_wc_target() |
| non_existent_url_target() |
| multiple_wc_targets() |
| multiple_url_targets() |
| |
| def add_multiple_targets(sbox): |
| "add multiple targets" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| file1 = sbox.ospath('file1') |
| file2 = sbox.ospath('file2') |
| non_existent_path = sbox.ospath('non-existent') |
| |
| svntest.main.file_write(file1, "file1 contents", 'w+') |
| svntest.main.file_write(file2, "file2 contents", 'w+') |
| |
| # One non-existing target |
| expected_err = ".*W155010.*\n.*E200009.*" |
| expected_err_re = re.compile(expected_err, re.DOTALL) |
| |
| # Build expected state |
| expected_output = wc.State(wc_dir, { |
| 'file1' : Item(verb='Adding'), |
| 'file2' : Item(verb='Adding'), |
| }) |
| |
| exit_code, output, error = svntest.main.run_svn(1, 'add', file1, |
| non_existent_path, file2) |
| |
| # Verify error |
| if not expected_err_re.match("".join(error)): |
| raise svntest.Failure('add failed: expected error "%s", but received ' |
| '"%s"' % (expected_err, "".join(error))) |
| |
| # Verify status |
| expected_status = svntest.verify.UnorderedOutput( |
| ['A ' + file1 + '\n', |
| 'A ' + file2 + '\n']) |
| svntest.actions.run_and_verify_svn(expected_status, [], |
| 'status', wc_dir) |
| |
| |
| def quiet_commits(sbox): |
| "commits with --quiet" |
| |
| sbox.build() |
| |
| svntest.main.file_append(sbox.ospath('A/mu'), 'xxx') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'commit', sbox.wc_dir, |
| '--message', 'commit', '--quiet') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'mkdir', sbox.repo_url + '/X', |
| '--message', 'mkdir URL', '--quiet') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'import', sbox.ospath('A/mu'), |
| sbox.repo_url + '/f', |
| '--message', 'import', '--quiet') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'rm', sbox.repo_url + '/f', |
| '--message', 'rm URL', '--quiet') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'copy', sbox.repo_url + '/X', |
| sbox.repo_url + '/Y', |
| '--message', 'cp URL URL', '--quiet') |
| |
| svntest.actions.run_and_verify_svn([], [], |
| 'move', sbox.repo_url + '/Y', |
| sbox.repo_url + '/Z', |
| '--message', 'mv URL URL', '--quiet') |
| |
| # Not fully testing each command, just that they all commit and |
| # produce no output. |
| expected_output = wc.State(sbox.wc_dir, { |
| 'X' : Item(status='A '), |
| 'Z' : Item(status='A '), |
| }) |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 7) |
| expected_status.add({ |
| 'X' : Item(status=' ', wc_rev=7), |
| 'Z' : Item(status=' ', wc_rev=7), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak('A/mu', |
| contents=expected_disk.desc['A/mu'].contents |
| + 'xxx') |
| expected_disk.add({ |
| 'X' : Item(), |
| 'Z' : Item() |
| }) |
| svntest.actions.run_and_verify_update(sbox.wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status) |
| |
| # Regression test for issue #4023: on Windows, 'svn rm' incorrectly deletes |
| # on-disk file if it is case-clashing with intended (non-on-disk) target. |
| @Issue(4023) |
| def rm_missing_with_case_clashing_ondisk_item(sbox): |
| """rm missing item with case-clashing ondisk item""" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| iota_path = sbox.ospath('iota') |
| IOTA_path = sbox.ospath('IOTA') |
| |
| # Out-of-svn move, to make iota missing, while IOTA appears as unversioned. |
| os.rename(iota_path, IOTA_path) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'iota' : Item(status='! ', wc_rev='1'), |
| 'IOTA' : Item(status='? '), |
| }) |
| svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status) |
| |
| # Verify that the casing is not updated, because the path is on-disk. |
| expected_output = [ 'D %s\n' % iota_path ] |
| # 'svn rm' iota, should leave IOTA alone. |
| svntest.actions.run_and_verify_svn(expected_output, [], |
| 'rm', iota_path) |
| |
| # Test status: the unversioned IOTA should still be there. |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'iota' : Item(status='D ', wc_rev='1'), |
| 'IOTA' : Item(status='? '), |
| }) |
| svntest.actions.run_and_verify_unquiet_status(wc_dir, expected_status) |
| |
| |
| def delete_conflicts_one_of_many(sbox): |
| """delete multiple targets one conflict""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| svntest.main.file_append(sbox.ospath('A/D/G/rho'), 'new rho') |
| sbox.simple_commit() |
| svntest.main.file_append(sbox.ospath('A/D/G/rho'), 'conflict rho') |
| svntest.actions.run_and_verify_svn(None, [], |
| 'update', '-r1', '--accept', 'postpone', |
| wc_dir) |
| |
| if not os.path.exists(sbox.ospath('A/D/G/rho.mine')): |
| raise svntest.Failure("conflict file rho.mine missing") |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'rm', '--force', |
| sbox.ospath('A/D/G/rho'), |
| sbox.ospath('A/D/G/tau')) |
| |
| verify_file_deleted("failed to remove conflict file", |
| sbox.ospath('A/D/G/rho.mine')) |
| |
| @Issue(3231) |
| @XFail() |
| def peg_rev_on_non_existent_wc_path(sbox): |
| """peg rev resolution on non-existent wc paths""" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # setup some history |
| sbox.simple_move('A', 'A2') |
| sbox.simple_move('A2/mu', 'A2/mu2') |
| with open(sbox.ospath('A2/mu2'), 'w') as f: |
| f.write('r2\n') |
| sbox.simple_commit(message='r2') |
| # |
| sbox.simple_move('A2/mu2', 'A2/mu3') |
| sbox.simple_move('A2', 'A3') |
| with open(sbox.ospath('A3/mu3'), 'w') as f: |
| f.write('r3\n') |
| sbox.simple_commit(message='r3') |
| # |
| sbox.simple_move('A3/mu3', 'A3/mu4') |
| with open(sbox.ospath('A3/mu4'), 'w') as f: |
| f.write('r4\n') |
| sbox.simple_move('A3', 'A4') |
| sbox.simple_commit(message='r4') |
| |
| # test something. |
| sbox.simple_update() |
| # This currently fails with ENOENT on A/mu3. |
| svntest.actions.run_and_verify_svn(['r2\n'], [], |
| 'cat', '-r2', sbox.ospath('A3/mu3') + '@3') |
| os.chdir(sbox.ospath('A4')) |
| svntest.actions.run_and_verify_svn(['r2\n'], [], |
| 'cat', '-r2', sbox.ospath('mu3') + '@3') |
| |
| |
| @Issue(4532) |
| def diff_previous_revision_of_r0(sbox): |
| """diff -rPREV on WC at revision 0""" |
| |
| sbox.build(empty=True) |
| svntest.actions.run_and_verify_svn(None, 'svn: E195002: ', |
| 'diff', '-rPREV', sbox.ospath('')) |
| |
| |
| # With 'svn mkdir --parents' the target directory may already exist on disk. |
| # In that case it was wrongly performing a recursive 'add' on its contents. |
| def mkdir_parents_target_exists_on_disk(sbox): |
| "mkdir parents target exists on disk" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| Y_path = sbox.ospath('Y') |
| Y_Z_path = sbox.ospath('Y/Z') |
| |
| os.mkdir(Y_path) |
| os.mkdir(Y_Z_path) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'mkdir', '--parents', Y_path) |
| |
| # Y should be added, and Z should not. There was a regression in which Z |
| # was also added. |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) |
| expected_status.add({ |
| 'Y' : Item(status='A ', wc_rev=0), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| @Skip(svntest.main.is_ra_type_file) |
| def plaintext_password_storage_disabled(sbox): |
| "test store-plaintext-passwords = no" |
| |
| sbox.build() |
| |
| wc_dir = sbox.wc_dir |
| sbox.simple_append("iota", "New content for iota.") |
| |
| config_dir_path = sbox.get_tempname(prefix="config-dir") |
| os.mkdir(config_dir_path) |
| |
| # disable all encryped password stores |
| config_file = open(os.path.join(config_dir_path, "config"), "w") |
| config_file.write("[auth]\npassword-stores =\n") |
| config_file.close() |
| |
| # disable plaintext password storage |
| servers_file = open(os.path.join(config_dir_path, "servers"), "w") |
| servers_file.write("[global]\nstore-plaintext-passwords=no\n") |
| servers_file.close() |
| |
| svntest.main.run_command(svntest.main.svn_binary, False, False, |
| "commit", "--config-dir", config_dir_path, |
| "-m", "committing with plaintext password storage disabled", |
| "--username", svntest.main.wc_author, |
| "--password", svntest.main.wc_passwd, |
| "--trust-server-cert-failures", "unknown-ca", |
| "--non-interactive", wc_dir) |
| |
| # Verify that the password was not stored in plaintext |
| for root, dirs, files, in os.walk(os.path.join(config_dir_path, "auth")): |
| for file_name in files: |
| path = os.path.join(root, file_name) |
| f = open(path, "r") |
| for line in f.readlines(): |
| if svntest.main.wc_passwd in line: |
| f.close() |
| raise svntest.Failure("password was found in '%s'" % path) |
| f.close() |
| |
| |
| @Skip(svntest.main.is_os_windows) |
| def filtered_ls(sbox): |
| "filtered 'svn ls'" |
| |
| sbox.build(read_only=True) |
| path = sbox.repo_url + "/A/D" |
| |
| # with and without externals, because without externals on a 1.10+ server |
| # a server-side code path is used |
| for extra_opts in [ [], ['--include-externals'] ]: |
| |
| expected = [ "H/omega\n", |
| "gamma\n" ] |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| expected, [], 'ls', path, '--depth=infinity', '--search=*a', *extra_opts) |
| |
| # check case-insensitivity |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| expected, [], 'ls', path, '--depth=infinity', '--search=*A', *extra_opts) |
| |
| expected = [ "H/\n" ] |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| expected, [], 'ls', path, '--depth=infinity', '--search=h', *extra_opts) |
| |
| # we don't match full paths |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| [], [], 'ls', path, '--depth=infinity', '--search=*/*', *extra_opts) |
| |
| @Issue(4700) |
| @XFail(svntest.main.is_fs_type_fsx) |
| def null_update_last_changed_revision(sbox): |
| "null 'update' updates last changed rev" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # r2: Random text change. |
| old_contents = open(sbox.path("iota")).read() |
| sbox.simple_append("iota", "Line 2.\n") |
| sbox.simple_commit(message='r2') |
| sbox.simple_update() |
| |
| # r3: Revert r2. |
| sbox.simple_append("iota", old_contents, truncate=True) |
| sbox.simple_commit(message='r3') |
| sbox.simple_update() |
| |
| # Perform a null update. |
| # |
| # This used to say '3'; probably because iota@3 and iota@1 were textually |
| # identical. It seems this problem was introduced in r1760570. |
| sbox.simple_update(revision='1') |
| svntest.actions.run_and_verify_svn(["1\n"], [], |
| 'info', sbox.path('iota'), |
| '--show-item', 'last-changed-revision') |
| |
| @Issue(4700) |
| @XFail(svntest.main.is_fs_type_bdb) |
| @XFail(svntest.main.is_fs_type_fsx) |
| def null_prop_update_last_changed_revision(sbox): |
| "null 'property update' updates last changed rev" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| sbox.simple_propset("prop", "value", "iota") |
| sbox.simple_commit(message='r2') |
| sbox.simple_update() |
| |
| # r3: change the property |
| sbox.simple_propset("prop", "changed", "iota") |
| sbox.simple_commit(message='r3') |
| sbox.simple_update() |
| |
| # r4: Revert r3. |
| sbox.simple_propset("prop", "value", "iota") |
| sbox.simple_commit(message='r4') |
| sbox.simple_update() |
| |
| # Perform a null update. |
| sbox.simple_update(revision='2') |
| svntest.actions.run_and_verify_svn(["2\n"], [], |
| 'info', sbox.path('iota'), |
| '--show-item', 'last-changed-revision') |
| |
| @Skip(svntest.main.is_os_windows) |
| def filtered_ls_top_level_path(sbox): |
| "filtered 'svn ls' top level path" |
| |
| sbox.build(read_only=True, create_wc=False) |
| d_path = sbox.repo_url + "/A/B" |
| f_path = sbox.repo_url + "/A/B/lambda" |
| |
| d_expected = svntest.verify.RegexListOutput([ |
| r".* \./", # expect '*B*' to match its name which is 'B' |
| r".* E/beta", |
| r".* lambda" ]) |
| f_expected = [ "lambda\n" ] |
| |
| # with and without externals, because without externals on a 1.10+ server |
| # a server-side code path is used |
| for extra_opts in [ [], ['--include-externals'] ]: |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| d_expected, [], 'ls', '-v', d_path, '-R', '--search=*B*', *extra_opts) |
| |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| f_expected, [], 'ls', f_path, '--search=lambda', *extra_opts) |
| |
| # we don't match full paths, even for the top level path |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| [], [], 'ls', '-v', d_path, '-R', '--search=*/*', *extra_opts) |
| exit_code, output, error = svntest.actions.run_and_verify_svn( |
| [], [], 'ls', f_path, '--search=*/*', *extra_opts) |
| |
| |
| ######################################################################## |
| # Run the tests |
| |
| # list all tests here, starting with None: |
| test_list = [ None, |
| basic_checkout, |
| basic_status, |
| basic_commit, |
| basic_update, |
| basic_mkdir_url, |
| basic_mkdir_url_with_parents, |
| basic_mkdir_wc_with_parents, |
| basic_commit_corruption, |
| basic_update_corruption, |
| basic_merging_update, |
| basic_conflict, |
| basic_cleanup, |
| basic_revert, |
| basic_switch, |
| basic_delete, |
| basic_checkout_deleted, |
| basic_node_kind_change, |
| basic_import, |
| basic_cat, |
| basic_ls, |
| nonexistent_repository, |
| basic_auth_cache, |
| basic_add_ignores, |
| basic_add_parents, |
| uri_syntax, |
| basic_checkout_file, |
| basic_info, |
| basic_add_local_ignores, |
| basic_add_no_ignores, |
| repos_root, |
| basic_peg_revision, |
| info_nonhead, |
| ls_nonhead, |
| cat_added_PREV, |
| ls_space_in_repo_name, |
| delete_keep_local, |
| delete_keep_local_twice, |
| special_paths_in_repos, |
| basic_rm_urls_one_repo, |
| basic_rm_urls_multi_repos, |
| automatic_conflict_resolution, |
| info_nonexisting_file, |
| basic_relative_url_using_current_dir, |
| basic_relative_url_using_other_targets, |
| basic_relative_url_multi_repo, |
| basic_relative_url_non_canonical, |
| basic_relative_url_with_peg_revisions, |
| basic_auth_test, |
| basic_add_svn_format_file, |
| basic_mkdir_mix_targets, |
| delete_from_url_with_spaces, |
| meta_correct_library_being_used, |
| delete_and_add_same_file, |
| delete_child_parent_update, |
| basic_relocate, |
| delete_urls_with_spaces, |
| ls_url_special_characters, |
| ls_multiple_and_non_existent_targets, |
| add_multiple_targets, |
| quiet_commits, |
| rm_missing_with_case_clashing_ondisk_item, |
| delete_conflicts_one_of_many, |
| peg_rev_on_non_existent_wc_path, |
| diff_previous_revision_of_r0, |
| mkdir_parents_target_exists_on_disk, |
| plaintext_password_storage_disabled, |
| filtered_ls, |
| null_update_last_changed_revision, |
| null_prop_update_last_changed_revision, |
| filtered_ls_top_level_path, |
| ] |
| |
| if __name__ == '__main__': |
| svntest.main.run_tests(test_list) |
| # NOTREACHED |
| |
| |
| ### End of file. |