| #!/usr/bin/env python |
| # |
| # special_tests.py: testing special and reserved file handling |
| # |
| # 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 sys, os, re, copy, stat |
| |
| # Our testing module |
| import svntest |
| |
| from svntest.main import server_has_mergeinfo, run_svn, file_write |
| |
| # (abbreviation) |
| Skip = svntest.testcase.Skip_deco |
| SkipUnless = svntest.testcase.SkipUnless_deco |
| XFail = svntest.testcase.XFail_deco |
| Issues = svntest.testcase.Issues_deco |
| Issue = svntest.testcase.Issue_deco |
| Wimp = svntest.testcase.Wimp_deco |
| Item = svntest.wc.StateItem |
| |
| |
| ###################################################################### |
| # Tests |
| # |
| # Each test must return on success or raise on failure. |
| |
| |
| #---------------------------------------------------------------------- |
| def general_symlink(sbox): |
| "general symlink handling" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # First try to just commit a symlink |
| newfile_path = sbox.ospath('newfile') |
| |
| sbox.simple_append('linktarget', 'this is just a link target') |
| sbox.simple_add('linktarget') |
| sbox.simple_add_symlink('linktarget', 'newfile') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Adding'), |
| 'linktarget' : Item(verb='Adding'), |
| }) |
| |
| # Run a diff and verify that we get the correct output |
| exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'diff', |
| wc_dir) |
| |
| regex = '^\+link linktarget' |
| for line in stdout_lines: |
| if re.match(regex, line): |
| break |
| else: |
| raise svntest.Failure |
| |
| # Commit and make sure everything is good |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'newfile' : Item(status=' ', wc_rev=2), |
| 'linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| ## Now we should update to the previous version, verify that no |
| ## symlink is present, then update back to HEAD and see if the symlink |
| ## is regenerated properly. |
| svntest.actions.run_and_verify_svn(None, [], |
| 'up', '-r', '1', wc_dir) |
| |
| # Is the symlink gone? |
| if os.path.isfile(newfile_path) or os.path.islink(newfile_path): |
| raise svntest.Failure |
| |
| svntest.actions.run_and_verify_svn(None, [], |
| 'up', '-r', '2', wc_dir) |
| |
| # Is the symlink back? |
| if svntest.main.is_posix_os(): |
| new_target = os.readlink(newfile_path) |
| if new_target != 'linktarget': |
| raise svntest.Failure |
| |
| ## Now change the target of the symlink, verify that it is shown as |
| ## modified and that a commit succeeds. |
| os.remove(newfile_path) |
| if svntest.main.is_posix_os(): |
| os.symlink('A', newfile_path) |
| else: |
| sbox.simple_append('newfile', 'link A', truncate = True) |
| |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| svntest.actions.run_and_verify_svn([ "M newfile\n" ], [], 'st') |
| |
| os.chdir(was_cwd) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Sending'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'newfile' : Item(status=' ', wc_rev=3), |
| 'linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| |
| @SkipUnless(svntest.main.is_posix_os) |
| def replace_file_with_symlink(sbox): |
| "replace a normal file with a special file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # First replace a normal file with a symlink and make sure we get an |
| # error |
| iota_path = os.path.join(wc_dir, 'iota') |
| os.remove(iota_path) |
| os.symlink('A', iota_path) |
| |
| # Does status show the obstruction? |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| svntest.actions.run_and_verify_svn([ "~ iota\n" ], [], 'st') |
| |
| # And does a commit fail? |
| os.chdir(was_cwd) |
| exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'ci', '-m', |
| 'log msg', |
| wc_dir) |
| |
| regex = 'svn: E145001: Commit failed' |
| for line in stderr_lines: |
| if re.match(regex, line): |
| break |
| else: |
| raise svntest.Failure |
| |
| |
| @SkipUnless(svntest.main.is_posix_os) |
| def import_export_symlink(sbox): |
| "import and export a symlink" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # create a new symlink to import |
| new_path = os.path.join(wc_dir, 'new_file') |
| |
| os.symlink('linktarget', new_path) |
| |
| # import this symlink into the repository |
| url = sbox.repo_url + "/dirA/dirB/new_link" |
| exit_code, output, errput = svntest.actions.run_and_verify_svn( |
| None, [], 'import', |
| '-m', 'log msg', new_path, url) |
| |
| regex = "(Committed|Imported) revision [0-9]+." |
| for line in output: |
| if re.match(regex, line): |
| break |
| else: |
| raise svntest.Failure |
| |
| # remove the unversioned link |
| os.remove(new_path) |
| |
| # run update and verify that the symlink is put back into place |
| svntest.actions.run_and_verify_svn(None, [], |
| 'up', wc_dir) |
| |
| # Is the symlink back? |
| link_path = wc_dir + "/dirA/dirB/new_link" |
| new_target = os.readlink(link_path) |
| if new_target != 'linktarget': |
| raise svntest.Failure |
| |
| ## Now we will try exporting from both the working copy and the |
| ## repository directly, verifying that the symlink is created in |
| ## both cases. |
| |
| for export_src, dest_dir in [(sbox.wc_dir, 'export-wc'), |
| (sbox.repo_url, 'export-url')]: |
| export_target = sbox.add_wc_path(dest_dir) |
| svntest.actions.run_and_verify_svn(None, [], |
| 'export', export_src, export_target) |
| |
| # is the link at the correct place? |
| link_path = os.path.join(export_target, "dirA/dirB/new_link") |
| new_target = os.readlink(link_path) |
| if new_target != 'linktarget': |
| raise svntest.Failure |
| |
| |
| #---------------------------------------------------------------------- |
| # Regression test for issue 1986 |
| @Issue(1986) |
| def copy_tree_with_symlink(sbox): |
| "'svn cp dir1 dir2' which contains a symlink" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a versioned symlink within directory 'A/D/H'. |
| newfile_path = sbox.ospath('A/D/H/newfile') |
| sbox.simple_append('A/D/H/linktarget', 'this is just a link target') |
| sbox.simple_add('A/D/H/linktarget') |
| sbox.simple_add_symlink('linktarget', 'A/D/H/newfile') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/H/newfile' : Item(verb='Adding'), |
| 'A/D/H/linktarget' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'A/D/H/newfile' : Item(status=' ', wc_rev=2), |
| 'A/D/H/linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| # Copy H to H2 |
| H_path = os.path.join(wc_dir, 'A', 'D', 'H') |
| H2_path = os.path.join(wc_dir, 'A', 'D', 'H2') |
| svntest.actions.run_and_verify_svn(None, [], 'cp', H_path, H2_path) |
| |
| # 'svn status' should show just "A/D/H2 A +". Nothing broken. |
| expected_status.add({ |
| 'A/D/H2' : Item(status='A ', copied='+', wc_rev='-'), |
| 'A/D/H2/chi' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/H2/omega' : Item(status=' ', copied='+', wc_rev='-'), |
| 'A/D/H2/psi' : Item(status=' ', copied='+', wc_rev='-'), |
| # linktarget and newfile are from r2, while h2 is from r1. |
| 'A/D/H2/linktarget' : Item(status='A ', copied='+', wc_rev='-', |
| entry_status=' '), |
| 'A/D/H2/newfile' : Item(status='A ', copied='+', wc_rev='-', |
| entry_status=' '), |
| }) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| |
| @SkipUnless(svntest.main.is_posix_os) |
| def replace_symlink_with_file(sbox): |
| "replace a special file with a non-special file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a new special file and commit it. |
| newfile_path = os.path.join(wc_dir, 'newfile') |
| linktarget_path = os.path.join(wc_dir, 'linktarget') |
| svntest.main.file_append(linktarget_path, 'this is just a link target') |
| os.symlink('linktarget', newfile_path) |
| svntest.main.run_svn(None, 'add', newfile_path, linktarget_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Adding'), |
| 'linktarget' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'newfile' : Item(status=' ', wc_rev=2), |
| 'linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| |
| # Now replace the symlink with a normal file and try to commit, we |
| # should get an error |
| os.remove(newfile_path) |
| svntest.main.file_append(newfile_path, "text of actual file") |
| |
| # Does status show the obstruction? |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| svntest.actions.run_and_verify_svn([ "~ newfile\n" ], [], 'st') |
| |
| # And does a commit fail? |
| os.chdir(was_cwd) |
| exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'ci', '-m', |
| 'log msg', |
| wc_dir) |
| |
| regex = 'svn: E145001: Commit failed' |
| for line in stderr_lines: |
| if re.match(regex, line): |
| break |
| else: |
| raise svntest.Failure |
| |
| |
| #---------------------------------------------------------------------- |
| def remove_symlink(sbox): |
| "remove a symlink" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Commit a symlink |
| newfile_path = os.path.join(wc_dir, 'newfile') |
| linktarget_path = os.path.join(wc_dir, 'linktarget') |
| svntest.main.file_append(linktarget_path, 'this is just a link target') |
| sbox.simple_add_symlink('linktarget', 'newfile') |
| sbox.simple_add('linktarget') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Adding'), |
| 'linktarget' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'newfile' : Item(status=' ', wc_rev=2), |
| 'linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Now remove it |
| svntest.actions.run_and_verify_svn(None, [], 'rm', newfile_path) |
| |
| # Commit and verify that it worked |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Deleting'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'linktarget' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| #---------------------------------------------------------------------- |
| @SkipUnless(server_has_mergeinfo) |
| @Issue(2530) |
| def merge_symlink_into_file(sbox): |
| "merge symlink into file" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| d_url = sbox.repo_url + '/A/D' |
| dprime_url = sbox.repo_url + '/A/Dprime' |
| |
| gamma_path = sbox.ospath('A/D/gamma') |
| gamma_prime_path = sbox.ospath('A/Dprime/gamma') |
| |
| # create a copy of the D directory to play with |
| svntest.main.run_svn(None, |
| 'copy', d_url, dprime_url, '-m', 'copy') |
| svntest.main.run_svn(None, |
| 'update', sbox.wc_dir) |
| |
| # remove A/Dprime/gamma |
| svntest.main.run_svn(None, 'delete', gamma_prime_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/Dprime/gamma' : Item(verb='Deleting'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| # Commit a symlink in its place |
| linktarget_path = os.path.join(wc_dir, 'linktarget') |
| svntest.main.file_append(linktarget_path, 'this is just a link target') |
| sbox.simple_add_symlink('linktarget', 'A/Dprime/gamma') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/Dprime/gamma' : Item(verb='Adding'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| # merge the creation of the symlink into the original directory |
| svntest.main.run_svn(None, |
| 'merge', '-r', '2:4', dprime_url, |
| os.path.join(wc_dir, 'A', 'D')) |
| |
| # now revert, we once got a strange error |
| svntest.main.run_svn(None, 'revert', '-R', wc_dir) |
| |
| # assuming we got past the revert because someone fixed that bug, lets |
| # try the merge and a commit, since that apparently used to throw us for |
| # a loop, see issue 2530 |
| svntest.main.run_svn(None, |
| 'merge', '-r', '2:4', dprime_url, |
| os.path.join(wc_dir, 'A', 'D')) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D' : Item(verb='Sending'), |
| 'A/D/gamma' : Item(verb='Replacing'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| |
| |
| #---------------------------------------------------------------------- |
| def merge_file_into_symlink(sbox): |
| "merge file into symlink" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| d_url = sbox.repo_url + '/A/D' |
| dprime_url = sbox.repo_url + '/A/Dprime' |
| |
| gamma_path = os.path.join(wc_dir, 'A', 'D', 'gamma') |
| gamma_prime_path = os.path.join(wc_dir, 'A', 'Dprime', 'gamma') |
| |
| # create a copy of the D directory to play with |
| svntest.main.run_svn(None, |
| 'copy', d_url, dprime_url, '-m', 'copy') |
| svntest.main.run_svn(None, |
| 'update', sbox.wc_dir) |
| |
| # remove A/Dprime/gamma |
| svntest.main.run_svn(None, 'delete', gamma_prime_path) |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/Dprime/gamma' : Item(verb='Deleting'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| # Commit a symlink in its place |
| linktarget_path = os.path.join(wc_dir, 'linktarget') |
| svntest.main.file_append(linktarget_path, 'this is just a link target') |
| sbox.simple_add_symlink('linktarget', 'A/Dprime/gamma') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/Dprime/gamma' : Item(verb='Adding'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| svntest.main.file_write(gamma_path, 'changed file', 'w+') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/D/gamma' : Item(verb='Sending'), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, None) |
| |
| # ok, now merge the change to the file into the symlink we created, this |
| # gives us a weird error |
| svntest.main.run_svn(None, |
| 'merge', '-r', '4:5', '--allow-mixed-revisions', d_url, |
| os.path.join(wc_dir, 'A', 'Dprime')) |
| |
| # Issue 2701: Tests to see repository with symlinks can be checked out on all |
| # platforms. |
| @Issue(2701) |
| def checkout_repo_with_symlinks(sbox): |
| "checkout a repository containing symlinks" |
| |
| svntest.actions.load_repo(sbox, os.path.join(os.path.dirname(sys.argv[0]), |
| 'special_tests_data', |
| 'symlink.dump'), |
| create_wc=False) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'from': Item(status='A '), |
| 'to': Item(status='A '), |
| }) |
| |
| if svntest.main.is_os_windows(): |
| expected_link_contents = 'link to' |
| else: |
| expected_link_contents = '' |
| |
| expected_wc = svntest.wc.State('', { |
| 'from' : Item(contents=expected_link_contents), |
| 'to' : Item(contents=''), |
| }) |
| svntest.actions.run_and_verify_checkout(sbox.repo_url, |
| sbox.wc_dir, |
| expected_output, |
| expected_wc) |
| |
| #---------------------------------------------------------------------- |
| # Issue 2716: 'svn diff' against a symlink to a directory within the wc |
| @Issue(2716) |
| def diff_symlink_to_dir(sbox): |
| "diff a symlink to a directory" |
| |
| sbox.build(read_only = True) |
| |
| # Create a symlink to A/D as link. |
| d_path = os.path.join('A', 'D') |
| sbox.simple_add_symlink('A/D', 'link') |
| |
| os.chdir(sbox.wc_dir) |
| |
| # Now diff the wc itself and check the results. |
| expected_output = [ |
| "Index: link\n", |
| "===================================================================\n", |
| "--- link\t(nonexistent)\n", |
| "+++ link\t(working copy)\n", |
| "@@ -0,0 +1 @@\n", |
| "+link A/D\n", |
| "\\ No newline at end of file\n", |
| "\n", |
| "Property changes on: link\n", |
| "___________________________________________________________________\n", |
| "Added: svn:special\n", |
| "## -0,0 +1 ##\n", |
| "+*\n", |
| "\\ No newline at end of property\n" |
| ] |
| svntest.actions.run_and_verify_svn(expected_output, [], 'diff', |
| '.') |
| # We should get the same output if we the diff the symlink itself. |
| svntest.actions.run_and_verify_svn(expected_output, [], 'diff', 'link') |
| |
| #---------------------------------------------------------------------- |
| # Issue 2692 (part of): Check that the client can check out a repository |
| # that contains an unknown special file type. |
| @Issue(2692) |
| def checkout_repo_with_unknown_special_type(sbox): |
| "checkout repository with unknown special file type" |
| |
| svntest.actions.load_repo(sbox, os.path.join(os.path.dirname(sys.argv[0]), |
| 'special_tests_data', |
| 'bad-special-type.dump'), |
| create_wc=False) |
| |
| expected_output = svntest.wc.State(sbox.wc_dir, { |
| 'special': Item(status='A '), |
| }) |
| expected_wc = svntest.wc.State('', { |
| 'special' : Item(contents='gimble wabe'), |
| }) |
| svntest.actions.run_and_verify_checkout(sbox.repo_url, |
| sbox.wc_dir, |
| expected_output, |
| expected_wc) |
| |
| def replace_symlink_with_dir(sbox): |
| "replace a special file with a directory" |
| |
| svntest.actions.load_repo(sbox, os.path.join(os.path.dirname(sys.argv[0]), |
| 'special_tests_data', |
| 'symlink.dump')) |
| |
| wc_dir = sbox.wc_dir |
| from_path = os.path.join(wc_dir, 'from') |
| |
| # Now replace the symlink with a directory and try to commit, we |
| # should get an error |
| os.remove(from_path) |
| os.mkdir(from_path) |
| |
| # Does status show the obstruction? |
| was_cwd = os.getcwd() |
| os.chdir(wc_dir) |
| svntest.actions.run_and_verify_svn([ "~ from\n" ], [], 'st') |
| |
| # The commit shouldn't do anything. |
| # I'd expect a failed commit here, but replacing a file locally with a |
| # directory seems to make svn think the file is unchanged. |
| os.chdir(was_cwd) |
| expected_output = svntest.wc.State(wc_dir, { |
| }) |
| |
| error_re_string = '.*E145001: (Entry|Node).*has.*changed (special|kind).*' |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| None, error_re_string) |
| |
| # test for issue #1808: svn up deletes local symlink that obstructs |
| # versioned file |
| @Issue(1808) |
| def update_obstructing_symlink(sbox): |
| "symlink obstructs incoming delete" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| mu_path = sbox.ospath('A/mu') |
| |
| iota_abspath = os.path.abspath(sbox.ospath('iota')) |
| |
| # delete mu and replace it with an (not-added) symlink |
| sbox.simple_rm('A/mu') |
| sbox.simple_symlink(iota_abspath, 'A/mu') |
| |
| # delete pi and replace it with an added symlink |
| sbox.simple_rm('A/D/G/pi') |
| sbox.simple_add_symlink(iota_abspath, 'A/D/G/pi') |
| |
| if not os.path.exists(mu_path): |
| raise svntest.Failure("mu should be there") |
| |
| # Now remove mu and pi in the repository |
| svntest.main.run_svn(None, 'rm', '-m', 'log msg', |
| sbox.repo_url + '/A/mu', |
| sbox.repo_url + '/A/D/G/pi') |
| |
| # We expect tree conflicts |
| expected_output = svntest.wc.State(wc_dir, { |
| 'A/mu': Item(status=' ', treeconflict='C'), |
| 'A/D/G/pi': Item(status=' ', treeconflict='C') |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.tweak('A/mu', status='? ', treeconflict='C', |
| wc_rev=None) |
| |
| expected_status.tweak('A/D/G/pi', status='A ',treeconflict='C', |
| wc_rev='-') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, None, |
| expected_status) |
| |
| expected_info = [ |
| { |
| 'Path': re.escape(sbox.ospath('A/D/G/pi')), |
| 'Tree conflict': 'local file replace, incoming file delete or move.*' |
| }, |
| { |
| 'Path': re.escape(sbox.ospath('A/mu')), |
| 'Tree conflict': 'local file delete, incoming file delete or move.*' |
| } |
| ] |
| |
| svntest.actions.run_and_verify_info(expected_info, |
| sbox.ospath('A/D/G/pi'), |
| sbox.ospath('A/mu')) |
| |
| # check that the symlink is still there |
| if not os.path.exists(mu_path): |
| raise svntest.Failure("mu should be there") |
| if svntest.main.is_posix_os(): |
| target = os.readlink(mu_path) |
| if target != iota_abspath: |
| raise svntest.Failure("mu no longer points to the same location") |
| |
| def warn_on_reserved_name(sbox): |
| "warn when attempt operation on a reserved name" |
| sbox.build() |
| reserved_path = os.path.join(sbox.wc_dir, svntest.main.get_admin_name()) |
| svntest.actions.run_and_verify_svn( |
| None, |
| ".*Skipping argument: E200025: '.+' ends in a reserved name.*", |
| 'lock', reserved_path) |
| |
| |
| def propvalue_normalized(sbox): |
| "'ps svn:special' should normalize to '*'" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Add a "symlink" |
| iota2_path = sbox.ospath('iota2') |
| svntest.main.file_write(iota2_path, "symlink destination") |
| svntest.main.run_svn(None, 'add', iota2_path) |
| svntest.main.run_svn(None, 'propset', 'svn:special', 'yes', iota2_path) |
| if svntest.main.is_posix_os(): |
| os.remove(iota2_path) |
| os.symlink("symlink destination", iota2_path) |
| |
| # Property value should be SVN_PROP_BOOLEAN_TRUE |
| expected_propval = ['*'] |
| svntest.actions.run_and_verify_svn(expected_propval, [], |
| 'propget', '--no-newline', 'svn:special', |
| iota2_path) |
| |
| # Commit and check again. |
| expected_output = svntest.wc.State(wc_dir, { |
| 'iota2' : Item(verb='Adding'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'iota2' : Item(status=' ', wc_rev=2), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| svntest.main.run_svn(None, 'update', wc_dir) |
| svntest.actions.run_and_verify_svn(expected_propval, [], |
| 'propget', '--no-newline', 'svn:special', |
| iota2_path) |
| |
| |
| # on users@: http://mid.gmane.org/1292856447.8650.24.camel@nimble.325Bayport |
| @SkipUnless(svntest.main.is_posix_os) |
| def unrelated_changed_special_status(sbox): |
| "commit foo while bar changed special status" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| os.chdir(os.path.join(sbox.wc_dir, 'A/D/H')) |
| |
| with open('chi', 'a') as f: |
| f.write('random local mod') |
| os.unlink('psi') |
| os.symlink('omega', 'psi') # omega is versioned! |
| svntest.main.run_svn(None, 'changelist', 'chi cl', 'chi') |
| svntest.actions.run_and_verify_svn(None, [], 'commit', |
| '--changelist', 'chi cl', |
| '-m', 'psi changed special status') |
| |
| #---------------------------------------------------------------------- |
| @Issue(3972) |
| def symlink_destination_change(sbox): |
| "revert a symlink destination change" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Create a new symlink and commit it. |
| newfile_path = os.path.join(wc_dir, 'newfile') |
| sbox.simple_add_symlink('linktarget', 'newfile') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 'newfile' : Item(verb='Adding'), |
| }) |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 1) |
| expected_status.add({ |
| 'newfile' : Item(status=' ', wc_rev=2), |
| }) |
| |
| svntest.actions.run_and_verify_commit(wc_dir, expected_output, |
| expected_status) |
| |
| # Modify the symlink to point somewhere else |
| os.remove(newfile_path) |
| if svntest.main.is_posix_os(): |
| os.symlink('linktarget2', newfile_path) |
| else: |
| sbox.simple_append('newfile', 'link linktarget2', truncate = True) |
| |
| expected_status.tweak('newfile', status='M ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Revert should restore the symlink to point to the original destination |
| svntest.main.run_svn(None, 'revert', '-R', wc_dir) |
| expected_status.tweak('newfile', status=' ') |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Issue 3972, repeat revert produces no output |
| svntest.actions.run_and_verify_svn([], [], 'revert', '-R', wc_dir) |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| # Now replace the symlink with a normal file and try to commit, we |
| |
| #---------------------------------------------------------------------- |
| # This used to lose the special status in the target working copy |
| # (disk and metadata). |
| @Issue(3884) |
| def merge_foreign_symlink(sbox): |
| "merge symlink-add from foreign repos" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| # Make a copy of this repository and associated working copy. Both |
| # should have nothing but a Greek tree in them, and the two |
| # repository UUIDs should differ. |
| sbox2 = sbox.clone_dependent(True) |
| sbox2.build() |
| wc_dir2 = sbox2.wc_dir |
| |
| # convenience variables |
| zeta_path = sbox.ospath('A/zeta') |
| zeta2_path = sbox2.ospath('A/zeta') |
| |
| # sbox2 r2: create zeta2 in sbox2 |
| sbox2.simple_add_symlink('target', 'A/zeta') |
| sbox2.simple_commit('A/zeta') |
| |
| |
| # sbox1: merge that |
| svntest.main.run_svn(None, 'merge', '-c', '2', sbox2.repo_url, |
| sbox.ospath('')) |
| |
| # Verify special status. |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({ |
| 'A/zeta': Item(contents="link target", props={ 'svn:special': '*' }) |
| }) |
| svntest.actions.verify_disk(sbox.ospath(''), expected_disk, True) |
| |
| # TODO: verify status: |
| # expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| # expected_status.add({ |
| # 'A/zeta' : Item(status='A ', wc_rev='-', props={'svn:special': '*'}), |
| # }) |
| |
| #---------------------------------------------------------------------- |
| # See also symlink_to_wc_svnversion(). |
| @Issue(2557,3987) |
| @SkipUnless(svntest.main.is_posix_os) |
| def symlink_to_wc_basic(sbox): |
| "operate on symlink to wc" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Create a symlink |
| symlink_path = sbox.add_wc_path('2') |
| assert not os.path.islink(symlink_path) |
| os.symlink(os.path.basename(wc_dir), symlink_path) ### implementation detail |
| symlink_basename = os.path.basename(symlink_path) |
| |
| # Some basic tests |
| wc_uuid = svntest.actions.get_wc_uuid(wc_dir) |
| expected_info = [{ |
| 'Path' : re.escape(os.path.join(symlink_path)), |
| 'Working Copy Root Path' : re.escape(os.path.abspath(wc_dir)), |
| 'Repository Root' : sbox.repo_url, |
| 'Repository UUID' : wc_uuid, |
| 'Revision' : '1', |
| 'Node Kind' : 'directory', |
| 'Schedule' : 'normal', |
| }, { |
| 'Name' : 'iota', |
| 'Path' : re.escape(os.path.join(symlink_path, 'iota')), |
| 'Working Copy Root Path' : re.escape(os.path.abspath(wc_dir)), |
| 'Repository Root' : sbox.repo_url, |
| 'Repository UUID' : wc_uuid, |
| 'Revision' : '1', |
| 'Node Kind' : 'file', |
| 'Schedule' : 'normal', |
| }] |
| svntest.actions.run_and_verify_info(expected_info, |
| symlink_path, symlink_path + '/iota') |
| |
| #---------------------------------------------------------------------- |
| # Similar to #2557/#3987; see symlink_to_wc_basic(). |
| @Issue(2557,3987) |
| @SkipUnless(svntest.main.is_posix_os) |
| def symlink_to_wc_svnversion(sbox): |
| "svnversion on symlink to wc" |
| |
| sbox.build(read_only = True) |
| wc_dir = sbox.wc_dir |
| |
| # Create a symlink |
| symlink_path = sbox.add_wc_path('2') |
| assert not os.path.islink(symlink_path) |
| os.symlink(os.path.basename(wc_dir), symlink_path) ### implementation detail |
| symlink_basename = os.path.basename(symlink_path) |
| |
| # Some basic tests |
| svntest.actions.run_and_verify_svnversion(symlink_path, sbox.repo_url, |
| [ "1\n" ], []) |
| |
| #---------------------------------------------------------------------- |
| # Regression in 1.7.0: Update fails to change a symlink |
| def update_symlink(sbox): |
| "update a symlink" |
| |
| svntest.actions.do_sleep_for_timestamps() |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| mu_path = sbox.ospath('A/mu') |
| iota_path = sbox.ospath('iota') |
| symlink_path = sbox.ospath('symlink') |
| |
| # create a symlink to /A/mu |
| sbox.simple_add_symlink("A/mu", 'symlink') |
| sbox.simple_commit() |
| |
| # change the symlink to /iota |
| os.remove(symlink_path) |
| if svntest.main.is_posix_os(): |
| os.symlink("iota", symlink_path) |
| else: |
| file_write(symlink_path, 'link iota') |
| sbox.simple_commit() |
| |
| # update back to r2 |
| svntest.main.run_svn(False, 'update', '-r', '2', wc_dir) |
| |
| # now update to head; 1.7.0 throws an assertion here |
| expected_output = svntest.wc.State(wc_dir, { |
| 'symlink' : Item(status='U '), |
| }) |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.add({'symlink': Item(contents="This is the file 'iota'.\n", |
| props={'svn:special' : '*'})}) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 3) |
| expected_status.add({ |
| 'symlink' : Item(status=' ', wc_rev='3'), |
| }) |
| |
| if not svntest.main.is_posix_os(): |
| expected_disk = None |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| expected_disk, |
| expected_status, |
| check_props=True) |
| |
| #---------------------------------------------------------------------- |
| @Issue(4091) |
| def replace_symlinks(sbox): |
| "replace symlinks" |
| sbox.build() |
| wc = sbox.ospath |
| |
| # Some of these tests are implemented for git (in test script |
| # t/t9100-git-svn-basic.sh) using the Perl bindings for Subversion. |
| # Our issue #4091 is about 'svn update' failures in the git tests. |
| |
| sbox.simple_mkdir('A/D/G/Z') |
| sbox.simple_mkdir('A/D/Gx') |
| sbox.simple_mkdir('A/D/Gx/Z') |
| sbox.simple_mkdir('A/D/Hx') |
| sbox.simple_mkdir('A/D/Y') |
| sbox.simple_mkdir('Ax') |
| |
| sbox.simple_add_symlink('../Y', 'A/D/H/Z') |
| sbox.simple_add_symlink('../Y', 'A/D/Hx/Z') |
| |
| for p in ['Ax/mu', |
| 'A/D/Gx/pi', |
| 'A/D/Hx/chi', |
| ]: |
| file_write(wc(p), 'This starts as a normal file.\n') |
| sbox.simple_add(p) |
| for p in ['iota.sh', |
| 'A/mu.sh', |
| 'Ax/mu.sh', |
| 'A/D/gamma.sh', |
| 'A/B/E/beta.sh', |
| 'A/D/G/rho.sh', |
| 'A/D/Gx/rho.sh', |
| 'A/D/H/psi.sh', |
| 'A/D/Hx/psi.sh', |
| ]: |
| file_write(wc(p), '#!/bin/sh\necho "hello, svn!"\n') |
| os.chmod(wc(p), svntest.main.S_ALL_RW | stat.S_IXUSR) |
| sbox.simple_add(p) |
| if not svntest.main.is_posix_os(): |
| sbox.simple_propset('svn:executable', 'X', p) |
| sbox.simple_commit() # r2 |
| sbox.simple_update() |
| expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 2) |
| expected_status.add({ |
| 'A/D/Y' : Item(status=' ', wc_rev=2), |
| 'A/D/G/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/G/rho.sh' : Item(status=' ', wc_rev=2), |
| 'A/D/Hx' : Item(status=' ', wc_rev=2), |
| 'A/D/Hx/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/Hx/chi' : Item(status=' ', wc_rev=2), |
| 'A/D/Hx/psi.sh' : Item(status=' ', wc_rev=2), |
| 'A/D/H/psi.sh' : Item(status=' ', wc_rev=2), |
| 'A/D/H/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/Gx' : Item(status=' ', wc_rev=2), |
| 'A/D/Gx/Z' : Item(status=' ', wc_rev=2), |
| 'A/D/Gx/pi' : Item(status=' ', wc_rev=2), |
| 'A/D/Gx/rho.sh' : Item(status=' ', wc_rev=2), |
| 'A/D/gamma.sh' : Item(status=' ', wc_rev=2), |
| 'A/B/E/beta.sh' : Item(status=' ', wc_rev=2), |
| 'Ax' : Item(status=' ', wc_rev=2), |
| 'Ax/mu' : Item(status=' ', wc_rev=2), |
| 'Ax/mu.sh' : Item(status=' ', wc_rev=2), |
| 'A/mu.sh' : Item(status=' ', wc_rev=2), |
| 'iota.sh' : Item(status=' ', wc_rev=2), |
| }) |
| expected_status_r2 = copy.deepcopy(expected_status) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2) |
| |
| # Failing git-svn test: 'new symlink is added to a file that was |
| # also just made executable', i.e., in the same revision. |
| sbox.simple_propset("svn:executable", "X", 'A/B/E/alpha') |
| sbox.simple_add_symlink('alpha', 'A/B/E/sym-alpha') |
| |
| # Add a symlink to a file made non-executable in the same revision. |
| sbox.simple_propdel("svn:executable", 'A/B/E/beta.sh') |
| sbox.simple_add_symlink('beta.sh', 'A/B/E/sym-beta.sh') |
| |
| # Replace a normal {file, exec, dir} with a symlink to the same kind |
| # via Subversion replacement. |
| sbox.simple_rm('A/D/G/pi', |
| 'A/D/G/rho.sh', |
| #'A/D/G/Z', # Ooops, not compatible with --bin=svn1.6. |
| ) |
| sbox.simple_add_symlink('../gamma', 'A/D/G/pi') |
| sbox.simple_add_symlink('../gamma.sh', 'A/D/G/rho.sh') |
| #sbox.simple_add_symlink('../Y', 'A/D/G/Z') |
| |
| # Replace a symlink to {file, exec, dir} with a normal item of the |
| # same kind via Subversion replacement. |
| sbox.simple_rm('A/D/H/chi', |
| 'A/D/H/psi.sh', |
| #'A/D/H/Z', |
| ) |
| sbox.simple_add_symlink('../gamma', 'A/D/H/chi') |
| sbox.simple_add_symlink('../gamma.sh', 'A/D/H/psi.sh') |
| #sbox.simple_add_symlink('../Y', 'A/D/H/Z') |
| |
| # Replace a normal {file, exec} with a symlink to {exec, file} via |
| # Subversion replacement. |
| sbox.simple_rm('A/mu', |
| 'A/mu.sh') |
| sbox.simple_add_symlink('../iota2', 'A/mu') |
| sbox.simple_add_symlink('../iota', 'A/mu.sh') |
| |
| # Ditto, without the Subversion replacement. Failing git-svn test |
| # 'executable file becomes a symlink to bar/zzz (file)'. |
| if svntest.main.is_posix_os(): |
| os.remove(wc('Ax/mu')) |
| os.remove(wc('Ax/mu.sh')) |
| os.symlink('../iota2', wc('Ax/mu')) |
| os.symlink('../iota', wc('Ax/mu.sh')) |
| else: |
| # At least modify the file a bit |
| |
| # ### Somehow this breaks the test when using multiline data? |
| # ### Is that intended behavior? |
| |
| file_write(sbox.ospath('Ax/mu'), 'Link to iota2') |
| file_write(sbox.ospath('Ax/mu.sh'), 'Link to iota') |
| |
| sbox.simple_propset('svn:special', 'X', |
| 'Ax/mu', |
| 'Ax/mu.sh') |
| sbox.simple_propdel('svn:executable', 'Ax/mu.sh') |
| |
| ### TODO Replace a normal {file, exec, dir, dir} with a symlink to |
| ### {dir, dir, file, exec}. And the same symlink-to-normal. |
| |
| expected_status.tweak('A/D/G/pi', |
| 'A/D/G/rho.sh', |
| 'A/D/H/psi.sh', |
| 'A/D/H/chi', |
| 'A/mu', |
| 'A/mu.sh', |
| status='RM') |
| expected_status.tweak('A/B/E/beta.sh', |
| 'A/B/E/alpha', |
| status=' M') |
| expected_status.tweak('Ax/mu', |
| 'Ax/mu.sh', |
| status='MM') |
| expected_status.add({ |
| 'A/B/E/sym-alpha' : Item(status='A ', wc_rev=0), |
| 'A/B/E/sym-beta.sh' : Item(status='A ', wc_rev=0), |
| }) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status) |
| |
| sbox.simple_commit() # r3 |
| sbox.simple_update() |
| |
| expected_status.tweak(status=' ', wc_rev=3) |
| expected_status_r3 = expected_status |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3) |
| |
| # Try updating from HEAD-1 to HEAD. This is currently XFAIL as the |
| # update to HEAD-1 produces a tree conflict. |
| run_svn(None, 'up', '-r2', sbox.wc_dir) |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r2) |
| sbox.simple_update() |
| svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status_r3) |
| |
| |
| @Issue(4102) |
| @SkipUnless(svntest.main.is_posix_os) |
| def externals_as_symlink_targets(sbox): |
| "externals as symlink targets" |
| sbox.build() |
| wc = sbox.ospath |
| |
| # Control: symlink to normal dir and file. |
| os.symlink('E', wc('sym_E')) |
| os.symlink('mu', wc('sym_mu')) |
| |
| # Test case: symlink to external dir and file. |
| sbox.simple_propset("svn:externals", |
| '^/A/B/E ext_E\n' |
| '^/A/mu ext_mu', |
| '') |
| sbox.simple_update() |
| os.symlink('ext_E', wc('sym_ext_E')) |
| os.symlink('ext_mu', wc('sym_ext_mu')) |
| |
| # Adding symlinks to normal items and to a file external is OK. |
| sbox.simple_add('sym_E', 'sym_mu', 'sym_ext_mu') |
| |
| ### Adding a symlink to an external dir failed with |
| ### svn: E200009: Could not add all targets because some targets are |
| ### already versioned |
| sbox.simple_add('sym_ext_E') |
| |
| sbox.simple_commit() |
| |
| #---------------------------------------------------------------------- |
| @XFail() |
| @Issue(4119) |
| def cat_added_symlink(sbox): |
| "cat added symlink" |
| |
| sbox.build(read_only = True) |
| |
| kappa_path = sbox.ospath('kappa') |
| sbox.simple_add_symlink('iota', 'kappa') |
| svntest.actions.run_and_verify_svn("link iota", [], |
| "cat", kappa_path) |
| |
| #---------------------------------------------------------------------- |
| def incoming_symlink_changes(sbox): |
| "verify incoming symlink change behavior" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| sbox.simple_add_symlink('iota', 's-replace') |
| sbox.simple_add_symlink('iota', 's-in-place') |
| sbox.simple_add_symlink('iota', 's-type') |
| sbox.simple_append('s-reverse', 'link iota') |
| sbox.simple_add('s-reverse') |
| sbox.simple_commit() # r2 |
| |
| # Replace s-replace |
| sbox.simple_rm('s-replace') |
| # Note that we don't use 'A/mu' as the length of that matches 'iota', which |
| # would make us depend on timestamp changes for detecting differences. |
| sbox.simple_add_symlink('A/D/G/pi', 's-replace') |
| |
| # Change target of s-in-place |
| if svntest.main.is_posix_os(): |
| os.remove(sbox.ospath('s-in-place')) |
| os.symlink('A/D/G/pi', sbox.ospath('s-in-place')) |
| else: |
| sbox.simple_append('s-in-place', 'link A/D/G/pi', truncate = True) |
| |
| # r3 |
| expected_output = svntest.wc.State(wc_dir, { |
| 's-replace' : Item(verb='Replacing'), |
| 's-in-place' : Item(verb='Sending'), |
| }) |
| svntest.actions.run_and_verify_commit(wc_dir, |
| expected_output, None) |
| |
| # r4 |
| svntest.main.run_svnmucc('propdel', 'svn:special', |
| sbox.repo_url + '/s-type', |
| '-m', 'Turn s-type into a file') |
| |
| # r5 |
| svntest.main.run_svnmucc('propset', 'svn:special', 'X', |
| sbox.repo_url + '/s-reverse', |
| '-m', 'Turn s-reverse into a symlink') |
| |
| # Currently we expect to see 'U'pdates, but we would like to see |
| # replacements |
| expected_output = svntest.wc.State(wc_dir, { |
| 's-reverse' : Item(status=' U'), |
| 's-type' : Item(status=' U'), |
| }) |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 5) |
| expected_status.add({ |
| 's-type' : Item(status=' ', wc_rev='5'), |
| 's-replace' : Item(status=' ', wc_rev='5'), |
| 's-reverse' : Item(status=' ', wc_rev='5'), |
| 's-in-place' : Item(status=' ', wc_rev='5'), |
| }) |
| |
| # Update to HEAD/r5 to fetch the r4 and r5 symlink changes |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| expected_status, |
| check_props=True) |
| |
| # Update back to r2, to prepare some local changes |
| expected_output = svntest.wc.State(wc_dir, { |
| # s-replace is D + A |
| 's-replace' : Item(status='A ', prev_status='D '), |
| 's-in-place' : Item(status='U '), |
| 's-reverse' : Item(status=' U'), |
| 's-type' : Item(status=' U'), |
| }) |
| expected_status.tweak(wc_rev=2) |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| expected_status, |
| [], True, |
| wc_dir, '-r', '2') |
| |
| # Ok, now add a property on all of them to make future symlinkness changes |
| # a tree conflict |
| # ### We should also try this with a 'textual change' |
| sbox.simple_propset('x', 'y', 's-replace', 's-in-place', 's-reverse', 's-type') |
| |
| expected_output = svntest.wc.State(wc_dir, { |
| 's-replace' : Item(prev_status = ' ', prev_treeconflict='C', |
| status=' ', treeconflict='A'), |
| 's-in-place' : Item(status='U '), |
| 's-reverse' : Item(status=' ', treeconflict='C'), |
| 's-type' : Item(status=' ', treeconflict='C'), |
| }) |
| expected_status.tweak(wc_rev=5) |
| expected_status.tweak('s-replace', 's-reverse', 's-type', status='RM', |
| copied='+', treeconflict='C', wc_rev='-') |
| expected_status.tweak('s-in-place', status=' M') |
| |
| svntest.actions.run_and_verify_update(wc_dir, |
| expected_output, |
| None, |
| expected_status, |
| check_props=True) |
| |
| #---------------------------------------------------------------------- |
| @Issue(4479) |
| def multiline_special(sbox): |
| "multiline file with svn:special" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| sbox.simple_append('iota', 'A second line.\n') |
| sbox.simple_commit(); |
| tmp = sbox.get_tempname() |
| svntest.main.file_write(tmp, '*', 'w+') |
| svntest.main.run_svnmucc('propsetf', 'svn:special', tmp, |
| sbox.repo_url + '/iota', |
| '-m', 'set svn:special') |
| |
| sbox.simple_update(revision=1); |
| sbox.simple_update(); |
| |
| expected_disk = svntest.main.greek_state.copy() |
| expected_disk.tweak() |
| expected_disk.tweak('iota', |
| contents="This is the file 'iota'.\nA second line.\n", |
| props={'svn:special' : '*'}) |
| svntest.actions.verify_disk(wc_dir, expected_disk.old_tree(), True) |
| |
| #---------------------------------------------------------------------- |
| @Issue(4482) |
| @XFail(svntest.main.is_posix_os) |
| def multiline_symlink_special(sbox): |
| "multiline link file with svn:special" |
| |
| sbox.build() |
| wc_dir = sbox.wc_dir |
| |
| sbox.simple_append('dodgy-link1', 'link foo\n') |
| sbox.simple_append('dodgy-link2', 'link foo\nbar\n') |
| svntest.main.run_svnmucc('put', sbox.ospath('dodgy-link1'), 'dodgy-link1', |
| 'put', sbox.ospath('dodgy-link2'), 'dodgy-link2', |
| 'propset', 'svn:special', 'X', 'dodgy-link1', |
| 'propset', 'svn:special', 'X', 'dodgy-link2', |
| '-U', sbox.repo_url, |
| '-m', 'Create dodgy symlinks') |
| os.remove(sbox.ospath('dodgy-link1')) |
| os.remove(sbox.ospath('dodgy-link2')) |
| |
| sbox.simple_update(); |
| |
| expected_status = svntest.actions.get_virginal_state(wc_dir, 2) |
| expected_status.add({ |
| 'dodgy-link1' : Item(status=' ', wc_rev=2), |
| 'dodgy-link2' : Item(status=' ', wc_rev=2), |
| }) |
| # XFAIL: Only content before \n used when creating the link but all |
| # content used when detecting modifications, so the pristine working |
| # copy shows up as modified. |
| svntest.actions.run_and_verify_status(wc_dir, expected_status) |
| |
| ######################################################################## |
| # Run the tests |
| |
| |
| # list all tests here, starting with None: |
| test_list = [ None, |
| general_symlink, |
| replace_file_with_symlink, |
| import_export_symlink, |
| copy_tree_with_symlink, |
| replace_symlink_with_file, |
| remove_symlink, |
| merge_symlink_into_file, |
| merge_file_into_symlink, |
| checkout_repo_with_symlinks, |
| diff_symlink_to_dir, |
| checkout_repo_with_unknown_special_type, |
| replace_symlink_with_dir, |
| update_obstructing_symlink, |
| warn_on_reserved_name, |
| propvalue_normalized, |
| unrelated_changed_special_status, |
| symlink_destination_change, |
| merge_foreign_symlink, |
| symlink_to_wc_basic, |
| symlink_to_wc_svnversion, |
| update_symlink, |
| replace_symlinks, |
| externals_as_symlink_targets, |
| cat_added_symlink, |
| incoming_symlink_changes, |
| multiline_special, |
| multiline_symlink_special, |
| ] |
| |
| if __name__ == '__main__': |
| svntest.main.run_tests(test_list) |
| # NOTREACHED |
| |
| |
| ### End of file. |