You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2019/07/18 13:39:31 UTC
svn commit: r1863305 - in /subversion/branches/1.10.x: ./ STATUS
subversion/libsvn_ra_svn/client.c subversion/svnserve/serve.c
subversion/tests/libsvn_ra/ra-test.c
Author: julianfoad
Date: Thu Jul 18 13:39:30 2019
New Revision: 1863305
URL: http://svn.apache.org/viewvc?rev=1863305&view=rev
Log:
Merge the r1860936 group from trunk:
* r1860936, r1860951, r1860958
Provide a way for svnserve's 'get-deleted-rev' API to return 'not deleted'.
Justification:
Error handling was inconsistent across RA layers.
Votes:
+1: julianfoad, stsp
Modified:
subversion/branches/1.10.x/ (props changed)
subversion/branches/1.10.x/STATUS
subversion/branches/1.10.x/subversion/libsvn_ra_svn/client.c
subversion/branches/1.10.x/subversion/svnserve/serve.c
subversion/branches/1.10.x/subversion/tests/libsvn_ra/ra-test.c
Propchange: subversion/branches/1.10.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Jul 18 13:39:30 2019
@@ -104,4 +104,4 @@
/subversion/branches/verify-at-commit:1462039-1462408
/subversion/branches/verify-keep-going:1439280-1546110
/subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1817837,1817856,1818577-1818578,1818584,1818651,1818662,1818727,1818801,1818803,1818807,1818868,1818871,1819036-1819037,1819043,1819049,1819052,1819093,1819146,1819162,1819444,1819556-1819557,1819603,1819804,1819911,1820044,1820046-1820047,1820518,1820627,1820718,1820778,1821183,1821224,1821621,1821678,1822401,1822587,1822591,1822996,1823202-1823203,1823211,1823327,1823791,1823966,1823989,1824033,1825024,1825045,1825215,1825266,1825306,1825709,1825711,1825721,1825736,1825778,1825783,1825787-1825788,1825979,1826720-1826721,1826747,1826811,1826814,1826877,1826907,1826971,1827105,1827114,1827191,1827562,1827574,1827670,1828613,1829012,1829015,1829241,1829260,1829344,1830083,1830882-1830883,1830885,1830900-1830901,1831110,1831112,1831540,1833465,1833621,1833836,1833842,1833864,1833866,1833895,1833897,1833899,1833901,1835760,1836306,1836762,1836802,1836960,1836963,1836968,1836976,1837037,1837790,1838813,1839662,1839703,1839734,1839739,1840991,1842260,1842262,1842264,184
3888,1844882,1844987,1845204,1845212,1845261,1845408,1845555,1845577,1846299,1846403,1846406,1846704,1847181-1847182,1847188,1847264,1847572,1847596,1847598,1847697,1847922,1847924,1847946,1850348,1850621,1850651,1851676,1851687,1851791,1851920,1852013,1852436,1853450,1853483,1853761,1854072,1854074,1854216,1855419,1856397,1857367,1857391,1863262
+/subversion/trunk:1817837,1817856,1818577-1818578,1818584,1818651,1818662,1818727,1818801,1818803,1818807,1818868,1818871,1819036-1819037,1819043,1819049,1819052,1819093,1819146,1819162,1819444,1819556-1819557,1819603,1819804,1819911,1820044,1820046-1820047,1820518,1820627,1820718,1820778,1821183,1821224,1821621,1821678,1822401,1822587,1822591,1822996,1823202-1823203,1823211,1823327,1823791,1823966,1823989,1824033,1825024,1825045,1825215,1825266,1825306,1825709,1825711,1825721,1825736,1825778,1825783,1825787-1825788,1825979,1826720-1826721,1826747,1826811,1826814,1826877,1826907,1826971,1827105,1827114,1827191,1827562,1827574,1827670,1828613,1829012,1829015,1829241,1829260,1829344,1830083,1830882-1830883,1830885,1830900-1830901,1831110,1831112,1831540,1833465,1833621,1833836,1833842,1833864,1833866,1833895,1833897,1833899,1833901,1835760,1836306,1836762,1836802,1836960,1836963,1836968,1836976,1837037,1837790,1838813,1839662,1839703,1839734,1839739,1840991,1842260,1842262,1842264,184
3888,1844882,1844987,1845204,1845212,1845261,1845408,1845555,1845577,1846299,1846403,1846406,1846704,1847181-1847182,1847188,1847264,1847572,1847596,1847598,1847697,1847922,1847924,1847946,1850348,1850621,1850651,1851676,1851687,1851791,1851920,1852013,1852436,1853450,1853483,1853761,1854072,1854074,1854216,1855419,1856397,1857367,1857391,1860936,1860951,1860958,1863262
Modified: subversion/branches/1.10.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/STATUS?rev=1863305&r1=1863304&r2=1863305&view=diff
==============================================================================
--- subversion/branches/1.10.x/STATUS (original)
+++ subversion/branches/1.10.x/STATUS Thu Jul 18 13:39:30 2019
@@ -20,10 +20,3 @@ Veto-blocked changes:
Approved changes:
=================
-
- * r1860936, r1860951, r1860958
- Provide a way for svnserve's 'get-deleted-rev' API to return 'not deleted'.
- Justification:
- Error handling was inconsistent across RA layers.
- Votes:
- +1: julianfoad, stsp
Modified: subversion/branches/1.10.x/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/subversion/libsvn_ra_svn/client.c?rev=1863305&r1=1863304&r2=1863305&view=diff
==============================================================================
--- subversion/branches/1.10.x/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/1.10.x/subversion/libsvn_ra_svn/client.c Thu Jul 18 13:39:30 2019
@@ -3105,6 +3105,7 @@ ra_svn_get_deleted_rev(svn_ra_session_t
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
+ svn_error_t *err;
path = reparent_path(session, path, pool);
@@ -3116,8 +3117,20 @@ ra_svn_get_deleted_rev(svn_ra_session_t
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
N_("'get-deleted-rev' not implemented")));
- return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, "r",
- revision_deleted));
+ err = svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, "r",
+ revision_deleted));
+ /* The protocol does not allow for a reply of SVN_INVALID_REVNUM directly.
+ Instead, a new enough server returns SVN_ERR_ENTRY_MISSING_REVISION to
+ indicate the answer to the query is SVN_INVALID_REVNUM. (An older server
+ closes the connection and returns SVN_ERR_RA_SVN_CONNECTION_CLOSED.) */
+ if (err && err->apr_err == SVN_ERR_ENTRY_MISSING_REVISION)
+ {
+ *revision_deleted = SVN_INVALID_REVNUM;
+ svn_error_clear(err);
+ }
+ else
+ SVN_ERR(err);
+ return SVN_NO_ERROR;
}
static svn_error_t *
Modified: subversion/branches/1.10.x/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/subversion/svnserve/serve.c?rev=1863305&r1=1863304&r2=1863305&view=diff
==============================================================================
--- subversion/branches/1.10.x/subversion/svnserve/serve.c (original)
+++ subversion/branches/1.10.x/subversion/svnserve/serve.c Thu Jul 18 13:39:30 2019
@@ -3505,8 +3505,21 @@ get_deleted_rev(svn_ra_svn_conn_t *conn,
svn_relpath_canonicalize(path, pool), pool);
SVN_ERR(log_command(b, conn, pool, "get-deleted-rev"));
SVN_ERR(trivial_auth_request(conn, pool, b));
- SVN_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision,
- end_revision, &revision_deleted, pool));
+ SVN_CMD_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision,
+ end_revision, &revision_deleted, pool));
+
+ /* The protocol does not allow for a reply of SVN_INVALID_REVNUM directly.
+ Instead, return SVN_ERR_ENTRY_MISSING_REVISION. A new enough client
+ knows that this means the answer to the query is SVN_INVALID_REVNUM.
+ (An older client reports this as an error.) */
+ if (revision_deleted == SVN_INVALID_REVNUM)
+ SVN_CMD_ERR(svn_error_createf(SVN_ERR_ENTRY_MISSING_REVISION, NULL,
+ "svn protocol command 'get-deleted-rev': "
+ "path '%s' was not deleted in r%ld-%ld; "
+ "NOTE: newer clients handle this case "
+ "and do not report it as an error",
+ full_path, peg_revision, end_revision));
+
SVN_ERR(svn_ra_svn__write_cmd_response(conn, pool, "r", revision_deleted));
return SVN_NO_ERROR;
}
@@ -4101,7 +4114,7 @@ construct_server_baton(server_baton_t **
serve_params_t *params,
apr_pool_t *scratch_pool)
{
- svn_error_t *err, *io_err;
+ svn_error_t *err;
apr_uint64_t ver;
const char *client_url, *ra_client_string, *client_string;
svn_ra_svn__list_t *caplist;
@@ -4239,11 +4252,12 @@ construct_server_baton(server_baton_t **
}
if (err)
{
- log_error(err, b);
- io_err = svn_ra_svn__write_cmd_failure(conn, scratch_pool, err);
- svn_error_clear(err);
- SVN_ERR(io_err);
- return svn_ra_svn__flush(conn, scratch_pool);
+ /* Report these errors to the client before closing the connection. */
+ err = svn_error_compose_create(err,
+ svn_ra_svn__write_cmd_failure(conn, scratch_pool, err));
+ err = svn_error_compose_create(err,
+ svn_ra_svn__flush(conn, scratch_pool));
+ return err;
}
SVN_ERR(svn_fs_get_uuid(b->repository->fs, &b->repository->uuid,
Modified: subversion/branches/1.10.x/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/subversion/tests/libsvn_ra/ra-test.c?rev=1863305&r1=1863304&r2=1863305&view=diff
==============================================================================
--- subversion/branches/1.10.x/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/1.10.x/subversion/tests/libsvn_ra/ra-test.c Thu Jul 18 13:39:30 2019
@@ -94,6 +94,41 @@ commit_changes(svn_ra_session_t *session
return SVN_NO_ERROR;
}
+/* Commit two revisions: add 'B', then delete 'A' */
+static svn_error_t *
+commit_two_changes(svn_ra_session_t *session,
+ apr_pool_t *pool)
+{
+ apr_hash_t *revprop_table = apr_hash_make(pool);
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ void *root_baton, *dir_baton;
+
+ /* mkdir B */
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ revprop_table,
+ NULL, NULL, NULL, TRUE, pool));
+ SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
+ pool, &root_baton));
+ SVN_ERR(editor->add_directory("B", root_baton, NULL, SVN_INVALID_REVNUM,
+ 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));
+
+ /* delete A */
+ SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &edit_baton,
+ revprop_table,
+ NULL, NULL, NULL, TRUE, pool));
+ SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
+ pool, &root_baton));
+ SVN_ERR(editor->delete_entry("A", SVN_INVALID_REVNUM, root_baton, pool));
+ SVN_ERR(editor->close_directory(root_baton, pool));
+ SVN_ERR(editor->close_edit(edit_baton, pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
commit_tree(svn_ra_session_t *session,
apr_pool_t *pool)
@@ -1784,6 +1819,63 @@ commit_locked_file(const svn_test_opts_t
return SVN_NO_ERROR;
}
+/* Cases of 'get-deleted-rev' that should return SVN_INVALID_REVNUM. */
+static svn_error_t *
+test_get_deleted_rev_no_delete(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ svn_revnum_t revision_deleted;
+
+ SVN_ERR(make_and_open_repos(&ra_session,
+ "test-repo-get-deleted-rev-no-delete", opts,
+ pool));
+ SVN_ERR(commit_changes(ra_session, pool));
+ SVN_ERR(commit_two_changes(ra_session, pool));
+
+ /* expect 'no deletion' in the range up to r2, when it is deleted in r3 */
+ /* This was failing over RA-SVN where the 'get-deleted-rev' wire command's
+ prototype cannot directly represent that result. A new enough client and
+ server collaborate on a work-around implemented using an error code. */
+ SVN_ERR(svn_ra_get_deleted_rev(ra_session, "A", 1, 2,
+ &revision_deleted, pool));
+ SVN_TEST_INT_ASSERT(revision_deleted, SVN_INVALID_REVNUM);
+
+ /* this connection should still be open: a simple case should still work */
+ SVN_ERR(svn_ra_get_deleted_rev(ra_session, "A", 1, 3,
+ &revision_deleted, pool));
+ SVN_TEST_INT_ASSERT(revision_deleted, 3);
+
+ return SVN_NO_ERROR;
+}
+
+/* Cases of 'get-deleted-rev' that should return an error. */
+static svn_error_t *
+test_get_deleted_rev_errors(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *ra_session;
+ svn_revnum_t revision_deleted;
+ svn_error_t *err;
+
+ SVN_ERR(make_and_open_repos(&ra_session,
+ "test-repo-get-deleted-rev-errors", opts, pool));
+ SVN_ERR(commit_changes(ra_session, pool));
+
+ /* expect an error when searching up to r3, when repository head is r1 */
+ err = svn_ra_get_deleted_rev(ra_session, "A", 1, 3, &revision_deleted, pool);
+
+ /* mod_dav_svn returns a generic error code for "500 Internal Server Error";
+ * the other RA layers return the specific error code for "no such revision".
+ * We should make these consistent, but for now that's how it is. */
+ if (opts->repos_url && strncmp(opts->repos_url, "http", 4) == 0)
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_RA_DAV_REQUEST_FAILED);
+ else
+ SVN_TEST_ASSERT_ERROR(err, SVN_ERR_FS_NO_SUCH_REVISION);
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
@@ -1820,6 +1912,10 @@ static struct svn_test_descriptor_t test
"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_PASS(test_get_deleted_rev_no_delete,
+ "test get-deleted-rev no delete"),
+ SVN_TEST_OPTS_PASS(test_get_deleted_rev_errors,
+ "test get-deleted-rev errors"),
SVN_TEST_NULL
};