import sys, os, re
import svntest
from svntest.main import server_has_mergeinfo
Skip = svntest.testcase.Skip
SkipUnless = svntest.testcase.SkipUnless
XFail = svntest.testcase.XFail
Item = svntest.wc.StateItem
def general_symlink(sbox):
"general symlink handling"
sbox.build()
wc_dir = sbox.wc_dir
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'),
})
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
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, None,
wc_dir)
svntest.actions.run_and_verify_svn(None, None, [],
'up', '-r', '1', wc_dir)
if os.path.isfile(newfile_path) or os.path.islink(newfile_path):
raise svntest.Failure
svntest.actions.run_and_verify_svn(None, None, [],
'up', '-r', '2', wc_dir)
new_target = os.readlink(newfile_path)
if new_target != 'linktarget':
raise svntest.Failure
os.remove(newfile_path)
os.symlink('A', newfile_path)
was_cwd = os.getcwd()
os.chdir(wc_dir)
svntest.actions.run_and_verify_svn(None, [ "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, None, wc_dir)
def replace_file_with_symlink(sbox):
"replace a normal file with a special file"
sbox.build()
wc_dir = sbox.wc_dir
iota_path = os.path.join(wc_dir, 'iota')
os.remove(iota_path)
os.symlink('A', iota_path)
was_cwd = os.getcwd()
os.chdir(wc_dir)
svntest.actions.run_and_verify_svn(None, [ "~ iota\n" ], [], 'st')
os.chdir(was_cwd)
exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'ci', '-m',
'log msg',
wc_dir)
regex = 'svn: Commit failed'
for line in stderr_lines:
if re.match(regex, line):
break
else:
raise svntest.Failure
def import_export_symlink(sbox):
"import and export a symlink"
sbox.build()
wc_dir = sbox.wc_dir
new_path = os.path.join(wc_dir, 'new_file')
os.symlink('linktarget', new_path)
url = sbox.repo_url + "/dirA/dirB/new_link"
exit_code, output, errput = svntest.actions.run_and_verify_svn(
'Import a symlink', 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
os.remove(new_path)
svntest.actions.run_and_verify_svn(None, None, [],
'up', wc_dir)
link_path = wc_dir + "/dirA/dirB/new_link"
new_target = os.readlink(link_path)
if new_target != 'linktarget':
raise svntest.Failure
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, None, [],
'export', export_src, export_target)
link_path = os.path.join(export_target, "dirA/dirB/new_link")
new_target = os.readlink(link_path)
if new_target != 'linktarget':
raise svntest.Failure
def copy_tree_with_symlink(sbox):
"'svn cp dir1 dir2' which contains a symlink"
sbox.build()
wc_dir = sbox.wc_dir
newfile_path = os.path.join(wc_dir, 'A', 'D', 'H', 'newfile')
linktarget_path = os.path.join(wc_dir, 'A', 'D', 'H', '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, {
'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, None, wc_dir)
H_path = os.path.join(wc_dir, 'A', 'D', 'H')
H2_path = os.path.join(wc_dir, 'A', 'D', 'H2')
svntest.actions.run_and_verify_svn(None, None, [], 'cp', H_path, H2_path)
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='-'),
'A/D/H2/linktarget' : Item(status=' ', copied='+', wc_rev='-'),
'A/D/H2/newfile' : Item(status=' ', copied='+', wc_rev='-'),
})
svntest.actions.run_and_verify_status(wc_dir, expected_status)
def replace_symlink_with_file(sbox):
"replace a special file with a non-special file"
sbox.build()
wc_dir = sbox.wc_dir
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, None, wc_dir)
os.remove(newfile_path);
svntest.main.file_append(newfile_path, "text of actual file");
was_cwd = os.getcwd()
os.chdir(wc_dir)
svntest.actions.run_and_verify_svn(None, [ "~ newfile\n" ], [], 'st')
os.chdir(was_cwd)
exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'ci', '-m',
'log msg',
wc_dir)
regex = 'svn: 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
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, None, wc_dir)
svntest.actions.run_and_verify_svn(None, None, [], 'rm', newfile_path)
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, None, wc_dir)
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 = os.path.join(wc_dir, 'A', 'D', 'gamma')
gamma_prime_path = os.path.join(wc_dir, 'A', 'Dprime', 'gamma')
svntest.main.run_svn(None,
'copy', d_url, dprime_url, '-m', 'copy')
svntest.main.run_svn(None,
'update', sbox.wc_dir)
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, None,
wc_dir)
linktarget_path = os.path.join(wc_dir, 'linktarget')
svntest.main.file_append(linktarget_path, 'this is just a link target')
os.symlink('linktarget', gamma_prime_path)
svntest.main.run_svn(None, 'add', gamma_prime_path)
expected_output = svntest.wc.State(wc_dir, {
'A/Dprime/gamma' : Item(verb='Adding'),
})
svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
wc_dir)
svntest.main.run_svn(None,
'merge', '-r', '2:4', dprime_url,
os.path.join(wc_dir, 'A', 'D'))
svntest.main.run_svn(None, 'revert', '-R', wc_dir)
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, None,
wc_dir)
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')
svntest.main.run_svn(None,
'copy', d_url, dprime_url, '-m', 'copy')
svntest.main.run_svn(None,
'update', sbox.wc_dir)
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, None,
wc_dir)
linktarget_path = os.path.join(wc_dir, 'linktarget')
svntest.main.file_append(linktarget_path, 'this is just a link target')
os.symlink('linktarget', gamma_prime_path)
svntest.main.run_svn(None, 'add', gamma_prime_path)
expected_output = svntest.wc.State(wc_dir, {
'A/Dprime/gamma' : Item(verb='Adding'),
})
svntest.actions.run_and_verify_commit(wc_dir, expected_output, None, None,
wc_dir)
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, None,
wc_dir)
svntest.main.run_svn(None,
'merge', '-r', '4:5', d_url,
os.path.join(wc_dir, 'A', 'Dprime'))
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'))
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)
def diff_symlink_to_dir(sbox):
"diff a symlink to a directory"
sbox.build(read_only = True)
os.chdir(sbox.wc_dir)
d_path = os.path.join('A', 'D')
link_path = 'link'
os.symlink(d_path, link_path)
svntest.main.run_svn(None, 'add', link_path)
expected_output = [
"Index: link\n",
"===================================================================\n",
"--- link\t(revision 0)\n",
"+++ link\t(revision 0)\n",
"@@ -0,0 +1 @@\n",
"+link " + d_path + "\n",
"\ No newline at end of file\n",
"\n",
"Property changes on: link\n",
"___________________________________________________________________\n",
"Added: svn:special\n",
" + *\n",
"\n" ]
svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
'.')
svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
link_path)
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'))
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')
os.remove(from_path);
os.mkdir(from_path);
was_cwd = os.getcwd()
os.chdir(wc_dir)
svntest.actions.run_and_verify_svn(None, [ "~ from\n" ], [], 'st')
os.chdir(was_cwd)
exit_code, stdout_lines, stderr_lines = svntest.main.run_svn(1, 'ci', '-m',
'log msg',
wc_dir)
if not (stdout_lines == [] or stderr_lines == []):
raise svntest.Failure
def update_obstructing_symlink(sbox):
"symlink obstructs incoming delete"
sbox.build()
wc_dir = sbox.wc_dir
mu_path = os.path.join(wc_dir, 'A', 'mu')
mu_url = sbox.repo_url + '/A/mu'
iota_path = os.path.join(wc_dir, 'iota')
svntest.main.run_svn(None, 'rm', mu_path)
os.symlink(iota_path, mu_path)
svntest.main.run_svn(None, 'rm', mu_url,
'-m', 'log msg')
svntest.main.run_svn(None,
'up', wc_dir)
target = os.readlink(mu_path)
if target != iota_path:
raise svntest.Failure
def warn_on_reserved_name(sbox):
"warn when attempt operation on a reserved name"
sbox.build()
wc_dir = sbox.wc_dir
if os.path.exists(os.path.join(wc_dir, ".svn")):
reserved_path = os.path.join(wc_dir, ".svn")
elif os.path.exists(os.path.join(wc_dir, "_svn")):
reserved_path = os.path.join(wc_dir, "_svn")
else:
return
svntest.actions.run_and_verify_svn(
"Locking a file with a reserved name failed to result in an error",
None,
".*Skipping argument: '.+' ends in a reserved name.*",
'lock', reserved_path)
test_list = [ None,
SkipUnless(general_symlink, svntest.main.is_posix_os),
SkipUnless(replace_file_with_symlink, svntest.main.is_posix_os),
SkipUnless(import_export_symlink, svntest.main.is_posix_os),
SkipUnless(copy_tree_with_symlink, svntest.main.is_posix_os),
SkipUnless(replace_symlink_with_file, svntest.main.is_posix_os),
SkipUnless(remove_symlink, svntest.main.is_posix_os),
SkipUnless(SkipUnless(merge_symlink_into_file,
svntest.main.is_posix_os),
server_has_mergeinfo),
SkipUnless(merge_file_into_symlink, svntest.main.is_posix_os),
checkout_repo_with_symlinks,
XFail(SkipUnless(diff_symlink_to_dir, svntest.main.is_posix_os)),
checkout_repo_with_unknown_special_type,
replace_symlink_with_dir,
SkipUnless(update_obstructing_symlink, svntest.main.is_posix_os),
warn_on_reserved_name,
]
if __name__ == '__main__':
svntest.main.run_tests(test_list)