> Dmitry Pavlenko wrote:
>> Hello Subversion community!
Hello Dmitry! Thanks for finding this. I confirm it.
>> I've run into an error: when performing 2 specially constructed updates one
>> after another
>> within the same session, SVN fails with
>>
>> $ ./ra-test 15
>> svn_tests: E160016: Can't get entries of non-directory
>> XFAIL: ra-test 15: check that there's no "Can't get entries" error
>
>> error. I believe these updates constructed that way are valid, so the
>> problem is
>> somewhere in FSFS code.
I agree.
Daniel Shahaf wrote:
> Could you please clarify whether the bug reproduces under other backends
> (FSX and BDB)?
I found that the test passes under FSX and BDB; it only fails under FSFS.
I found that the RA method (local, svn, serf) makes no difference.
> You make all commits using the same EDITOR. Is that allowed?
I found that it doesn't affect the outcome, in this case.
(Generally, as Brane said, it's undocumented and not a good idea. The attached
version of the patch, 'cant_get_entries_test-j1.patch', uses a separate editor
for each edit.)
--
- Julian
Index: subversion/tests/libsvn_ra/ra-test.c
===================================================================
--- subversion/tests/libsvn_ra/ra-test.c (revision 1846979)
+++ subversion/tests/libsvn_ra/ra-test.c (working copy)
@@ -1784,6 +1784,128 @@
return SVN_NO_ERROR;
}
+static svn_error_t *
+cant_get_entries_of_non_directory(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_ra_session_t *session;
+
+ SVN_ERR(make_and_open_repos(&session,
+ "cant_get_entries_of_non_directory", opts,
+ pool));
+
+ {
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton;
+ void *dir_baton;
+ void *file_baton;
+
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ apr_hash_make(pool), NULL,
+ NULL, NULL, FALSE, pool));
+ SVN_ERR(editor->open_root(edit_baton, 0, pool, &root_baton));
+ SVN_ERR(editor->add_directory("A", root_baton, NULL, SVN_INVALID_REVNUM,
+ pool, &dir_baton));
+ SVN_ERR(editor->add_file("A/mu", dir_baton, NULL, SVN_INVALID_REVNUM,
+ pool, &file_baton));
+ SVN_ERR(editor->close_file(file_baton, NULL, pool));
+ SVN_ERR(editor->close_directory(dir_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+ }
+ {
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton;
+ void *dir_baton;
+ const char* repos_root_url;
+ const char* A_url;
+
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
+ A_url = svn_path_url_add_component2(repos_root_url, "A", pool);
+
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ apr_hash_make(pool), NULL,
+ NULL, NULL, FALSE, pool));
+ SVN_ERR(editor->open_root(edit_baton, 1, pool, &root_baton));
+ SVN_ERR(editor->add_directory("B", root_baton, A_url, 1,
+ pool, &dir_baton));
+ SVN_ERR(editor->close_directory(dir_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+ }
+ {
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton;
+
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ apr_hash_make(pool), NULL,
+ NULL, NULL, FALSE, pool));
+ SVN_ERR(editor->open_root(edit_baton, 2, pool, &root_baton));
+ SVN_ERR(editor->delete_entry("B/mu", 2, root_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+ }
+ {
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton;
+ void *dir_baton;
+ void *subdir_baton;
+ void *file_baton;
+
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ apr_hash_make(pool), NULL,
+ NULL, NULL, FALSE, pool));
+ SVN_ERR(editor->open_root(edit_baton, 3, pool, &root_baton));
+ SVN_ERR(editor->open_directory("B", root_baton, 3, pool, &dir_baton));
+ SVN_ERR(editor->add_directory("B/mu", root_baton, NULL, SVN_INVALID_REVNUM,
+ pool, &subdir_baton));
+ SVN_ERR(editor->add_file("B/mu/iota", subdir_baton, NULL, SVN_INVALID_REVNUM,
+ pool, &file_baton));
+ SVN_ERR(editor->close_file(file_baton, NULL, pool));
+ SVN_ERR(editor->close_directory(subdir_baton, pool));
+ SVN_ERR(editor->close_directory(dir_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+ }
+ /* The following updates fail when executed in this order
+ one after another within the same session.
+
+ When commenting out one of the blocks the test passes
+ */
+ {
+ const svn_ra_reporter3_t *reporter;
+ void *report_baton;
+
+ SVN_ERR(svn_ra_do_update3(session, &reporter, &report_baton,
+ 3, "", svn_depth_infinity, TRUE, FALSE,
+ svn_delta_default_editor(pool), NULL,
+ pool, pool));
+ SVN_ERR(reporter->set_path(report_baton, "", 3, svn_depth_infinity, FALSE,
+ NULL, pool));
+ SVN_ERR(reporter->set_path(report_baton, "B", 2, svn_depth_infinity, FALSE,
+ NULL, pool));
+ SVN_ERR(reporter->finish_report(report_baton, pool));
+ }
+ {
+ const svn_ra_reporter3_t *reporter;
+ void *report_baton;
+
+ SVN_ERR(svn_ra_do_update3(session, &reporter, &report_baton,
+ 4, "", svn_depth_infinity, TRUE, FALSE,
+ svn_delta_default_editor(pool), NULL,
+ pool, pool));
+ SVN_ERR(reporter->set_path(report_baton, "", 4, svn_depth_infinity, FALSE,
+ NULL, pool));
+ SVN_ERR(reporter->set_path(report_baton, "B", 3, svn_depth_infinity, FALSE,
+ NULL, pool));
+ SVN_ERR(reporter->finish_report(report_baton, pool));
+ }
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
@@ -1820,6 +1942,8 @@
"check how last change applies to empty commit"),
SVN_TEST_OPTS_PASS(commit_locked_file,
"check commit editor for a locked file"),
+ SVN_TEST_OPTS_XFAIL(cant_get_entries_of_non_directory,
+ "check that there's no \"Can't get entries\" error"),
SVN_TEST_NULL
};