[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: tree conflicts: segfault in merge_dir_opened

From: Neels Janosch Hofmeyr <neels_at_elego.de>
Date: Sat, 16 Aug 2008 04:10:20 +0200

My mail client seriously messed this one up.
I'll have to retype all of it... >:(

Neels Janosch Hofmeyr wrote:
> # Run the tests
> =20
> @@ -2232,7 +2496,7 @@
> switch_urls_with_spaces,
> switch_to_dir_with_peg_rev2,
> switch_to_root,
> - tree_conflicts_in_switched_files,
> + tree_conflicts_on_switch,
> ]
> =20
> if __name__ =3D=3D '__main__':
> Index: subversion/tests/cmdline/update_tests.py
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- subversion/tests/cmdline/update_tests.py (revision 32499)
> +++ subversion/tests/cmdline/update_tests.py (working copy)
> @@ -3862,50 +3862,251 @@
> =20
> #----------------------------------------------------------------------
> =20
> -def tree_conflicts_in_updated_files(sbox):
> - "tree conflicts in updated files"
> +# Detect tree conflicts among files and directories,
> +# edited or deleted in a deep directory structure.
> +#
> +# See use cases 1-3 in notes/tree-conflicts/use-cases.txt for background=
> =2E
> +#
> +def tree_conflicts_on_update(sbox):
> + "tree conflicts on update (tc use cases 1 to 3)"
> =20
> - # Detect simple tree conflicts among files edited or deleted in a sing=
> le
> - # directory.
> + # Each case is constructed and then appended to this table, which
> + # is initially empty:
> + greater_scheme =3D [];
> =20
> - # See use cases 1-3 in notes/tree-conflicts/use-cases.txt for backgrou=
> nd.
> - # Note that we do not try to track renames. The only difference from
> - # the behavior of Subversion 1.4 and 1.5 is the conflicted status of t=
> he
> - # parent directory.
> + # convenience definitions
> + leaf_edit =3D svntest.actions.deep_trees_leaf_edit
> + tree_del =3D svntest.actions.deep_trees_tree_del
> + leaf_del =3D svntest.actions.deep_trees_leaf_del
> =20
> - sbox.build()
> - wc_dir =3D sbox.wc_dir
> + state_after_leaf_edit =3D svntest.actions.deep_trees_after_leaf_edit
> + state_after_leaf_del =3D svntest.actions.deep_trees_after_leaf_del
> + state_after_tree_del =3D svntest.actions.deep_trees_after_tree_del
> =20
> - # Set up tree conflicts in wc 2
> - wc_dir_2 =3D svntest.actions.set_up_tree_conflicts(sbox)
> + DeepTreesTestCase =3D svntest.actions.DeepTreesTestCase
> =20
> - # Update in wc 2
> - expected_output =3D wc.State(wc_dir_2, {
> - 'A/D/G' : Item(status=3D'C '),
> - 'A/D/G/pi' : Item(status=3D'U '),
> - 'A/D/G/rho' : Item(status=3D'D '),
> - 'A/D/G/tau' : Item(status=3D'D '),
> +
> + # use case 1, as in notes/tree-conflicts/use-cases.txt
> + # 1.1) local tree delete, incoming leaf edit
> +
> + expected_output =3D wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'U '),
> + 'D' : Item(status=3D'C '),
> + 'D/D1/delta' : Item(status=3D'A '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'C '),
> + 'DF/D1/beta' : Item(status=3D'U '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'C '),
> + 'DD/D1/D2/epsilon' : Item(status=3D'A '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'C '),
> + 'DDF/D1/D2' : Item(status=3D'C '),
> + 'DDF/D1/D2/gamma' : Item(status=3D'U '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'C '),
> + 'DDD/D1/D2' : Item(status=3D'C '),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D'A '),
> })
> =20
> - expected_disk =3D svntest.main.greek_state.copy()
> - expected_disk.tweak('A/D/G/pi',
> - contents=3D"This is the file 'pi'.\nEdited in wc 1=
> =2E\n")
> - expected_disk.tweak('A/D/G/rho',
> - contents=3D"This is the file 'rho'.\nEdited in wc =
> 2.\n")
> - expected_disk.remove('A/D/G/tau')
> + expected_disk =3D state_after_leaf_edit
> =20
> - expected_status =3D svntest.actions.get_virginal_state(wc_dir_2, 2)
> - expected_status.tweak('A/D/G', status=3D'C ')
> - expected_status.tweak('A/D/G/pi', status=3D'D ')
> - expected_status.remove('A/D/G/rho',
> - 'A/D/G/tau')
> + expected_status =3D wc.State('', {
> + '' : Item(status=3D' ', wc_rev=3D'3'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'D/D1/delta' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DD/D1/D2/epsilon' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D' ', wc_rev=3D'3'),
> + })
> =20
> - svntest.actions.run_and_verify_update(wc_dir_2,
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_leaf_=
> edit",
> + tree_del,
> + leaf_edit,
> expected_output,
> expected_disk,
> - expected_status)
> + expected_status) ]
> =20
> =20
> + # 1.2) local tree delete, incoming leaf delete
> +
> + expected_output =3D wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'C '),
> + 'DF/D1/beta' : Item(status=3D'D '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'C '),
> + 'DD/D1/D2' : Item(status=3D'D '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'C '),
> + 'DDF/D1/D2' : Item(status=3D'C '),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'C '),
> + 'DDD/D1/D2' : Item(status=3D'C '),
> + 'DDD/D1/D2/D3' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D state_after_leaf_del
> +
> + expected_status =3D wc.State('', {
> + '' : Item(status=3D' ', wc_rev=3D'3'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'3'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'3'),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_leaf_=
> del",
> + tree_del,
> + leaf_del,
> + expected_output,
> + expected_disk,
> + expected_status) ]
> +
> +
> + # use case 2, as in notes/tree-conflicts/use-cases.txt
> + # 2.1) local leaf edit, incoming tree delete
> +
> + expected_output =3D wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + 'D/D1' : Item(status=3D'D '),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DDF/D1' : Item(status=3D'D '),
> + 'DDD/D1' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D state_after_leaf_edit
> +
> + expected_status =3D wc.State('', {
> + '' : Item(status=3D' ', wc_rev=3D'3'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'D' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'3'),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_leaf_edit_incoming_tree=
> _del",
> + leaf_edit,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status) ]
> +
> +
> + # 2.2) local leaf delete, incoming tree delete
> +
> + expected_output =3D wc.State('', {
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + 'DD' : Item(),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DF' : Item(),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(),
> + 'DDD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(),
> + 'DDF/D1' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D state_after_tree_del
> +
> + expected_status =3D wc.State('', {
> + '' : Item(status=3D' ', wc_rev=3D'3'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'3'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'3'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'3'),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_leaf_del_incoming_tree_=
> del",
> + leaf_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status) ]
> +
> +
> + # use case 3, as in notes/tree-conflicts/use-cases.txt
> + # local tree delete, incoming tree delete
> +
> + expected_output =3D wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D state_after_tree_del
> +
> + expected_status =3D wc.State('', {
> + '' : Item(status=3D' ', wc_rev=3D'3'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'3'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'3'),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_tree_=
> del",
> + tree_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status) ]
> +
> +
> + # now run the whole bunch of them.
> + svntest.actions.deep_trees_run_tests_scheme_for_update(sbox, greater_s=
> cheme)
> +
> +
> +
> #######################################################################
> # Run the tests
> =20
> @@ -3959,7 +4160,7 @@
> update_accept_conflicts,
> eof_in_interactive_conflict_resolver,
> update_uuid_changed,
> - tree_conflicts_in_updated_files,
> + tree_conflicts_on_update,
> ]
> =20
> if __name__ =3D=3D '__main__':
> Index: subversion/tests/cmdline/svntest/tree.py
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- subversion/tests/cmdline/svntest/tree.py (revision 32499)
> +++ subversion/tests/cmdline/svntest/tree.py (working copy)
> @@ -207,6 +207,40 @@
> else:
> print >> stream, " Children: None (node is probably a file)"
> =20
> + def print_script(self, stream =3D sys.stdout, strip =3D 0):
> + "Python-script-print the meta data for this node."
> + =20
> + path =3D self.path
> + if len(path) > len(root_node_name) and path.startswith(root_node_nam=
> e):
> + path =3D path[(len(root_node_name)+1):]
> + if len(path) > strip:
> + path =3D path[strip:]
> +
> + line =3D "%-20s: Item(" % ("'%s'" % path)
> + comma =3D False
> +
> + mime_type =3D self.props.get("svn:mime-type")
> + if not mime_type or mime_type.startswith("text/"):
> + if self.children is None and not self.contents is None:
> + line +=3D "contents=3D\"\"\"%s\"\"\"" % self.contents
> + comma =3D True
> +
> + for name in self.atts:
> + if comma:
> + line +=3D ", "
> + line +=3D "%s=3D'%s'" % (name, self.atts[name])
> + comma =3D True
> +
> +# for name in self.props:
> +# if comma:
> +# line +=3D ", "
> +# line +=3D "%s=3D'%s'" % (name, self.props[name])
> +# comma =3D True
> +
> + line +=3D "),"
> + print >> stream, line
> +
> +
> def __str__(self):
> import StringIO
> s =3D StringIO.StringIO()
> @@ -555,7 +589,7 @@
> =20
> # Visually show a tree's structure
> =20
> -def dump_tree(n,indent=3D""):
> +def dump_tree(n,indent=3D"",verbose=3DFalse):
> "Print out a nice representation of the tree's structure."
> =20
> # Code partially stolen from Dave Beazley
> @@ -569,17 +603,41 @@
> else:
> print "%s%s" % (indent, n.name)
> =20
> + if verbose:
> + n.pprint()
> +
> indent =3D indent.replace("-", " ")
> indent =3D indent.replace("+", " ")
> for i in range(len(tmp_children)):
> c =3D tmp_children[i]
> if i =3D=3D len(tmp_children
> )-1:
> - dump_tree(c,indent + " +-- ")
> + dump_tree(c,indent + " +-- ",verbose)
> else:
> - dump_tree(c,indent + " |-- ")
> + dump_tree(c,indent + " |-- ",verbose)
> =20
> +def dump_tree_script(n, strip=3D0):
> =20
> + for i in range(len(tmp_children)):
> + c =3D tmp_children[i]
> + if i =3D=3D len(tmp_children
> + )-1:
> + dump_tree_script(c, strip=3Dstrip)
> + else:
> + dump_tree_script(c, strip=3Dstrip)
> +
> +
> ###################################################################
> ###################################################################
> # PARSERS that return trees made of SVNTreeNodes....
> Index: subversion/tests/cmdline/merge_tests.py
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- subversion/tests/cmdline/merge_tests.py (revision 32499)
> +++ subversion/tests/cmdline/merge_tests.py (working copy)
> @@ -12548,6 +12548,8 @@
> None, None, None, None, None, 1)
> os.chdir(saved_cwd)
> =20
> +
> +#----------------------------------------------------------------------
> # Helper for text output.
> def verify_lines(lines, regexes):
> """Return True if each of the given regular expressions matches
> @@ -12581,107 +12583,10 @@
> actions_and_victims)):
> raise svntest.Failure("Wrong tree-conflict result")
> =20
> -# This test involves tree conflicts.
> -def tree_conflicts_in_merged_files(sbox):
> - "tree conflicts in merged files"
> =20
> - # Detect simple tree conflicts among files edited or deleted in a sing=
> le
> - # directory.
> =20
> - # See use cases 4-6 in notes/tree-conflicts/use-cases.txt for backgrou=
> nd.
> - # Note that we do not try to track renames. The only difference from
> - # the behavior of Subversion 1.4 and 1.5 is the conflicted status of t=
> he
> - # parent directory.
> +#----------------------------------------------------------------------
> =20
> - sbox.build()
> - wc_dir =3D sbox.wc_dir
> -
> - # Set up tree conflicts in wc 2
> - wc_dir_2 =3D svntest.actions.set_up_tree_conflicts_for_merge(sbox)
> - j =3D os.path.join
> - A2 =3D j(wc_dir, 'A2')
> - D2 =3D j(wc_dir, 'A2', 'D')
> - G2 =3D j(wc_dir, 'A2', 'D', 'G')
> - svntest.main.run_svn(None, 'ci', '-m', 'Changes in wc 2.', A2)
> -
> - # Merge a revision from url 1 into wc 2
> - expected_output =3D wc.State(A2, {
> - 'D' : Item(status=3D'C '),
> - 'D/sigma' : Item(status=3D'D '),
> - 'D/G' : Item(status=3D'C '),
> - 'D/G/rho' : Item(status=3D'D '),
> - })
> -
> - expected_disk =3D wc.State('', {
> - 'mu' : Item("This is the file 'mu'.\n"),
> - 'B' : Item(),
> - 'B/lambda' : Item("This is the file 'lambda'.\n"),
> - 'B/E' : Item(),
> - 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
> - 'B/E/beta' : Item("This is the file 'beta'.\n"),
> - 'B/F' : Item(),
> - 'C' : Item(),
> - 'D' : Item(),
> - 'D/sigma' : Item("This is the file 'sigma'.\nEdited in wc 2.\n"),
> - 'D/G' : Item(),
> - 'D/G/rho' : Item("This is the file 'rho'.\nEdited in wc 2.\n"),
> - 'D/H' : Item(),
> - 'D/H/chi' : Item("This is the file 'chi'.\n"),
> - 'D/H/psi' : Item("This is the file 'psi'.\n"),
> - 'D/H/omega' : Item("This is the file 'omega'.\n"),
> - })
> -
> - expected_status =3D wc.State(A2, {
> - '' : Item(),
> - 'mu' : Item(),
> - 'B' : Item(),
> - 'B/lambda' : Item(),
> - 'B/E' : Item(),
> - 'B/E/alpha' : Item(),
> - 'B/E/beta' : Item(),
> - 'B/F' : Item(),
> - 'C' : Item(),
> - 'D' : Item(),
> - 'D/sigma' : Item(),
> - 'D/G' : Item(),
> - 'D/G/rho' : Item(),
> - 'D/H' : Item(),
> - 'D/H/chi' : Item(),
> - 'D/H/psi' : Item(),
> - 'D/H/omega' : Item(),
> - })
> - expected_status.tweak(status=3D' ', wc_rev=3D3)
> - expected_status.tweak('', status=3D' M')
> - expected_status.tweak('D', 'D/G', status=3D'C ')
> - expected_status.tweak('D/sigma', 'D/G/rho', status=3D'D ', wc_rev=3D5)=
>
> -
> - expected_skip =3D wc.State(A2, {
> - 'D/gamma' : Item(),
> - 'D/theta' : Item(),
> - 'D/G/pi' : Item(),
> - 'D/G/tau' : Item(),
> - })
> -
> - svntest.actions.run_and_verify_merge(A2, 3, 4,
> - sbox.repo_url + '/A',
> - expected_output,
> - expected_disk,
> - expected_status,
> - expected_skip)
> -
> - # Make sure all victims have been found.
> - verify_tree_conflict_info(D2,
> - [('edit', 'gamma'), # use case 4
> - ('delete', 'sigma'), # use case 5
> - ('delete', 'theta'), # use case 6
> - ])
> - verify_tree_conflict_info(G2,
> - [('edit', 'pi'), # use case 4
> - ('delete', 'rho'), # use case 5
> - ('delete', 'tau'), # use case 6
> - ])
> -
> -
> # This test involves tree conflicts.
> def tree_conflicts_and_obstructions(sbox):
> "tree conflicts and obstructions"
> @@ -12752,6 +12657,646 @@
> [('add', 'alpha-moved')])
> =20
> =20
> +#----------------------------------------------------------------------
> +
> +# Detect tree conflicts among files and directories,
> +# edited or deleted in a deep directory structure.
> +#
> +# See use cases 4-6 in notes/tree-conflicts/use-cases.txt for background=
> =2E
> +# Note that we do not try to track renames. The only difference from
> +# the behavior of Subversion 1.4 and 1.5 is the conflicted status of the=
>
> +# parent directory.
> +#
> +def tree_conflicts_on_merge_local_ci(sbox):
> + "tree conflicts on merge, local commit (tc 4-6)"
> +
> + # Each case is constructed and then appended to the table, which
> + # is initially empty:
> + greater_scheme =3D [];
> +
> + # convenience definitions
> + leaf_edit =3D svntest.actions.deep_trees_leaf_edit
> + tree_del =3D svntest.actions.deep_trees_tree_del
> + leaf_del =3D svntest.actions.deep_trees_leaf_del
> +
> + state_after_leaf_edit =3D svntest.actions.deep_trees_after_leaf_edit
> + state_after_leaf_del =3D svntest.actions.deep_trees_after_leaf_del
> + state_after_tree_del =3D svntest.actions.deep_trees_after_tree_del
> +
> + j =3D os.path.join
> +
> + DeepTreesTestCase =3D svntest.actions.DeepTreesTestCase
> +
> +
> + # use case 1, as in notes/tree-conflicts/use-cases.txt
> + # 1.1) local tree delete, incoming leaf edit
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'D' : Item(status=3D'C '),
> + 'DF' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDD' : Item(status=3D'C '),
> + })
> +
> + expected_disk =3D state_after_tree_del
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + 'DF/D1/beta' : Item(),
> + 'DDF/D1/D2/gamma' : Item(),
> + 'D/D1/delta' : Item(),
> + 'DD/D1/D2/epsilon' : Item(),
> + 'DDD/D1/D2/D3/zeta' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_leaf_=
> edit",
> + tree_del,
> + leaf_edit,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip) ]
> +
> + # 1.2) local tree delete, incoming leaf delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'D' : Item(status=3D'C '),
> + 'DF' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDD' : Item(status=3D'C '),
> + })
> +
> + expected_disk =3D state_after_tree_del
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + 'DF/D1/beta' : Item(),
> + 'DDF/D1/D2/gamma' : Item(),
> + 'D/D1' : Item(),
> + 'DD/D1/D2' : Item(),
> + 'DDD/D1/D2/D3' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_leaf_=
> del",
> + tree_del,
> + leaf_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip) ]
> +
> +
> +
> +
> + # use case 2, as in notes/tree-conflicts/use-cases.txt
> + # 2.1) local leaf edit, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'D' : Item(),
> + 'D/D1' : Item(status=3D'D '),
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + 'DD' : Item(),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DF' : Item(),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(),
> + 'DDD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(),
> + 'DDF/D1' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'DF' : Item(),
> + 'DF/D1' : Item(),
> + 'DDF' : Item(),
> + 'DDF/D1' : Item(),
> + 'DDF/D1/D2' : Item(),
> + 'F' : Item(),
> + 'F/alpha' : Item(contents=3D"This is the file 'alpha'.\nMo=
> re text for file alpha.\n"),
> + 'DDD' : Item(),
> + 'DDD/D1' : Item(),
> + 'DDD/D1/D2' : Item(),
> + 'DDD/D1/D2/D3' : Item(),
> + 'DD' : Item(),
> + 'DD/D1' : Item(),
> + 'DD/D1/D2' : Item(),
> + 'D' : Item(),
> + 'D/D1' : Item(),
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'D' : Item(status=3D' ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D/D1/delta' : Item(status=3D'D ', wc_rev=3D'8'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'8'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2/epsilon' : Item(status=3D'D ', wc_rev=3D'8'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'8'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D'D ', wc_rev=3D'8'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'8'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {})
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_leaf_edit_incoming_tree=
> _del",
> + leaf_edit,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip) ]
> +
> +
> + # 2.2) local leaf del, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'D' : Item(status=3D'C '),
> + 'F' : Item(status=3D'C '),
> + 'DD' : Item(),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DF' : Item(),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(),
> + 'DDD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(),
> + 'DDF/D1' : Item(status=3D'D '),
> + })
> +
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'F' : Item(),
> + 'D' : Item(),
> + 'DF/D1' : Item(),
> + 'DD/D1' : Item(),
> + 'DDF/D1/D2' : Item(),
> + 'DDD/D1/D2' : Item(),
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + 'D/D1' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_leaf_del_incoming_tree_=
> del",
> + leaf_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip) ]
> +
> +
> + # use case 3, as in notes/tree-conflicts/use-cases.txt
> + # local tree delete, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'D' : Item(status=3D'C '),
> + 'DF' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDD' : Item(status=3D'C '),
> + })
> +
> + expected_disk =3D state_after_tree_del
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'D/D1' : Item(),
> + 'F/alpha' : Item(),
> + 'DD/D1' : Item(),
> + 'DF/D1' : Item(),
> + 'DDD/D1' : Item(),
> + 'DDF/D1' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase("local_tree_del_incoming_tree_=
> del",
> + tree_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip) ]
> +
> +
> + # now run the whole bunch of them.
> + svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox, greater_sc=
> heme,
> + True)
> +
> +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> +
> +def tree_conflicts_on_merge_no_local_ci(sbox):
> + "tree conflicts on merge, NO local commit (tc 4-6)"
> +
> + # Each case is constructed and then appended to the table, which
> + # is initially empty:
> + greater_scheme =3D [];
> +
> + # convenience definitions
> + leaf_edit =3D svntest.actions.deep_trees_leaf_edit
> + tree_del =3D svntest.actions.deep_trees_tree_del
> + leaf_del =3D svntest.actions.deep_trees_leaf_del
> +
> + state_after_leaf_edit =3D svntest.actions.deep_trees_after_leaf_edit
> + state_after_leaf_del =3D svntest.actions.deep_trees_after_leaf_del
> + state_after_tree_del =3D svntest.actions.deep_trees_after_tree_del
> +
> + j =3D os.path.join
> +
> + DeepTreesTestCase =3D svntest.actions.DeepTreesTestCase
> +
> +
> + # use case 1, as in notes/tree-conflicts/use-cases.txt
> + # 1.1) local tree delete, incoming leaf edit
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(),
> + 'D/D1/delta' : Item(status=3D'A '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'C '),
> + 'DD/D1/D2' : Item(),
> + 'DD/D1/D2/epsilon' : Item(status=3D'A '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'C '),
> + 'DDF/D1/D2' : Item(status=3D'C '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'C '),
> + 'DDD/D1/D2' : Item(status=3D'C '),
> + 'DDD/D1/D2/D3' : Item(),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D'A '),
> + })
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'F' : Item(),
> + 'D/D1/delta' : Item(contents=3D"This is the file 'delta'.\n")=
> ,
> + 'DF/D1' : Item(),
> + 'DD/D1/D2/epsilon' : Item(contents=3D"This is the file 'epsilon'.\n=
> "),
> + 'DDF/D1/D2' : Item(),
> + 'DDD/D1/D2/D3/zeta' : Item(contents=3D"This is the file 'zeta'.\n"),=
>
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2/epsilon' : Item(status=3D'A ', copied=3D'+', wc_rev=3D'-'=
> ),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D'A ', copied=3D'+', wc_rev=3D'-'=
> ),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D/D1/delta' : Item(status=3D'A ', copied=3D'+', wc_rev=3D'-'=
> ),
> + })
> +
> + alpha_beta_gamma =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + 'DF/D1/beta' : Item(),
> + 'DDF/D1/D2/gamma' : Item(),
> + })
> +
> + expected_skip =3D alpha_beta_gamma
> +
> + greater_scheme +=3D [ DeepTreesTestCase(
> + "local_tree_del_incoming_leaf_edit",
> + tree_del,
> + leaf_edit,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip,
> + ) ]
> +
> + # 1.2) local tree delete, incoming leaf delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'C '),
> + 'DD/D1/D2' : Item(status=3D'D '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'C '),
> + 'DDF/D1/D2' : Item(status=3D'C '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'C '),
> + 'DDD/D1/D2' : Item(status=3D'C '),
> + 'DDD/D1/D2/D3' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'F' : Item(),
> + 'D/D1' : Item(),
> + 'DF/D1' : Item(),
> + 'DD/D1/D2' : Item(),
> + 'DDF/D1/D2' : Item(),
> + 'DDD/D1/D2/D3' : Item(),
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D alpha_beta_gamma
> +
> + greater_scheme +=3D [ DeepTreesTestCase(
> + "local_tree_del_incoming_leaf_del",
> + tree_del,
> + leaf_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip,
> + ) ]
> +
> +
> +
> +
> + # use case 2, as in notes/tree-conflicts/use-cases.txt
> + # 2.1) local leaf edit, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'F' : Item(status=3D'C '),
> + 'F/alpha' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D state_after_leaf_edit
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'D' : Item(status=3D' ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D' M', wc_rev=3D'7'),
> + 'D/D1/delta' : Item(status=3D'A ', wc_rev=3D'0'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D' M', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DD/D1/D2/epsilon' : Item(status=3D'A ', wc_rev=3D'0'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D' M', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'M ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D' M', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3/zeta' : Item(status=3D'A ', wc_rev=3D'0'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D' M', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'M ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'D/D1' : Item(),
> + 'DF/D1' : Item(),
> + 'DD/D1' : Item(),
> + 'DDF/D1' : Item(),
> + 'DDD/D1' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase(
> + "local_leaf_edit_incoming_tree_del",
> + leaf_edit,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip,
> + ) ]
> +
> +
> + # 2.2) local leaf del, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'F' : Item(status=3D'C '),
> + 'DD' : Item(),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DF' : Item(),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(),
> + 'DDD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(),
> + 'DDF/D1' : Item(status=3D'D '),
> + })
> +
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'F' : Item(),
> + 'D/D1' : Item(),
> + 'DF/D1' : Item(),
> + 'DD/D1/D2' : Item(),
> + 'DDF/D1/D2' : Item(),
> + 'DDD/D1/D2/D3' : Item(),
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D' ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase(
> + "local_leaf_del_incoming_tree_del",
> + leaf_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip,
> + ) ]
> +
> +
> + # use case 3, as in notes/tree-conflicts/use-cases.txt
> + # local tree delete, incoming tree delete
> +
> + expected_output =3D svntest.wc.State('', {
> + 'D' : Item(status=3D'C '),
> + 'D/D1' : Item(status=3D'D '),
> + 'F' : Item(status=3D'C '),
> + 'DD' : Item(status=3D'C '),
> + 'DD/D1' : Item(status=3D'D '),
> + 'DF' : Item(status=3D'C '),
> + 'DF/D1' : Item(status=3D'D '),
> + 'DDD' : Item(status=3D'C '),
> + 'DDD/D1' : Item(status=3D'D '),
> + 'DDF' : Item(status=3D'C '),
> + 'DDF/D1' : Item(status=3D'D '),
> + })
> +
> + expected_disk =3D svntest.wc.State('', {
> + 'F' : Item(),
> + 'D/D1' : Item(),
> + 'DF/D1' : Item(),
> + 'DD/D1/D2' : Item(),
> + 'DDF/D1/D2' : Item(),
> + 'DDD/D1/D2/D3' : Item(),
> + })
> +
> + expected_status =3D svntest.wc.State('', {
> + '' : Item(status=3D' M', wc_rev=3D'7'),
> + 'DDF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDF/D1/D2/gamma' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'D' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'D/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'F' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'F/alpha' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DF/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DF/D1/beta' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD' : Item(status=3D'C ', wc_rev=3D'7'),
> + 'DDD/D1' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2' : Item(status=3D'D ', wc_rev=3D'7'),
> + 'DDD/D1/D2/D3' : Item(status=3D'D ', wc_rev=3D'7'),
> + })
> +
> + expected_skip =3D svntest.wc.State('', {
> + 'F/alpha' : Item(),
> + })
> +
> + greater_scheme +=3D [ DeepTreesTestCase(
> + "local_tree_del_incoming_tree_del",
> + tree_del,
> + tree_del,
> + expected_output,
> + expected_disk,
> + expected_status,
> + expected_skip,
> + ) ]
> +
> +
> + # now run the whole bunch of them.
> + svntest.actions.deep_trees_run_tests_scheme_for_merge(sbox, greater_sc=
> heme,
> + False)
> +
> +
> +
> ########################################################################=
>
> # Run the tests
> =20
> @@ -12925,8 +13470,9 @@
> server_has_mergeinfo),
> XFail(SkipUnless(subtrees_with_empty_mergeinfo,
> server_has_mergeinfo)),
> - tree_conflicts_in_merged_files,
> tree_conflicts_and_obstructions,
> + tree_conflicts_on_merge_local_ci,
> + tree_conflicts_on_merge_no_local_ci,
> ]
> =20
> if __name__ =3D=3D '__main__':
>
> --------------080409030609080001000909
> Content-Type: text/x-diff;
> name="merge_patch.diff"
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: inline;
> filename="merge_patch.diff"
>
> Index: subversion/libsvn_client/merge.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- subversion/libsvn_client/merge.c (revision 32499)
> +++ subversion/libsvn_client/merge.c (working copy)
> @@ -1516,27 +1516,35 @@
> svn_revnum_t rev,
> void *baton)
> {
> + // TODO This function segfaulted for adm_access =3D=3D NULL. I disable=
> d all of
> + // the code that was added on the tree-conflicts branch for the case o=
> f
> + // adm_access =3D=3D NULL. It remains to be seen if that's ok.
> +
> + if (adm_access !=3D NULL)
> + {
> - merge_cmd_baton_t *merge_b =3D baton;
> - apr_pool_t *subpool =3D svn_pool_create(merge_b->pool);
> - svn_node_kind_t kind;
> - const svn_wc_entry_t *entry;
> + merge_cmd_baton_t *merge_b =3D baton;
> + apr_pool_t *subpool =3D svn_pool_create(merge_b->pool);
> + svn_node_kind_t kind;
> + const svn_wc_entry_t *entry =3D NULL;
> =20
> - /* Find the version-control and on-disk states of this path */
> - SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, subpool));
> - SVN_ERR(svn_io_check_path(path, &kind, subpool));
> + /* Find the version-control and on-disk states of this path */
> + SVN_ERR(svn_wc_entry(&entry, path, adm_access, TRUE, subpool));
> + SVN_ERR(svn_io_check_path(path, &kind, subpool));
> =20
> - /* If we're trying to open a directory that's not a directory,
> - * raise a tree conflict. */
> - if (!entry || entry->schedule =3D=3D svn_wc_schedule_delete
> - || kind !=3D svn_node_dir)
> - {
> - SVN_ERR(tree_conflict(merge_b, adm_access, path,
> - svn_node_dir,
> - svn_wc_conflict_action_edit,
> - svn_wc_conflict_reason_deleted));
> - }
> + /* If we're trying to open a directory that's not a directory,
> + * raise a tree conflict. */
> + if (!entry || entry->schedule =3D=3D svn_wc_schedule_delete
> + || kind !=3D svn_node_dir)
> + {
> + SVN_ERR(tree_conflict(merge_b, adm_access, path,
> + svn_node_dir,
> + svn_wc_conflict_action_edit,
> + svn_wc_conflict_reason_deleted));
> + }
>
> - svn_pool_destroy(subpool);
> + svn_pool_destroy(subpool);
> + }
> =20
> return SVN_NO_ERROR;
> }
> =20
>
> --------------080409030609080001000909
> Content-Type: text/plain;
> name="segfault.backtrace"
> Content-Transfer-Encoding: quoted-printable
> Content-Disposition: inline;
> filename="segfault.backtrace"
>
> The segmentation fault occurs in merge_tests.py:101,
> subtest local_tree_del_incoming_leaf_edit.
>
> It occurs when calling svn_wc_entry with parameter adm_access=3D=3DNULL,
> when trying to merge the addition of the file
>
> DD/D1/D2/epsilon
>
> , while in the local working copy, on another branch sharing ancestry,
> a removal of DD/D1 has been committed.
>
> It occurs while trying to get adm_access information on DD/D1/D2.
>
> My guess is that adm_access becomes NULL since neither D2 nor its parent
> D1 are present on the branch.
>
>
> neels_at_dub:/arch/elego/svn/tc/subversion/tests/cmdline=20
> $ ./merge_tests.py 101
> <artificially exiting just before the segmentation fault:
> put `return None` in svntest/actions.py:2063, just after "8) Merge all">=
>
> PASS: merge_tests.py 101: tree conflicts on merge, local commit (tc 4-6)=
>
>
> neels_at_dub:/arch/elego/svn/tc/subversion/tests/cmdline=20
> $ gdb /arch/elego/svn/tc/subversion/svn/svn
> GNU gdb 6.8-debian
> Copyright (C) 2008 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.h=
> tml>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying=
> "
> and "show warranty" for details.
> This GDB was configured as "i486-linux-gnu"...
>
> (gdb) run merge file:///arch/elego/svn/tc/subversion/tests/cmdline/svn-te=
> st-work/repositories/merge_tests-101/local_tree_del_incoming_leaf_edit/in=
> coming svn-test-work/working_copies/merge_tests-101/local_tree_del_incomi=
> ng_leaf_edit/local --config-dir /arch/elego/svn/tc/subversion/tests/cmdli=
> ne/svn-test-work/local_tmp/config --password rayjandom --no-auth-cache --=
> username jrandom
> Starting program: /arch/elego/svn/tc/subversion/svn/svn merge file:///arc=
> h/elego/svn/tc/subversion/tests/cmdline/svn-test-work/repositories/merge_=
> tests-101/local_tree_del_incoming_leaf_edit/incoming svn-test-work/workin=
> g_copies/merge_tests-101/local_tree_del_incoming_leaf_edit/local --config=
> -dir /arch/elego/svn/tc/subversion/tests/cmdline/svn-test-work/local_tmp/=
> config --password rayjandom --no-auth-cache --username jrandom
> [Thread debugging using libthread_db enabled]
> Skipped missing target: 'svn-test-work/working_copies/merge_tests-101/loc=
> al_tree_del_incoming_leaf_edit/local/D/D1/delta'
> Skipped missing target: 'svn-test-work/working_copies/merge_tests-101/loc=
> al_tree_del_incoming_leaf_edit/local/D/D1'
> --- Merging r3 through r8 into 'svn-test-work/working_copies/merge_tests-=
> 101/local_tree_del_incoming_leaf_edit/local':
> C svn-test-work/working_copies/merge_tests-101/local_tree_del_incoming=
> _leaf_edit/local/D
> Skipped missing target: 'svn-test-work/working_copies/merge_tests-101/loc=
> al_tree_del_incoming_leaf_edit/local/F/alpha'
> C svn-test-work/working_copies/merge_tests-101/local_tree_del_incoming=
> _leaf_edit/local/F
> [New Thread 0xb7a8c6d0 (LWP 584)]
>
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0xb7a8c6d0 (LWP 584)]
> 0x080ada84 in svn_wc__adm_retrieve_internal (adm_access=3D0xbfc76890, ass=
> ociated=3D0x0,=20
> path=3D0x829b5b0 "svn-test-work/working_copies/merge_tests-101/local_=
> tree_del_incoming_leaf_edit/local/DD/D1/D2", pool=3D0x82cc038) at subvers=
> ion/libsvn_wc/lock.c:894
> 894 if (associated->set)
> (gdb) bt
> #0 0x080ada84 in svn_wc__adm_retrieve_internal (adm_access=3D0xbfc76890,=
> associated=3D0x0,=20
> path=3D0x829b5b0 "svn-test-work/working_copies/merge_tests-101/local_=
> tree_del_incoming_leaf_edit/local/DD/D1/D2", pool=3D0x82cc038) at subvers=
> ion/libsvn_wc/lock.c:894
> #1 0x080a88fe in svn_wc_entry (entry=3D0xbfc768d8, path=3D0x829b5b0 "svn=
> -test-work/working_copies/merge_tests-101/local_tree_del_incoming_leaf_ed=
> it/local/DD/D1/D2",=20
> adm_access=3D0x0, show_hidden=3D1, pool=3D0x82cc038) at subversion/li=
> bsvn_wc/entries.c:1247
> #2 0x08080d20 in merge_dir_opened (adm_access=3D0x0, path=3D0x829b5b0 "s=
> vn-test-work/working_copies/merge_tests-101/local_tree_del_incoming_leaf_=
> edit/local/DD/D1/D2", rev=3D2,=20
> baton=3D0xbfc77348) at subversion/libsvn_client/merge.c:1531
> #3 0x08091af2 in open_directory (path=3D0x829b480 "DD/D1/D2", parent_bat=
> on=3D0x82b6d28, base_revision=3D2, pool=3D0x829b3c0, child_baton=3D0x829b=
> 514)
> at subversion/libsvn_client/repos_diff.c:616
> #4 0x081313dd in open_directory (path=3D0x829b480 "DD/D1/D2", parent_bat=
> on=3D0x82b6d20, base_revision=3D2, pool=3D0x829b3c0, child_baton=3D0x829b=
> 50c)
> at subversion/libsvn_delta/cancel.c:140
> #5 0x081313dd in open_directory (path=3D0x829b480 "DD/D1/D2", parent_bat=
> on=3D0x82b6d18, base_revision=3D2, pool=3D0x829b3c0, child_baton=3D0xbfc7=
> 6aa0)
> at subversion/libsvn_delta/cancel.c:140
> #6 0x080e76df in update_entry (b=3D0x8207680, s_rev=3D2, s_path=3D0x829b=
> 438 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1/D2", s_entry=3D0x8=
> 2a6e08,=20
> t_path=3D0x829b4d0 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1=
> /D2", t_entry=3D0x82a73b8, dir_baton=3D0x82b6d18, e_path=3D0x829b480 "DD/=
> D1/D2", info=3D0x0,=20
> wc_depth=3Dsvn_depth_infinity, requested_depth=3Dsvn_depth_infinity, =
> pool=3D0x829b3c0) at subversion/libsvn_repos/reporter.c:830
> #7 0x080e82a6 in delta_dirs (b=3D0x8207680, s_rev=3D2, s_path=3D0x82b6c5=
> 8 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1",=20
> t_path=3D0x82b6ce0 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1=
> ", dir_baton=3D0x82b6d18, e_path=3D0x82b6ca0 "DD/D1", start_empty=3D0, wc=
> _depth=3Dsvn_depth_infinity,=20
> requested_depth=3Dsvn_depth_infinity, pool=3D0x82b6be8) at subversion=
> /libsvn_repos/reporter.c:1110
> #8 0x080e77cf in update_entry (b=3D0x8207680, s_rev=3D2, s_path=3D0x82b6=
> c58 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1", s_entry=3D0x8296=
> d90,=20
> t_path=3D0x82b6ce0 "/local_tree_del_incoming_leaf_edit/incoming/DD/D1=
> ", t_entry=3D0x8297320, dir_baton=3D0x8275448, e_path=3D0x82b6ca0 "DD/D1"=
> , info=3D0x0,=20
> wc_depth=3Dsvn_depth_infinity, requested_depth=3Dsvn_depth_infinity, =
> pool=3D0x82b6be8) at subversion/libsvn_repos/reporter.c:837
> #9 0x080e82a6 in delta_dirs (b=3D0x8207680, s_rev=3D2, s_path=3D0x827539=
> 8 "/local_tree_del_incoming_leaf_edit/incoming/DD",=20
> t_path=3D0x8275418 "/local_tree_del_incoming_leaf_edit/incoming/DD", =
> dir_baton=3D0x8275448, e_path=3D0x82753d8 "DD", start_empty=3D0, wc_depth=
> =3Dsvn_depth_infinity,=20
> requested_depth=3Dsvn_depth_infinity, pool=3D0x8275328) at subversion=
> /libsvn_repos/reporter.c:1110
> #10 0x080e77cf in update_entry (b=3D0x8207680, s_rev=3D2, s_path=3D0x8275=
> 398 "/local_tree_del_incoming_leaf_edit/incoming/DD", s_entry=3D0x8282360=
> ,=20
> t_path=3D0x8275418 "/local_tree_del_incoming_leaf_edit/incoming/DD", =
> t_entry=3D0x82830c0, dir_baton=3D0x828ab38, e_path=3D0x82753d8 "DD", info=
> =3D0x0, wc_depth=3Dsvn_depth_infinity,=20
> requested_depth=3Dsvn_depth_infinity, pool=3D0x8275328) at subversion=
> /libsvn_repos/reporter.c:837
> #11 0x080e82a6 in delta_dirs (b=3D0x8207680, s_rev=3D2, s_path=3D0x826583=
> 8 "/local_tree_del_incoming_leaf_edit/incoming",=20
> t_path=3D0x8207475 "/local_tree_del_incoming_leaf_edit/incoming", dir=
> _baton=3D0x828ab38, e_path=3D0x819e96b "", start_empty=3D0, wc_depth=3Dsv=
> n_depth_infinity,=20
> requested_depth=3Dsvn_depth_infinity, pool=3D0x8207200) at subversion=
> /libsvn_repos/reporter.c:1110
> #12 0x080e865e in drive (b=3D0x8207680, s_rev=3D2, info=3D0x8208e50, pool=
> =3D0x8207200) at subversion/libsvn_repos/reporter.c:1174
> #13 0x080e8a13 in finish_report (b=3D0x8207680, pool=3D0x8207200) at subv=
> ersion/libsvn_repos/reporter.c:1241
> #14 0x080e8ed7 in svn_repos_finish_report (baton=3D0x8207680, pool=3D0x82=
> 07200) at subversion/libsvn_repos/reporter.c:1365
> #15 0x080dac25 in reporter_finish_report (reporter_baton=3D0x8208e18, poo=
> l=3D0x8207200) at subversion/libsvn_ra_local/ra_plugin.c:210
> #16 0x08082a37 in drive_merge_report_editor (target_wcpath=3D0x81d19b0 "s=
> vn-test-work/working_copies/merge_tests-101/local_tree_del_incoming_leaf_=
> edit/local",=20
> url1=3D0x81f3f38 "file:///arch/elego/svn/tc/subversion/tests/cmdline/=
> svn-test-work/repositories/merge_tests-101/local_tree_del_incoming_leaf_e=
> dit/incoming", revision1=3D2,=20
> url2=3D0x81f40c8 "file:///arch/elego/svn/tc/subversion/tests/cmdline/=
> svn-test-work/repositories/merge_tests-101/local_tree_del_incoming_leaf_e=
> dit/incoming", revision2=3D8,=20
> children_with_mergeinfo=3D0x81ef618, is_rollback=3D0, depth=3Dsvn_dep=
> th_infinity, notify_b=3D0xbfc773a0, adm_access=3D0x81d1e48, callbacks=3D0=
> x8198520, merge_b=3D0xbfc77348,=20
> pool=3D0x8207200) at subversion/libsvn_client/merge.c:2791
> #17 0x080865e6 in do_directory_merge (
> url1=3D0x81f3f38 "file:///arch/elego/svn/tc/subversion/tests/cmdline/=
> svn-test-work/repositories/merge_tests-101/local_tree_del_incoming_leaf_e=
> dit/incoming", revision1=3D2,=20
> url2=3D0x81f40c8 "file:///arch/elego/svn/tc/subversion/tests/cmdline/=
> svn-test-work/repositories/merge_tests-101/local_tree_del_incoming_leaf_e=
> dit/incoming", revision2=3D8,=20
> parent_entry=3D0x81d1f30, adm_access=3D0x81d1e48, depth=3Dsvn_depth_i=
> nfinity, notify_b=3D0xbfc773a0, merge_b=3D0xbfc77348, pool=3D0x81e7198) a=
> t subversion/libsvn_client/merge.c:4912
> #18 0x08087747 in do_merge (merge_sources=3D0x81f3b68, target=3D0x81d19b0=
> "svn-test-work/working_copies/merge_tests-101/local_tree_del_incoming_le=
> af_edit/local",=20
> target_entry=3D0x81d1f30, adm_access=3D0x81d1e48, sources_ancestral=3D=
> 1, sources_related=3D1, same_repos=3D1, ignore_ancestry=3D0, force=3D0, d=
> ry_run=3D0, record_only=3D0,=20
> depth=3Dsvn_depth_infinity, merge_options=3D0x0, ctx=3D0x81d07a8, poo=
> l=3D0x81d01e0) at subversion/libsvn_client/merge.c:5395
> #19 0x08089d23 in svn_client_merge_peg3 (
> source=3D0x81d1690 "file:///arch/elego/svn/tc/subversion/tests/cmdlin=
> e/svn-test-work/repositories/merge_tests-101/local_tree_del_incoming_leaf=
> _edit/incoming",=20
> ranges_to_merge=3D0x81d1a40, peg_revision=3D0xbfc77524, target_wcpath=
> =3D0x81d19b0 "svn-test-work/working_copies/merge_tests-101/local_tree_del=
> _incoming_leaf_edit/local",=20
> depth=3Dsvn_depth_unknown, ignore_ancestry=3D0, force=3D0, record_onl=
> y=3D0, dry_run=3D0, merge_options=3D0x0, ctx=3D0x81d07a8, pool=3D0x81d01e=
> 0) at subversion/libsvn_client/merge.c:6339
> #20 0x08058d36 in svn_cl__merge (os=3D0x81d0380, baton=3D0xbfc77760, pool=
> =3D0x81d01e0) at subversion/svn/merge-cmd.c:307
> #21 0x080582d1 in main (argc=3D11, argv=3D0xbfc77894) at subversion/svn/m=
> ain.c:1981
>
>
> --------------080409030609080001000909--

-- 
Neels Hofmeyr -- elego Software Solutions GmbH
Gustav-Meyer-Allee 25 / Gebäude 12, 13355 Berlin, Germany
phone: +49 30 23458696  mobile: +49 177 2345869  fax: +49 30 23458695
http://www.elegosoft.com | Geschäftsführer: Olaf Wagner | Sitz: Berlin
Handelsreg: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194

Received on 2008-08-16 04:11:18 CEST

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.