blob: c60dab5ce8c928b57c4f0f6d7d8ec5a207eb0320 [file] [log] [blame]
#!/usr/bin/env python
#
# upgrade_tests.py: test the working copy upgrade process
#
# Subversion is a tool for revision control.
# See http://subversion.apache.org for more information.
#
# ====================================================================
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
######################################################################
#
# These tests exercise the upgrade capabilities of 'svn upgrade' as it
# moves working copies between wc-1 and wc-ng.
#
import os
import re
import shutil
import sys
import tarfile
import tempfile
import logging
import stat
logger = logging.getLogger()
import svntest
from svntest import wc
Item = svntest.wc.StateItem
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
wc_is_too_old_regex = (".*is too old \(format \d+.*\).*")
def get_current_format():
# Get current format from subversion/libsvn_wc/wc.h
format_file = open(os.path.join(os.path.dirname(__file__), "..", "..", "libsvn_wc", "wc.h")).read()
return int(re.search("\n#define SVN_WC__VERSION (\d+)\n", format_file).group(1))
def replace_sbox_with_tarfile(sbox, tar_filename,
dir=None):
try:
svntest.main.safe_rmtree(sbox.wc_dir)
except OSError as e:
pass
if not dir:
dir = tar_filename.split('.')[0]
tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
tar_filename)
t = tarfile.open(tarpath, 'r:bz2')
extract_dir = tempfile.mkdtemp(dir=svntest.main.temp_dir)
for member in t.getmembers():
t.extract(member, extract_dir)
shutil.move(os.path.join(extract_dir, dir), sbox.wc_dir)
def replace_sbox_repo_with_tarfile(sbox, tar_filename, dir=None):
try:
svntest.main.safe_rmtree(sbox.repo_dir)
except OSError as e:
pass
if not dir:
dir = tar_filename.split('.')[0]
tarpath = os.path.join(os.path.dirname(sys.argv[0]), 'upgrade_tests_data',
tar_filename)
t = tarfile.open(tarpath, 'r:bz2')
extract_dir = tempfile.mkdtemp(dir=svntest.main.temp_dir)
for member in t.getmembers():
t.extract(member, extract_dir)
shutil.move(os.path.join(extract_dir, dir), sbox.repo_dir)
def check_format(sbox, expected_format):
dot_svn = svntest.main.get_admin_name()
for root, dirs, files in os.walk(sbox.wc_dir):
db = svntest.sqlite3.connect(os.path.join(root, dot_svn, 'wc.db'))
c = db.cursor()
c.execute('pragma user_version;')
found_format = c.fetchone()[0]
db.close()
if found_format != expected_format:
raise svntest.Failure("found format '%d'; expected '%d'; in wc '%s'" %
(found_format, expected_format, root))
dirs[:] = []
if dot_svn in dirs:
dirs.remove(dot_svn)
def check_pristine(sbox, files):
for file in files:
file_path = sbox.ospath(file)
file_text = open(file_path, 'r').read()
file_pristine = open(svntest.wc.text_base_path(file_path), 'r').read()
if (file_text != file_pristine):
raise svntest.Failure("pristine mismatch for '%s'" % (file))
def check_dav_cache(dir_path, wc_id, expected_dav_caches):
dot_svn = svntest.main.get_admin_name()
db = svntest.sqlite3.connect(os.path.join(dir_path, dot_svn, 'wc.db'))
c = db.cursor()
# Check if python's sqlite can read our db
c.execute('select sqlite_version()')
sqlite_ver = svntest.main.ensure_list(map(int, c.fetchone()[0].split('.')))
# SQLite versions have 3 or 4 number groups
major = sqlite_ver[0]
minor = sqlite_ver[1]
patch = sqlite_ver[2]
if major < 3 or (major == 3 and minor < 6) \
or (major == 3 and minor == 6 and patch < 18):
return # We need a newer SQLite
for local_relpath, expected_dav_cache in expected_dav_caches.items():
# NODES conversion is complete enough that we can use it if it exists
c.execute("""pragma table_info(nodes)""")
if c.fetchone():
c.execute('select dav_cache from nodes ' +
'where wc_id=? and local_relpath=? and op_depth = 0',
(wc_id, local_relpath))
row = c.fetchone()
else:
c.execute('select dav_cache from base_node ' +
'where wc_id=? and local_relpath=?',
(wc_id, local_relpath))
row = c.fetchone()
if row is None:
raise svntest.Failure("no dav cache for '%s'" % (local_relpath))
dav_cache = str(row[0])
if dav_cache != str(expected_dav_cache):
raise svntest.Failure(
"wrong dav cache for '%s'\n Found: '%s'\n Expected: '%s'" %
(local_relpath, dav_cache, expected_dav_cache))
db.close()
# Very simple working copy property diff handler for single line textual properties
# Should probably be moved to svntest/actions.py after some major refactoring.
def simple_property_verify(dir_path, expected_props):
# Shows all items in dict1 that are not also in dict2
def diff_props(dict1, dict2, name, match):
equal = True;
for key in dict1:
node = dict1[key]
node2 = dict2.get(key, None)
if node2:
for prop in node:
v1 = node[prop]
v2 = node2.get(prop, None)
if not v2:
logger.warn('\'%s\' property on \'%s\' not found in %s',
prop, key, name)
equal = False
if match and v1 != v2:
logger.warn('Expected \'%s\' on \'%s\' to be \'%s\', but found \'%s\'',
prop, key, v1, v2)
equal = False
else:
logger.warn('\'%s\': %s not found in %s', key, dict1[key], name)
equal = False
return equal
exit_code, output, errput = svntest.main.run_svn(None, 'proplist', '-R',
'-v', dir_path)
actual_props = {}
target = None
name = None
for i in output:
if i.startswith('Properties on '):
target = i[15+len(dir_path)+1:-3].replace(os.path.sep, '/')
elif not i.startswith(' '):
name = i.strip()
else:
v = actual_props.get(target, {})
v[name] = i.strip()
actual_props[target] = v
v1 = diff_props(expected_props, actual_props, 'actual', True)
v2 = diff_props(actual_props, expected_props, 'expected', False)
if not v1 or not v2:
logger.warn('Actual properties: %s', actual_props)
raise svntest.Failure("Properties unequal")
def simple_checksum_verify(expected_checksums):
for path, checksum in expected_checksums:
exit_code, output, errput = svntest.main.run_svn(None, 'info', path)
if exit_code:
raise svntest.Failure()
if checksum:
if not svntest.verify.RegexOutput('Checksum: ' + checksum,
match_all=False).matches(output):
raise svntest.Failure("did not get expected checksum " + checksum)
if not checksum:
if svntest.verify.RegexOutput('Checksum: ',
match_all=False).matches(output):
raise svntest.Failure("unexpected checksum")
def run_and_verify_status_no_server(wc_dir, expected_status):
"same as svntest.actions.run_and_verify_status(), but without '-u'"
exit_code, output, errput = svntest.main.run_svn(None, 'st', '-q', '-v',
wc_dir)
actual = svntest.tree.build_tree_from_status(output)
try:
svntest.tree.compare_trees("status", actual, expected_status.old_tree())
except svntest.tree.SVNTreeError:
svntest.verify.display_trees(None, 'STATUS OUTPUT TREE',
expected_status.old_tree(), actual)
logger.warn("ACTUAL STATUS TREE:")
svntest.tree.dump_tree_script(actual, wc_dir + os.sep)
raise
def basic_upgrade(sbox):
"basic upgrade behavior"
replace_sbox_with_tarfile(sbox, 'basic_upgrade.tar.bz2')
# Attempt to use the working copy, this should give an error
svntest.actions.run_and_verify_svn(None, wc_is_too_old_regex,
'info', sbox.wc_dir)
# Upgrade on something anywhere within a versioned subdir gives a
# 'not a working copy root' error. Upgrade on something without any
# versioned parent gives a 'not a working copy' error.
# Both cases use the same error code.
not_wc = ".*(E155007|E155019).*%s'.*not a working copy.*"
os.mkdir(sbox.ospath('X'))
svntest.actions.run_and_verify_svn(None, not_wc % 'X',
'upgrade', sbox.ospath('X'))
# Upgrade on a non-existent subdir within an old WC gives a
# 'not a working copy' error.
svntest.actions.run_and_verify_svn(None, not_wc % 'Y',
'upgrade', sbox.ospath('Y'))
# Upgrade on a versioned file within an old WC gives a
# 'not a working copy' error.
svntest.actions.run_and_verify_svn(None, not_wc % 'mu',
'upgrade', sbox.ospath('A/mu'))
# Upgrade on a versioned dir within an old WC gives a
# 'not a working copy' error.
svntest.actions.run_and_verify_svn(None, not_wc % 'A',
'upgrade', sbox.ospath('A'))
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
# Now check the contents of the working copy
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
check_pristine(sbox, ['iota', 'A/mu'])
def upgrade_with_externals(sbox):
"upgrade with externals"
# Create wc from tarfile, uses the same structure of the wc as the tests
# in externals_tests.py.
replace_sbox_with_tarfile(sbox, 'upgrade_with_externals.tar.bz2')
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
'info', sbox.wc_dir)
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
check_pristine(sbox, ['iota', 'A/mu',
'A/D/x/lambda', 'A/D/x/E/alpha'])
def upgrade_1_5_body(sbox, subcommand):
replace_sbox_with_tarfile(sbox, 'upgrade_1_5.tar.bz2')
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
subcommand, sbox.wc_dir)
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# Check the format of the working copy
check_format(sbox, get_current_format())
# Now check the contents of the working copy
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
check_pristine(sbox, ['iota', 'A/mu'])
def upgrade_1_5(sbox):
"test upgrading from a 1.5-era working copy"
return upgrade_1_5_body(sbox, 'info')
def update_1_5(sbox):
"test updating a 1.5-era working copy"
# The 'update' printed:
# Skipped 'svn-test-work\working_copies\upgrade_tests-3'
# Summary of conflicts:
# Skipped paths: 1
return upgrade_1_5_body(sbox, 'update')
def logs_left_1_5(sbox):
"test upgrading from a 1.5-era wc with stale logs"
replace_sbox_with_tarfile(sbox, 'logs_left_1_5.tar.bz2')
# Try to upgrade, this should give an error
expected_stderr = (".*Cannot upgrade with existing logs; .*")
svntest.actions.run_and_verify_svn(None, expected_stderr,
'upgrade', sbox.wc_dir)
def upgrade_wcprops(sbox):
"test upgrading a working copy with wcprops"
replace_sbox_with_tarfile(sbox, 'upgrade_wcprops.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# Make sure that .svn/all-wcprops has disappeared
dot_svn = svntest.main.get_admin_name()
if os.path.exists(os.path.join(sbox.wc_dir, dot_svn, 'all-wcprops')):
raise svntest.Failure("all-wcprops file still exists")
# Just for kicks, let's see if the wcprops are what we'd expect them
# to be. (This could be smarter.)
expected_dav_caches = {
'' :
b'(svn:wc:ra_dav:version-url 41 /svn-test-work/local_tmp/repos/!svn/ver/1)',
'iota' :
b'(svn:wc:ra_dav:version-url 46 /svn-test-work/local_tmp/repos/!svn/ver/1/iota)',
}
check_dav_cache(sbox.wc_dir, 1, expected_dav_caches)
# Poor mans relocate to fix up an 1.0 (xml style) working copy to refer to a
# valid repository, so svn upgrade can do its work on it
def xml_entries_relocate(path, from_url, to_url):
adm_name = svntest.main.get_admin_name()
entries = os.path.join(path, adm_name, 'entries')
txt = open(entries).read().replace('url="' + from_url, 'url="' + to_url)
os.chmod(entries, svntest.main.S_ALL_RWX)
with open(entries, 'w') as f:
f.write(txt)
for dirent in os.listdir(path):
item_path = os.path.join(path, dirent)
if dirent == svntest.main.get_admin_name():
continue
if os.path.isdir(os.path.join(item_path, adm_name)):
xml_entries_relocate(item_path, from_url, to_url)
# Poor mans relocate to fix up an working copy to refer to a
# valid repository, so svn upgrade can do its work on it
def simple_entries_replace(path, from_url, to_url):
adm_name = svntest.main.get_admin_name()
entries = os.path.join(path, adm_name, 'entries')
txt = open(entries).read().replace(from_url, to_url)
os.chmod(entries, svntest.main.S_ALL_RWX)
with open(entries, 'wb') as f:
f.write(txt.encode())
for dirent in os.listdir(path):
item_path = os.path.join(path, dirent)
if dirent == svntest.main.get_admin_name():
continue
if os.path.isdir(os.path.join(item_path, adm_name)):
simple_entries_replace(item_path, from_url, to_url)
def basic_upgrade_1_0(sbox):
"test upgrading a working copy created with 1.0.0"
sbox.build(create_wc = False)
replace_sbox_with_tarfile(sbox, 'upgrade_1_0.tar.bz2')
url = sbox.repo_url
# This is non-canonical by the rules of svn_uri_canonicalize, it gets
# written into the entries file and upgrade has to canonicalize.
non_canonical_url = url[:-1] + '%%%02x' % ord(url[-1])
xml_entries_relocate(sbox.wc_dir, 'file:///1.0.0/repos', non_canonical_url)
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
'info', sbox.wc_dir)
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# And the separate working copy below COPIED or check_format() fails
svntest.actions.run_and_verify_svn(None, [],
'upgrade',
os.path.join(sbox.wc_dir, 'COPIED', 'G'))
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
# Now check the contents of the working copy
# #### This working copy is not just a basic tree,
# fix with the right data once we get here
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev=7),
'B' : Item(status=' ', wc_rev='7'),
'B/mu' : Item(status=' ', wc_rev='7'),
'B/D' : Item(status=' ', wc_rev='7'),
'B/D/H' : Item(status=' ', wc_rev='7'),
'B/D/H/psi' : Item(status=' ', wc_rev='7'),
'B/D/H/omega' : Item(status=' ', wc_rev='7'),
'B/D/H/zeta' : Item(status='MM', wc_rev='7'),
'B/D/H/chi' : Item(status=' ', wc_rev='7'),
'B/D/gamma' : Item(status=' ', wc_rev='9'),
'B/D/G' : Item(status=' ', wc_rev='7'),
'B/D/G/tau' : Item(status=' ', wc_rev='7'),
'B/D/G/rho' : Item(status=' ', wc_rev='7'),
'B/D/G/pi' : Item(status=' ', wc_rev='7'),
'B/B' : Item(status=' ', wc_rev='7'),
'B/B/lambda' : Item(status=' ', wc_rev='7'),
'MKDIR' : Item(status='A ', wc_rev='0'),
'MKDIR/MKDIR' : Item(status='A ', wc_rev='0'),
'A' : Item(status=' ', wc_rev='7'),
'A/B' : Item(status=' ', wc_rev='7'),
'A/B/lambda' : Item(status=' ', wc_rev='7'),
'A/D' : Item(status=' ', wc_rev='7'),
'A/D/G' : Item(status=' ', wc_rev='7'),
'A/D/G/rho' : Item(status=' ', wc_rev='7'),
'A/D/G/pi' : Item(status=' ', wc_rev='7'),
'A/D/G/tau' : Item(status=' ', wc_rev='7'),
'A/D/H' : Item(status=' ', wc_rev='7'),
'A/D/H/psi' : Item(status=' ', wc_rev='7'),
'A/D/H/omega' : Item(status=' ', wc_rev='7'),
'A/D/H/zeta' : Item(status=' ', wc_rev='7'),
'A/D/H/chi' : Item(status=' ', wc_rev='7'),
'A/D/gamma' : Item(status=' ', wc_rev='7'),
'A/mu' : Item(status=' ', wc_rev='7'),
'iota' : Item(status=' ', wc_rev='7'),
'COPIED' : Item(status=' ', wc_rev='10'),
'DELETED' : Item(status='D ', wc_rev='10'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
expected_infos = [ {
'Node Kind': 'directory',
'Schedule': 'normal',
'Revision': '7',
'Last Changed Author' : 'Bert',
'Last Changed Rev' : '7'
} ]
svntest.actions.run_and_verify_info(expected_infos, sbox.wc_dir)
expected_infos = [ {
'Node Kind': 'directory',
'Schedule': 'delete',
'Revision': '10',
'Last Changed Author' : 'Bert',
'Last Changed Rev' : '10'
} ]
svntest.actions.run_and_verify_info(expected_infos,
os.path.join(sbox.wc_dir, 'DELETED'))
check_pristine(sbox, ['iota', 'A/mu', 'A/D/H/zeta'])
# Helper function for the x3 tests.
def do_x3_upgrade(sbox, expected_error=[]):
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
'info', sbox.wc_dir)
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, expected_error,
'upgrade', sbox.wc_dir)
if expected_error != []:
return
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
# Now check the contents of the working copy
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='2'),
'A' : Item(status=' ', wc_rev='2'),
'A/D' : Item(status=' ', wc_rev='2'),
'A/D/H' : Item(status=' ', wc_rev='2'),
'A/D/H/omega' : Item(status=' ', wc_rev='2'),
'A/D/H/psi' : Item(status='D ', wc_rev='2'),
'A/D/H/new' : Item(status='A ', copied='+', wc_rev='-'),
'A/D/H/chi' : Item(status='R ', copied='+', wc_rev='-'),
'A/D/gamma' : Item(status='D ', wc_rev='2'),
'A/D/G' : Item(status=' ', wc_rev='2'),
'A/B_new' : Item(status='A ', copied='+', wc_rev='-'),
'A/B_new/B' : Item(status='A ', copied='+', wc_rev='-'),
'A/B_new/B/E' : Item(status=' M', copied='+', wc_rev='-'),
'A/B_new/B/E/alpha' : Item(status=' ', copied='+', wc_rev='-'),
'A/B_new/B/E/beta' : Item(status='R ', copied='+', wc_rev='-'),
'A/B_new/B/new' : Item(status='A ', copied='+', wc_rev='-'),
'A/B_new/B/lambda' : Item(status='R ', copied='+', wc_rev='-'),
'A/B_new/B/F' : Item(status=' ', copied='+', wc_rev='-'),
'A/B_new/E' : Item(status=' M', copied='+', wc_rev='-'),
'A/B_new/E/alpha' : Item(status=' M', copied='+', wc_rev='-'),
'A/B_new/E/beta' : Item(status='RM', copied='+', wc_rev='-'),
'A/B_new/lambda' : Item(status='R ', copied='+', wc_rev='-'),
'A/B_new/new' : Item(status='A ', copied='+', wc_rev='-'),
'A/B_new/F' : Item(status=' ', copied='+', wc_rev='-'),
'A/B' : Item(status=' ', wc_rev='2'),
'A/B/E' : Item(status=' ', wc_rev='2'),
'A/B/E/beta' : Item(status='RM', copied='+', wc_rev='-'),
'A/B/E/alpha' : Item(status=' M', wc_rev='2'),
'A/B/F' : Item(status=' ', wc_rev='2'),
'A/B/lambda' : Item(status='R ', copied='+', wc_rev='-'),
'A/B/new' : Item(status='A ', copied='+', wc_rev='-'),
'A/G_new' : Item(status='A ', copied='+', wc_rev='-'),
'A/G_new/rho' : Item(status='R ', copied='+', wc_rev='-'),
'iota' : Item(status=' ', wc_rev='2'),
'A_new' : Item(status='A ', wc_rev='0'),
'A_new/alpha' : Item(status='A ', copied='+', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
simple_property_verify(sbox.wc_dir, {
'A/B_new/E/beta' : {'x3' : '3x',
'svn:eol-style': 'native'},
'A/B/E/beta' : {'s' : 't',
'svn:eol-style': 'native'},
'A/B_new/B/E/alpha' : {'svn:eol-style': 'native'},
'A/B/E/alpha' : {'q': 'r',
'svn:eol-style': 'native'},
'A_new/alpha' : {'svn:eol-style': 'native'},
'A/B_new/B/new' : {'svn:eol-style': 'native'},
'A/B_new/E/alpha' : {'svn:eol-style': 'native',
'u': 'v'},
'A/B_new/B/E' : {'q': 'r'},
'A/B_new/lambda' : {'svn:eol-style': 'native'},
'A/B_new/E' : {'x3': '3x'},
'A/B_new/new' : {'svn:eol-style': 'native'},
'A/B/lambda' : {'svn:eol-style': 'native'},
'A/B_new/B/E/beta' : {'svn:eol-style': 'native'},
'A/B_new/B/lambda' : {'svn:eol-style': 'native'},
'A/B/new' : {'svn:eol-style': 'native'},
'A/G_new/rho' : {'svn:eol-style': 'native'}
})
svntest.actions.run_and_verify_svn('Reverted.*', [],
'revert', '-R', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='2'),
'A' : Item(status=' ', wc_rev='2'),
'A/D' : Item(status=' ', wc_rev='2'),
'A/D/H' : Item(status=' ', wc_rev='2'),
'A/D/H/omega' : Item(status=' ', wc_rev='2'),
'A/D/H/psi' : Item(status=' ', wc_rev='2'),
'A/D/H/chi' : Item(status=' ', wc_rev='2'),
'A/D/gamma' : Item(status=' ', wc_rev='2'),
'A/D/G' : Item(status=' ', wc_rev='2'),
'A/B' : Item(status=' ', wc_rev='2'),
'A/B/F' : Item(status=' ', wc_rev='2'),
'A/B/E' : Item(status=' ', wc_rev='2'),
'A/B/E/beta' : Item(status=' ', wc_rev='2'),
'A/B/E/alpha' : Item(status=' ', wc_rev='2'),
'A/B/lambda' : Item(status=' ', wc_rev='2'),
'iota' : Item(status=' ', wc_rev='2'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
simple_property_verify(sbox.wc_dir, {
'A/B/E/beta' : {'svn:eol-style': 'native'},
# 'A/B/lambda' : {'svn:eol-style': 'native'},
'A/B/E/alpha' : {'svn:eol-style': 'native'}
})
@Issue(2530)
def x3_1_4_0(sbox):
"3x same wc upgrade 1.4.0 test"
replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.0.tar.bz2', dir='wc-1.4.0')
do_x3_upgrade(sbox, expected_error='.*E155016: The properties of.*are in an '
'indeterminate state and cannot be upgraded. See issue #2530.')
@Issue(3811)
def x3_1_4_6(sbox):
"3x same wc upgrade 1.4.6 test"
replace_sbox_with_tarfile(sbox, 'wc-3x-1.4.6.tar.bz2', dir='wc-1.4.6')
do_x3_upgrade(sbox)
@Issue(3811)
def x3_1_6_12(sbox):
"3x same wc upgrade 1.6.12 test"
replace_sbox_with_tarfile(sbox, 'wc-3x-1.6.12.tar.bz2', dir='wc-1.6.12')
do_x3_upgrade(sbox)
def missing_dirs(sbox):
"missing directories and obstructing files"
# tarball wc looks like:
# svn co URL wc
# svn cp wc/A/B wc/A/B_new
# rm -rf wc/A/B/E wc/A/D wc/A/B_new/E wc/A/B_new/F
# touch wc/A/D wc/A/B_new/F
replace_sbox_with_tarfile(sbox, 'missing-dirs.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='1'),
'A' : Item(status=' ', wc_rev='1'),
'A/mu' : Item(status=' ', wc_rev='1'),
'A/C' : Item(status=' ', wc_rev='1'),
'A/D' : Item(status='! ', wc_rev='1'),
'A/B' : Item(status=' ', wc_rev='1'),
'A/B/F' : Item(status=' ', wc_rev='1'),
'A/B/E' : Item(status='! ', wc_rev='1'),
'A/B/lambda' : Item(status=' ', wc_rev='1'),
'iota' : Item(status=' ', wc_rev='1'),
'A/B_new' : Item(status='A ', wc_rev='-', copied='+'),
'A/B_new/E' : Item(status='! ', wc_rev='-'),
'A/B_new/F' : Item(status='! ', wc_rev='-'),
'A/B_new/lambda' : Item(status=' ', wc_rev='-', copied='+'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
def missing_dirs2(sbox):
"missing directories and obstructing dirs"
replace_sbox_with_tarfile(sbox, 'missing-dirs.tar.bz2')
os.remove(sbox.ospath('A/D'))
os.remove(sbox.ospath('A/B_new/F'))
os.mkdir(sbox.ospath('A/D'))
os.mkdir(sbox.ospath('A/B_new/F'))
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='1'),
'A' : Item(status=' ', wc_rev='1'),
'A/mu' : Item(status=' ', wc_rev='1'),
'A/C' : Item(status=' ', wc_rev='1'),
'A/D' : Item(status='! ', wc_rev='1'),
'A/B' : Item(status=' ', wc_rev='1'),
'A/B/F' : Item(status=' ', wc_rev='1'),
'A/B/E' : Item(status='! ', wc_rev='1'),
'A/B/lambda' : Item(status=' ', wc_rev='1'),
'iota' : Item(status=' ', wc_rev='1'),
'A/B_new' : Item(status='A ', wc_rev='-', copied='+'),
'A/B_new/E' : Item(status='! ', wc_rev='-'),
'A/B_new/F' : Item(status='! ', wc_rev='-'),
'A/B_new/lambda' : Item(status=' ', wc_rev='-', copied='+'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3808)
def delete_and_keep_local(sbox):
"check status delete and delete --keep-local"
replace_sbox_with_tarfile(sbox, 'wc-delete.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='0'),
'Normal' : Item(status=' ', wc_rev='1'),
'Deleted-Keep-Local': Item(status='D ', wc_rev='1'),
'Deleted' : Item(status='D ', wc_rev='1'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
# Deleted-Keep-Local should still exist after the upgrade
if not os.path.exists(os.path.join(sbox.wc_dir, 'Deleted-Keep-Local')):
raise svntest.Failure('wc/Deleted-Keep-Local should exist')
# Deleted should be removed after the upgrade as it was
# schedule delete and doesn't contain unversioned changes.
if os.path.exists(os.path.join(sbox.wc_dir, 'Deleted')):
raise svntest.Failure('wc/Deleted should not exist')
def dirs_only_upgrade(sbox):
"upgrade a wc without files"
replace_sbox_with_tarfile(sbox, 'dirs-only.tar.bz2')
expected_output = ["Upgraded '%s'\n" % (sbox.ospath('').rstrip(os.path.sep)),
"Upgraded '%s'\n" % (sbox.ospath('A'))]
svntest.actions.run_and_verify_svn(expected_output, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir, {
'' : Item(status=' ', wc_rev='1'),
'A' : Item(status=' ', wc_rev='1'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3898)
def delete_in_copy_upgrade(sbox):
"upgrade a delete within a copy"
wc_dir = sbox.wc_dir
replace_sbox_with_tarfile(sbox, 'delete-in-copy.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
expected_status.add({
'A/B-copied' : Item(status='A ', copied='+', wc_rev='-'),
'A/B-copied/lambda' : Item(status=' ', copied='+', wc_rev='-'),
'A/B-copied/E' : Item(status='D ', copied='+', wc_rev='-'),
'A/B-copied/E/alpha' : Item(status='D ', copied='+', wc_rev='-'),
'A/B-copied/E/beta' : Item(status='D ', copied='+', wc_rev='-'),
'A/B-copied/F' : Item(status=' ', copied='+', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
svntest.actions.run_and_verify_svn('Reverted.*', [], 'revert', '-R',
sbox.ospath('A/B-copied/E'))
expected_status.tweak('A/B-copied/E',
'A/B-copied/E/alpha',
'A/B-copied/E/beta',
status=' ')
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
simple_checksum_verify([[sbox.ospath('A/B-copied/E/alpha'),
'b347d1da69df9a6a70433ceeaa0d46c8483e8c03']])
def replaced_files(sbox):
"upgrade with base and working replaced files"
wc_dir = sbox.wc_dir
replace_sbox_with_tarfile(sbox, 'replaced-files.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# A is a checked-out dir containing A/f and A/g, then
# svn cp wc/A wc/B
# svn rm wc/A/f wc/B/f
# svn cp wc/A/g wc/A/f # A/f replaced by copied A/g
# svn cp wc/A/g wc/B/f # B/f replaced by copied A/g (working-only)
# svn rm wc/A/g wc/B/g
# touch wc/A/g wc/B/g
# svn add wc/A/g wc/B/g # A/g replaced, B/g replaced (working-only)
# svn ps pX vX wc/A/g
# svn ps pY vY wc/B/g
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='5'),
'A' : Item(status=' ', wc_rev='5'),
'A/f' : Item(status='R ', wc_rev='-', copied='+'),
'A/g' : Item(status='RM', wc_rev='5'),
'B' : Item(status='A ', wc_rev='-', copied='+'),
'B/f' : Item(status='R ', wc_rev='-', copied='+'),
'B/g' : Item(status='RM', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
simple_property_verify(sbox.wc_dir, {
'A/f' : {'pAg' : 'vAg' },
'A/g' : {'pX' : 'vX' },
'B/f' : {'pAg' : 'vAg' },
'B/g' : {'pY' : 'vY' },
})
simple_checksum_verify([
[sbox.ospath('A/f'), '395dfb603d8a4e0348d0b082803f2b7426c76eb9'],
[sbox.ospath('A/g'), None],
[sbox.ospath('B/f'), '395dfb603d8a4e0348d0b082803f2b7426c76eb9'],
[sbox.ospath('B/g'), None]])
svntest.actions.run_and_verify_svn('Reverted.*', [], 'revert',
sbox.ospath('A/f'), sbox.ospath('B/f'),
sbox.ospath('A/g'), sbox.ospath('B/g'))
simple_property_verify(sbox.wc_dir, {
'A/f' : {'pAf' : 'vAf' },
'A/g' : {'pAg' : 'vAg' },
'B/f' : {'pAf' : 'vAf' },
'B/g' : {'pAg' : 'vAg' },
})
simple_checksum_verify([
[sbox.ospath('A/f'), '958eb2d755df2d9e0de6f7b835aec16b64d83f6f'],
[sbox.ospath('A/g'), '395dfb603d8a4e0348d0b082803f2b7426c76eb9'],
[sbox.ospath('B/f'), '958eb2d755df2d9e0de6f7b835aec16b64d83f6f'],
[sbox.ospath('B/g'), '395dfb603d8a4e0348d0b082803f2b7426c76eb9']])
def upgrade_with_scheduled_change(sbox):
"upgrade 1.6.x wc with a scheduled change"
replace_sbox_with_tarfile(sbox, 'upgrade_with_scheduled_change.tar.bz2')
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
expected_status.add({
'A/scheduled_file_1' : Item(status='A ', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3777)
def tree_replace1(sbox):
"upgrade 1.6 with tree replaced"
replace_sbox_with_tarfile(sbox, 'tree-replace1.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' M', wc_rev=17),
'B' : Item(status='R ', copied='+', wc_rev='-'),
'B/f' : Item(status=' ', copied='+', wc_rev='-'),
'B/g' : Item(status='D ', wc_rev=17),
'B/h' : Item(status=' ', copied='+', wc_rev='-'),
'B/C' : Item(status=' ', copied='+', wc_rev='-'),
'B/C/f' : Item(status=' ', copied='+', wc_rev='-'),
'B/D' : Item(status='D ', wc_rev=17),
'B/D/f' : Item(status='D ', wc_rev=17),
'B/E' : Item(status=' ', copied='+', wc_rev='-'),
'B/E/f' : Item(status=' ', copied='+', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3777)
def tree_replace2(sbox):
"upgrade 1.6 with tree replaced (2)"
replace_sbox_with_tarfile(sbox, 'tree-replace2.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' M', wc_rev=12),
'B' : Item(status='R ', copied='+', wc_rev='-'),
'B/f' : Item(status='D ', wc_rev=12),
'B/D' : Item(status='D ', wc_rev=12),
'B/g' : Item(status=' ', copied='+', wc_rev='-'),
'B/E' : Item(status=' ', copied='+', wc_rev='-'),
'C' : Item(status='R ', copied='+', wc_rev='-'),
'C/f' : Item(status=' ', copied='+', wc_rev='-'),
'C/D' : Item(status=' ', copied='+', wc_rev='-'),
'C/g' : Item(status='D ', wc_rev=12),
'C/E' : Item(status='D ', wc_rev=12),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3901)
def depth_exclude(sbox):
"upgrade 1.6.x wc that has depth=exclude"
replace_sbox_with_tarfile(sbox, 'depth_exclude.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='1'),
'A' : Item(status=' ', wc_rev='1'),
'X' : Item(status='A ', copied='+', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3901)
def depth_exclude_2(sbox):
"1.6.x wc that has depth=exclude inside a delete"
replace_sbox_with_tarfile(sbox, 'depth_exclude_2.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='1'),
'A' : Item(status='D ', wc_rev='1'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3916)
def add_add_del_del_tc(sbox):
"wc with add-add and del-del tree conflicts"
replace_sbox_with_tarfile(sbox, 'add_add_del_del_tc.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='4'),
'A' : Item(status=' ', wc_rev='4'),
'A/B' : Item(status='A ', treeconflict='C', copied='+', wc_rev='-'),
'X' : Item(status=' ', wc_rev='3'),
'X/Y' : Item(status='! ', treeconflict='C')
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3916)
def add_add_x2(sbox):
"wc with 2 tree conflicts in same entry"
replace_sbox_with_tarfile(sbox, 'add_add_x2.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev='3'),
'A' : Item(status=' ', wc_rev='3'),
'A/X' : Item(status='A ', treeconflict='C', copied='+', wc_rev='-'),
'A/Y' : Item(status='A ', treeconflict='C', copied='+', wc_rev='-'),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(3940)
def upgrade_with_missing_subdir(sbox):
"test upgrading a working copy with missing subdir"
sbox.build(create_wc = False)
replace_sbox_with_tarfile(sbox, 'basic_upgrade.tar.bz2')
simple_entries_replace(sbox.wc_dir,
'file:///Users/Hyrum/dev/test/greek-1.6.repo',
sbox.repo_url)
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'cafefeed-babe-face-dead-beeff00dfade')
url = sbox.repo_url
wc_dir = sbox.wc_dir
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
'info', sbox.wc_dir)
# Now remove a subdirectory
svntest.main.safe_rmtree(sbox.ospath('A/B'))
# Now upgrade the working copy and expect a missing subdir
expected_output = svntest.verify.UnorderedOutput([
"Upgraded '%s'\n" % sbox.wc_dir,
"Upgraded '%s'\n" % sbox.ospath('A'),
"Skipped '%s'\n" % sbox.ospath('A/B'),
"Upgraded '%s'\n" % sbox.ospath('A/C'),
"Upgraded '%s'\n" % sbox.ospath('A/D'),
"Upgraded '%s'\n" % sbox.ospath('A/D/G'),
"Upgraded '%s'\n" % sbox.ospath('A/D/H'),
])
svntest.actions.run_and_verify_svn(expected_output, [],
'upgrade', sbox.wc_dir)
# And now perform an update. (This used to fail with an assertion)
expected_output = svntest.wc.State(wc_dir, {
'A/B' : Item(verb='Restored'),
'A/B/E' : Item(status='A '),
'A/B/E/alpha' : Item(status='A '),
'A/B/E/beta' : Item(status='A '),
'A/B/lambda' : Item(status='A '),
'A/B/F' : Item(status='A '),
})
expected_disk = svntest.main.greek_state.copy()
expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
# Do the update and check the results in three ways.
svntest.actions.run_and_verify_update(wc_dir,
expected_output,
expected_disk,
expected_status)
@Issue(3994)
def upgrade_locked(sbox):
"upgrade working copy with locked files"
replace_sbox_with_tarfile(sbox, 'upgrade_locked.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' ', wc_rev=1),
'A' : Item(status='D ', wc_rev=2),
'A/third' : Item(status='D ', writelocked='K', wc_rev=2),
'other' : Item(status='D ', writelocked='K', wc_rev=4),
'iota' : Item(status=' ', writelocked='K', wc_rev=3),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
@Issue(4015)
def upgrade_file_externals(sbox):
"upgrade with file externals"
sbox.build()
replace_sbox_with_tarfile(sbox, 'upgrade_file_externals.tar.bz2')
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'07146bbd-0b64-4aaf-ab70-cd76a0df2d41')
expected_output = svntest.verify.RegexOutput(b'r2 committed.*')
svntest.actions.run_and_verify_svnmucc(expected_output, [],
'-m', 'r2',
'propset', 'svn:externals',
'^/A/B/E EX\n^/A/mu muX',
sbox.repo_url + '/A/B/F')
expected_output = svntest.verify.RegexOutput(b'r3 committed.*')
svntest.actions.run_and_verify_svnmucc(expected_output, [],
'-m', 'r3',
'propset', 'svn:externals',
'^/A/B/F FX\n^/A/B/lambda lambdaX',
sbox.repo_url + '/A/C')
expected_output = svntest.verify.RegexOutput(b'r4 committed.*')
svntest.actions.run_and_verify_svnmucc(expected_output, [],
'-m', 'r4',
'propset', 'pname1', 'pvalue1',
sbox.repo_url + '/A/mu',
'propset', 'pname2', 'pvalue2',
sbox.repo_url + '/A/B/lambda',
'propset', 'pname3', 'pvalue3',
sbox.repo_url + '/A/B/E/alpha')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
svntest.actions.run_and_verify_svn(None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url,
sbox.wc_dir)
expected_output = svntest.wc.State(sbox.wc_dir, {
'A/mu' : Item(status=' U'),
'A/B/lambda' : Item(status=' U'),
'A/B/E/alpha' : Item(status=' U'),
'A/C/FX/EX/alpha' : Item(status=' U'),
'A/C/FX/muX' : Item(status=' U'),
'A/C/lambdaX' : Item(status=' U'),
'A/B/F/EX/alpha' : Item(status=' U'),
'A/B/F/muX' : Item(status=' U'),
})
svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
None, None)
### simple_property_verify only sees last line of multi-line
### property values such as svn:externals
simple_property_verify(sbox.wc_dir, {
'A/mu' : {'pname1' : 'pvalue1' },
'A/B/lambda' : {'pname2' : 'pvalue2' },
'A/B/E/alpha' : {'pname3' : 'pvalue3' },
'A/B/F' : {'svn:externals' : '^/A/mu muX'},
'A/C' : {'svn:externals' : '^/A/B/lambda lambdaX'},
'A/B/F/muX' : {'pname1' : 'pvalue1' },
'A/C/lambdaX' : {'pname2' : 'pvalue2' },
})
simple_property_verify(sbox.ospath('A/C/FX'), {
'' : {'svn:externals' : '^/A/mu muX'},
'muX' : {'pname1' : 'pvalue1' },
})
simple_property_verify(sbox.ospath('A/C/FX/EX'), {
'alpha' : {'pname3' : 'pvalue3' },
})
@Issue(4035)
def upgrade_missing_replaced(sbox):
"upgrade with missing replaced dir"
sbox.build(create_wc=False)
replace_sbox_with_tarfile(sbox, 'upgrade_missing_replaced.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'd7130b12-92f6-45c9-9217-b9f0472c3fab')
svntest.actions.run_and_verify_svn(None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url,
sbox.wc_dir)
expected_output = svntest.wc.State(sbox.wc_dir, {
'A/B/E' : Item(status=' ', treeconflict='C',
prev_verb='Restored'),
'A/B/E/alpha' : Item(status=' ', treeconflict='A'),
'A/B/E/beta' : Item(status=' ', treeconflict='A'),
})
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
expected_status.tweak('A/B/E', status='! ', treeconflict='C', wc_rev='-',
entry_status='R ', entry_rev='1')
expected_status.tweak('A/B/E/alpha', 'A/B/E/beta', status='D ')
# This upgrade installs an INCOMPLETE node in WORKING for E, which makes the
# database technically invalid... but we did that for 1.7 and nobody noticed.
# Pass the old status tree to avoid testing via entries-dump
# as fetching the entries crashes on the invalid db state.
svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
None, expected_status)
svntest.actions.run_and_verify_svn('Reverted.*', [], 'revert', '-R',
sbox.wc_dir)
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
# And verify that the state is now valid in both the entries an status world.
svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
@Issue(4033)
def upgrade_not_present_replaced(sbox):
"upgrade with not-present replaced nodes"
sbox.build(create_wc=False)
replace_sbox_with_tarfile(sbox, 'upgrade_not_present_replaced.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'd7130b12-92f6-45c9-9217-b9f0472c3fab')
svntest.actions.run_and_verify_svn(None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url,
sbox.wc_dir)
expected_output = svntest.wc.State(sbox.wc_dir, {
'A/B/E' : Item(status=' ', treeconflict='C'),
'A/B/E/beta' : Item(status=' ', treeconflict='A'),
'A/B/E/alpha' : Item(status=' ', treeconflict='A'),
'A/B/lambda' : Item(status=' ', treeconflict='C'),
})
expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
expected_status.tweak('A/B/E', status='R ', treeconflict='C'),
expected_status.tweak('A/B/E/beta', status='D '),
expected_status.tweak('A/B/E/alpha', status='D '),
expected_status.tweak('A/B/lambda', status='R ', treeconflict='C'),
svntest.actions.run_and_verify_update(sbox.wc_dir, expected_output,
None, expected_status)
@Issue(4307)
def upgrade_from_1_7_conflict(sbox):
"upgrade from 1.7 WC with conflict (format 29)"
sbox.build(create_wc=False)
replace_sbox_with_tarfile(sbox, 'upgrade_from_1_7_wc.tar.bz2')
# The working copy contains a text conflict, and upgrading such
# a working copy used to cause a pointless 'upgrade required' error.
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
def do_iprops_upgrade(nonrootfile, rootfile, sbox):
wc_dir = sbox.wc_dir
replace_sbox_with_tarfile(sbox, nonrootfile)
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
svntest.actions.run_and_verify_svn(None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url, wc_dir)
expected_output = []
expected_disk = svntest.wc.State('', {
'E' : Item(),
'E/alpha' : Item(contents="This is the file 'alpha'.\n"),
'E/beta' : Item(contents="This is the file 'beta'.\n"),
'F' : Item(),
'lambda' : Item(contents="This is the file 'lambda'.\n"),
})
expected_status = svntest.wc.State(sbox.wc_dir, {
'' : Item(),
'E' : Item(switched='S'),
'E/alpha' : Item(),
'E/beta' : Item(),
'F' : Item(),
'lambda' : Item(),
})
expected_status.tweak(status=' ', wc_rev=2)
# No inherited props after upgrade until an update
expected_iprops = {}
expected_explicit_props = {}
svntest.actions.run_and_verify_inherited_prop_xml(
wc_dir, expected_iprops, expected_explicit_props)
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('E'), expected_iprops, expected_explicit_props)
# Update populates the inherited props
svntest.actions.run_and_verify_update(wc_dir,
expected_output,
expected_disk,
expected_status)
expected_iprops = {sbox.repo_url : {'p' : 'v'},
sbox.repo_url + '/A' : {'pA' : 'vA'}}
svntest.actions.run_and_verify_inherited_prop_xml(
wc_dir, expected_iprops, expected_explicit_props)
expected_iprops = {sbox.repo_url : {'p' : 'v'},
sbox.repo_url + '/X' : {'pX' : 'vX'}}
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('E'), expected_iprops, expected_explicit_props)
# Now try with a repository root working copy
replace_sbox_with_tarfile(sbox, rootfile)
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
svntest.actions.run_and_verify_svn(None, [], 'relocate',
'file:///tmp/repo', sbox.repo_url, wc_dir)
# Unswitched inherited props available after upgrade
expected_iprops = {wc_dir : {'p' : 'v'},
sbox.ospath('A') : {'pA' : 'vA'}}
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('A/B'), expected_iprops, expected_explicit_props)
# Switched inherited props not populated until update after upgrade
expected_iprops = {}
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('A/B/E'), expected_iprops, expected_explicit_props)
expected_disk = svntest.wc.State('', {
'A' : Item(),
'A/B' : Item(),
'A/B/E' : Item(),
})
expected_status = svntest.wc.State(sbox.wc_dir, {
'' : Item(),
'A' : Item(),
'A/B' : Item(),
'A/B/E' : Item(switched='S'),
})
expected_status.tweak(status=' ', wc_rev=2)
svntest.actions.run_and_verify_update(wc_dir,
expected_output,
expected_disk,
expected_status)
expected_iprops = {wc_dir : {'p' : 'v'},
sbox.ospath('A') : {'pA' : 'vA'}}
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('A/B'), expected_iprops, expected_explicit_props)
expected_iprops = {sbox.repo_url : {'p' : 'v'},
sbox.repo_url + '/X' : {'pX' : 'vX'}}
expected_explicit_props = {}
svntest.actions.run_and_verify_inherited_prop_xml(
sbox.ospath('A/B/E'), expected_iprops, expected_explicit_props)
def iprops_upgrade(sbox):
"inherited properties after upgrade from 1.7"
sbox.build()
sbox.simple_copy('A', 'X')
sbox.simple_propset('p', 'v', '')
sbox.simple_propset('pA', 'vA', 'A')
sbox.simple_propset('pX', 'vX', 'X')
sbox.simple_commit()
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'8f4d0ebe-2ebf-4f62-ad11-804fd88c2382')
do_iprops_upgrade('iprops_upgrade_nonroot.tar.bz2',
'iprops_upgrade_root.tar.bz2',
sbox)
def iprops_upgrade1_6(sbox):
"inherited properties after upgrade from 1.6"
sbox.build()
sbox.simple_copy('A', 'X')
sbox.simple_propset('p', 'v', '')
sbox.simple_propset('pA', 'vA', 'A')
sbox.simple_propset('pX', 'vX', 'X')
sbox.simple_commit()
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'8f4d0ebe-2ebf-4f62-ad11-804fd88c2382')
do_iprops_upgrade('iprops_upgrade_nonroot1_6.tar.bz2',
'iprops_upgrade_root1_6.tar.bz2',
sbox)
def changelist_upgrade_1_6(sbox):
"upgrade from 1.6 with changelist"
sbox.build(create_wc = False)
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'aa4c97bd-2e1a-4e55-a1e5-3db22cff2673')
replace_sbox_with_tarfile(sbox, 'changelist_upgrade_1_6.tar.bz2')
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
exit_code, output, errput = svntest.main.run_svn(None, 'info', sbox.wc_dir,
'--depth', 'infinity',
'--changelist', 'foo')
paths = [x for x in output if x[:6] == 'Path: ']
expected_paths = ['Path: %s\n' % sbox.ospath('A/D/gamma')]
if paths != expected_paths:
raise svntest.Failure("changelist not matched")
def upgrade_1_7_dir_external(sbox):
"upgrade from 1.7 with dir external"
sbox.build(create_wc = False)
replace_sbox_with_tarfile(sbox, 'upgrade_1_7_dir_external.tar.bz2')
# This fails for 'make check EXCLUSIVE_WC_LOCKS=1' giving an error:
# svn: warning: W200033: sqlite[S5]: database is locked
svntest.actions.run_and_verify_svn(None, [], 'upgrade', sbox.wc_dir)
@SkipUnless(svntest.wc.python_sqlite_can_read_wc)
def auto_analyze(sbox):
"""automatic SQLite ANALYZE"""
sbox.build(create_wc = False)
replace_sbox_with_tarfile(sbox, 'wc-without-stat1.tar.bz2')
svntest.main.run_svnadmin('setuuid', sbox.repo_dir,
'52ec7e4b-e5f0-451d-829f-f05d5571b4ab')
# Don't use svn to do relocate as that will add the table.
svntest.wc.sqlite_exec(sbox.wc_dir,
"update repository "
"set root ='" + sbox.repo_url + "'")
val = svntest.wc.sqlite_stmt(sbox.wc_dir,
"select 1 from sqlite_master "
"where name = 'sqlite_stat1'")
if val != []:
raise svntest.Failure("initial state failed")
# Make working copy read-only (but not wc_dir itself as
# svntest.main.chmod_tree will not reset it.)
for path, subdirs, files in os.walk(sbox.wc_dir):
for d in subdirs:
os.chmod(os.path.join(path, d), svntest.main.S_ALL_RX)
for f in files:
os.chmod(os.path.join(path, f), svntest.main.S_ALL_READ)
state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
svntest.actions.run_and_verify_status(sbox.wc_dir, state)
svntest.main.chmod_tree(sbox.wc_dir, svntest.main.S_ALL_RW,
stat.S_IWGRP | stat.S_IWOTH)
state = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
svntest.actions.run_and_verify_status(sbox.wc_dir, state)
val = svntest.wc.sqlite_stmt(sbox.wc_dir,
"select 1 from sqlite_master "
"where name = 'sqlite_stat1'")
if val != [(1,)]:
raise svntest.Failure("analyze failed")
def upgrade_1_0_with_externals(sbox):
"test upgrading 1.0.0 working copy with externals"
sbox.build(create_wc = False)
replace_sbox_with_tarfile(sbox, 'upgrade_1_0_with_externals.tar.bz2')
url = sbox.repo_url
# This is non-canonical by the rules of svn_uri_canonicalize, it gets
# written into the entries file and upgrade has to canonicalize.
non_canonical_url = url[:-1] + '%%%02x' % ord(url[-1])
xml_entries_relocate(sbox.wc_dir, 'file:///1.0.0/repos', non_canonical_url)
externals_propval = 'exdir_G ' + sbox.repo_url + '/A/D/G' + '\n'
adm_name = svntest.main.get_admin_name()
dir_props_file = os.path.join(sbox.wc_dir, adm_name, 'dir-props')
svntest.main.file_write(dir_props_file,
('K 13\n'
'svn:externals\n'
'V %d\n' % len(externals_propval))
+ externals_propval + '\nEND\n', 'wb')
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
svntest.actions.run_and_verify_svn(None, expected_stderr,
'info', sbox.wc_dir)
# Now upgrade the working copy
svntest.actions.run_and_verify_svn(None, [],
'upgrade', sbox.wc_dir)
# And the separate working copy below COPIED or check_format() fails
svntest.actions.run_and_verify_svn(None, [],
'upgrade',
os.path.join(sbox.wc_dir, 'COPIED', 'G'))
# Actually check the format number of the upgraded working copy
check_format(sbox, get_current_format())
# Now check the contents of the working copy
# #### This working copy is not just a basic tree,
# fix with the right data once we get here
expected_status = svntest.wc.State(sbox.wc_dir,
{
'' : Item(status=' M', wc_rev=7),
'B' : Item(status=' ', wc_rev='7'),
'B/mu' : Item(status=' ', wc_rev='7'),
'B/D' : Item(status=' ', wc_rev='7'),
'B/D/H' : Item(status=' ', wc_rev='7'),
'B/D/H/psi' : Item(status=' ', wc_rev='7'),
'B/D/H/omega' : Item(status=' ', wc_rev='7'),
'B/D/H/zeta' : Item(status='MM', wc_rev='7'),
'B/D/H/chi' : Item(status=' ', wc_rev='7'),
'B/D/gamma' : Item(status=' ', wc_rev='9'),
'B/D/G' : Item(status=' ', wc_rev='7'),
'B/D/G/tau' : Item(status=' ', wc_rev='7'),
'B/D/G/rho' : Item(status=' ', wc_rev='7'),
'B/D/G/pi' : Item(status=' ', wc_rev='7'),
'B/B' : Item(status=' ', wc_rev='7'),
'B/B/lambda' : Item(status=' ', wc_rev='7'),
'MKDIR' : Item(status='A ', wc_rev='0'),
'MKDIR/MKDIR' : Item(status='A ', wc_rev='0'),
'A' : Item(status=' ', wc_rev='7'),
'A/B' : Item(status=' ', wc_rev='7'),
'A/B/lambda' : Item(status=' ', wc_rev='7'),
'A/D' : Item(status=' ', wc_rev='7'),
'A/D/G' : Item(status=' ', wc_rev='7'),
'A/D/G/rho' : Item(status=' ', wc_rev='7'),
'A/D/G/pi' : Item(status=' ', wc_rev='7'),
'A/D/G/tau' : Item(status=' ', wc_rev='7'),
'A/D/H' : Item(status=' ', wc_rev='7'),
'A/D/H/psi' : Item(status=' ', wc_rev='7'),
'A/D/H/omega' : Item(status=' ', wc_rev='7'),
'A/D/H/zeta' : Item(status=' ', wc_rev='7'),
'A/D/H/chi' : Item(status=' ', wc_rev='7'),
'A/D/gamma' : Item(status=' ', wc_rev='7'),
'A/mu' : Item(status=' ', wc_rev='7'),
'iota' : Item(status=' ', wc_rev='7'),
'COPIED' : Item(status=' ', wc_rev='10'),
'DELETED' : Item(status='D ', wc_rev='10'),
'exdir_G' : Item(status='X '),
})
run_and_verify_status_no_server(sbox.wc_dir, expected_status)
########################################################################
# Run the tests
# prop states
#
# .base simple checkout
# .base, .revert delete, copy-here
# .working add, propset
# .base, .working checkout, propset
# .base, .revert, .working delete, copy-here, propset
# .revert, .working delete, add, propset
# .revert delete, add
#
# 1.3.x (f4)
# 1.4.0 (f8, buggy)
# 1.4.6 (f8, fixed)
# list all tests here, starting with None:
test_list = [ None,
basic_upgrade,
upgrade_with_externals,
upgrade_1_5,
update_1_5,
logs_left_1_5,
upgrade_wcprops,
basic_upgrade_1_0,
# Upgrading from 1.4.0-1.4.5 with specific states fails
# See issue #2530
x3_1_4_0,
x3_1_4_6,
x3_1_6_12,
missing_dirs,
missing_dirs2,
delete_and_keep_local,
dirs_only_upgrade,
delete_in_copy_upgrade,
replaced_files,
upgrade_with_scheduled_change,
tree_replace1,
tree_replace2,
depth_exclude,
depth_exclude_2,
add_add_del_del_tc,
add_add_x2,
upgrade_with_missing_subdir,
upgrade_locked,
upgrade_file_externals,
upgrade_missing_replaced,
upgrade_not_present_replaced,
upgrade_from_1_7_conflict,
iprops_upgrade,
iprops_upgrade1_6,
changelist_upgrade_1_6,
upgrade_1_7_dir_external,
auto_analyze,
upgrade_1_0_with_externals,
]
if __name__ == '__main__':
svntest.main.run_tests(test_list)
# NOTREACHED