I might be able to get help from Sussman on this, but maybe not.
So any other neon or serf experts, please chime in :).
I found a bug in ra -neon and -serf that can't be shown with the
client library, but only when using the ra commit editor to build
up a relatively complex transaction. Presumably you can
demonstrate this problem with mucc, but I have not tried.
The problem is basically:
1. Delete /trunk/dir1/dir2/
=> commit r13
2. In one transaction:
a. Copy /trunk@13 to /branch
b. Create /branch/dir1/dir2
=> commit r14
3. In one transaction:
a. Delete /branch
b. Copy /trunk@13 to /branch
c. Create /branch/dir1/dir2
=> ERROR: .../branch/dir1/dir2 already exists
Of course, /branch/dir1/dir2 does *not* exist in the transaction
I'm building in step 3! Some or all of Neon, serf, and
mod-dav-svn are looking at branch/dir1/dir2 in the revision root
rather than the transaction root.
There's a bit more to it, and serf is slightly different than
neon, but that's basically it. See the test script for details.
Plop it into subversion/bindings/swig/python/tests and run it.
Comment out both REOPS_URL settings to see it run over local.
0 trunk2% python subversion/bindings/swig/python/tests/bug.py
*** testing over file
D trunk/dir1/dir2/
*** Committed r13
branch 0
A branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r14
branch 1
R branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r15
branch 2
R branch/ (from trunk@13)
A branch/dir1/dir2
*** Committed r16
branch 3
R branch/ (from trunk@13)
A branch/dir1/dir2
*** Committed r17
.
----------------------------------------------------------------------
Ran 1 test in 0.760s
OK
0 trunk2% python subversion/bindings/swig/python/tests/bug.py
*** testing over svn+ssh
D trunk/dir1/dir2/
*** Committed r13
branch 0
A branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r14
branch 1
R branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r15
branch 2
R branch/ (from trunk@13)
A branch/dir1/dir2
*** Committed r16
branch 3
R branch/ (from trunk@13)
A branch/dir1/dir2
*** Committed r17
.
----------------------------------------------------------------------
Ran 1 test in 0.902s
OK
0 trunk2% python subversion/bindings/swig/python/tests/bug.py
*** testing over http
D trunk/dir1/dir2/
*** Committed r13
branch 0
A branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r14
branch 1
R branch/ (from trunk@13)
A branch/dir1/dir2/
*** Committed r15
branch 2
R branch/ (from trunk@13)
A branch/dir1/dir2
E
======================================================================
ERROR: test_bug (__main__.SubversionRepositoryAccessTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "subversion/bindings/swig/python/tests/bug.py", line 152, in test_bug
driver_cb)
File "/usr/local/google/home/epg/work/svn/trunk2/subversion/bindings/swig/python/libsvn/delta.py", line 514, in svn_delta_path_driver
return apply(_delta.svn_delta_path_driver, args)
File "subversion/bindings/swig/python/tests/bug.py", line 149, in driver_cb
editor.close_file(editor.add_file(path, parent, None, -1),
File "/usr/local/google/home/epg/work/svn/trunk2/subversion/bindings/swig/python/libsvn/delta.py", line 441, in add_file
return svn_delta_editor_invoke_add_file(self, *args)
File "/usr/local/google/home/epg/work/svn/trunk2/subversion/bindings/swig/python/libsvn/delta.py", line 651, in svn_delta_editor_invoke_add_file
return apply(_delta.svn_delta_editor_invoke_add_file, args)
SubversionException: ("File '/svn-test-work/repositories/basic_tests-1/branch/dir1/dir2' already exists", 175005)
import unittest, os, setup_path
from svn import core, repos, fs, delta, client, ra
from StringIO import StringIO
# Use repository path where davautochec.sh-started httpd looks.
import trac.versioncontrol.tests.svn_fs
trac.versioncontrol.tests.svn_fs.REPOS_PATH = os.path.abspath(os.path.dirname(__file__) + '/../../../../tests/cmdline/svn-test-work/repositories/basic_tests-1')
# works over ra -local and -svn
trac.versioncontrol.tests.svn_fs.REPOS_URL = 'svn+ssh://localhost + trac.versioncontrol.tests.svn_fs.REPOS_PATH
# not over ra-neon
trac.versioncontrol.tests.svn_fs.REPOS_URL = 'http://localhost:7818/svn-test-work/repositories/basic_tests-1'
from trac.versioncontrol.tests.svn_fs import SubversionRepositoryTestSetup, \
REPOS_PATH, REPOS_URL
class Callbacks:
open_tmp_file = None
progress_func = None
cancel_func = None
get_wc_prop = None
push_wc_prop = None
def __init__(self):
self.auth_baton = core.svn_auth_open([
client.get_simple_provider(),
client.get_username_provider(),
])
core.svn_auth_set_parameter(self.auth_baton,
core.SVN_AUTH_PARAM_DEFAULT_USERNAME,
'jrandom')
core.svn_auth_set_parameter(self.auth_baton,
core.SVN_AUTH_PARAM_DEFAULT_PASSWORD,
'rayjandom')
class SubversionRepositoryAccessTestCase(unittest.TestCase):
def setUp(self):
SubversionRepositoryTestSetup().setUp()
ra.initialize()
# Open repository directly for cross-checking
self.repos = repos.open(REPOS_PATH)
self.fs = repos.fs(self.repos)
self.callbacks = Callbacks()
svn_config_dir = os.path.expanduser('~/.subversion')
self.svn_config = core.svn_config_get_config(svn_config_dir)
print '*** testing over', REPOS_URL[:REPOS_URL.find(':')]
self.ra_ctx = ra.open2(REPOS_URL, self.callbacks, self.svn_config, None)
def test_bug(self):
head = fs.youngest_rev(self.fs)
info = [None]
def commit_cb(commit_info, pool):
info[0] = commit_info
revprops = {"svn:log": "foobar"}
print 'D trunk/dir1/dir2/'
(editor, edit_baton) = ra.get_commit_editor3(self.ra_ctx, revprops,
commit_cb, None, False)
def driver_cb(parent, path, pool):
editor.delete_entry(path, head, parent, pool)
delta.path_driver(editor, edit_baton, head, ['trunk/dir1/dir2'], driver_cb)
editor.close_edit(edit_baton)
self.assertEqual(info[0].revision, head + 1)
head = info[0].revision
print '*** Committed r' + str(head)
# Prepare for branch operations.
branch_code = 'A'
copyfrom_rev = head
# Four operations: branch 0 and 1 add a directory as
# branch/dir1/dir2, followed by branch 2 and 3 adding a file as
# branch/dir1/dir2. All work over svn, but branch 2 fails over
# neon.
# Comment out branch 0 and 1 (leaving only the file operations),
# and then it's branch 3 that fails. Basically, if
# branch/dir1/dir2 exists at all (file or dir), then adding
# branch/dir1/dir2 as a file fails; adding dir2 as a directory is
# no problem at all.
# serf has the problem with directories as well as files, as it
# fails even branch 1.
print 'branch 0'
print '%c branch/ (from trunk@%d)' % (branch_code, copyfrom_rev)
print 'A branch/dir1/dir2/'
editor, edit_baton = ra.get_commit_editor3(self.ra_ctx, revprops,
commit_cb, None, False)
def driver_cb(parent, path, pool):
if path == 'branch':
if branch_code == 'R':
editor.delete_entry(path, head, parent, pool)
return editor.add_directory(path, parent,
'/'.join([REPOS_URL, 'trunk']),
copyfrom_rev)
elif path == 'branch/dir1/dir2':
return editor.add_directory(path, parent, None, -1)
delta.path_driver(editor, edit_baton, head, ['branch', 'branch/dir1/dir2'],
driver_cb)
editor.close_edit(edit_baton)
self.assertEqual(info[0].revision, head + 1)
head = info[0].revision
print '*** Committed r' + str(head)
branch_code = 'R'
print 'branch 1'
print '%c branch/ (from trunk@%d)' % (branch_code, copyfrom_rev)
print 'A branch/dir1/dir2/'
editor, edit_baton = ra.get_commit_editor3(self.ra_ctx, revprops,
commit_cb, None, False)
def driver_cb(parent, path, pool):
if path == 'branch':
if branch_code == 'R':
editor.delete_entry(path, head, parent, pool)
return editor.add_directory(path, parent,
'/'.join([REPOS_URL, 'trunk']),
copyfrom_rev)
elif path == 'branch/dir1/dir2':
return editor.add_directory(path, parent, None, -1)
delta.path_driver(editor, edit_baton, head, ['branch', 'branch/dir1/dir2'],
driver_cb)
editor.close_edit(edit_baton)
self.assertEqual(info[0].revision, head + 1)
head = info[0].revision
print '*** Committed r' + str(head)
branch_code = 'R'
print 'branch 2'
print '%c branch/ (from trunk@%d)' % (branch_code, copyfrom_rev)
print 'A branch/dir1/dir2'
editor, edit_baton = ra.get_commit_editor3(self.ra_ctx, revprops,
commit_cb, None, False)
def driver_cb(parent, path, pool):
if path == 'branch':
if branch_code == 'R':
editor.delete_entry(path, head, parent, pool)
return editor.add_directory(path, parent,
'/'.join([REPOS_URL, 'trunk']),
copyfrom_rev)
elif path == 'branch/dir1/dir2':
editor.close_file(editor.add_file(path, parent, None, -1),
None, pool)
delta.path_driver(editor, edit_baton, head, ['branch', 'branch/dir1/dir2'],
driver_cb)
editor.close_edit(edit_baton)
self.assertEqual(info[0].revision, head + 1)
head = info[0].revision
print '*** Committed r' + str(head)
branch_code = 'R'
print 'branch 3'
print '%c branch/ (from trunk@%d)' % (branch_code, copyfrom_rev)
print 'A branch/dir1/dir2'
editor, edit_baton = ra.get_commit_editor3(self.ra_ctx, revprops,
commit_cb, None, False)
def driver_cb(parent, path, pool):
if path == 'branch':
if branch_code == 'R':
editor.delete_entry(path, head, parent, pool)
return editor.add_directory(path, parent,
'/'.join([REPOS_URL, 'trunk']),
copyfrom_rev)
elif path == 'branch/dir1/dir2':
editor.close_file(editor.add_file(path, parent, None, -1),
None, pool)
delta.path_driver(editor, edit_baton, head, ['branch', 'branch/dir1/dir2'],
driver_cb)
editor.close_edit(edit_baton)
self.assertEqual(info[0].revision, head + 1)
head = info[0].revision
print '*** Committed r' + str(head)
branch_code = 'R'
def suite():
return unittest.makeSuite(SubversionRepositoryAccessTestCase, 'test')
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Sep 12 23:54:42 2007