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