> 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 };