You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gb...@apache.org on 2013/10/13 18:11:00 UTC
svn commit: r1531702 [4/4] - in
/subversion/branches/invoke-diff-cmd-feature: ./
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/i...
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/svnserve/svnserve.c Sun Oct 13 16:10:59 2013
@@ -55,6 +55,7 @@
#include "private/svn_cmdline_private.h"
#include "private/svn_atomic.h"
#include "private/svn_mutex.h"
+#include "private/svn_subr_private.h"
/* Alas! old APR-Utils don't provide thread pools */
#if APR_HAS_THREADS
@@ -77,6 +78,7 @@
#endif
#include "server.h"
+#include "logger.h"
/* The strategy for handling incoming connections. Some of these may be
unavailable due to platform limitations. */
@@ -350,14 +352,6 @@ static const apr_getopt_option_t svnserv
{0, 0, 0, 0}
};
-/* unused connection pools.
- * Use CONNECTION_POOLS_MUTEX to serialize access to this collection.
- */
-apr_array_header_t *connection_pools = NULL;
-
-/* Mutex to serialize access to connection_pools */
-svn_mutex__t *connection_pools_mutex = NULL;
-
static void usage(const char *progname, apr_pool_t *pool)
{
if (!progname)
@@ -451,74 +445,6 @@ static apr_status_t redirect_stdout(void
return apr_file_dup2(out_file, err_file, pool);
}
-/* Create the global collection object for unused connection pools plus
- * the necessary mutex. Their lifetime will be bound to POOL.
- */
-static svn_error_t *
-initialize_connection_pools(apr_pool_t *pool)
-{
- SVN_ERR(svn_mutex__init(&connection_pools_mutex, TRUE, pool));
- connection_pools = apr_array_make(pool, 16, sizeof(apr_pool_t *));
-
- return SVN_NO_ERROR;
-}
-
-/* Return a currently unused connection pool in *POOL. If no such pool
- * exists, create a new root pool and return that in *POOL.
- */
-static svn_error_t *
-acquire_connection_pool_internal(apr_pool_t **pool)
-{
- SVN_ERR(svn_mutex__lock(connection_pools_mutex));
- *pool = connection_pools->nelts
- ? *(apr_pool_t **)apr_array_pop(connection_pools)
- : apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
- SVN_ERR(svn_mutex__unlock(connection_pools_mutex, SVN_NO_ERROR));
-
- return SVN_NO_ERROR;
-}
-
-/* Return a currently unused connection pool. If no such pool exists,
- * create a new root pool and return that.
- */
-static apr_pool_t *
-acquire_connection_pool(void)
-{
- apr_pool_t *pool;
- svn_error_t *err = acquire_connection_pool_internal(&pool);
- if (err)
- {
- /* Mutex failure?! Well, try to continue with unrecycled data. */
- svn_error_clear(err);
- pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
- }
-
- return pool;
-}
-
-/* Clear and release the given connection POOL.
- */
-static void
-release_connection_pool(apr_pool_t *pool)
-{
- svn_error_t *err;
-
- svn_pool_clear(pool);
-
- err = svn_mutex__lock(connection_pools_mutex);
- if (err)
- {
- svn_error_clear(err);
- svn_pool_destroy(pool);
- }
- else
- {
- APR_ARRAY_PUSH(connection_pools, apr_pool_t *) = pool;
- svn_error_clear(svn_mutex__unlock(connection_pools_mutex,
- SVN_NO_ERROR));
- }
-}
-
#if APR_HAS_THREADS
/* The pool passed to apr_thread_create can only be released when both
@@ -528,17 +454,20 @@ release_connection_pool(apr_pool_t *pool
So we set the atomic counter to 2 then both the calling thread and
the new thread decrease it and when it reaches 0 the pool can be
released. */
-struct shared_pool_t {
+typedef struct shared_pool_t {
svn_atomic_t count;
- apr_pool_t *pool;
-};
-
-static struct shared_pool_t *
-attach_shared_pool(apr_pool_t *pool)
+ apr_pool_t *pool; /* root pool used to allocate the socket */
+ svn_root_pools__t *root_pools; /* put it back into this after use */
+} shared_pool_t;
+
+static shared_pool_t *
+attach_shared_pool(apr_pool_t *pool,
+ svn_root_pools__t *root_pools)
{
- struct shared_pool_t *shared = apr_palloc(pool, sizeof(struct shared_pool_t));
+ shared_pool_t *shared = apr_palloc(pool, sizeof(*shared));
shared->pool = pool;
+ shared->root_pools = root_pools;
svn_atomic_set(&shared->count, 2);
return shared;
@@ -548,7 +477,7 @@ static void
release_shared_pool(struct shared_pool_t *shared)
{
if (svn_atomic_dec(&shared->count) == 0)
- release_connection_pool(shared->pool);
+ svn_root_pools__release_pool(shared->pool, shared->root_pools);
}
#endif
@@ -588,8 +517,8 @@ serve_socket(apr_socket_t *usock,
/* process the actual request and log errors */
err = serve(conn, params, pool);
if (err)
- log_error(err, params->log_file, params->log_file_mutex,
- svn_ra_svn_conn_remote_host(conn), NULL, NULL, pool);
+ logger__log_error(params->logger, err, NULL,
+ get_client_info(conn, params, pool));
return svn_error_trace(err);
}
@@ -598,15 +527,25 @@ serve_socket(apr_socket_t *usock,
struct serve_thread_t {
apr_socket_t *usock;
serve_params_t *params;
- struct shared_pool_t *shared_pool;
+#if APR_HAS_THREADS
+ shared_pool_t *shared_pool;
+#endif
};
#if APR_HAS_THREADS
+
+/* allocate and recycle root pools for connection objects.
+ There should be at most THREADPOOL_MAX_SIZE such pools. */
+svn_root_pools__t *connection_pools;
+
static void * APR_THREAD_FUNC serve_thread(apr_thread_t *tid, void *data)
{
struct serve_thread_t *d = data;
- svn_error_clear(serve_socket(d->usock, d->params, d->shared_pool->pool));
+ apr_pool_t *pool = svn_root_pools__acquire_pool(connection_pools);
+ svn_error_clear(serve_socket(d->usock, d->params, pool));
+ svn_root_pools__release_pool(pool, connection_pools);
+
release_shared_pool(d->shared_pool);
return NULL;
@@ -660,7 +599,6 @@ int main(int argc, const char *argv[])
apr_file_t *in_file, *out_file;
apr_sockaddr_t *sa;
apr_pool_t *pool;
- apr_pool_t *connection_pool;
svn_error_t *err;
apr_getopt_t *os;
int opt;
@@ -669,7 +607,7 @@ int main(int argc, const char *argv[])
apr_status_t status;
apr_proc_t proc;
#if APR_HAS_THREADS
- struct shared_pool_t *shared_pool;
+ shared_pool_t *shared_pool;
struct serve_thread_t *thread_data;
#if HAVE_THREADPOOLS
apr_thread_pool_t *threads;
@@ -694,6 +632,7 @@ int main(int argc, const char *argv[])
const char *pid_filename = NULL;
const char *log_filename = NULL;
svn_node_kind_t kind;
+ svn_root_pools__t *socket_pools;
/* Initialize the app. */
if (svn_cmdline_init("svnserve", stderr) != EXIT_SUCCESS)
@@ -727,8 +666,7 @@ int main(int argc, const char *argv[])
params.base = NULL;
params.cfg = NULL;
params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
- params.log_file = NULL;
- params.log_file_mutex = NULL;
+ params.logger = NULL;
params.vhost = FALSE;
params.username_case = CASE_ASIS;
params.memory_cache_size = (apr_uint64_t)-1;
@@ -984,12 +922,7 @@ int main(int argc, const char *argv[])
}
if (log_filename)
- {
- SVN_INT_ERR(svn_io_file_open(¶ms.log_file, log_filename,
- APR_WRITE | APR_CREATE | APR_APPEND,
- APR_OS_DEFAULT, pool));
- SVN_INT_ERR(svn_mutex__init(¶ms.log_file_mutex, TRUE, pool));
- }
+ SVN_INT_ERR(logger__create(¶ms.logger, log_filename, pool));
if (params.tunnel_user && run_mode != run_mode_tunnel)
{
@@ -1002,6 +935,7 @@ int main(int argc, const char *argv[])
if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
{
+ apr_pool_t *connection_pool;
svn_ra_svn_conn_t *conn;
params.tunnel = (run_mode == run_mode_tunnel);
@@ -1212,10 +1146,18 @@ int main(int argc, const char *argv[])
svn_cache_config_set(&settings);
}
- err = initialize_connection_pools(pool);
+ /* we use (and recycle) separate pools for sockets (many small ones)
+ and connections (fewer but larger ones) */
+ err = svn_root_pools__create(&socket_pools);
if (err)
return svn_cmdline_handle_exit_error(err, pool, "svnserve: ");
+#if APR_HAS_THREADS
+ err = svn_root_pools__create(&connection_pools);
+ if (err)
+ return svn_cmdline_handle_exit_error(err, pool, "svnserve: ");
+#endif
+
#if HAVE_THREADPOOLS
if (handling_mode == connection_mode_thread)
{
@@ -1241,6 +1183,8 @@ int main(int argc, const char *argv[])
while (1)
{
+ apr_pool_t *socket_pool;
+
#ifdef WIN32
if (winservice_is_stopping())
return ERROR_SUCCESS;
@@ -1250,21 +1194,21 @@ int main(int argc, const char *argv[])
the connection threads so it cannot clean up after each one. So
separate pools that can be cleared at thread exit are used. */
- connection_pool = acquire_connection_pool();
+ socket_pool = svn_root_pools__acquire_pool(socket_pools);
- status = apr_socket_accept(&usock, sock, connection_pool);
+ status = apr_socket_accept(&usock, sock, socket_pool);
if (handling_mode == connection_mode_fork)
{
/* Collect any zombie child processes. */
while (apr_proc_wait_all_procs(&proc, NULL, NULL, APR_NOWAIT,
- connection_pool) == APR_CHILD_DONE)
+ socket_pool) == APR_CHILD_DONE)
;
}
if (APR_STATUS_IS_EINTR(status)
|| APR_STATUS_IS_ECONNABORTED(status)
|| APR_STATUS_IS_ECONNRESET(status))
{
- release_connection_pool(connection_pool);
+ svn_root_pools__release_pool(socket_pool, socket_pools);
continue;
}
if (status)
@@ -1276,7 +1220,7 @@ int main(int argc, const char *argv[])
if (run_mode == run_mode_listen_once)
{
- err = serve_socket(usock, ¶ms, connection_pool);
+ err = serve_socket(usock, ¶ms, socket_pool);
if (err)
svn_handle_error2(err, stdout, FALSE, "svnserve: ");
@@ -1291,11 +1235,11 @@ int main(int argc, const char *argv[])
{
case connection_mode_fork:
#if APR_HAS_FORK
- status = apr_proc_fork(&proc, connection_pool);
+ status = apr_proc_fork(&proc, socket_pool);
if (status == APR_INCHILD)
{
apr_socket_close(sock);
- svn_error_clear(serve_socket(usock, ¶ms, connection_pool));
+ svn_error_clear(serve_socket(usock, ¶ms, socket_pool));
apr_socket_close(usock);
exit(0);
}
@@ -1306,13 +1250,11 @@ int main(int argc, const char *argv[])
else
{
err = svn_error_wrap_apr(status, "apr_proc_fork");
- log_error(err, params.log_file, params.log_file_mutex,
- NULL, NULL, NULL, /* ip, user, repos */
- connection_pool);
+ logger__log_error(params.logger, err, NULL, NULL);
svn_error_clear(err);
apr_socket_close(usock);
}
- release_connection_pool(connection_pool);
+ svn_root_pools__release_pool(socket_pool, socket_pools);
#endif
break;
@@ -1321,9 +1263,9 @@ int main(int argc, const char *argv[])
particularly sophisticated strategy for a threaded server, it's
little different from forking one process per connection. */
#if APR_HAS_THREADS
- shared_pool = attach_shared_pool(connection_pool);
+ shared_pool = attach_shared_pool(socket_pool, socket_pools);
- thread_data = apr_palloc(connection_pool, sizeof(*thread_data));
+ thread_data = apr_palloc(socket_pool, sizeof(*thread_data));
thread_data->usock = usock;
thread_data->params = ¶ms;
thread_data->shared_pool = shared_pool;
@@ -1331,7 +1273,7 @@ int main(int argc, const char *argv[])
status = apr_thread_pool_push(threads, serve_thread, thread_data,
0, NULL);
#else
- status = apr_threadattr_create(&tattr, connection_pool);
+ status = apr_threadattr_create(&tattr, socket_pool);
if (status)
{
err = svn_error_wrap_apr(status, _("Can't create threadattr"));
@@ -1363,8 +1305,8 @@ int main(int argc, const char *argv[])
case connection_mode_single:
/* Serve one connection at a time. */
- svn_error_clear(serve_socket(usock, ¶ms, connection_pool));
- release_connection_pool(connection_pool);
+ svn_error_clear(serve_socket(usock, ¶ms, socket_pool));
+ svn_root_pools__release_pool(socket_pool, socket_pools);
}
}
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/move_tests.py Sun Oct 13 16:10:59 2013
@@ -1338,6 +1338,191 @@ def nested_replaces(sbox):
svntest.main.run_svn(None, 'update', '-r1', wc_dir)
svntest.actions.run_and_verify_status(wc_dir, r1_status)
+def setup_move_many(sbox):
+ "helper function which creates a wc with node A/A/A which is moved 3 times"
+
+ sbox.simple_rm('A', 'iota')
+ sbox.simple_mkdir('A',
+ 'A/A',
+ 'A/A/A',
+ 'A/A/A/A',
+ 'B',
+ 'B/A',
+ 'B/A/A',
+ 'B/A/A/A',
+ 'C',
+ 'C/A',
+ 'C/A/A',
+ 'C/A/A/A')
+ sbox.simple_commit()
+ sbox.simple_update()
+
+ sbox.simple_move('A/A/A', 'AAA_1')
+
+ sbox.simple_rm('A')
+ sbox.simple_move('B', 'A')
+
+ sbox.simple_move('A/A/A', 'AAA_2')
+
+ sbox.simple_rm('A/A')
+ sbox.simple_move('C/A', 'A/A')
+
+ sbox.simple_move('A/A/A', 'AAA_3')
+
+def move_many_status(wc_dir):
+ "obtain standard status after setup_move_many"
+
+ return svntest.wc.State(wc_dir, {
+ '' : Item(status=' ', wc_rev='2'),
+
+ 'AAA_1' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_1/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'AAA_2' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_2/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'AAA_3' : Item(status='A ', copied='+', moved_from='A/A/A', wc_rev='-'),
+ 'AAA_3/A' : Item(status=' ', copied='+', wc_rev='-'),
+
+ 'A' : Item(status='R ', copied='+', moved_from='B', wc_rev='-'),
+ 'A/A' : Item(status='R ', copied='+', moved_from='C/A', wc_rev='-'),
+ 'A/A/A' : Item(status='D ', copied='+', wc_rev='-', moved_to='AAA_3'),
+ 'A/A/A/A' : Item(status='D ', copied='+', wc_rev='-'),
+
+ 'B' : Item(status='D ', wc_rev='2', moved_to='A'),
+ 'B/A' : Item(status='D ', wc_rev='2'),
+ 'B/A/A' : Item(status='D ', wc_rev='2'),
+ 'B/A/A/A' : Item(status='D ', wc_rev='2'),
+
+ 'C' : Item(status=' ', wc_rev='2'),
+ 'C/A' : Item(status='D ', wc_rev='2', moved_to='A/A'),
+ 'C/A/A' : Item(status='D ', wc_rev='2'),
+ 'C/A/A/A' : Item(status='D ', wc_rev='2'),
+ })
+
+def move_many_update_delete(sbox):
+ "move many and delete-on-update"
+
+ sbox.build()
+ setup_move_many(sbox)
+
+ wc_dir = sbox.wc_dir
+
+ # Verify start situation
+ expected_status = move_many_status(wc_dir)
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ # And now create a tree conflict
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', sbox.repo_url + '/B',
+ '-m', '')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'B' : Item(status=' ', treeconflict='C'),
+ })
+
+
+ expected_status.tweak('', 'C', 'C/A', 'C/A/A', 'C/A/A/A', wc_rev='3')
+ expected_status.tweak('A', moved_from=None)
+ expected_status.remove('B/A', 'B/A/A', 'B/A/A/A')
+ expected_status.tweak('B', status='! ', treeconflict='C', wc_rev=None, moved_to=None)
+
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status)
+
+ # Would be nice if we could run the resolver as a separate step,
+ # but 'svn resolve' just fails for any value but working
+
+@XFail()
+def move_many_update_add(sbox):
+ "move many and add-on-update"
+
+ sbox.build()
+ setup_move_many(sbox)
+
+ wc_dir = sbox.wc_dir
+
+ # Verify start situation
+ expected_status = move_many_status(wc_dir)
+ #svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+ # And now create a tree conflict
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', sbox.repo_url + '/B/A/A/BB',
+ '-m', '')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'B' : Item(status=' ', treeconflict='C'),
+ 'B/A' : Item(status=' ', treeconflict='U'),
+ 'B/A/A' : Item(status=' ', treeconflict='U'),
+ 'B/A/A/BB' : Item(status=' ', treeconflict='A'),
+ # And while resolving
+ 'A/A/' : Item(status=' ', treeconflict='C')
+ })
+
+ expected_status.tweak('',
+ 'B', 'B/A', 'B/A/A', 'B/A/A/A',
+ 'C', 'C/A', 'C/A/A', 'C/A/A/A',
+ wc_rev='3')
+
+ expected_status.tweak('A/A', treeconflict='C')
+ expected_status.add({
+ 'A/A/A/BB' : Item(status='D ', copied='+', wc_rev='-'),
+ 'B/A/A/BB' : Item(status='D ', wc_rev='3'),
+ })
+
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status,
+ None, None, None,
+ None, None, None,
+ wc_dir, '--accept', 'mine-conflict')
+
+ # And another one
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', sbox.repo_url + '/C/A/A/BB',
+ '-m', '')
+
+ expected_status.tweak('',
+ 'B', 'B/A', 'B/A/A', 'B/A/A/A',
+ 'C', 'C/A', 'C/A/A', 'C/A/A/A',
+ wc_rev='4')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'C/A' : Item(status=' ', treeconflict='C'),
+ 'C/A/A' : Item(status=' ', treeconflict='U'),
+ 'C/A/A/BB' : Item(status=' ', treeconflict='A'),
+ })
+
+ # This currently triggers an assertion failure
+ svntest.actions.run_and_verify_update(wc_dir, expected_output, None,
+ expected_status,
+ None, None, None,
+ None, None, None,
+ wc_dir, '--accept', 'mine-conflict')
+
+@Issue(4437)
+@XFail()
+def move_del_moved(sbox):
+ "delete moved node, still a move"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ sbox.simple_mkdir('A/NEW')
+ sbox.simple_move('A/mu', 'A/NEW/mu')
+ sbox.simple_rm('A/NEW/mu')
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('A/mu', status='D ')
+ expected_status.add({
+ 'A/NEW' : Item(status='A ', wc_rev='-')
+ })
+
+ # A/mu still reports that it is moved to A/NEW/mu, while it is already
+ # deleted there.
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
#######################################################################
# Run the tests
@@ -1350,6 +1535,9 @@ test_list = [ None,
property_merge,
move_missing,
nested_replaces,
+ move_many_update_delete,
+ move_many_update_add,
+ move_del_moved,
]
if __name__ == '__main__':
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/revert_tests.py?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/cmdline/revert_tests.py Sun Oct 13 16:10:59 2013
@@ -1644,6 +1644,8 @@ def revert_obstructing_wc(sbox):
'revert', '-R', wc_dir)
+
+
########################################################################
# Run the tests
@@ -1683,7 +1685,7 @@ test_list = [ None,
revert_no_text_change_conflict_recursive,
revert_with_unversioned_targets,
revert_nonexistent,
- revert_obstructing_wc
+ revert_obstructing_wc,
]
if __name__ == '__main__':
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_ra/ra-test.c?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_ra/ra-test.c Sun Oct 13 16:10:59 2013
@@ -25,17 +25,23 @@
#include <apr_general.h>
#include <apr_pools.h>
+#include <apr_file_io.h>
#define SVN_DEPRECATED
#include "svn_error.h"
#include "svn_delta.h"
#include "svn_ra.h"
+#include "svn_pools.h"
+#include "svn_cmdline.h"
+#include "svn_dirent_uri.h"
#include "../svn_test.h"
#include "../svn_test_fs.h"
#include "../../libsvn_ra_local/ra_local.h"
+static const char tunnel_repos_name[] = "test-repo-tunnel";
+
/*-------------------------------------------------------------------*/
/** Helper routines. **/
@@ -58,7 +64,7 @@ make_and_open_local_repos(svn_ra_session
SVN_ERR(svn_uri_get_file_url_from_dirent(&url, repos_name, pool));
- SVN_ERR(svn_ra_open3(session, url, NULL, cbtable, NULL, NULL, pool));
+ SVN_ERR(svn_ra_open4(session, NULL, url, NULL, cbtable, NULL, NULL, pool));
return SVN_NO_ERROR;
}
@@ -88,6 +94,75 @@ commit_changes(svn_ra_session_t *session
return SVN_NO_ERROR;
}
+static int tunnel_open_count;
+
+static svn_error_t *
+open_tunnel(apr_file_t **request, apr_file_t **response,
+ void **tunnel_baton, void *callbacks_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port,
+ apr_pool_t *pool)
+{
+ svn_node_kind_t kind;
+ apr_proc_t *proc;
+ apr_procattr_t *attr;
+ apr_status_t status;
+ const char *args[] = { "svnserve", "-t", "-r", ".", NULL };
+ const char *svnserve;
+
+ SVN_ERR(svn_dirent_get_absolute(&svnserve, "../../svnserve/svnserve", pool));
+#ifdef WIN32
+ svnserve = apr_pstrcat(pool, svnserve, ".exe", NULL);
+#endif
+ SVN_ERR(svn_io_check_path(svnserve, &kind, pool));
+ if (kind != svn_node_file)
+ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
+ "Could not find svnserve at %s",
+ svn_dirent_local_style(svnserve, pool));
+
+ status = apr_procattr_create(&attr, pool);
+ if (status == APR_SUCCESS)
+ status = apr_procattr_io_set(attr, 1, 1, 0);
+ if (status == APR_SUCCESS)
+ status = apr_procattr_cmdtype_set(attr, APR_PROGRAM);
+ proc = apr_palloc(pool, sizeof(*proc));
+ if (status == APR_SUCCESS)
+ status = apr_proc_create(proc,
+ svn_dirent_local_style(svnserve, pool),
+ args, NULL, attr, pool);
+ if (status != APR_SUCCESS)
+ return svn_error_wrap_apr(status, "Could not run svnserve");
+#ifdef WIN32
+ apr_pool_note_subprocess(pool, proc, APR_KILL_NEVER);
+#else
+ apr_pool_note_subprocess(pool, proc, APR_KILL_ONLY_ONCE);
+#endif
+
+ /* APR pipe objects inherit by default. But we don't want the
+ * tunnel agent's pipes held open by future child processes
+ * (such as other ra_svn sessions), so turn that off. */
+ apr_file_inherit_unset(proc->in);
+ apr_file_inherit_unset(proc->out);
+
+ *request = proc->in;
+ *response = proc->out;
+ *tunnel_baton = NULL;
+ ++tunnel_open_count;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+close_tunnel(void *tunnel_baton, void *callbacks_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port)
+{
+ --tunnel_open_count;
+ return SVN_NO_ERROR;
+}
+
+
+
+
/*-------------------------------------------------------------------*/
/** The tests **/
@@ -151,6 +226,50 @@ location_segments_test(const svn_test_op
}
+/* Test ra_svn tunnel callbacks. */
+static svn_error_t *
+tunel_callback_test(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ apr_pool_t *connection_pool;
+ svn_repos_t *repos;
+ const char *url;
+ svn_ra_callbacks2_t *cbtable;
+ svn_ra_session_t *session;
+ svn_error_t *err;
+
+ SVN_ERR(svn_test__create_repos(&repos, tunnel_repos_name, opts, pool));
+
+ url = apr_pstrcat(pool, "svn+test://localhost/", tunnel_repos_name, NULL);
+ SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
+ cbtable->open_tunnel = open_tunnel;
+ cbtable->close_tunnel = close_tunnel;
+ SVN_ERR(svn_cmdline_create_auth_baton(&cbtable->auth_baton,
+ TRUE /* non_interactive */,
+ "jrandom", "rayjandom",
+ NULL,
+ TRUE /* no_auth_cache */,
+ FALSE /* trust_server_cert */,
+ NULL, NULL, NULL, pool));
+
+ tunnel_open_count = 0;
+ connection_pool = svn_pool_create(pool);
+ err = svn_ra_open4(&session, NULL, url, NULL, cbtable, NULL, NULL,
+ connection_pool);
+ if (err && err->apr_err == SVN_ERR_TEST_FAILED)
+ {
+ svn_handle_error2(err, stderr, FALSE, "svn_tests: ");
+ svn_error_clear(err);
+ return SVN_NO_ERROR;
+ }
+ SVN_ERR(err);
+ SVN_TEST_ASSERT(tunnel_open_count > 0);
+ svn_pool_destroy(connection_pool);
+ SVN_TEST_ASSERT(tunnel_open_count == 0);
+ return SVN_NO_ERROR;
+}
+
+
/* The test table. */
struct svn_test_descriptor_t test_funcs[] =
@@ -158,5 +277,7 @@ struct svn_test_descriptor_t test_funcs[
SVN_TEST_NULL,
SVN_TEST_OPTS_PASS(location_segments_test,
"test svn_ra_get_location_segments"),
+ SVN_TEST_OPTS_PASS(tunel_callback_test,
+ "test ra_svn tunnel creation callbacks"),
SVN_TEST_NULL
};
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_wc/op-depth-test.c?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/subversion/tests/libsvn_wc/op-depth-test.c Sun Oct 13 16:10:59 2013
@@ -8262,6 +8262,195 @@ copy_mixed_rev_mods(const svn_test_opts_
return SVN_NO_ERROR;
}
+static svn_error_t *
+move_child_to_parent_revert(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_child_to_parent_revert", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+
+ SVN_ERR(sbox_wc_move(&b, "A/B", "B"));
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ /* Verify that the move is still recorded correctly */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+
+ {1, "A", "base-deleted", NO_COPY_FROM},
+ {1, "A/B", "base-deleted", NO_COPY_FROM, "B"},
+
+ {1, "B", "normal", 1, "A/B", MOVED_HERE},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+ /* Verify that the move is now just a copy */
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 0, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 1, "A/B"},
+
+ {1, "B", "normal", 1, "A/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_abspath_more_than_once(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_child_to_parent_revert", opts,
+ pool));
+
+ SVN_ERR(sbox_wc_mkdir(&b, "A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "B/A/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A"));
+ SVN_ERR(sbox_wc_mkdir(&b, "C/A/A/A"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_1"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+ SVN_ERR(sbox_wc_move(&b, "B", "A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_2"));
+
+ SVN_ERR(sbox_wc_delete(&b, "A/A"));
+ SVN_ERR(sbox_wc_move(&b, "C/A", "A/A"));
+
+ SVN_ERR(sbox_wc_move(&b, "A/A/A", "AAA_3"));
+
+ /* Verify that the move is still recorded correctly */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A", MOVED_HERE},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A", MOVED_HERE},
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {1, "A", "normal", 1, "B", MOVED_HERE},
+ {1, "A/A", "normal", 1, "B/A", MOVED_HERE},
+ {1, "A/A/A", "normal", 1, "B/A/A", FALSE, "AAA_1", TRUE},
+ {1, "A/A/A/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+
+ {2, "A/A", "normal", 1, "C/A", MOVED_HERE},
+ {2, "A/A/A", "normal", 1, "C/A/A", FALSE, "AAA_2", TRUE},
+ {2, "A/A/A/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {3, "A/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {3, "A/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM, "A"},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM, "A/A"},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ /* Ok, now we are in the very ugly case where A/A/A is moved away 3 times */
+
+ /* Let's revert A */
+ SVN_ERR(sbox_wc_revert(&b, "A", svn_depth_infinity));
+
+ /* AAA_1 should now be a copy, but AAA_2 and AAA_3 should still be moves,
+ but now from the original location instead of from "A/A/A" */
+ {
+ nodes_row_t nodes[] = {
+
+ {0, "", "normal", 0, ""},
+
+ {1, "AAA_1", "normal", 1, "A/A/A",},
+ {1, "AAA_1/A", "normal", 1, "A/A/A/A"},
+ {1, "AAA_2", "normal", 1, "B/A/A", MOVED_HERE},
+ {1, "AAA_2/A", "normal", 1, "B/A/A/A", MOVED_HERE},
+ {1, "AAA_3", "normal", 1, "C/A/A", MOVED_HERE},
+ {1, "AAA_3/A", "normal", 1, "C/A/A/A", MOVED_HERE},
+
+ {0, "A", "normal", 1, "A"},
+ {0, "A/A", "normal", 1, "A/A"},
+ {0, "A/A/A", "normal", 1, "A/A/A"},
+ {0, "A/A/A/A", "normal", 1, "A/A/A/A"},
+
+ {0, "B", "normal", 1, "B"},
+ {0, "B/A", "normal", 1, "B/A"},
+ {0, "B/A/A", "normal", 1, "B/A/A"},
+ {0, "B/A/A/A", "normal", 1, "B/A/A/A"},
+
+ {1, "B", "base-deleted", NO_COPY_FROM},
+ {1, "B/A", "base-deleted", NO_COPY_FROM},
+ {1, "B/A/A", "base-deleted", NO_COPY_FROM, "AAA_2"},
+ {1, "B/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ {0, "C", "normal", 1, "C"},
+ {0, "C/A", "normal", 1, "C/A"},
+ {0, "C/A/A", "normal", 1, "C/A/A"},
+ {0, "C/A/A/A", "normal", 1, "C/A/A/A"},
+
+ {2, "C/A", "base-deleted", NO_COPY_FROM},
+ {2, "C/A/A", "base-deleted", NO_COPY_FROM, "AAA_3"},
+ {2, "C/A/A/A", "base-deleted", NO_COPY_FROM},
+
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -8419,5 +8608,9 @@ struct svn_test_descriptor_t test_funcs[
"move update with replaced parent (issue 4388)"),
SVN_TEST_OPTS_XFAIL(copy_mixed_rev_mods,
"copy mixed-rev with mods"),
+ SVN_TEST_OPTS_PASS(move_child_to_parent_revert,
+ "move child to parent and revert (issue 4436)"),
+ SVN_TEST_OPTS_XFAIL(move_abspath_more_than_once,
+ "move one abspath more than once"),
SVN_TEST_NULL
};
Modified: subversion/branches/invoke-diff-cmd-feature/tools/dev/fsfs-access-map.c
URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/tools/dev/fsfs-access-map.c?rev=1531702&r1=1531701&r2=1531702&view=diff
==============================================================================
--- subversion/branches/invoke-diff-cmd-feature/tools/dev/fsfs-access-map.c (original)
+++ subversion/branches/invoke-diff-cmd-feature/tools/dev/fsfs-access-map.c Sun Oct 13 16:10:59 2013
@@ -791,4 +791,4 @@ int main(int argc, const char *argv[])
apr_file_close(file);
return 0;
-}
\ No newline at end of file
+}